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 } |
