解释器模式 -- Interpret

2017-04-07 15:21:36   最后更新: 2017-04-07 15:21:36   访问数量:408




解释器模式主要是用来解释一种给定的语言的文法表示的

最常见的应用是计算器的实现,算式 291 + 18 - 279 就是一种公式语言,他定义了一套运算的集合,解释器使用一种通用的算法来解释执行一个公式

上面说的公式中仅有两个元素:运算元素和运算符号,291、18、279 就是运算元素,他们作为值是计时器能够处理的最小单元逻辑,不可以进行拆分,因此被称为“终结符号”,每个运算符号都需要对应处理单元,否则公式就无法被顺利解析

针对运算元素与运算单元,我们就需要对应的解析器:

  1. VarExpression -- 运算元素解析器
  2. SymbolExpression -- 运算符号解析器

 

从而构成了抽象语法树:

 

 

 

 

如上图所示,解释器模式由以下组件构成:

  1. AbstractExpression -- 抽象表达式,为抽象语法树中所有节点声明解释操作
  2. TerminalExpression -- 终结符表达式,实现文法中终结符号相关的解释操作
  3. NonterminalExpression -- 非终结符表达式,每一个规则都需要一个 NonterminalExpression 类,例如上文提到的 AddExpression、SubExpression,甚至还会有 DivExpression、MulExpression、LeftBracketExpress、RightBracketExpress 等

 

整个解释过程是递归进行的,每一个非终结符表达式节点定义了相应的子表达式的解释操作,而各个终结符表达式的解释操作则构成了递归的基础

整个解释器保存有一份上下文,用来存储和访问解释器的状态

 

解释器模式具有以下优点:

  1. 易于改变和扩展,通过继承可以创建新的解释器,而不会对已有的解释器造成任何影响
  2. 实现新的表达式变得容易

 

但是解释器模式很难维护复杂的文法,因为每一条规则都需要至少定义一个类,如果使用巴克斯范式(BNF)定义的文法规则,就需要更多的类,如果包含了很多规则的文法,那么类将庞大到无法管理和维护的地步

 

在使用中,如果经常要创建一种新的解释器,那么 Visitor 模式可能是一种更好地选择,使用一个访问者以避免在每一个类上都定义这些解释操作会很方便

如果一个终结符多次出现,通过 Flyweight 模式共享这个终结符会是一个更好地选择,例如计算机程序中反复出现的变量,由于在解释的过程中,任何解释器所需要的上下文信息都是由父节点传递给他们的,因此他们的共享状态和内部状态具有明确的区分,可以很容易的使用 Flyweight 模式

 






技术帖      龙潭书斋      词法分析      语法分析      设计模式      design pattern      解释器      interpret      visitor      编译原理     


京ICP备15018585号