下面我们写个客户端去计算几个表达式试一下。
package com.interpreter;
import java.util.ArrayList;
import java.util.List;
public class Client {
public static void main(String[] args) {
List<String> inputList = new ArrayList<String>();
//三个正确的,三个错误的
inputList.add("1+2+3+4+5+6+7+8+9");
inputList.add("1-2+3-4+5-6+7-8+9");
inputList.add("9");
inputList.add("-1+2+3+5");
inputList.add("1*2");
inputList.add("11+2+3+9");
GrammarParser grammarParser = new GrammarParser();//语法分析器
for (String input : inputList) {
Context context = new Context(input.toCharArray());
try {
grammarParser.parse(context);//语法分析器会调用解释器解释表达式
System.out.println(input + "=" + context.getResult());
} catch (Exception e) {
System.out.println("语法错误,请输入正确的表达式!");
}
}
}
}
输出结果:
123456789=45
1-23-45-67-89=5
9=9
语法错误,请输入正确的表达式!
语法错误,请输入正确的表达式!
语法错误,请输入正确的表达式!
可以看到,前三个表达式是符合我们的文法规则的,而后三个都不符合规则,所以提示了错误,这样的结果,与我们文法所表述的规则是相符的。
LZ需要提示的是,这里面本来是客户端使用解释器来解释语句的,不过由于我们抽离出了语法分析器,所以由语法分析器调用解释器来解释语句,这消除了客户端对解释器的关联,与标准类图不符,不过这其实只是我们所做的简单的改善而已,并不影响解释器模式的结构。
另外,上面的例子当中,还有两点是LZ要提一下的。LZ为了方便理解,已经尽量的将例子简化,不过其中有两个地方的转换是得注意的。
1、一个是操作数满足条件时,会产生一个ArithmeticExpression表达式。
2、另外一个是从DigitExpression直接转换成NumberExpression的地方,这其实和第1点一样,都是对文法规则的使用,不过这个更加清晰。我们可以清楚的看到,0-9的数字或者说DigitExpression只对应唯一一种方式的非终结者符号,就是number,所以我们直接转换成NumberExpression。
不过我们的转换是由终结者符号反向转换成非终结者符号的顺序,也就是相当于从抽象语法树的低端向上转换的顺序。其实相当于LZ省去了抽象语法树的潜在构建过程,直接开始解释表达式。
本文来自电脑杂谈,转载请注明本文网址:
https://www.pc-fly.com/a/jisuanjixue/article-34001-5.html
忍无可忍