/************************************************************ * This is a recursive descent tree builder 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 SLPRecTree implements SLPTokeniserConstants { public static Token t; public static Stm Stm() { Stm s=null; String id; Exp e; ExpList el; if (t.kind == ID) { id = t.image; t = SLPTokeniser.getNextToken(); if (t.kind == ASSIGN) { t = SLPTokeniser.getNextToken(); e = Exp(); s = new AssignStm(id,e); } else error(":="); } else if (t.kind == PRINT) { t = SLPTokeniser.getNextToken(); if (t.kind == LBR) { t = SLPTokeniser.getNextToken(); el = ExpList(); if (t.kind == RBR) { t = SLPTokeniser.getNextToken(); s = new PrintStm(el); } else error(")"); } else error("("); } else error("identifier or print"); return Stm_Prime(s); } public static Stm Stm_Prime(Stm s1) { Stm s2; if (t.kind == SEMIC) { t = SLPTokeniser.getNextToken(); s2 = Stm(); return new CompoundStm(s1,s2); } else return s1; } public static Exp Exp() { Exp e=null; Stm s; if (t.kind == ID) { e = new IdExp(t.image); t = SLPTokeniser.getNextToken(); } else if (t.kind == NUM) { e = new NumExp(Integer.parseInt(t.image)); t = SLPTokeniser.getNextToken(); } else if (t.kind == LBR) { t = SLPTokeniser.getNextToken(); s = Stm(); if (t.kind == COMMA) { t = SLPTokeniser.getNextToken(); e = Exp(); if (t.kind == RBR) { t = SLPTokeniser.getNextToken(); e = new EseqExp(s,e); } else error(")"); } else error(","); } else error("identifier, number or ("); return Exp_Prime(e); } public static Exp Exp_Prime(Exp e1) { int oper; Exp e2; switch(t.kind) { case PLUS_SIGN: Binop(); e2 = Exp(); return new OpExp(e1,1,e2); case MINUS_SIGN: Binop(); e2 = Exp(); return new OpExp(e1,2,e2); case MULT_SIGN: Binop(); e2 = Exp(); return new OpExp(e1,3,e2); case DIV_SIGN: Binop(); e2 = Exp(); return new OpExp(e1,4,e2); default: return e1; } } public static ExpList ExpList() { Exp e; e = Exp(); return ExpList_Prime(e); } public static ExpList ExpList_Prime(Exp e) { ExpList el; if (t.kind == COMMA) { t = SLPTokeniser.getNextToken(); el = ExpList(); return new PairExpList(e,el); } else return new LastExpList(e); } 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 TreeBuilder: Usage is one of:"); System.out.println(" java SLPRecTree < inputfile"); System.out.println("OR"); System.out.println(" java SLPRecTree inputfile"); return; } t = SLPTokeniser.getNextToken(); Stm s = Stm(); s.interp(); } }