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
import java.util.*; import Library.*; class Token { public int kind; public String val; public Token(int kind, String val) { this.kind = kind; this.val = val; } } 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.exit(1); } // +++++++++++++++++++++++ token kinds enumeration +++++++++++++++++++++++++ static final int noSym = 0, // others needed like this // +++++++++++++++++++++++++++++ Character Handler ++++++++++++++++++++++++++ static final char EOF = '\0'; static boolean 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); } } // +++++++++++++++++++++++++++++++ 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); } // 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) { System.out.println("Usage: EBNFParser FileName"); System.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 System.out.println("Parsed correctly"); output.close(); } }
Home © P.D. Terry