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 { 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 Clone() { var clone = new InputScanner(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.UnreachableState) { // scanner stops on the next position after last recognized symbol m_position = offset; return false; } m_state = next; offset++; } m_position = offset; return true; } } }