/************************************************************ * This is a recursive descent parser for the SLP language. * * This parser uses the SLP lexical analyser produced by * * JavaCC. Before implementing the parser, the grammar of * * the language was converted into the following form to * * allow predictive parsing: * * * * Stm -> id := Exp Stm' * * | print ( ExpList ) Stm' * * Stm' -> ; Stm * * | (empty string) * * Exp -> id Exp' * * | num Exp' * * | ( Stm , Exp ) Exp' * * Exp' -> Binop Exp * * | (empty string) * * ExpList -> Exp ExpList' * * ExpList' -> , ExpList * * | (empty string) * * Binop -> + * * | - * * | * * * | / * * * ************************************************************/ public class SLPRecDes implements SLPTokeniserConstants { public static Token t; public static void Stm() { if (t.kind == ID) { t = SLPTokeniser.getNextToken(); if (t.kind == ASSIGN) { t = SLPTokeniser.getNextToken(); Exp(); Stm_Prime(); } else error(":="); } else if (t.kind == PRINT) { t = SLPTokeniser.getNextToken(); if (t.kind == LBR) { t = SLPTokeniser.getNextToken(); ExpList(); if (t.kind == RBR) { t = SLPTokeniser.getNextToken(); Stm_Prime(); } else error(")"); } else error("("); } else error("identifier or print"); } public static void Stm_Prime() { if (t.kind == SEMIC) { t = SLPTokeniser.getNextToken(); Stm(); } } public static void Exp() { if ((t.kind == ID) || (t.kind == NUM)) { t = SLPTokeniser.getNextToken(); Exp_Prime(); } else if (t.kind == LBR) { t = SLPTokeniser.getNextToken(); Stm(); if (t.kind == COMMA) { t = SLPTokeniser.getNextToken(); Exp(); if (t.kind == RBR) { t = SLPTokeniser.getNextToken(); Exp_Prime(); } else error(")"); } else error(","); } else error("identifier, number or ("); } public static void Exp_Prime() { if ((t.kind == PLUS_SIGN) || (t.kind == MINUS_SIGN) || (t.kind == MULT_SIGN) || (t.kind == DIV_SIGN)) { Binop(); Exp(); } } public static void ExpList() { Exp(); ExpList_Prime(); } public static void ExpList_Prime() { if (t.kind == COMMA) { t = SLPTokeniser.getNextToken(); ExpList(); } } public static void Binop() { t = SLPTokeniser.getNextToken(); } /* * The error routine prints out the line number of the error, * along with the encountered lexeme. The String argument * indicates which tokens were expected in the input. */ public static void error(String msg) { System.out.print("Syntax error at line " + t.beginLine); System.out.println(": encountered " + t.image + " when " + msg + " expected"); System.exit(0); } public static void main(String args[]) { SLPTokeniser tokeniser; /* * Firstly, decide if we're taking input from standard input * or from a file whose name was given as an argument... * (This piece of code is fairly standard) */ if (args.length == 0) { System.out.println("Reading from standard input . . ."); tokeniser = new SLPTokeniser(System.in); } else if (args.length == 1) { try { tokeniser = new SLPTokeniser(new java.io.FileInputStream(args[0])); } catch (java.io.FileNotFoundException e) { System.err.println("File " + args[0] + " not found."); return; } } else { System.out.println("SLP Recursive Descent Parser: Usage is one of:"); System.out.println(" java SLPRecDes < inputfile"); System.out.println("OR"); System.out.println(" java SLPRecDes inputfile"); return; } t = SLPTokeniser.getNextToken(); Stm(); } }