Mercurial > pub > ImplabNet
diff Implab/Parsing/Scanner.cs @ 59:21611344d366
code cleanup
author | cin |
---|---|
date | Wed, 18 Jun 2014 03:54:02 +0400 |
parents | 7759c80cad95 |
children | 10c7337d29e7 |
line wrap: on
line diff
--- a/Implab/Parsing/Scanner.cs Tue Jun 17 19:40:43 2014 +0400 +++ b/Implab/Parsing/Scanner.cs Wed Jun 18 03:54:02 2014 +0400 @@ -1,6 +1,7 @@ using Implab; using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -14,7 +15,7 @@ /// указателя, начала и конца токена, при перемещении искользуется ДКА для определения /// конца токена и допустимости текущего символа. /// </remarks> - public class Scanner { + public abstract class Scanner : Disposable { struct ScannerConfig { public DFAStateDescriptior[] states; public int[] alphabetMap; @@ -35,15 +36,10 @@ protected int m_bufferSize; protected int m_pointer; - public Scanner(CDFADefinition definition, string text) { - Safe.ArgumentNotNull(definition, "definition"); - Safe.ArgumentNotEmpty(text, "text"); - - m_states = definition.States; - m_alphabetMap = definition.Alphabet.GetTranslationMap(); - - Feed(text.ToCharArray()); - } + TextReader m_reader; + bool m_disposeReader; + int m_chunkSize = 1024; // 1k + int m_limit = 10 * 1024 * 1024; // 10Mb public Scanner(CDFADefinition definition) { Safe.ArgumentNotNull(definition, "definition"); @@ -76,6 +72,7 @@ public void Feed(char[] data, int length) { Safe.ArgumentNotNull(data, "data"); Safe.ArgumentInRange(length, 0, data.Length, "length"); + AssertNotDisposed(); m_pointer = -1; m_buffer = data; @@ -83,18 +80,33 @@ Shift(); } + public void Feed(TextReader reader, bool dispose) { + Safe.ArgumentNotNull(reader, "reader"); + AssertNotDisposed(); + + if (m_reader != null && m_disposeReader) + m_reader.Dispose(); + + m_reader = reader; + m_disposeReader = dispose; + m_pointer = -1; + m_buffer = new char[m_chunkSize]; + m_bufferSize = 0; + Shift(); + } + /// <summary> /// Получает текущий токен в виде строки. /// </summary> /// <returns></returns> - public string GetTokenValue() { + protected string GetTokenValue() { return new String(m_buffer, m_tokenOffset, m_tokenLen); } /// <summary> /// Метки текущего токена, которые были назначены в регулярном выражении. /// </summary> - public int[] TokenTags { + protected int[] TokenTags { get { return m_currentState.tag; } @@ -163,13 +175,31 @@ return true; } - /// <summary> - /// Вызывается по достижению конца входного буффера для получения - /// новых данных. - /// </summary> - /// <returns><c>true</c> - новые двнные получены, можно продолжать обработку.</returns> - protected virtual bool ReadNextChunk() { - return false; + bool ReadNextChunk() { + if (m_reader == null) + return false; + + // extend buffer if nesessary + if (m_pointer + m_chunkSize > m_buffer.Length) { + // trim unused buffer head + var size = m_tokenLen + m_chunkSize; + if (size >= m_limit) + throw new ParserException(String.Format("Input buffer {0} bytes limit exceeded", m_limit)); + var temp = new char[size]; + Array.Copy(m_buffer, m_tokenOffset, temp, 0, m_tokenLen); + m_pointer -= m_tokenOffset; + m_bufferSize -= m_tokenOffset; + m_tokenOffset = 0; + m_buffer = temp; + } + + var read = m_reader.Read(m_buffer, m_tokenLen, m_chunkSize); + if (read == 0) + return false; + + m_bufferSize += read; + + return true; } /// <summary> @@ -212,5 +242,18 @@ m_alphabetMap = prev.alphabetMap; m_previewCode = m_alphabetMap[m_buffer[m_pointer]]; } + + protected override void Dispose(bool disposing) { + if (disposing) { + if (m_reader != null && m_disposeReader) + m_reader.Dispose(); + m_buffer = null; + m_bufferSize = 0; + m_pointer = 0; + m_tokenLen = 0; + m_tokenOffset = 0; + } + base.Dispose(disposing); + } } }