一、介绍
- 在编译原理中,一个算术表达式通过词法分析器形成词法单元,而后这些词法单元再通过词法分析器构建语法分析树,最终形成一棵抽象的语法分析树。这里的词法分析器和语法分析器都可以看做是解释器
- 解释器模式:是指给定一个语言(表达式),定义它的文法的一种表示,并定义一个解释器,使用该解释器来解释语言中的句子(表达式)
- 应用场景
a. 应用可以将一个需要解释执行的语言中的句子表示为一个抽象语法树
b.一些重复出现的问题可以用一种简单的语言来表达
c.一个简单语法需要解释的场景 - 这样的例子还有,比如编译器、运算表达式、正则表达式、机器人等
二、原理类图
![1](https://i-blog.csdnimg.cn/blog_migrate/0697a79c9225a13568ac434b1535c702.jpeg)
2.1 角色和职责
- 抽象表达式(Abstract Expression)角色:该角色声明一个所有的具体表达式角色都需要实现的抽象接口,该接口主要是一个解释操作interpret()方法。
- 终结符表达式(Terminal Expression)角色:该角色实现了抽象表达式角色所要求的接口,文法中的每一个终结符都有一个具体终结表达式与之对应。
- 非终结符表达式(Nonterminal Expression)角色:该角色是一个具体角色,文法中的每一条规则都对应一个非终结符表达式类。
- 环境(Context)角色:该角色提供解释器之外的一些全局信息。
- 客户端(Client)角色:该角色创建一个抽象语法树,调用解释操作。
2.2 代码分析
- 抽象表达式AbstractExpression的代码如下所示。
【代码 6-27】 AbstractExpression.java
public abstract class AbstractExpression {
public abstract Object interpreter(Context ctx);
}
- 终结符表达式TerminalExpression的代码如下所示。
【代码 6-28】 TerminalExpression.java
public class TerminalExpression extends AbstractExpression {
public Object interpreter(Context ctx) {
return null;
}
}
- 非终结符表达式NonterminalExpression的代码如下所示。
【代码 6-29】 NonterminalExpression.java
public class NonterminalExpression extends AbstractExpression {
public NonterminalExpression(AbstractExpression expression){
}
public Object interpreter(Context ctx) {
return null;
}
}
- 环境Context采用HashMap容纳一个具体的表达式,其代码如下所示。
【代码 6-30】 Context.java
public class Context {
private HashMap map=new HashMap();
......
}
- 客户端Client的代码如下所示。
【代码 6-31】 Client.java
public class Client {
public static void main(String[] args) {
Context ctx = new Context();
for (;;) {
}
......
}
}
三、优缺点
3.1 优点
- 简单的语法分析工具。
- 扩展性,修改语法规则只要修改相应的非终结符表达式即可,若扩展语法,则只要增加非终结符类即可。
3.2 缺点
- 解释器模式会引起类膨胀。每个语法都要产生一个非终结符表达式,语法比较复杂时就可能产生大量的类文件,不易维护。
- 采用递归调用方法。每个非终结符表达式只关心与自己有关的表达式,每个表达式需要知道最终的结果,必须一层一层地剥茧,无论是面向过程的语言还是面向对象的语言,递归都是在必要条件下使用的,不易调试且影响效率。
四、应用场景
- 重复发生的问题可以使用解释器模式。例如,多个应用服务器,每天产生大量的日志,需要对日志文件进行分析处理,由于各个服务器的日志格式不同,但是数据要素是相同的,按照解释器的说法就是终结符表达式都是相同的,非终结符表达式就需要制定。
- 一个简单语法需要解释的场景。