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