这个模式比较模糊,光看UML图的话很好实现,但是要想明白是什么东西,为什么叫解释器?边看边学习吧。
AbstractExpression:声明一个抽象的解释操作,这个接口被抽象语法树中所有的节点所共享;
TernimalExpression:一个句子中的每个终结符需要该类的一个实例,它实现与文法中的终结符相关联的解释操作;
NonternimalExpression:
- 对于文法中的每一条规则都需要一个NonternimalExpression类;
- 为文法中的的每个符号都维护一个AbstractExpression类型的实例变量;
- 为文法中的非终结符实现解释操作,在实现时,一般要递归地调用表示文法符号的那些对象的解释操作;
Context:包含解释器之外的一些全局信息;
Client:构建一个需要进行解释操作的文法句子,然后调用解释操作进行解释。
实际进行解释时,按照以下时序进行的:
- Client构建一个句子,它是NonterminalExpression和TerminalExpression的实例的一个抽象语法树,然后初始化上下文并调用解释操作;
- 每一非终结符表达式节点定义相应子表达式的解释操作。而各终结符表达式的解释操作构成了递归的基础;
- 每一节点的解释操作用作用上下文来存储和访问解释器的状态。
看完还有诸多不解,突然想起来了之前学的课程《有限自动机理论》 ,里面有上下文无关文法中终结符和非终结符的介绍,先解释一下不太熟悉的官方词,通俗的说,终结符号就是语言中用到的基本元素,一般不能再被分解;名词,动词,形容词,助词,等等基本语言单位。非终结符则是"语法"中用到的元素,除非谈论"语法",一般交谈语言中并不会用到非终结符.比如,主语,短语,词组,句子。
从形式语言中定义看,终结符(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;
}