1.意图
给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用
该表示来解释语言中的句子。
2.参与者
AbstractExpression -(抽象表达式)声明一个抽象的解释操作,这个接口为
抽象语法树中所有节点所共享
TermindExpression (终结符表达式) -实现与文法中的终结符相关联的解释操作
NonterminalExpression (非终结符)-文法中的每一条规则都需要一个NonterminalExpression类
-为文法中的非终结符实现解释操作
Context - 包含解释器之外的一些全局信息
Client - 构建抽象语法树 -调用解释操作
3.结构
4.代码结构
public interface AbstractExpression {
TermindExpression Evaluate();//执行表达式
void addExpression(AbstractExpression expression);//添加子表达式
void addSymbol(String str);//添加符号
String getSymbol();//获取符号
void setFather(AbstractExpression expression);//设置父节点
AbstractExpression getFather();//获取父节点
int getLevel();//获取优先级
AbstractExpression remove();//移除一个子表达式
}
public class NonterminalExpressionKH implements AbstractExpression {
private String symbol = "";
private TermindExpression value;
private AbstractExpression expression;
private AbstractExpression fexpression;
@Override
public TermindExpression Evaluate() {
if("()".equals(symbol) || expression != null){
value = expression.Evaluate();
}
if("(".equals(symbol)){
throw new RuntimeException("括号不匹配");
}
return value;
}
public TermindExpression getValue() {
return value;
}
public void setValue(TermindExpression value) {
this.value = value;
}
@Override
public void addExpression(AbstractExpression expression) {
this.expression = expression;
}
@Override
public void setFather(AbstractExpression expression) {
this.fexpression = expression;
}
@Override
public AbstractExpression getFather() {
return fexpression;
}
@Override
public int getLevel() {
// TODO Auto-generated method stub
return -1;
}
@Override
public void addSymbol(String str) {
symbol += str;
}
@Override
public String getSymbol() {
return symbol;
}
@Override
public AbstractExpression remove() {
AbstractExpression expression = this.expression;
this.expression = null;
return expression;
}
}
public class NonterminalExpressionOne implements AbstractExpression {
private String symbol = "";
private int level;
private TermindExpression value;
private AbstractExpression expression;
private AbstractExpression fexpression;
NonterminalExpressionOne(String symbol,int level){
this.level = level;
this.symbol = symbol;
}
@Override
public TermindExpression Evaluate() {
if (expression != null) {
value = expression.Evaluate();
}else{
throw new RuntimeException("一元表达式没有数值");
}
return Calculate.One(symbol, value);
}
public TermindExpression getValue() {
return value;
}
public void setValue(TermindExpression value) {
this.value = value;
}
@Override
public void addExpression(AbstractExpression expression) {
this.expression = expression;
}
@Override
public void setFather(AbstractExpression expression) {
this.fexpression = expression;
}
@Override
public AbstractExpression getFather() {
return fexpression;
}
@Override
public int getLevel() {
// TODO Auto-generated method stub
return level;
}
@Override
public void addSymbol(String str) {
symbol += str;
}
@Override
public String getSymbol() {
return symbol;
}
@Override
public AbstractExpression remove() {
AbstractExpression expression = this.expression;
this.expression = null;
return expression;
}
}
public class NonterminalExpressionTwo implements AbstractExpression {
private String symbol;
private TermindExpression value1;
private TermindExpression value2;
private List<AbstractExpression> expressionList;
private AbstractExpression fexpression;
private int level ;
NonterminalExpressionTwo(String symbol,int level){
this.level = level;
this.symbol = symbol;
}
@Override
public TermindExpression Evaluate() {
if (expressionList != null && expressionList.size() > 0) {
if (value1 == null) {
value1 = expressionList.get(0).Evaluate();
}
if (value2 == null) {
value2 = expressionList.get(1).Evaluate();
}
}
return Calculate.two(symbol, value1, value2);
}
public TermindExpression getValue1() {
return value1;
}
public void setValue1(TermindExpression value1) {
this.value1 = value1;
}
public TermindExpression getValue2() {
return value2;
}
public void setValue2(TermindExpression value2) {
this.value2 = value2;
}
@Override
public void addExpression(AbstractExpression expression) {
if (expressionList == null) {
expressionList = new ArrayList<AbstractExpression>(2);
}
expressionList.add(expression);
}
@Override
public void setFather(AbstractExpression expression) {
this.fexpression = expression;
}
@Override
public AbstractExpression getFather() {
return fexpression;
}
@Override
public int getLevel() {
return level;
}
@Override
public void addSymbol(String str) {
symbol += str;
}
@Override
public String getSymbol() {
return symbol;
}
@Override
public AbstractExpression remove() {
AbstractExpression expression = expressionList.get(expressionList.size()-1);
expressionList.remove(expression);
return expression;
}
}
public class TermindExpression implements AbstractExpression {
private AbstractExpression fexpression;
private double value;
private int level ;
TermindExpression(double value) {
this.value = value;
}
@Override
public TermindExpression Evaluate() {
return this;
}
public double getValue() {
return value;
}
public void setValue(double value) {
this.value = value;
}
@Override
public void addExpression(AbstractExpression expression) {
throw new RuntimeException("终结符没子表达式");
}
public void setFather(AbstractExpression expression) {
this.fexpression = expression;
}
@Override
public AbstractExpression getFather() {
return fexpression;
}
@Override
public int getLevel() {
return 0;
}
@Override
public void addSymbol(String str) {
// TODO Auto-generated method stub
}
@Override
public String getSymbol() {
// TODO Auto-generated method stub
return null;
}
@Override
public AbstractExpression remove() {
// TODO Auto-generated method stub
return null;
}
}
public class Context {
private Pattern pattern = Pattern.compile("-?[0-9]+.?[0-9]*");// 数字定义为零元表达式可以直接获取结果
private String One = "sin cos tan !";// 一元表达式
private String left = "!";
private String Two = "+ - * / ^";// 二元表达式
private String khbegain = "(";// 双符号表达式的开始符号只指向一个表达式定义为一个表达式的开始
private String khEnd = ")";// 双符号表达式结束符号
private final static Context context = new Context();
private Context() {
}
public static Context Instance() {
return context;
}
public boolean getCompass(String str) {
if (left.contains(str)) {
return true;
}
return false;
}
/**
* 获取符号的类别
*
* @param str
* 符号
* @return
*/
public int getClass(String str) {
if (str == null) {
return -1;
}
if (pattern.matcher(str).matches()) {
return 0;
}
if (One.contains(str)) {
return 1;
}
if (Two.contains(str)) {
return 2;
}
if (khbegain.contains(str)) {
return 3;
}
if (khEnd.contains(str)) {
return 4;
}
return -1;
}
private String fiveLevel = "sin cos tan ";
private String fourLevel = "^";
private String threeLevel = "!";
private String TwoLevel = "* /";
private String OneLevel = "+ -";
/**
* 获取优先级 数字越大优先级越大
*
* @param str
* 符号
* @return
*/
public int getLevel(String str) {
if (OneLevel.contains(str)) {
return 1;
}
if (TwoLevel.contains(str)) {
return 2;
}
if (threeLevel.contains(str)) {
return 3;
}
if (fourLevel.contains(str)) {
return 4;
}
if (fiveLevel.contains(str)) {
return 5;
}
return 0;
}
}
public class Calculate {
private Calculate() {
throw new RuntimeException();
}
/**
* 一元表达式计算
* @param symbol
* @param T
* @return
*/
public static TermindExpression One(String symbol, TermindExpression T) {
TermindExpression result = null;
double k = 0;
if ("sin".equals(symbol)) {
k = Math.sin(T.getValue());
result = new TermindExpression(k);
} else if ("cos".equals(symbol)) {
k = Math.cos(T.getValue());
result = new TermindExpression(k);
} else if ("tan".equals(symbol)) {
k = Math.tan(T.getValue());
result = new TermindExpression(k);
}if ("!".equals(symbol)) {
try{
k = factorial(new Double(T.getValue()).intValue());
}catch(NumberFormatException e){
throw new NumberFormatException("阶乘只针对整数");
}
result = new TermindExpression(k);
}
return result;
}
public static double factorial(int n){
double result = 1;
for(;n>1;n--){
result = result * n;
}
return result;
}
/**
* 二元表达式计算
* @param symbol
* @param T1
* @param T2
* @return
*/
public static TermindExpression two(String symbol, TermindExpression T1,
TermindExpression T2) {
TermindExpression result = null;
double k ;
if ("+".equals(symbol)) {
k = T1.getValue() + T2.getValue();
result = new TermindExpression(k);
} else if ("-".equals(symbol)) {
k = T1.getValue() - T2.getValue();
result = new TermindExpression(k);
} else if ("*".equals(symbol)) {
k = T1.getValue() * T2.getValue();
result = new TermindExpression(k);
} else if ("/".equals(symbol)) {
k = T1.getValue() / T2.getValue();
result = new TermindExpression(k);
}else if ("^".equals(symbol)) {
k = Math.pow(T1.getValue(), T2.getValue());
result = new TermindExpression(k);
}
return result;
}
}
public class Client {
public static void main(String[] args) {
String expression = "8 + ( 7 - 4 ! ) * ( 5 - 2 ) + ( 2.5 - 3 ) * 4";
// 切割表达式
String[] elements = expression.split(" ");
// 一次扫描构建语法树
AbstractExpression BeginExpression = new NonterminalExpressionKH();
AbstractExpression preExpression = BeginExpression;
AbstractExpression nextExpression;
for (String str : elements) {
int flag = Context.Instance().getClass(str);
int level = Context.Instance().getLevel(str);
switch (flag) {
case 0:// 零元表达式的构建动作
nextExpression = new TermindExpression(Double.valueOf(str));
preExpression.addExpression(nextExpression);
nextExpression.setFather(preExpression);
preExpression = nextExpression;
nextExpression = null;
break;
case 1:// 一元表达式的构建动作
nextExpression = new NonterminalExpressionOne(str, level);
if (Context.Instance().getCompass(str)) {
while (preExpression.getSymbol() == null) {
preExpression = preExpression.getFather();
}
AbstractExpression move = preExpression.remove();
preExpression.addExpression(nextExpression);
nextExpression.setFather(preExpression);
nextExpression.addExpression(move);
move.setFather(nextExpression);
preExpression = nextExpression;
nextExpression = null;
} else {
preExpression.addExpression(nextExpression);
nextExpression.setFather(preExpression);
preExpression = nextExpression;
nextExpression = null;
}
break;
case 2:// 二元表达式的构建动作
nextExpression = new NonterminalExpressionTwo(str, level);
while (preExpression.getSymbol() == null) {
preExpression = preExpression.getFather();
}
if (level <= preExpression.getLevel()) {
if (preExpression.getFather() != null
&& preExpression.getFather().getLevel() == level) {
/***
* ( + * - )同级运算从左向右计算,调整构造数先算 * 再算+最后算-
* 当-的优先级低于*时,查看*的父节点+的优先级,因为+的优先级和-一样所以 +的表达式成为 -
* 的左表达式并且 - 替代 +表达式
*/
preExpression = preExpression.getFather().getFather();
} else {
preExpression = preExpression.getFather();
}
}
AbstractExpression move = preExpression.remove();
preExpression.addExpression(nextExpression);
nextExpression.setFather(preExpression);
nextExpression.addExpression(move);
move.setFather(nextExpression);
preExpression = nextExpression;
nextExpression = null;
break;
case 3:// 双符号元表达式的开始构建动作
nextExpression = new NonterminalExpressionKH();
nextExpression.addSymbol(str);
preExpression.addExpression(nextExpression);
nextExpression.setFather(preExpression);
preExpression = nextExpression;
nextExpression = null;
break;
case 4:// 双符号表达式的结束动作
while (Context.Instance().getClass(preExpression.getSymbol()) != 3) {
preExpression = preExpression.getFather();
}
preExpression.addSymbol(str);
preExpression = preExpression.getFather();
nextExpression = null;
break;
default:
throw new RuntimeException("运算符识别错误");
}
}
System.out.println(BeginExpression.Evaluate().getValue());
}
}
5.解释代码:代码实现了一个计算文法,定义了零元表达式 TermindExpression(终结符,存储值),一元表达式NonterminalExpressionOne(非终结符),二元表达式 NonterminalExpressionTwo (非终结符),root表达式(存在开始和结束,指向一条具体表达式)NonterminalExpressionKH。Evaluate方法表示对当前表达式归约成TermindExpression终结符即计算表达式的值,归约的过程时从左向右自底向上,在Client通过构建语法树的时候满足优先级和同级自左向右计算法则。Content存储了各种计算规则的运算符,提供了返回运算符类别和优先级的方法。Calculate类定义了运算符计算方法。使用了单例,组合,解释器模式,整个框架可以添加新的运算符,只要在Content定义运算符、优先级以及在Calculate提供计算方法,那么就可以识别表达式,构建语法树,计算表达式结果。