228
|
1 using Implab.Automaton;
|
|
2 using System;
|
|
3 using System.Collections.Generic;
|
|
4 using System.Linq;
|
229
|
5 using System.Runtime.CompilerServices;
|
228
|
6 using System.Text;
|
|
7 using System.Threading.Tasks;
|
|
8
|
|
9 namespace Implab.Formats {
|
|
10 public class InputScanner<TTag> {
|
|
11 readonly TTag[] m_tags;
|
|
12 readonly int m_initialState;
|
|
13 readonly int[,] m_dfa;
|
|
14 readonly CharMap m_alphabet;
|
|
15 readonly bool[] m_final;
|
|
16
|
|
17 int m_position;
|
|
18 int m_state;
|
|
19
|
|
20 public InputScanner(int[,] dfaTable, bool[] finalStates, TTag[] tags, int initialState, CharMap alphabet) {
|
|
21 Safe.ArgumentNotNull(dfaTable, nameof(dfaTable));
|
|
22 Safe.ArgumentNotNull(finalStates, nameof(finalStates));
|
|
23 Safe.ArgumentNotNull(tags, nameof(tags));
|
|
24 Safe.ArgumentNotNull(alphabet, nameof(alphabet));
|
|
25
|
|
26 m_dfa = dfaTable;
|
|
27 m_final = finalStates;
|
|
28 m_tags = tags;
|
|
29 m_initialState = initialState;
|
|
30 m_alphabet = alphabet;
|
|
31 }
|
|
32
|
|
33 public TTag Tag {
|
229
|
34 [MethodImpl(MethodImplOptions.AggressiveInlining)]
|
228
|
35 get {
|
|
36 return m_tags[m_state];
|
|
37 }
|
|
38 }
|
|
39
|
|
40 public int Position {
|
229
|
41 [MethodImpl(MethodImplOptions.AggressiveInlining)]
|
228
|
42 get {
|
|
43 return m_position;
|
|
44 }
|
|
45 }
|
|
46
|
|
47 public bool IsFinal {
|
229
|
48 [MethodImpl(MethodImplOptions.AggressiveInlining)]
|
228
|
49 get {
|
|
50 return m_final[m_state];
|
|
51 }
|
|
52 }
|
|
53
|
229
|
54 [MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
55 public void ResetState() {
|
228
|
56 m_state = m_initialState;
|
|
57 }
|
|
58
|
|
59 public InputScanner<TTag> Clone() {
|
|
60 var clone = new InputScanner<TTag>(m_dfa, m_final, m_tags, m_initialState, m_alphabet);
|
|
61 clone.m_state = m_state;
|
|
62 clone.m_position = m_position;
|
|
63 return clone;
|
|
64 }
|
|
65
|
229
|
66 //[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
67 public bool Scan(char[] data, int offset, int max) {
|
228
|
68 var next = m_state;
|
|
69
|
|
70 while(offset < max) {
|
|
71 next = m_dfa[next, m_alphabet.Translate(data[offset])];
|
236
|
72 if (next == AutomatonConst.UnreachableState) {
|
228
|
73 // scanner stops on the next position after last recognized symbol
|
|
74 m_position = offset;
|
|
75 return false;
|
|
76 }
|
|
77 m_state = next;
|
|
78 offset++;
|
|
79 }
|
|
80 m_position = offset;
|
|
81 return true;
|
|
82 }
|
|
83 }
|
|
84 }
|