options { NODE_DEFAULT_VOID = true; // only generate explicitly requested nodes NODE_PREFIX = ""; // don't prefix them with AST MULTI = true; // don't only use SimpleNode VISITOR = true; // create Visitor interface } PARSER_BEGIN(Expression) import java.io.InputStreamReader; import java.io.IOException; import java.io.ObjectOutputStream; import java.util.EmptyStackException; import java.util.Vector; /** recognizes, stores, and evaluates arithmetic expressions using a parser generated with jjtree. */ public class Expression { /** reads lines from standard input, parses, and evaluates them. or writes them as a Vector to standard output if -c is set. @param args if -c is specified, a Vector is written. */ public static void main (String args []) { boolean cflag = args.length > 0 && args[0].equals("-c"); try { new Expression(new InputStreamReader(System.in)).lines(); if (cflag) { ObjectOutputStream out = new ObjectOutputStream(System.out); Vector v = new Vector(); ExpressionVisitor gen = new Gen(); try { for (;;) v.insertElementAt(jjtree.popNode().jjtAccept(gen, null), 0); } catch (EmptyStackException e) { } out.writeObject(v); out.close(); } else try { ExpressionVisitor eval = new Eval(); for (;;) { // order reversed SimpleNode n = (SimpleNode)jjtree.popNode(); n.dump("\t"); System.out.println(n.jjtAccept(eval, null)); } } catch (EmptyStackException e) { } } catch (IOException e) { System.err.println(e); } catch (ParseException e) { } // cannot happen } } PARSER_END(Expression) SKIP: // defines input to be ignored { " " | "\r" | "\t" | < "#" (~ ["\n"])* > // comment from # to end of line } // re: many of negated character class TOKEN: // defines token names { < EOL: "\n" > | < INT: ( )+ > // re: some | < LONG: ( )+ ["l", "L"] > // re: class | < DOUBLE: ( )+ "." ( )* ( )? // re: many | "." ( )+ ( )? // re: alt | ( )+ > | < #DIGIT: ["0" - "9"] > // private re | < #EXP: ["e", "E"] ( ["+", "-"] )? ( )+ > // re: opt } void lines (): // lines: [{ [ sum ] "\n" }]; { Vector v = new Vector(); Number t; } { ( try { ( sum() | | { return; } ) } catch (ParseException err) { System.err.println(err); skip: for (;;) switch (getNextToken().kind) { case EOF: return; case EOL: break skip; } } )* } 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() #Mod(2) | "/" term() #Div(2) )* } void term(): // term: "+"term | "-"term | "("sum")" | Number; {} { "+" term() // no need to make node | "-" term() #Minus // insert sign change node | "(" sum() ")" // Lit must be patched to inser value node | ( { jjtThis.val = new Integer(token.image); } ) #Lit | ( { jjtThis.val = new Long(token.image.substring(0, token.image.length()-1)); } ) #Lit | ( { jjtThis.val = new Double(token.image); } ) #Lit }