Mercurial > pub > ImplabNet
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) |