一、定义:
给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。这种官话理解起来有点蛋疼。举个例子说明上述含义。“给定一个语言,定义它的文法的一种表示”,就是定义一个语言的规则,比如定义一个以阿拉伯数字0开头和以0结束的规则;“并定义一个解释器,这个解释器使用该表示来解释语言中的句子”:定义一个解析器,解析传过来的参数,若符合以阿拉伯数字0开头和以0结束这这种规则,返回true,否则返回false。
二、角色
1.AbstractExpression(抽象表达式) 声明一个抽象的解释操作,这个接口为抽象语法树中所有的节点所共享。
2.TerminalExpression(终结符表达式) 实现与文法中的终结符相关联的解释操作。 一个句子中的每个终结符需要该类的一个实例。
3.NonterminalExpression(非终结符表达式) 为文法中的非终结符实现解释(Interpret)操作。
4.Context(上下文) 包含解释器之外的一些全局信息。
5.Client(客户) 构建(或被给定)表示该文法定义的语言中一个特定的句子的抽象语法树。 该抽象语法树由NonterminalExpression和TerminalExpression的实例装配而成。 调j用解释操作。
三、解析字符串,实现乘除运算的demo(本demo无需保存解析器以外的全局信息,所以没有定义Context类)。此处,定义的文法便是符号“*”代表乘,“/”代表除,其余代表数字。当然,也可自行扩展,添加减等文法规则。
1.AbstractExpression(抽象表达式) ,申明了一个interpret()的解析操作,不管终结符表达式还是非终结符表达式都要继承抽象表达式。
package com.exaple.interpret;
/**
* 抽象表达式
* @author zeng
*
*/
public interface Expression {
public int interpret();
}
2.TerminalExpression(终结符表达式),也就是不能再继续推导的表达式,比如传入一个数字,就解析成一个数字。
package com.exaple.interpret;
/**
* 终结符表达式
* @author zeng
*
*/
public class TerminalExpression implements Expression {
private int value;
public TerminalExpression(int value) {
super();
this.value = value;
}
@Override
public int interpret() {
return value;
}
}
3.NonterminalExpression(非终结符表达式) ,非终结符可以推导出其他表达式,比如S = S1 + S2,那么S就可以推导出S1 + S2,在本demo中,至少包含两个终结符,也可以包含一个终结符和一个非终结符。
package com.exaple.interpret;
/**
* 非终结表达式
* @author zeng
*
*/
public abstract class NonterminalExpression implements Expression {
protected Expression left;
protected Expression right;
public NonterminalExpression(Expression left, Expression right) {
super();
this.left = left;
this.right = right;
}
}
package com.exaple.interpret;
/**
* 除法表达式
* @author zeng
*
*/
public class DivExpression extends NonterminalExpression{
public DivExpression(Expression left, Expression right) {
super(left, right);
}
@Override
public int interpret() {
int val = right.interpret();
if (val == 0) {
System.out.println("零不能做分母");
return -1;
}else {
return left.interpret() / right.interpret();
}
}
}
package com.exaple.interpret;
/**
* 乘法表达式
* @author zeng
*
*/
public class MulExpression extends NonterminalExpression{
public MulExpression(Expression left, Expression right) {
super(left, right);
}
@Override
public int interpret() {
return left.interpret() * right.interpret();
}
}
4.Client(客户):装配终结符表达式和非终结符表达式实例。 调j用解释操作。
package com.exaple.interpret;
/**
* 计算器(客户)
* @author zeng
*
*/
public class Caculator {
public int caculate(String statement){
Expression left = null;
Expression right = null;
Expression lastExpression = null;
String[] statements = statement.split(" ");
for (int i = 0; i < statements.length; i++) {
if (statements[i].equals("*")) {
left = lastExpression;
int val = Integer.parseInt(statements[++i]);
//statements[++i]表示一个数字,实例化一个终结符表达式
right = new TerminalExpression(val);
lastExpression = new MulExpression(left, right);
}else if (statements[i].equals("/")) {
left = lastExpression;
int val = Integer.parseInt(statements[++i]);
//statements[++i]表示一个数字,实例化一个终结符表达式
right = new TerminalExpression(val);
lastExpression = new DivExpression(left, right);
}else {
lastExpression = new TerminalExpression(Integer.parseInt(statements[i]));
}
}
return lastExpression.interpret();
}
}
测试
package com.exaple.interpret;
/**
* 客户
* @author zeng
*
*/
public class Test {
public static void main(String[] args) {
String content = "6 * 4 * 8 / 6";
Caculator caculator = new Caculator();
int result = caculator.caculate(content);
System.out.println("计算结果: " + result);
}
}
打印结果:
计算结果: 32