描述:对一个表达式进行解释时,将表达式分为终结符、非终结符、运算环境,这样区分可以把表达式的各个部分独立出来扩展。
名称解释:
- 表达式:一条运算语句,如c = a + b,它有一个解释方法,可以计算表达式结果
- 终结符:表达式中的变量,如a、b,终结符表达式负责解释终结符,即计算结果
- 非终结符:表达式中的运算符,如+,非终结符表达式负责计算非终结符的结果
- 运算环境:负责给终结符赋值,如a=1
场景:写个解释器,解释a+b=3,其中a=1,b=2,c=0,另外扩展一个相反数运算使-a=-1。
实现:
抽象一个表达式,负责解释终结符或者非终结符,其定义一个解释方法,计算表达式的值,同时覆盖equals和hashCode方法,方便判断两个表达式是否相同
abstract class Expression {
String name;
Expression(String name) {
this.name = name;
}
abstract int interpret(Context ctx);
@Override
public boolean equals(Object obj) {
if(null == obj) {
return false;
}
if(obj instanceof String && name.equals(obj)) {
return true;
}
return false;
}
@Override
public int hashCode() {
return name.hashCode();
}
}
定义一个终结符表达式,也就是负责计算变量的值
class Variable extends Expression {
Variable(String name) {
super(name);
}
@Override
int interpret(Context ctx) {
return ctx.lookup(this);
}
}
定一个非终结符表达式,其名为加法,负责计算两个终结符的值
class AddExpression extends Expression {
Expression var1;
Expression var2;
AddExpression(Expression var1, String name, Expression var2) {
super(name);
this.var1 = var1;
this.var2 = var2;
}
@Override
int interpret(Context ctx) {
return var1.interpret(ctx) + var2.interpret(ctx);
}
}
如果想扩展一种运算,可以直接定义一个非终结符表达式,比如定义一个求相反数的运算
//一个数的相反数
class OppositeExpression extends Expression {
Expression var;
OppositeExpression(String name, Expression var) {
super(name);
this.var = var;
}
@Override
int interpret(Context ctx) {
return -var.interpret(ctx);
}
}
定义一个运算环境,用于给变量赋值
class Context {
Map<Expression, Integer> map = new HashMap<Expression, Integer>();
void assign(Expression var, int value) {
map.put(var, value);
}
int lookup(Expression var) {
Object obj = map.get(var);
if(null == obj) {
// 如果变量未初始化,默认是0
return 0;
}
return (Integer) obj;
}
}
客户端调用:
public static void main(String[] args) {
Context ctx = new Context();
Variable a = new Variable("a");
Variable b = new Variable("b");
Variable c = new Variable("c"); // 不初始化,默认为0
ctx.assign(a, 1);
ctx.assign(b, 2);
System.out.println("a = " + a.interpret(ctx));
System.out.println("b = " + b.interpret(ctx));
System.out.println("c = " + c.interpret(ctx));
// 相反数运算
OppositeExpression opposite = new OppositeExpression("-", a);
int rs = opposite.interpret(ctx);
String exp = String.format("%s%s = %d", opposite.name, a.name, rs);
System.out.println(exp);
// 加运算
AddExpression add = new AddExpression(a, "+", b);
rs = add.interpret(ctx);
exp = String.format("%s %s %s = %d", a.name, add.name, b.name, rs);
System.out.println(exp);
}
结果:
a = 1
b = 2
c = 0
-a = -1
a + b = 3
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。