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

这个模式比较模糊,光看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; 
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值