Mercurial > pub > ImplabNet
view Implab/Formats/BufferScanner.cs @ 173:ecfece82ca11 ref20160224
Working on text scanner
author | cin |
---|---|
date | Tue, 15 Mar 2016 02:11:06 +0300 |
parents | |
children | 983df35b3ca1 |
line wrap: on
line source
using System; using Implab.Automaton.RegularExpressions; using Implab.Automaton; namespace Implab.Formats { public struct BufferScanner<TTag> { char[] m_buffer; int m_offset; int m_position; int m_hi; readonly int m_chunk; readonly int m_limit; readonly DFAStateDescriptor<TTag>[] m_dfa; int m_state; public BufferScanner(DFAStateDescriptor<TTag>[] dfa, int initialState, int chunk, int limit) { m_dfa = dfa; m_state = initialState; m_chunk = chunk; m_limit = limit; m_buffer = null; m_offset = 0; m_position = 0; m_hi = 0; } public char[] Buffer { get { return m_buffer; } } public int HiMark { get { return m_hi; } } public int Position { get { return m_position; } } public int Length { get { return m_hi - m_position; } } public int TokenOffset { get { return m_offset; } } public int TokenLength { get { return m_position - m_offset; } } public void Init(char[] buffer, int position, int length) { m_buffer = buffer; m_position = position; m_offset = position; m_hi = position + length; } public int Extend() { // free space var free = m_buffer.Length - m_hi; // if the buffer have enough free space if (free > 0) return free; // effective size of the buffer var size = m_buffer.Length - m_offset; // calculate the new size int grow = Math.Min(m_limit - size, m_chunk); if (grow <= 0) throw new ParserException(String.Format("Input buffer {0} bytes limit exceeded", m_limit)); var temp = new char[size + grow]; Array.Copy(m_buffer, m_offset, temp, 0, m_hi - m_offset); m_position -= m_offset; m_hi -= m_offset; m_offset = 0; m_buffer = temp; return free + grow; } public void RaiseMark(int size) { m_hi += size; } /// <summary> /// Scan this instance. /// </summary> /// <returns><c>true</c> - additional data required</returns> public bool Scan() { while (m_position < m_hi) { var ch = m_buffer[m_position]; var next = m_dfa[m_state].transitions[(int)ch]; if (next == DFAConst.UNREACHABLE_STATE) { if (m_dfa[m_state].final) return false; throw new ParserException( String.Format( "Unexpected token '{0}'", new string(m_buffer, m_offset, m_position - m_offset) ) ); } m_state = next; m_position++; } return true; } public void Eof() { if (!m_dfa[m_state].final) throw new ParserException( String.Format( "Unexpected token '{0}'", new string(m_buffer, m_offset, m_position - m_offset) ) ); } public TTag[] GetTokenTags() { return m_dfa[m_state].tags; } } }