|
|
using Implab.Automaton;
|
|
|
using System;
|
|
|
using System.Collections.Generic;
|
|
|
using System.Linq;
|
|
|
using System.Runtime.CompilerServices;
|
|
|
using System.Text;
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
|
namespace Implab.Formats {
|
|
|
public class InputScanner<TTag> {
|
|
|
readonly TTag[] m_tags;
|
|
|
readonly int m_initialState;
|
|
|
readonly int[,] m_dfa;
|
|
|
readonly CharMap m_alphabet;
|
|
|
readonly bool[] m_final;
|
|
|
|
|
|
int m_position;
|
|
|
int m_state;
|
|
|
|
|
|
public InputScanner(int[,] dfaTable, bool[] finalStates, TTag[] tags, int initialState, CharMap alphabet) {
|
|
|
Safe.ArgumentNotNull(dfaTable, nameof(dfaTable));
|
|
|
Safe.ArgumentNotNull(finalStates, nameof(finalStates));
|
|
|
Safe.ArgumentNotNull(tags, nameof(tags));
|
|
|
Safe.ArgumentNotNull(alphabet, nameof(alphabet));
|
|
|
|
|
|
m_dfa = dfaTable;
|
|
|
m_final = finalStates;
|
|
|
m_tags = tags;
|
|
|
m_initialState = initialState;
|
|
|
m_alphabet = alphabet;
|
|
|
}
|
|
|
|
|
|
public TTag Tag {
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
|
get {
|
|
|
return m_tags[m_state];
|
|
|
}
|
|
|
}
|
|
|
|
|
|
public int Position {
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
|
get {
|
|
|
return m_position;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
public bool IsFinal {
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
|
get {
|
|
|
return m_final[m_state];
|
|
|
}
|
|
|
}
|
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
|
public void ResetState() {
|
|
|
m_state = m_initialState;
|
|
|
}
|
|
|
|
|
|
public InputScanner<TTag> Clone() {
|
|
|
var clone = new InputScanner<TTag>(m_dfa, m_final, m_tags, m_initialState, m_alphabet);
|
|
|
clone.m_state = m_state;
|
|
|
clone.m_position = m_position;
|
|
|
return clone;
|
|
|
}
|
|
|
|
|
|
//[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
|
public bool Scan(char[] data, int offset, int max) {
|
|
|
var next = m_state;
|
|
|
|
|
|
while(offset < max) {
|
|
|
next = m_dfa[next, m_alphabet.Translate(data[offset])];
|
|
|
if (next == AutomatonConst.UNREACHABLE_STATE) {
|
|
|
// scanner stops on the next position after last recognized symbol
|
|
|
m_position = offset;
|
|
|
return false;
|
|
|
}
|
|
|
m_state = next;
|
|
|
offset++;
|
|
|
}
|
|
|
m_position = offset;
|
|
|
return true;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|