Develop a recursive descent parser and scanner for the EBNF grammar like those described in chapter 8:
EBNF = { Production } EOF . Production = nonterminal "=" Expression "." . Expression = Term { "|" Term } . Term = [ Factor { Factor } ] . Factor = nonterminal | terminal | "[" Expression "]" | "(" Expression ")" | "{" Expression "}" .
For your convenience a skeleton of the code appears below
using Library; using System; using System.Text; class Token { public int kind; public string val; public Token(int kind, string val) { this.kind = kind; this.val = val; } // constructor } // Token class EBNFParser { // +++++++++++++++++++++++++ File Handling and Error handlers ++++++++++++++++++++ static InFile input; static OutFile output; static string NewFileName(string oldFileName, string ext) { // as in textbook - no need to expand this static void ReportError(string errorMessage) { // as in textbook - no need to expand this static void Abort(string errorMessage) { // Abandons parsing after issuing error message ReportError(errorMessage); output.Close(); System.Environment.Exit(1); } // +++++++++++++++++++++++ token kinds enumeration +++++++++++++++++++++++++ const int noSym = 0, // add to this EOFSym = 1; // +++++++++++++++++++++++++++++ Character Handler ++++++++++++++++++++++++++ const char EOF = '\0'; static bool atEndOfFile = false; // Declaring ch as a global variable is done for expediency - global variables // are not always a good thing static char ch; // look ahead character for scanner static void GetChar() { // Obtains next character ch from input, or CHR(0) if EOF reached. // Reflect ch to output if (atEndOfFile) ch = EOF; else { ch = input.ReadChar(); atEndOfFile = ch == EOF; if (!atEndOfFile) output.Write(ch); } } // GetChar // +++++++++++++++++++++++++++++++ Scanner ++++++++++++++++++++++++++++++++++ // Declaring sym as a global variable is done for expediency - global variables // are not always a good thing static Token sym; static void GetSym() { // Scans for next sym from input while (ch > EOF && ch <= ' ') GetChar(); // Rest of scanner comes here sym = new Token(symKind, symLex.ToString()); } // +++++++++++++++++++++++++++++++ Parser +++++++++++++++++++++++++++++++++++ static void Accept(int wantedSym, string errorMessage) { // Checks that lookahead token is wantedSym if (sym.kind == wantedSym) GetSym(); else Abort(errorMessage); } // Accept static void Accept(IntSet allowedSet, string errorMessage) { // Checks that lookahead token is in allowedSet if (allowedSet.Contains(sym.kind)) GetSym(); else Abort(errorMessage); } // Accept // Parser Routines come here // +++++++++++++++++++++ Main driver function +++++++++++++++++++++++++++++++ public static void Main(string[] args) { // Open input and output files from command line arguments if (args.Length == 0) { Console.WriteLine("Usage: EBNFParser FileName"); System.Environment.Exit(1); } input = new InFile(args[0]); output = new OutFile(NewFileName(args[0], ".out")); GetChar(); // Lookahead character GetSym(); // Lookahead symbol EBNF(); // Start to parse from the goal symbol // if we get back here everything must have been satisfactory Console.WriteLine("Parsed correctly"); output.Close(); } // Main } // class EBNFParser
Home © P.D. Terry