diff --git a/Module1/Lexer.cs b/Module1/Lexer.cs new file mode 100644 index 0000000000000000000000000000000000000000..db21a1314c2f0a47d0e7f355d072694200c49e31 --- /dev/null +++ b/Module1/Lexer.cs @@ -0,0 +1,108 @@ +public class LexerException : System.Exception +{ + public LexerException(string msg) + : base(msg) + { + } + +} + +public class Lexer +{ + + protected int position; + protected char currentCh; // очередной считанный символ + protected int currentCharValue; // целое значение очередного считанного символа + protected System.IO.StringReader inputReader; + protected string inputString; + + public Lexer(string input) + { + inputReader = new System.IO.StringReader(input); + inputString = input; + } + + public void Error() + { + System.Text.StringBuilder o = new System.Text.StringBuilder(); + o.Append(inputString + '\n'); + o.Append(new System.String(' ', position - 1) + "^\n"); + o.AppendFormat("Error in symbol {0}", currentCh); + throw new LexerException(o.ToString()); + } + + protected void NextCh() + { + this.currentCharValue = this.inputReader.Read(); + this.currentCh = (char)currentCharValue; + this.position += 1; + } + + public virtual void Parse() + { + + } +} + +public class IntLexer : Lexer +{ + + protected System.Text.StringBuilder intString; + + public IntLexer(string input) + : base(input) + { + intString = new System.Text.StringBuilder(); + } + + public override void Parse() + { + NextCh(); + if (currentCh == '+' || currentCh == '-') + { + NextCh(); + } + + if (char.IsDigit(currentCh)) + { + NextCh(); + } + else + { + Error(); + } + + while (char.IsDigit(currentCh)) + { + NextCh(); + } + + + if (currentCharValue != -1) // StringReader вернет -1 в конце строки + { + Error(); + } + + System.Console.WriteLine("Interger is recognized"); + + } +} + + +public class Program +{ + public static void Main() + { + string input = "154216"; + Lexer L = new IntLexer(input); + try + { + L.Parse(); + } + catch (LexerException e) + { + System.Console.WriteLine(e.Message); + } + + } +} \ No newline at end of file diff --git a/Module2/Lexer.cs b/Module2/Lexer.cs new file mode 100644 index 0000000000000000000000000000000000000000..9dd18460846954e232c394d38a27ef0836dd6e00 --- /dev/null +++ b/Module2/Lexer.cs @@ -0,0 +1,204 @@ +using System; +using System.Collections.Generic; +using System.IO; + +public class LexerException : System.Exception +{ + public LexerException(string msg) + : base(msg) + { + } + +} + +public enum Tok +{ + EOF, + ID, + INUM, + COLON, + SEMICOLON, + ASSIGN, + BEGIN, + END, + CYCLE +} + +public class Lexer +{ + + private string inputText; + private int position; + private char currentCh; // Текущий символ + private int LexRow, LexCol; // Строка-столбец начала лексемы. Конец лексемы = LexCol+LexText.Length + private int row, col; // текущие строка и столбец в файле + private StringReader inputReader; + private Dictionary<string, Tok> keywordsMap; // Словарь, сопоставляющий ключевым словам константы типа TLex. Инициализируется процедурой InitKeywords + private Tok LexKind; // Тип лексемы + private string LexText; // Текст лексемы + private int LexValue; // Целое значение, связанное с лексемой LexNum + + public Lexer(string input) + { + inputText = input; + inputReader = new StringReader(input); + keywordsMap = new Dictionary<string, Tok>(); + InitKeywords(); + row = 1; col = 1; + NextCh(); // Считать первый символ в ch + NextLexem(); // Считать первую лексему, заполнив LexText, LexKind и, возможно, LexValue + } + + private void PassSpaces() + { + while (char.IsWhiteSpace(currentCh)) + { + NextCh(); + } + } + + 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++) + { + reader.ReadLine(); + } + 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'); + if (message != "") + { + errorDescription.Append(message); + } + throw new LexerException(errorDescription.ToString()); + } + + private void NextCh() + { + // В LexText накапливается предыдущий символ и считывается следующий символ + LexText += currentCh; + var nextChar = inputReader.Read(); + if (nextChar != -1) + { + currentCh = (char)nextChar; + if (currentCh != '\n') + { + col += 1; + } + else + { + row += 1; + col = 1; + } + } + else + { + currentCh = (char)0; // если достигнут конец файла, то возвращается #0 + } + } + + private void NextLexem() + { + PassSpaces(); + // R К этому моменту первый символ лексемы считан в ch + LexText = ""; + LexRow = row; + LexCol = col; + // Тип лексемы определяется по ее первому символу + // Для каждой лексемы строится синтаксическая диаграмма + if (currentCh == ';') { + NextCh(); + LexKind = Tok.SEMICOLON; + } else if (currentCh == ':') { + NextCh(); + if (currentCh != '=') + { + LexError("= was expected"); + } + NextCh(); + LexKind = Tok.ASSIGN; + } else if (char.IsLetter(currentCh)) { + while (char.IsLetterOrDigit(currentCh)) + { + NextCh(); + } + if (keywordsMap.ContainsKey(LexText)) + { + LexKind = keywordsMap[LexText]; + } + else + { + LexKind = Tok.ID; + } + } + else if (char.IsDigit(currentCh)) + { + while (char.IsDigit(currentCh)) + { + NextCh(); + } + LexValue = Int32.Parse(LexText); + LexKind = Tok.INUM; + } else if ((int)currentCh == 0) { + LexKind = Tok.EOF; + } else { + LexError("Incorrect symbol " + currentCh); + } + } + + public virtual void Parse() + { + do + { + Console.WriteLine(TokToString(LexKind)); + NextLexem(); + } while (LexKind != Tok.EOF); + } + + private string TokToString(Tok t) + { + var result = t.ToString(); + switch (t) + { + case Tok.ID: result += ' ' + LexText; + break; + case Tok.INUM: result += ' ' + LexValue.ToString(); + break; + } + return result; + } +} + + +public class Program +{ + public static void Main() + { + string fileContents = @"begin +id23 := 24; +cycle; 2 id258 id29 ; +end"; + Lexer l = new Lexer(fileContents); + try + { + l.Parse(); + } + catch (LexerException e) + { + Console.WriteLine("lexer error: " + e.Message); + } + } +} \ No newline at end of file