using System.Collections.Generic;
public class LexerException : System.Exception
public LexerException(string msg)
private string inputText;
private int LexRow, LexCol;
private StringReader inputReader;
private Dictionary<string, Tok> keywordsMap;
public Lexer(string input)
inputReader = new StringReader(input);
keywordsMap = new Dictionary<string, Tok>();
private void PassSpaces()
while (char.IsWhiteSpace(currentCh))
private void InitKeywords()
keywordsMap["begin"] = Tok.BEGIN;
keywordsMap["end"] = Tok.END;
keywordsMap["cycle"] = Tok.CYCLE;
private void LexError(string message)
var reader = new StringReader(inputText);
for (int i = 0; i < row - 1; i++)
var errorString = reader.ReadLine();
System.Text.StringBuilder errorDescription = new System.Text.StringBuilder();
errorDescription.AppendFormat("Lexical error in line {0}:", row);
errorDescription.Append("\n");
errorDescription.Append(errorString);
errorDescription.Append("\n");
errorDescription.Append(new String(' ', col - 1) + '^');
errorDescription.Append('\n');
errorDescription.Append(message);
throw new LexerException(errorDescription.ToString());
var nextChar = inputReader.Read();
currentCh = (char)nextChar;
} else if (currentCh == ':') {
LexError("= was expected");
} else if (char.IsLetter(currentCh)) {
while (char.IsLetterOrDigit(currentCh))
if (keywordsMap.ContainsKey(LexText))
LexKind = keywordsMap[LexText];
else if (char.IsDigit(currentCh))
while (char.IsDigit(currentCh))
LexValue = Int32.Parse(LexText);
} else if ((int)currentCh == 0) {
LexError("Incorrect symbol " + currentCh);
public virtual void Parse()
Console.WriteLine(TokToString(LexKind));
} while (LexKind != Tok.EOF);
private string TokToString(Tok t)
var result = t.ToString();
case Tok.ID: result += ' ' + LexText;
case Tok.INUM: result += ' ' + LexValue.ToString();
public static void Main()
string fileContents = @"begin
Lexer l = new Lexer(fileContents);
Console.WriteLine("lexer error: " + e.Message);