You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

112 lines
2.3 KiB
Java

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
public class ExpressionParserRecursiveDescent {
String s;
int pos;
char token;
double tokval;
static boolean isDigitOrDot(char x) {
return Character.isDigit(x) || x == '.';
}
int next() {
while (true) {
if (pos == s.length())
return token = 255;
char c = s.charAt(pos++);
if ("+-*/^()\n".indexOf(c) != -1)
return token = c;
if (Character.isSpaceChar(c))
continue;
if (Character.isDigit(c) || c == '.') {
String operand = "" + c;
while (pos < s.length() && isDigitOrDot(s.charAt(pos)))
operand += c = s.charAt(pos++);
tokval = Double.parseDouble(operand);
return token = 'n';
}
throw new RuntimeException("Bad character: " + c);
}
}
void skip(int ch) {
if (token != ch)
throw new RuntimeException("Bad character: " + token + ", expected: " + ch);
next();
}
// number ::= number | '(' expression ')'
double number() {
if (token == 'n') {
double v = tokval;
skip('n');
return v;
}
skip('(');
double v = expression();
skip(')');
return v;
}
// factor ::= number | number '^' factor
double factor() {
double v = number();
if (token == '^') {
skip('^');
v = Math.pow(v, factor());
}
return v;
}
// term ::= factor | term '*' factor | term '/' factor
double term() {
double v = factor();
while (true) {
if (token == '*') {
skip('*');
v *= factor();
} else if (token == '/') {
skip('/');
v /= factor();
} else
return v;
}
}
// expression ::= term | expression '+' term | expression '-' term
double expression() {
double v = term();
for (; ; ) {
if (token == '+') {
skip('+');
v += term();
} else if (token == '-') {
skip('-');
v -= term();
} else
return v;
}
}
public static void main(String[] args) throws Exception {
ScriptEngine engine = new ScriptEngineManager().getEngineByName("JavaScript");
String exp = "1+2*3*4+3*(2+2)-100\n";
System.out.println(engine.eval(exp));
ExpressionParserRecursiveDescent parser = new ExpressionParserRecursiveDescent();
parser.s = exp;
parser.next();
while (parser.token != 255) {
if (parser.token == '\n') {
parser.skip('\n');
continue;
}
System.out.printf("%.5f", parser.expression());
}
}
}