定义
给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
解释器模式需要解决的是,如果一种特定类型的问题发生的频率足够高,那么可能就值得将该问题的各个实例表述为一个简单语言中的句子。这样就可以构建一个解释器,该解释器通过解释这些句子来解决该问题[DP]。比方说,我们常常会在字符串中搜索匹配的字符或判断一个字符串是否符合我们规
举例
如常见的计算器,用来计算表达式"1 + 2 + 3 - 2",我们可以直接这样输入,但是机器并不是这样读取的,而是翻译成机器可读的语言,得出来得结果再翻译成人类可读得语言
结构
实现
//AbstractExpression(抽象表达式),声明一个抽象的解释操作,这个接口为抽象语法树中所有的节点所共享。
abstract class AbstractExpression
{
public abstract void Interpret(Context context);
}
//TerminalExpression(终结符表达式),实现与文法中的终结符相关联的解释操作。实现抽象表达式中所要求的接口,主要是一个interpret()方法。文法中每一个终结符都有一个具体终结表达式与之相对应。
class TerminalExpression : AbstractExpression
{
public override void Interpret(Context context)
{
Console.WriteLine("终端解释器");
}
}
/// <summary>
//NonterminalExpression(非终结符表达式),为文法中的非终结符实现解释操作。
//对文法中每一条规则R1、R2……Rn都需要一个具体的非终结符表达式类。
//通过实现抽象表达式的 interpret()方法实现解释操作。
//解释操作以递归方式调用上面所提到的代表R1、R2……Rn中各个符号的实例变量。
/// </summary>
class NonterminalExpression : AbstractExpression
{
public override void Interpret(Context context)
{
Console.WriteLine("非终端解释器");
}
}
//包含解释器之外的一些全局信息。
class Context
{
private string input;
public string Input
{
get { return input; }
set
{
input = value;
}
}
private string output;
public string Output
{
get { return output; }
set { output = value; }
}
}
class Program
{
static void Main(string[] args)
{
//调用解释器操作
Context context = new Context();
IList<AbstractExpression> list = new List<AbstractExpression>();
list.Add(new TerminalExpression());
list.Add(new NonterminalExpression());
list.Add(new TerminalExpression());
list.Add(new TerminalExpression());
foreach (AbstractExpression exp in list)
{
exp.Interpret(context);
}
}
}
优点
- (1)解释器模式易于改变和扩展文法。
- (2)在解释器模式中,每一条文法规则都可以表示为一个类,因此可以方便地实现一个简单的语言。
- (3)实现文法较为容易。在抽象语法树中每一个表达式结点类的实现方式都是相似的,这些类的代码编写都不会特别复杂,还可以通过一些工具自动生成结点类代码。
- (4)增加新的解释表达式较为方便。如果用户需要增加新的解释表达式只需要对应增加一个新的终结符表达式或非终结符表达式类,原有表达式类代码无须修改,符合开闭原则
缺点
- (1)解释器模式对于复杂文法难以维护。在解释器模式中,每一条规则至少需要定义一个类,因此如果一个语言包含太多的文法规则,类的个数将会急剧增加,从而导致系统难以管理和维护,此时可以考虑使用语法分析程序等方式来取代解释器模式。
- (2)其执行效率较低。由于在解释器模式中使用了大量的循环和递归调用,因此在解释较为复杂的句子时其速度很慢,而且代码的调试过程也比较麻烦。
适用环境
- (1)可以将一个需要解释执行的语言中的句子表示为一棵抽象语法树。
- (2)一些重复出现的问题可以用一种简单的语言进行表达。
- (3)一个语言的文法较为简单。对于复杂的文法,解释器模式中的文法类层次结构将变得很庞大而无法管理,此时最好使用语法分析程序生成器。
- (4)执行效率不是关键问题。高效的解释器通常不是通过直接解释抽象语法树来实现的,而是需要将它们转换成其他形式,使用解释器模式的执行效率并不高。