加法/减法解释器示意图:
分析:C#语言无法直接解释类似“1 + 2 + 3 – 4 + 1”这样的字符串。定义一套文法规则来实现对这些语句的解释,即设计一个自定义语言。基于现有的编程语言 -> 面向对象编程语言 -> 解释器模式。
解释器模式定义:
注:
文法规则:
expression ::= value | operation
operation ::= expression ‘+’ expression | expression ‘-‘ expression
value ::= an integer //一个整数值
抽象语法树:抽象语法树(Abstract Syntax Tree, AST):描述了如何构成一个复杂的句子,通过对抽象语法树的分析,可以识别出语言中的终结符类和非终结符类
其中的operation节点为“非终结符表达式”,value为“终结符表达式”
解释器模式的结构:
解释器模式包含以下4个角色:
在抽象表达式中声明了抽象的解释操作,它是所有的终结符表达式和非终结符表达式的公共父类。
终结符表达式是抽象表达式的子类,它实现了与文法中的终结符相关联的解释操作,在句子中的每一个终结符都是该类的一个实例。通常在一个解释器模式中只有少数几个终结符表达式类,他们的实例可以通过非终结符表达式组成较为复杂的句子。
非终结符表达式也是抽象表达式的子类,它实现了文法中非终结符的解释操作,由于在非终结符表达式中可以包含终结符表达式,也可以继续包含非终结符表达式,因此其解释 操作一般通过递归的方式来完成。
环境类又称为上下文类,他用于存储解释器之外的一些全局信息,通常它临时存储了需要解释器的语句。
在客户类中构造了表示该文法定义的语言中一个特定句子的抽象语法树,该抽象语法树由非终结符表达式和终结符表达式实例组合而成,在客户类中还将调用解释操作,实现对句子的解释。有时候为了简化客户类的代码,可以将抽象语法树的构造工作封装到专门的类中完成,客户端只需要提供待解释的句子并调用该类的解释操作即可,该类可以称为解释器封装类。
典型的抽象表达式类代码:
public abstract class AbstractExpression
{
public abstract void interpret(Context ctx);
}
典型的终结符表达式类代码:
public class TerminalExpression extends AbstractExpression
{
public void interpret(Context ctx)
{
//对于终结符表达式的解释操作
}
}
典型的非终结符表达式类代码:
public class NonterminalExpression extends AbstractExpression
{
private AbstractExpression left;
private AbstractExpression right;
public NonterminalExpression(AbstractExpression left,AbstractExpression right)
{
this.left=left;
this.right=right;
}
public void interpret(Context ctx)
{
//递归调用每一个组成部分的interpret()方法
//在递归调用时指定组成部分的连接方式,即非终结符的功能
}
}
典型的环境类代码:
环境类Context:
public class Context
{
private HashMap map = new HashMap();
public void assign(String key, String value)
{
//往环境类中设值
}
public String lookup(String key)
{
//获取存储在环境类中的值
}
}
实例:数学运算解释器
现需要构造一个语言解释器,使得系统可以执行整数间的乘、除和求模运算。如用户输入表达式“3 * 4 / 2 % 4”,输出结果为2。使用解释器模式实现该功能。
实例类图:
实例解析:
实例二:
某软件公司要开发一套机器人控制程序,在该机器人控制程序中包含一些简单的英文控制指令,每一个指令对应一个表达式(expression),该表达式可以是简单表达式也可以是复合表达式。每一个简单表达式由移动方向(direction),移动方式(action)和移动距离(distance)三部分组成,其中,移动方向包括向上(up)、向下(down)、向左(left)、向右(right);移动方式包括移动(move)和快速移动(run);移动距离为一个正整数。两个表达式之间可以通过与(and)连接,形成复合(composite)表达式。
用户通过对图形化的设置界面进行操作可以创建一个机器人控制指令,机器人在收到指令后将按照指令的设置进行移动,例如输入控制指令“up move 5”将“向上移动5个单位”;输入控制指令“down run 10 and left move 20”将“向下快速移动10个单位再向左移动20个单位”。
现使用解释器模式来设计该程序并模拟实现。
实例分析及类图
文法规则:
expression ::= direction action distance | composite //表达式
composite ::= expression ‘and’ expression //复合表达式
direction ::= ‘up’ | ‘down’ | ‘left’ | ‘right’ //移动方向
action ::= ‘move’ | ‘run’ //移动方式
distance ::= an integer //移动距离
抽象语法树:
实例分析及类图:
实例代码:
结果及分析:
down run 10 and left move 20
向下快速移动10再向左移动20
up move 5 and down run 10 and left move 5
向上移动5再向下快速移动10再向左移动5
模式优点:
模式缺点:
模式适用环境: