Mercurial > pub > ImplabNet
comparison Implab/Parsing/Scanner.cs @ 59:21611344d366
code cleanup
author | cin |
---|---|
date | Wed, 18 Jun 2014 03:54:02 +0400 |
parents | 7759c80cad95 |
children | 10c7337d29e7 |
comparison
equal
deleted
inserted
replaced
58:1710dcda34bb | 59:21611344d366 |
---|---|
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.Linq; | 5 using System.Linq; |
5 using System.Text; | 6 using System.Text; |
6 using System.Threading.Tasks; | 7 using System.Threading.Tasks; |
7 | 8 |
8 namespace Implab.Parsing { | 9 namespace Implab.Parsing { |
12 /// <remarks> | 13 /// <remarks> |
13 /// Сканнер имеет внутри буффер с симолами входного текста, по которому перемещаются два | 14 /// Сканнер имеет внутри буффер с симолами входного текста, по которому перемещаются два |
14 /// указателя, начала и конца токена, при перемещении искользуется ДКА для определения | 15 /// указателя, начала и конца токена, при перемещении искользуется ДКА для определения |
15 /// конца токена и допустимости текущего символа. | 16 /// конца токена и допустимости текущего символа. |
16 /// </remarks> | 17 /// </remarks> |
17 public class Scanner { | 18 public abstract class Scanner : Disposable { |
18 struct ScannerConfig { | 19 struct ScannerConfig { |
19 public DFAStateDescriptior[] states; | 20 public DFAStateDescriptior[] states; |
20 public int[] alphabetMap; | 21 public int[] alphabetMap; |
21 } | 22 } |
22 | 23 |
33 | 34 |
34 protected char[] m_buffer; | 35 protected char[] m_buffer; |
35 protected int m_bufferSize; | 36 protected int m_bufferSize; |
36 protected int m_pointer; | 37 protected int m_pointer; |
37 | 38 |
38 public Scanner(CDFADefinition definition, string text) { | 39 TextReader m_reader; |
39 Safe.ArgumentNotNull(definition, "definition"); | 40 bool m_disposeReader; |
40 Safe.ArgumentNotEmpty(text, "text"); | 41 int m_chunkSize = 1024; // 1k |
41 | 42 int m_limit = 10 * 1024 * 1024; // 10Mb |
42 m_states = definition.States; | |
43 m_alphabetMap = definition.Alphabet.GetTranslationMap(); | |
44 | |
45 Feed(text.ToCharArray()); | |
46 } | |
47 | 43 |
48 public Scanner(CDFADefinition definition) { | 44 public Scanner(CDFADefinition definition) { |
49 Safe.ArgumentNotNull(definition, "definition"); | 45 Safe.ArgumentNotNull(definition, "definition"); |
50 | 46 |
51 m_states = definition.States; | 47 m_states = definition.States; |
74 /// <remarks>Копирование данных не происходит, переданный массив используется в | 70 /// <remarks>Копирование данных не происходит, переданный массив используется в |
75 /// качестве входного буффера.</remarks> | 71 /// качестве входного буффера.</remarks> |
76 public void Feed(char[] data, int length) { | 72 public void Feed(char[] data, int length) { |
77 Safe.ArgumentNotNull(data, "data"); | 73 Safe.ArgumentNotNull(data, "data"); |
78 Safe.ArgumentInRange(length, 0, data.Length, "length"); | 74 Safe.ArgumentInRange(length, 0, data.Length, "length"); |
75 AssertNotDisposed(); | |
79 | 76 |
80 m_pointer = -1; | 77 m_pointer = -1; |
81 m_buffer = data; | 78 m_buffer = data; |
82 m_bufferSize = length; | 79 m_bufferSize = length; |
83 Shift(); | 80 Shift(); |
84 } | 81 } |
85 | 82 |
83 public void Feed(TextReader reader, bool dispose) { | |
84 Safe.ArgumentNotNull(reader, "reader"); | |
85 AssertNotDisposed(); | |
86 | |
87 if (m_reader != null && m_disposeReader) | |
88 m_reader.Dispose(); | |
89 | |
90 m_reader = reader; | |
91 m_disposeReader = dispose; | |
92 m_pointer = -1; | |
93 m_buffer = new char[m_chunkSize]; | |
94 m_bufferSize = 0; | |
95 Shift(); | |
96 } | |
97 | |
86 /// <summary> | 98 /// <summary> |
87 /// Получает текущий токен в виде строки. | 99 /// Получает текущий токен в виде строки. |
88 /// </summary> | 100 /// </summary> |
89 /// <returns></returns> | 101 /// <returns></returns> |
90 public string GetTokenValue() { | 102 protected string GetTokenValue() { |
91 return new String(m_buffer, m_tokenOffset, m_tokenLen); | 103 return new String(m_buffer, m_tokenOffset, m_tokenLen); |
92 } | 104 } |
93 | 105 |
94 /// <summary> | 106 /// <summary> |
95 /// Метки текущего токена, которые были назначены в регулярном выражении. | 107 /// Метки текущего токена, которые были назначены в регулярном выражении. |
96 /// </summary> | 108 /// </summary> |
97 public int[] TokenTags { | 109 protected int[] TokenTags { |
98 get { | 110 get { |
99 return m_currentState.tag; | 111 return m_currentState.tag; |
100 } | 112 } |
101 } | 113 } |
102 | 114 |
161 m_previewCode = m_alphabetMap[m_buffer[m_pointer]]; | 173 m_previewCode = m_alphabetMap[m_buffer[m_pointer]]; |
162 | 174 |
163 return true; | 175 return true; |
164 } | 176 } |
165 | 177 |
166 /// <summary> | 178 bool ReadNextChunk() { |
167 /// Вызывается по достижению конца входного буффера для получения | 179 if (m_reader == null) |
168 /// новых данных. | 180 return false; |
169 /// </summary> | 181 |
170 /// <returns><c>true</c> - новые двнные получены, можно продолжать обработку.</returns> | 182 // extend buffer if nesessary |
171 protected virtual bool ReadNextChunk() { | 183 if (m_pointer + m_chunkSize > m_buffer.Length) { |
172 return false; | 184 // trim unused buffer head |
185 var size = m_tokenLen + m_chunkSize; | |
186 if (size >= m_limit) | |
187 throw new ParserException(String.Format("Input buffer {0} bytes limit exceeded", m_limit)); | |
188 var temp = new char[size]; | |
189 Array.Copy(m_buffer, m_tokenOffset, temp, 0, m_tokenLen); | |
190 m_pointer -= m_tokenOffset; | |
191 m_bufferSize -= m_tokenOffset; | |
192 m_tokenOffset = 0; | |
193 m_buffer = temp; | |
194 } | |
195 | |
196 var read = m_reader.Read(m_buffer, m_tokenLen, m_chunkSize); | |
197 if (read == 0) | |
198 return false; | |
199 | |
200 m_bufferSize += read; | |
201 | |
202 return true; | |
173 } | 203 } |
174 | 204 |
175 /// <summary> | 205 /// <summary> |
176 /// Позиция сканнера во входном буфере | 206 /// Позиция сканнера во входном буфере |
177 /// </summary> | 207 /// </summary> |
210 var prev = m_defs.Pop(); | 240 var prev = m_defs.Pop(); |
211 m_states = prev.states; | 241 m_states = prev.states; |
212 m_alphabetMap = prev.alphabetMap; | 242 m_alphabetMap = prev.alphabetMap; |
213 m_previewCode = m_alphabetMap[m_buffer[m_pointer]]; | 243 m_previewCode = m_alphabetMap[m_buffer[m_pointer]]; |
214 } | 244 } |
245 | |
246 protected override void Dispose(bool disposing) { | |
247 if (disposing) { | |
248 if (m_reader != null && m_disposeReader) | |
249 m_reader.Dispose(); | |
250 m_buffer = null; | |
251 m_bufferSize = 0; | |
252 m_pointer = 0; | |
253 m_tokenLen = 0; | |
254 m_tokenOffset = 0; | |
255 } | |
256 base.Dispose(disposing); | |
257 } | |
215 } | 258 } |
216 } | 259 } |