BufferScanner.cs
143 lines
| 3.7 KiB
| text/x-csharp
|
CSharpLexer
|
|
r173 | 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; | ||||
| } | ||||
| } | ||||
| } | ||||
