141 lines
2.5 KiB
Java
141 lines
2.5 KiB
Java
|
public class Calc2 {
|
||
|
|
||
|
static enum TOKEN {
|
||
|
PLUS, MINUS, MUL, DIV, NUMBER, LP, RP, END, FUNCTION;
|
||
|
}
|
||
|
|
||
|
double expr() {
|
||
|
double left = term();
|
||
|
while (true) {
|
||
|
switch (curr_tok) {
|
||
|
case PLUS:
|
||
|
left += term();
|
||
|
break;
|
||
|
case MINUS:
|
||
|
left -= term();
|
||
|
break;
|
||
|
default:
|
||
|
return left;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
double term() {
|
||
|
double left = prim();
|
||
|
while (true) {
|
||
|
switch (curr_tok) {
|
||
|
case MUL:
|
||
|
left *= prim();
|
||
|
break;
|
||
|
case DIV:
|
||
|
left /= prim();
|
||
|
break;
|
||
|
default:
|
||
|
return left;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
double prim() {
|
||
|
get_token();
|
||
|
switch (curr_tok) {
|
||
|
case NUMBER:
|
||
|
double v = number_value;
|
||
|
get_token();
|
||
|
return v;
|
||
|
case MINUS:
|
||
|
return -prim();
|
||
|
case LP:
|
||
|
double e = expr();
|
||
|
if (curr_tok != TOKEN.RP)
|
||
|
return error(")expected");
|
||
|
return e;
|
||
|
case FUNCTION:
|
||
|
String f = function_name;
|
||
|
get_token();
|
||
|
if (curr_tok != TOKEN.LP)
|
||
|
return error("( expected");
|
||
|
double z = prim();
|
||
|
if (curr_tok != TOKEN.RP)
|
||
|
return error(") expected");
|
||
|
if ("sin".equals(f)) {
|
||
|
return Math.sin(z);
|
||
|
} else {
|
||
|
return error("unknown function");
|
||
|
}
|
||
|
default:
|
||
|
return error("primary expression expected");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
double error(String msg) {
|
||
|
error_msg = msg;
|
||
|
return Double.NaN;
|
||
|
}
|
||
|
|
||
|
TOKEN curr_tok;
|
||
|
double number_value;
|
||
|
String function_name;
|
||
|
String error_msg;
|
||
|
String input;
|
||
|
int pos;
|
||
|
|
||
|
void get_token() {
|
||
|
if (pos >= input.length()) {
|
||
|
curr_tok = TOKEN.END;
|
||
|
return;
|
||
|
}
|
||
|
char x = input.charAt(pos++);
|
||
|
switch (x) {
|
||
|
case '+':
|
||
|
curr_tok = TOKEN.PLUS;
|
||
|
break;
|
||
|
case '-':
|
||
|
curr_tok = TOKEN.MINUS;
|
||
|
break;
|
||
|
case '*':
|
||
|
curr_tok = TOKEN.MUL;
|
||
|
break;
|
||
|
case '/':
|
||
|
curr_tok = TOKEN.DIV;
|
||
|
break;
|
||
|
case '(':
|
||
|
curr_tok = TOKEN.LP;
|
||
|
break;
|
||
|
case ')':
|
||
|
curr_tok = TOKEN.RP;
|
||
|
break;
|
||
|
default:
|
||
|
if (Character.isDigit(x) || x == '.') {
|
||
|
curr_tok = TOKEN.NUMBER;
|
||
|
String s = "" + x;
|
||
|
while (pos < input.length() && (Character.isDigit(input.charAt(pos)) || input.charAt(pos) == '.')) {
|
||
|
s += input.charAt(pos);
|
||
|
++pos;
|
||
|
}
|
||
|
number_value = Double.parseDouble(s);
|
||
|
} else if (Character.isLetter(x)) {
|
||
|
curr_tok = TOKEN.FUNCTION;
|
||
|
String s = "" + x;
|
||
|
while (pos < input.length() && Character.isLetter(input.charAt(pos))) {
|
||
|
s += input.charAt(pos);
|
||
|
++pos;
|
||
|
}
|
||
|
function_name = s;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public static void main(String[] args) {
|
||
|
Calc2 calc = new Calc2();
|
||
|
calc.input = "sin(1)";
|
||
|
calc.pos = 0;
|
||
|
double res = calc.expr();
|
||
|
if (Double.isNaN(res)) {
|
||
|
System.out.println(calc.error_msg);
|
||
|
} else {
|
||
|
System.out.println(res);
|
||
|
}
|
||
|
}
|
||
|
}
|