/* A simple calculator in CUP */ import java_cup.runtime.*; import java.util.*; scan with {: return myscanner.next_token(); :} parser code {: // Hand coded scanner for arithmetic expressions // Symbol types in sym are generated by CUP public static class myscanner implements java_cup.runtime.Scanner { public Symbol next_token() { if (!input.hasNext()) { return new Symbol(sym.EOF); // No more input } else if (input.hasNext("[0-9].*")) { String s = input.findWithinHorizon("[0-9]+",0); return new Symbol(sym.NUMBER, new Integer(s)); // A number } // Otherwise look for operators or grouping String s = input.findWithinHorizon("[-()+*]", 0); switch(s.charAt(0)) { case '(': return new Symbol(sym.LPAREN); case ')': return new Symbol(sym.RPAREN); case '+': return new Symbol(sym.PLUS); case '-': return new Symbol(sym.MINUS); case '*': return new Symbol(sym.TIMES); } System.err.println("unrecognized input:" + input.next()); return new Symbol(sym.ERROR); } private static java.util.Scanner input = new java.util.Scanner(System.in); } public static void main(String [] args) throws Exception { parser parser = new parser(myscanner); parser.parse(); // or debug_parse(); } private static java_cup.runtime.Scanner myscanner = new myscanner(); :} terminal Integer NUMBER; terminal PLUS, MINUS, TIMES, LPAREN, RPAREN; terminal ERROR; non terminal command; non terminal Integer exp, term, factor; start with command; /* Calculator grammar */ command ::= exp:e {: System.out.println("Result is " + e); :} ; /* allows printing of the result */ exp ::= exp:e PLUS term:t {: RESULT = new Integer(e.intValue()+t.intValue()); :} | exp:e MINUS term:t {: RESULT = new Integer(e.intValue()-t.intValue()); :} | term:t {: RESULT = t; :} ; term ::= term:t TIMES factor:f {: RESULT = new Integer(t.intValue()*f.intValue()); :} | factor:f {: RESULT = f; :} ; factor ::= NUMBER:n {: RESULT = n; :} | LPAREN exp:e RPAREN {: RESULT = e; :} ;