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 }