C++设计模式[十四]解释器模式

来源:互联网 发布:mac chm文件怎么打开 编辑:程序博客网 时间:2024/06/05 18:30

这个模式比较模糊,光看UML图的话很好实现,但是要想明白是什么东西,为什么叫解释器?边看边学习吧。

果冻想 | 一个原创文章分享网站

AbstractExpression:声明一个抽象的解释操作,这个接口被抽象语法树中所有的节点所共享;
TernimalExpression:一个句子中的每个终结符需要该类的一个实例,它实现与文法中的终结符相关联的解释操作;
NonternimalExpression:

  • 对于文法中的每一条规则都需要一个NonternimalExpression类;
  • 为文法中的的每个符号都维护一个AbstractExpression类型的实例变量;
  • 为文法中的非终结符实现解释操作,在实现时,一般要递归地调用表示文法符号的那些对象的解释操作;

Context:包含解释器之外的一些全局信息;
Client:构建一个需要进行解释操作的文法句子,然后调用解释操作进行解释。

实际进行解释时,按照以下时序进行的:

  1. Client构建一个句子,它是NonterminalExpression和TerminalExpression的实例的一个抽象语法树,然后初始化上下文并调用解释操作;
  2. 每一非终结符表达式节点定义相应子表达式的解释操作。而各终结符表达式的解释操作构成了递归的基础;
  3. 每一节点的解释操作用作用上下文来存储和访问解释器的状态。

看完还有诸多不解,突然想起来了之前学的课程《有限自动机理论》 ,里面有上下文无关文法中终结符和非终结符的介绍,先解释一下不太熟悉的官方词,通俗的说,终结符号就是语言中用到的基本元素,一般不能再被分解;名词,动词,形容词,助词,等等基本语言单位。非终结符则是"语法"中用到的元素,除非谈论"语法",一般交谈语言中并不会用到非终结符.比如,主语,短语,词组,句子。
从形式语言中定义看,终结符(T)就是不可再分的字符或串。
而非终结符(N)是一个递归形式的定义:由终结符和至少一个非终结符号组成的串。

然后这个不熟悉的词就变为了我们能够理解的白菜萝卜了。接着再看看该模式的结构:

解释器模式的结构

  • 抽象解释器:声明一个所有具体表达式都要实现的抽象接口(或者抽象类),接口中主要是一个interpret()方法,称为解释操作。具体解释任务由它的各个实现类来完成,具体的解释器分别由终结符解释器TerminalExpression和非终结符解释器NonterminalExpression完成。
  • 终结符表达式:实现与文法中的元素相关联的解释操作,通常一个解释器模式中只有一个终结符表达式,但有多个实例,对应不同的终结符。终结符一半是文法中的运算单元,比如有一个简单的公式R=R1+R2,在里面R1和R2就是终结符,对应的解析R1和R2的解释器就是终结符表达式。                                
  • 非终结符表达式:文法中的每条规则对应于一个非终结符表达式,非终结符表达式一般是文法中的运算符或者其他关键字,比如公式R=R1+R2中,+就是非终结符,解析+的解释器就是一个非终结符表达式。非终结符表达式根据逻辑的复杂程度而增加,原则上每个文法规则都对应一个非终结符表达式。
  • 环境角色:这个角色的任务一般是用来存放文法中各个终结符所对应的具体值,比如R=R1+R2,我们给R1赋值100,给R2赋值200。这些信息需要存放到环境角色中,很多情况下我们使用Map来充当环境角色就足够了。

例子:

//包含解释器之外的一些全局信息class Context { public: Context() {}~Context() {}};class AbstractExpression { public: virtual ~AbstractExpression() {}virtual void Interpret(const Context& c) {}protected: AbstractExpression() {}};//终结符表达式class TerminalExpression:public AbstractExpression {public: TerminalExpression(const string& statement){this->_statement = statement;}~TerminalExpression(){}void Interpret(const Context& c){cout<<this->_statement<<" Terminal Expression..."<<endl; }private: string _statement; };//非终结符表达式 class NonterminalExpression:public AbstractExpression { public: NonterminalExpression(const string& statement){this->_statement = statement;} ~NonterminalExpression() {}void Interpret(const Context& c){cout<<this->_statement<<" Nonterminal Expression..."<<endl; }private:string _statement; };//测试代码int main(int argc,char* argv[]){ Context* c = new Context();list<AbstractExpression*> ls;ls.push_back(new TerminalExpression("A"));ls.push_back(new NonterminalExpression("B"));ls.push_back(new TerminalExpression("C"));ls.push_back(new NonterminalExpression("D"));list<AbstractExpression*>::iterator it = ls.begin();for (it; it != ls.end(); ++it){(*it)->Interpret(*c);}return 0; }



0 0