options { NODE_DEFAULT_VOID = true; NODE_PREFIX = ""; MULTI = true; VISITOR = true; } PARSER_BEGIN(Calc5) public class Calc5 { public static void main (String args []) { Calc5 parser = new Calc5(System.in); for (;; jjtree.reset()) try { switch (parser.expr()) { default: System.out.println("\t"+ jjtree.rootNode().jjtAccept(new Infix(), null)); System.out.println("\t"+ ((int[]) jjtree.rootNode().jjtAccept(new Value(), null))[0]); case 0: break; case -1: System.exit(0); } } catch (Exception e) { e.printStackTrace(); System.exit(1); } } } PARSER_END(Calc5) SKIP: // defines input to be ignored { " " | "\r" | "\t" } TOKEN: // defines token names { < EOL: "\n" > | < CONSTANT: ( )+ > // re: 1 or more | < #DIGIT: ["0" - "9"] > // private re } int expr(): // expr: sum \n {} // -1 at eof, 0 at eol/error { try { ( sum() { return 1; } | { return 0; } | { return -1; } ) } catch (ParseException pe) { System.err.println(pe); for (;;) switch (getNextToken().kind) { case EOF: return -1; case EOL: return 0; } } } void sum(): // sum: product { +- product } {} { product() ( "+" product() #Add(2) // Add with 2 descendants | "-" product() #Sub(2) )* } void product(): // product: term { *%/ term } {} { term() ( "*" term() #Mul(2) | "%" term() #Rem(2) | "/" term() #Div(2) )* } void term(): // term: +term | -term | (sum) | number { Token t; } { "+" term() // no need to make node | "-" term() #Neg(1) // insert negation node | "(" sum() ")" | ( t = { jjtThis.val = new Integer(t.image); } ) #IntLit // requires val in IntLit }