using System; namespace SyntaxAnalyzer { public class Parser { public const int _EOF = 0; public const int _ident = 1; public const int maxT = 30; const bool T = true; const bool x = false; const int minErrDist = 2; public Scanner scanner; public Errors errors; public Token t; // last recognized token public Token la; // lookahead token int errDist = minErrDist; public Parser(Scanner scanner) { this.scanner = scanner; errors = new Errors(); } void SynErr (int n) { if (errDist >= minErrDist) errors.SynErr(la.line, la.col, n); errDist = 0; } public void SemErr (string msg) { if (errDist >= minErrDist) errors.SemErr(t.line, t.col, msg); errDist = 0; } void Get () { for (;;) { t = la; la = scanner.Scan(); if (la.kind <= maxT) { ++errDist; break; } la = t; } } void Expect (int n) { if (la.kind==n) Get(); else { SynErr(n); } } bool StartOf (int s) { return set[s, la.kind]; } void ExpectWeak (int n, int follow) { if (la.kind == n) Get(); else { SynErr(n); while (!StartOf(follow)) Get(); } } bool WeakSeparator(int n, int syFol, int repFol) { int kind = la.kind; if (kind == n) {Get(); return true;} else if (StartOf(repFol)) {return false;} else { SynErr(n); while (!(set[syFol, kind] || set[repFol, kind] || set[0, kind])) { Get(); kind = la.kind; } return StartOf(syFol); } } void GPDefSyntaxAnalyzer() { Expect(2); Expect(1); if (la.kind == 3) { Get(); Expect(4); while (StartOf(1)) { Get(); } Expect(5); } if (la.kind == 6) { Get(); Expect(4); while (StartOf(1)) { Get(); } Expect(5); } Expect(7); while (la.kind == 1) { NonterminalDecl(); } Expect(8); while (la.kind == 1) { TerminalDecl(); } Expect(9); while (la.kind == 1) { RuleDef(); } if (la.kind == 10) { Get(); } else if (la.kind == 11) { Get(); } else SynErr(31); Expect(4); while (StartOf(1)) { Get(); } Expect(5); Expect(12); Expect(1); Expect(13); } void NonterminalDecl() { Expect(1); if (la.kind == 4) { Get(); while (StartOf(1)) { Get(); } Expect(5); } Expect(13); } void TerminalDecl() { Expect(1); if (la.kind == 4) { Get(); while (StartOf(1)) { Get(); } Expect(5); } if (la.kind == 16) { Get(); ConstraintDef(); } Expect(13); } void RuleDef() { Expect(1); if (la.kind == 4) { Get(); while (StartOf(1)) { Get(); } Expect(5); } Expect(21); if (la.kind == 14) { SemDecl(); } SynExpr(); Expect(13); } void SemDecl() { Expect(14); Expect(4); while (StartOf(1)) { Get(); } Expect(5); } void SemAction() { Expect(15); Expect(4); while (StartOf(1)) { Get(); } Expect(5); } void ConstraintDef() { while (la.kind == 1) { ConstraintRule(); } } void ConstraintRule() { Expect(1); Expect(17); SetDefinition(); } void SetDefinition() { if (la.kind == 18) { Get(); Expect(4); while (StartOf(1)) { Get(); } Expect(5); } else if (la.kind == 19) { Get(); Expect(4); while (StartOf(1)) { Get(); } Expect(5); Expect(20); Expect(4); while (StartOf(1)) { Get(); } Expect(5); } else SynErr(32); } void SynExpr() { SynTerm(); while (la.kind == 22) { Get(); SynTerm(); } } void SynTerm() { SynFact(); while (StartOf(2)) { SynFact(); } } void SynFact() { switch (la.kind) { case 1: { Get(); if (la.kind == 4) { Get(); while (StartOf(1)) { Get(); } Expect(5); } break; } case 23: { Get(); break; } case 24: { Get(); SynExpr(); Expect(25); break; } case 26: { Get(); SynExpr(); Expect(27); break; } case 28: { Get(); SynExpr(); Expect(29); break; } case 15: { SemAction(); break; } default: SynErr(33); break; } } public void Parse() { la = new Token(); la.val = ""; Get(); GPDefSyntaxAnalyzer(); Expect(0); } static readonly bool[,] set = { {T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x}, {x,T,T,T, T,x,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,x}, {x,T,x,x, x,x,x,x, x,x,x,x, x,x,x,T, x,x,x,x, x,x,x,T, T,x,T,x, T,x,x,x} }; } // end Parser public class Errors { public int count = 0; // number of errors detected public System.IO.TextWriter errorStream = Console.Out; // error messages go to this stream public string errMsgFormat = "-- line {0} col {1}: {2}"; // 0=line, 1=column, 2=text public virtual void SynErr (int line, int col, int n) { string s; switch (n) { case 0: s = "EOF expected"; break; case 1: s = "ident expected"; break; case 2: s = "\"PROBLEM\" expected"; break; case 3: s = "\"CODE\" expected"; break; case 4: s = "\"<<\" expected"; break; case 5: s = "\">>\" expected"; break; case 6: s = "\"INIT\" expected"; break; case 7: s = "\"NONTERMINALS\" expected"; break; case 8: s = "\"TERMINALS\" expected"; break; case 9: s = "\"RULES\" expected"; break; case 10: s = "\"MAXIMIZE\" expected"; break; case 11: s = "\"MINIMIZE\" expected"; break; case 12: s = "\"END\" expected"; break; case 13: s = "\".\" expected"; break; case 14: s = "\"LOCAL\" expected"; break; case 15: s = "\"SEM\" expected"; break; case 16: s = "\"CONSTRAINTS\" expected"; break; case 17: s = "\"IN\" expected"; break; case 18: s = "\"SET\" expected"; break; case 19: s = "\"RANGE\" expected"; break; case 20: s = "\"..\" expected"; break; case 21: s = "\"=\" expected"; break; case 22: s = "\"|\" expected"; break; case 23: s = "\"EPS\" expected"; break; case 24: s = "\"(\" expected"; break; case 25: s = "\")\" expected"; break; case 26: s = "\"[\" expected"; break; case 27: s = "\"]\" expected"; break; case 28: s = "\"{\" expected"; break; case 29: s = "\"}\" expected"; break; case 30: s = "??? expected"; break; case 31: s = "invalid GPDefSyntaxAnalyzer"; break; case 32: s = "invalid SetDefinition"; break; case 33: s = "invalid SynFact"; break; default: s = "error " + n; break; } errorStream.WriteLine(errMsgFormat, line, col, s); count++; } public virtual void SemErr (int line, int col, string s) { errorStream.WriteLine(errMsgFormat, line, col, s); count++; } public virtual void SemErr (string s) { errorStream.WriteLine(s); count++; } public virtual void Warning (int line, int col, string s) { errorStream.WriteLine(errMsgFormat, line, col, s); } public virtual void Warning(string s) { errorStream.WriteLine(s); } } // Errors public class FatalError: Exception { public FatalError(string m): base(m) {} } }