import java.io.*; import java.util.*; /** * Not-completely-naive integer expression calculator application. * Repeatedly reads a numerical expression from standard input and * writes its value to standard output. * Expressions are expected to be one-line strings in the language * defined by the following grammar: * exp -> term { addop term } * term -> factor { mulop factor } * factor -> number | ( exp ) * addop -> + | - * mulop -> * | / * It simply reports a syntax error if the input is not in this language. * It uses a recursive descent parser. * R.W. Topor, March 2006, 2007. */ public class CalcRD { /** Current string tokenizer */ private StringTokenizer tokenizer; /** Current token */ private String token; /** Main program. */ public static void main(String[] args) throws Exception { CalcRD app = new CalcRD(); app.run(); } /** Repeatedly reads and evaluates expressions and prints results. */ private void run() throws Exception { BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); // Read the first expression String expr = in.readLine(); while (expr != null) { // Evaluate and print this expression evaluate(expr); // Read the next expression expr = in.readLine(); } } /** Returns the double value of the (well-formed) expression. */ private void evaluate (String expr) throws Exception { try { tokenizer = new StringTokenizer(expr, "+-*/()", true); token = getToken(); double val = exp(); System.out.println(val); } catch (Exception e) { System.out.println("Syntax error"); } } /** Returns the double value of the next (well-formed) exression. */ private double exp () throws Exception { double val = term(); while (token.equals("+") || token.equals("-")) { char op = token.charAt(0); token = getToken(); double nextVal = term(); switch (op) { case '+' : val += nextVal; break; case '-' : val -= nextVal; break; } } return val; } /** Returns the double value of the next (well-formed) term. */ private double term() throws Exception { double val = factor(); while (token.equals("*") || token.equals("/")) { char op = token.charAt(0); token = getToken(); double nextVal = factor(); switch (op) { case '*' : val *= nextVal; break; case '/' : val /= nextVal; break; } } return val; } /** Returns the double value of the next (well-formed) factor. */ private double factor () throws Exception { double val; if (token.equals("(")) { token = getToken(); val = exp(); if (token.equals(")")) { token = getToken(); return val; } else { throw new Exception(); } } else { // token should be a number! val = Double.valueOf(token).doubleValue(); token = getToken(); // easy to forget this return val; } } private String getToken () { if (tokenizer.hasMoreTokens()) { String token = tokenizer.nextToken().trim(); if (token.equals("")) { // skip blank tokens return getToken(); } else { return token; } } else { return "$"; // end of expression } } }