InputScanner.cs
84 lines
| 2.6 KiB
| text/x-csharp
|
CSharpLexer
cin
|
r289 | 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.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; | ||||
} | ||||
} | ||||
} | ||||