1public static double eval(final String str) {
2 return new Object() {
3 int pos = -1, ch;
4
5 void nextChar() {
6 ch = (++pos < str.length()) ? str.charAt(pos) : -1;
7 }
8
9 boolean eat(int charToEat) {
10 while (ch == ' ') nextChar();
11 if (ch == charToEat) {
12 nextChar();
13 return true;
14 }
15 return false;
16 }
17
18 double parse() {
19 nextChar();
20 double x = parseExpression();
21 if (pos < str.length()) throw new RuntimeException("Unexpected: " + (char)ch);
22 return x;
23 }
24
25 // Grammar:
26 // expression = term | expression `+` term | expression `-` term
27 // term = factor | term `*` factor | term `/` factor
28 // factor = `+` factor | `-` factor | `(` expression `)`
29 // | number | functionName factor | factor `^` factor
30
31 double parseExpression() {
32 double x = parseTerm();
33 for (;;) {
34 if (eat('+')) x += parseTerm(); // addition
35 else if (eat('-')) x -= parseTerm(); // subtraction
36 else return x;
37 }
38 }
39
40 double parseTerm() {
41 double x = parseFactor();
42 for (;;) {
43 if (eat('*')) x *= parseFactor(); // multiplication
44 else if (eat('/')) x /= parseFactor(); // division
45 else return x;
46 }
47 }
48
49 double parseFactor() {
50 if (eat('+')) return parseFactor(); // unary plus
51 if (eat('-')) return -parseFactor(); // unary minus
52
53 double x;
54 int startPos = this.pos;
55 if (eat('(')) { // parentheses
56 x = parseExpression();
57 eat(')');
58 } else if ((ch >= '0' && ch <= '9') || ch == '.') { // numbers
59 while ((ch >= '0' && ch <= '9') || ch == '.') nextChar();
60 x = Double.parseDouble(str.substring(startPos, this.pos));
61 } else if (ch >= 'a' && ch <= 'z') { // functions
62 while (ch >= 'a' && ch <= 'z') nextChar();
63 String func = str.substring(startPos, this.pos);
64 x = parseFactor();
65 if (func.equals("sqrt")) x = Math.sqrt(x);
66 else if (func.equals("sin")) x = Math.sin(Math.toRadians(x));
67 else if (func.equals("cos")) x = Math.cos(Math.toRadians(x));
68 else if (func.equals("tan")) x = Math.tan(Math.toRadians(x));
69 else throw new RuntimeException("Unknown function: " + func);
70 } else {
71 throw new RuntimeException("Unexpected: " + (char)ch);
72 }
73
74 if (eat('^')) x = Math.pow(x, parseFactor()); // exponentiation
75
76 return x;
77 }
78 }.parse();
79}
80