comparison Implab/Automaton/Scanner.cs @ 172:92d5278d1b10 ref20160224

Working on text scanner
author cin
date Mon, 14 Mar 2016 01:19:38 +0300
parents e227e78d72e4
children 983df35b3ca1
comparison
equal deleted inserted replaced
171:0f70905b4652 172:92d5278d1b10
1 using Implab; 1 using Implab;
2 using System; 2 using System;
3 using System.Collections.Generic; 3 using System.Collections.Generic;
4 using System.IO; 4 using System.IO;
5 using Implab.Components; 5 using Implab.Components;
6 using Implab.Automaton.RegularExpressions;
6 7
7 namespace Implab.Automaton { 8 namespace Implab.Automaton {
8 /// <summary> 9 /// <summary>
9 /// Базовый класс для разбора потока входных символов на токены. 10 /// Базовый класс для разбора потока входных символов на токены.
10 /// </summary> 11 /// </summary>
12 /// Сканнер имеет внутри буффер с симолами входного текста, по которому перемещаются два 13 /// Сканнер имеет внутри буффер с симолами входного текста, по которому перемещаются два
13 /// указателя, начала и конца токена, при перемещении искользуется ДКА для определения 14 /// указателя, начала и конца токена, при перемещении искользуется ДКА для определения
14 /// конца токена и допустимости текущего символа. 15 /// конца токена и допустимости текущего символа.
15 /// </remarks> 16 /// </remarks>
16 public abstract class Scanner<TTag> : Disposable { 17 public abstract class Scanner<TTag> : Disposable {
17 struct ScannerConfig { 18 protected struct ScannerConfig {
18 public DFAStateDescriptior<TTag>[] states; 19 public readonly DFAStateDescriptor<TTag>[] states;
19 public int[] alphabetMap; 20 public readonly int[] alphabet;
20 public int initialState; 21 public readonly int initialState;
22
23 public ScannerConfig(DFAStateDescriptor<TTag>[] states, int[] alphabet, int initialState) {
24 this.initialState = initialState;
25 this.alphabet = alphabet;
26 this.states = states;
27 }
21 } 28 }
22 29
23 Stack<ScannerConfig> m_defs = new Stack<ScannerConfig>(); 30 Stack<ScannerConfig> m_defs = new Stack<ScannerConfig>();
24 31
25 DFAStateDescriptior<TTag>[] m_states; 32 ScannerConfig m_config;
26 int[] m_alphabetMap; 33
27 int m_initialState; 34 protected DFAStateDescriptor<TTag> m_currentState;
28
29 protected DFAStateDescriptior<TTag> m_currentState;
30 int m_previewCode; 35 int m_previewCode;
31 36
32 protected int m_tokenLen; 37 protected int m_tokenLen;
33 protected int m_tokenOffset; 38 protected int m_tokenOffset;
34 39
39 TextReader m_reader; 44 TextReader m_reader;
40 bool m_disposeReader; 45 bool m_disposeReader;
41 int m_chunkSize = 1024; // 1k 46 int m_chunkSize = 1024; // 1k
42 int m_limit = 10 * 1024 * 1024; // 10Mb 47 int m_limit = 10 * 1024 * 1024; // 10Mb
43 48
44 protected Scanner(DFAStateDescriptior<TTag>[] states, int[] alphabet, int initialState) { 49 protected Scanner(ScannerConfig config) {
45 Safe.ArgumentNotEmpty(states, "states"); 50 Safe.ArgumentNotEmpty(config.states, "config.states");
46 Safe.ArgumentNotNull(alphabet, "alphabet"); 51 Safe.ArgumentNotNull(config.alphabet, "config.alphabet");
47 52
48 m_states = states; 53 m_config = config;
49 m_alphabetMap = alphabet;
50 m_initialState = initialState;
51
52 Feed(new char[0]);
53 } 54 }
54 55
55 /// <summary> 56 /// <summary>
56 /// Заполняет входными данными буффер. 57 /// Заполняет входными данными буффер.
57 /// </summary> 58 /// </summary>
108 /// <summary> 109 /// <summary>
109 /// Метки текущего токена, которые были назначены в регулярном выражении. 110 /// Метки текущего токена, которые были назначены в регулярном выражении.
110 /// </summary> 111 /// </summary>
111 protected TTag[] TokenTags { 112 protected TTag[] TokenTags {
112 get { 113 get {
113 return m_currentState.tag; 114 return m_currentState.tags;
114 } 115 }
115 } 116 }
116 117
117 /// <summary> 118 /// <summary>
118 /// Признак конца данных 119 /// Признак конца данных
131 /// <returns><c>false</c> - достигнут конец данных, токен не прочитан.</returns> 132 /// <returns><c>false</c> - достигнут конец данных, токен не прочитан.</returns>
132 protected bool ReadTokenInternal() { 133 protected bool ReadTokenInternal() {
133 if (m_pointer >= m_bufferSize) 134 if (m_pointer >= m_bufferSize)
134 return false; 135 return false;
135 136
136 m_currentState = m_states[m_initialState]; 137 m_currentState = m_config.states[m_config.initialState];
137 m_tokenLen = 0; 138 m_tokenLen = 0;
138 m_tokenOffset = m_pointer; 139 m_tokenOffset = m_pointer;
139 int nextState; 140 int nextState;
140 do { 141 do {
141 nextState = m_currentState.transitions[m_previewCode]; 142 nextState = m_currentState.transitions[m_previewCode];
149 m_buffer[m_pointer], 150 m_buffer[m_pointer],
150 Position 151 Position
151 ) 152 )
152 ); 153 );
153 } 154 }
154 m_currentState = m_states[nextState]; 155 m_currentState = m_config.states[nextState];
155 m_tokenLen++; 156 m_tokenLen++;
156 157
157 } while (Shift()); 158 } while (Shift());
158 159
159 // END OF DATA 160 // END OF DATA
170 if (m_pointer >= m_bufferSize) { 171 if (m_pointer >= m_bufferSize) {
171 if (!ReadNextChunk()) 172 if (!ReadNextChunk())
172 return false; 173 return false;
173 } 174 }
174 175
175 m_previewCode = m_alphabetMap[m_buffer[m_pointer]]; 176 m_previewCode = m_config.alphabet[m_buffer[m_pointer]];
176 177
177 return true; 178 return true;
178 } 179 }
179 180
180 bool ReadNextChunk() { 181 bool ReadNextChunk() {
215 216
216 /// <summary> 217 /// <summary>
217 /// Преключает внутренний ДКА на указанный, позволяет реализовать подобие захватывающей 218 /// Преключает внутренний ДКА на указанный, позволяет реализовать подобие захватывающей
218 /// группировки. 219 /// группировки.
219 /// </summary> 220 /// </summary>
220 /// <param name="states">Таблица состояний нового ДКА</param> 221 /// <param name = "config"></param>
221 /// <param name="alphabet">Таблица входных символов для нового ДКА</param> 222 protected void Switch(ScannerConfig config) {
222 /// <param name = "initialState"></param> 223 Safe.ArgumentNotNull(config.states, "config.states");
223 protected void Switch(DFAStateDescriptior<TTag>[] states, int[] alphabet, int initialState) { 224
224 Safe.ArgumentNotNull(states, "dfa"); 225 m_defs.Push(m_config);
225 226 m_config = config;
226 m_defs.Push(new ScannerConfig { 227
227 states = m_states, 228 m_previewCode = m_config.alphabet[m_buffer[m_pointer]];
228 alphabetMap = m_alphabetMap,
229 initialState = m_initialState
230 });
231
232 m_states = states;
233 m_alphabetMap = alphabet;
234 m_initialState = initialState;
235
236 m_previewCode = m_alphabetMap[m_buffer[m_pointer]];
237 } 229 }
238 230
239 /// <summary> 231 /// <summary>
240 /// Восстанавливает предыдущей ДКА сканнера. 232 /// Восстанавливает предыдущей ДКА сканнера.
241 /// </summary> 233 /// </summary>
242 protected void Restore() { 234 protected void Restore() {
243 if (m_defs.Count == 0) 235 if (m_defs.Count == 0)
244 throw new InvalidOperationException(); 236 throw new InvalidOperationException();
245 var prev = m_defs.Pop(); 237 m_config = m_defs.Pop();
246 m_states = prev.states; 238
247 m_alphabetMap = prev.alphabetMap; 239 m_previewCode = m_config.alphabet[m_buffer[m_pointer]];
248 m_initialState = prev.initialState;
249 m_previewCode = m_alphabetMap[m_buffer[m_pointer]];
250 } 240 }
251 241
252 protected override void Dispose(bool disposing) { 242 protected override void Dispose(bool disposing) {
253 if (disposing) { 243 if (disposing) {
254 if (m_reader != null && m_disposeReader) 244 if (m_reader != null && m_disposeReader)