-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathBinaryOpNode.java
More file actions
82 lines (72 loc) · 2.72 KB
/
Copy pathBinaryOpNode.java
File metadata and controls
82 lines (72 loc) · 2.72 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
package cn.czyx007.expression_parser.ast;
import cn.czyx007.expression_parser.exception.ErrorCode;
import cn.czyx007.expression_parser.exception.ExpressionException;
import cn.czyx007.expression_parser.lexer.Token;
import java.util.Map;
/**
* 二元运算节点<br/>
* 表示二元运算表达式,如加减乘除、幂运算、取模等<br/>
* 仅支持标量运算
*/
public class BinaryOpNode extends ExprNode {
private final ExprNode left;
private final ExprNode right;
private final Token op;
/**
* 构造二元运算节点
* @param left 左操作数
* @param op 运算符 token
* @param right 右操作数
*/
public BinaryOpNode(ExprNode left, Token op, ExprNode right) {
this.left = left;
this.right = right;
this.op = op;
}
@Override
public double eval(Map<String, Double> context) {
double leftVal = left.eval(context);
double rightVal = right.eval(context);
return eval(leftVal, rightVal);
}
@Override
public Value evalValue(Map<String, Object> context) {
// 先通过 evalValue 获取子节点的值(支持数组变量)
Value leftVal = left.evalValue(context);
Value rightVal = right.evalValue(context);
// 二元运算只支持标量
if (!leftVal.isScalar()) {
throw new ExpressionException(ErrorCode.ARRAY_NOT_SUPPORTED_LEFT, op.value());
}
if (!rightVal.isScalar()) {
throw new ExpressionException(ErrorCode.ARRAY_NOT_SUPPORTED_RIGHT, op.value());
}
double leftScalar = leftVal.asScalar();
double rightScalar = rightVal.asScalar();
return new Value(eval(leftScalar, rightScalar));
}
/**
* 核心计算逻辑(复用于 eval 和 evalValue)
* @param leftVal 左操作数
* @param rightVal 右操作数
* @return 计算结果
*/
private double eval(double leftVal, double rightVal) {
double result;
switch (op.type()) {
case PLUS: result = leftVal + rightVal; break;
case MINUS: result = leftVal - rightVal; break;
case MULTIPLY: result = leftVal * rightVal; break;
case DIVIDE:
if (rightVal == 0) throw new ExpressionException(ErrorCode.DIVISION_BY_ZERO);
result = leftVal / rightVal; break;
case MODULO:
if (rightVal == 0) throw new ExpressionException(ErrorCode.MODULO_BY_ZERO);
result = leftVal % rightVal; break;
case POWER:
result = Math.pow(leftVal, rightVal); break;
default: throw new ExpressionException(ErrorCode.UNKNOWN_OPERATOR, op.type());
}
return fixPrecision(result);
}
}