$ template make_lexer() $ output $basedir + '/lexer.cs' /* This file was generated by SableCC (http://www.sablecc.org/). */ using System; using System.Collections; using System.Text; using System.IO; using @package.node; namespace @package.lexer { internal class PushbackReader { private TextReader reader; private Stack stack = new Stack (); internal PushbackReader (TextReader reader) { this.reader = reader; } internal int Peek () { if ( stack.Count > 0 ) return (int)stack.Peek(); return reader.Peek(); } internal int Read () { if ( stack.Count > 0 ) return (int)stack.Pop(); return reader.Read(); } internal void Unread (int v) { stack.Push (v); } } $ // generate the LexerException class public class LexerException : ApplicationException { public LexerException(String message) : base (message) { } } $ // generate the Lexer class public class Lexer { protected Token token; protected State state = State.${lexer_data/state/@name}; private PushbackReader input; private int line; private int pos; private bool cr; private bool eof; private StringBuilder text = new StringBuilder(); protected virtual void Filter() { } public Lexer(TextReader input) { this.input = new PushbackReader(input); } public virtual Token Peek() { while(token == null) { token = GetToken(); Filter(); } return token; } public virtual Token Next() { while(token == null) { token = GetToken(); Filter(); } Token result = token; token = null; return result; } protected virtual Token GetToken() { int dfa_state = 0; int start_pos = pos; int start_line = line; int accept_state = -1; int accept_token = -1; int accept_length = -1; int accept_pos = -1; int accept_line = -1; int[][][] gotoTable = Lexer.gotoTable[state.id()]; int[] accept = Lexer.accept[state.id()]; text.Length = 0; while(true) { int c = GetChar(); if(c != -1) { switch(c) { case 10: if(cr) { cr = false; } else { line++; pos = 0; } break; case 13: line++; pos = 0; cr = true; break; default: pos++; cr = false; break; }; text.Append((char) c); do { int oldState = (dfa_state < -1) ? (-2 -dfa_state) : dfa_state; dfa_state = -1; int[][] tmp1 = gotoTable[oldState]; int low = 0; int high = tmp1.Length - 1; while(low <= high) { int middle = (low + high) / 2; int[] tmp2 = tmp1[middle]; if(c < tmp2[0]) { high = middle - 1; } else if(c > tmp2[1]) { low = middle + 1; } else { dfa_state = tmp2[2]; break; } } }while(dfa_state < -1); } else { dfa_state = -1; } if(dfa_state >= 0) { if(accept[dfa_state] != -1) { accept_state = dfa_state; accept_token = accept[dfa_state]; accept_length = text.Length; accept_pos = pos; accept_line = line; } } else { if(accept_state != -1) { switch(accept_token) { $ foreach {//token} case ${position()-1}: { $ if {not(@value)} Token token = New${position()-1}( GetText(accept_length), start_line + 1, start_pos + 1); $ else Token token = New${position()-1}( start_line + 1, start_pos + 1); $ end PushBack(accept_length); pos = accept_pos; line = accept_line; $ if {count(transition[@from!=@to])!=0} switch (state.id()) { $ foreach transition in {transition[@from!=@to]} case ${/parser/lexer_data/state[@name=$transition/@from]/@id}: state = State.@to; break; $ end foreach } $ end if return token; } $ end foreach } } else { if(text.Length > 0) { throw new LexerException( "[" + (start_line + 1) + "," + (start_pos + 1) + "]" + " Unknown token: " + text); } else { EOF token = new EOF( start_line + 1, start_pos + 1); return token; } } } } } $ foreach {//token} $ if @value private Token New${position()-1}(int line, int pos) { return new @ename(line, pos); } $ else private Token New${position()-1}(String text, int line, int pos) { return new @ename(text, line, pos); } $ end if $ end foreach private int GetChar() { if(eof) { return -1; } int result = input.Read(); if(result == -1) { eof = true; } return result; } private void PushBack(int acceptLength) { int length = text.Length; for(int i = length - 1; i >= acceptLength; i--) { eof = false; input.Unread(text[i]); } } protected virtual void Unread(Token token) { String text = token.Text; int length = text.Length; for(int i = length - 1; i >= 0; i--) { eof = false; input.Unread(text[i]); } pos = token.Pos - 1; line = token.Line - 1; } private string GetText(int acceptLength) { StringBuilder s = new StringBuilder(acceptLength); for(int i = 0; i < acceptLength; i++) { s.Append(text[i]); } return s.ToString(); } private static int[][][][] gotoTable = { $ foreach {lexer_data/goto_table/state} new int[][][] { $ foreach {row} new int[][] { $ foreach {goto} new int[] {@low, @high, @state}, $ end foreach }, $ end foreach }, $ end foreach }; private static int[][] accept = { $ foreach {lexer_data/accept_table/state} new int[] { [-foreach {i}-]${.}, [-end foreach-] }, $ end foreach }; public class State { $ foreach {lexer_data/state} public static State @name = new State(@id); $ end foreach private int _id; private State(int _id) { this._id = _id; } public int id() { return _id; } } } } $ end output $ end template