解释器模式
来源:互联网 发布:淘宝网充气浴缸 编辑:程序博客网 时间:2024/05/22 03:51
定义
解释器模式(InterpreterPattern)给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
解释器模式通用类图
AbstractExpression——抽象解释器
具体的解释任务由各个实现类完成,具体的解释器分别由TerminalExpression和NonterminalExpression完成。
TerminalExpression——终结符表达式
实现与文法中的元素相关联的解释操作,通常以一个解释器模式中只有一个终结符表达式,但有多个实例,对应不同的终结符。
NonterminalExpression——非终结符表达式
文法中的每条规则对应于一个非终结表达式,原则上每一个文法规则都需要一个非终结符号表达式。
Context——环境角色
包含解释器之外的一些全局信息
解释器模式的优点
易于改变和扩展文法 因为该模式使用类来表示文法规则,你可使用继承来改变或扩展该文法。已有的表达式可被增量式地改变,而新的表达式可定义为旧表达式的变体。
缺点
复杂的文法难以维护 解释器模式为文法中的每一条规则至少定义了一个类(使用BNF定
义的文法规则需要更多的类)。因此包含许多规则的文法可能难以管理和维护。可应用其他的设计模式来缓解这一问题。但当文法非常复杂时,其他的技术如语法分析程序或编译器生成器更为合适。
举例:
四则运算,简单起见,不含乘除法和括号,即运算不分优先级,只有加减法。
C++源码
#include <iostream>#include <map>#include <stack>using namespace std;class Expression{ //表达式抽象基类public: virtual int interpreter(map<string,int>& var)=0; virtual ~ Expression(){};};class VarExpression:public Expression{ //终结符表达式,这里为数值元素private: string key;public: VarExpression(string _key):key(_key){} int interpreter(map<string,int>& var) { map<string,int>::iterator it = var.find(this->key); return it->second; }};class SymbolExpression:public Expression{protected: Expression *left; Expression *right;public: SymbolExpression(Expression *_left,Expression *_right) { this->left=_left; this->right=_right; } virtual ~ SymbolExpression(){ if(left != NULL) delete left; if(right != NULL) delete right; }};class AddExpression : public SymbolExpression{public: AddExpression(Expression *_left,Expression *_right):SymbolExpression(_left,_right){}; int interpreter(map<string,int> &var){ return left->interpreter(var) + right->interpreter(var); }};class SubExpression : public SymbolExpression{public: SubExpression(Expression *_left,Expression *_right):SymbolExpression(_left,_right){}; int interpreter(map<string,int> &var){ return left->interpreter(var) - right->interpreter(var); }};class Calculator{private: Expression *expression;public: Calculator(string expStr){ stack<Expression *> expStack; Expression *left = NULL; Expression *right = NULL; for(size_t i=0;i<expStr.length();i++){ switch(expStr[i]) { case '+': left = expStack.top(); expStack.pop(); right = new VarExpression(expStr.substr(++i,1)); expStack.push(new AddExpression(left,right)); break; case '-': left = expStack.top(); expStack.pop(); right = new VarExpression(expStr.substr(++i,1)); expStack.push(new SubExpression(left,right)); break; default: expStack.push(new VarExpression(expStr.substr(i,1))); } } this->expression = expStack.top(); expStack.pop(); } int run(map<string,int> &var){ return this->expression->interpreter(var); } ~Calculator(){ delete expression; }};int main(){ string expStr; cout<<"请输入表达式:"<<flush; cin>>expStr; map<string,int> var ; for(size_t i=0;i<expStr.length();i++) { if(expStr[i] != '+' && expStr[i] != '-'){ if(var.end() == var.find(expStr.substr(i,1))) { cout<<"请输入"<<expStr.substr(i,1)<<"的值"<<flush; int temp; cin>>temp; var.insert(make_pair(expStr.substr(i,1),temp)); } } } Calculator cal(expStr); cout<<"运算结果为:"<<expStr<<" = "<<cal.run(var); return 0;}
对于表达式 a+b-c的语法树分析图:
很明显,这是一棵二叉树,其中,终结符表达式(VarExpression)对象均为树的叶子节点,非终结表达式(SymbolExpression的子类)对象均为树的非叶节点,因为都是二元操作符,所以每个非终结表达式均带两个子树,子树根节点的类型可以为终结符表达式或非终结符表达式。对表达式进行代数运算实际就是后序遍历这棵语法树(由interpreter的递归调用方式就可以看出来)。
运行结果:
- 深入浅出解释器模式
- 解释器(Interpreter )模式
- Interpreter解释器模式
- Interperter 解释器模式
- 解释器模式 InterpretePattern
- 解释器模式
- 解释器模式
- 深入浅出解释器模式
- 解释器模式(python)
- 解释器模式
- 解释器模式 详解
- 解释器模式
- Java解释器模式
- 解释器模式
- Interpreter 解释器模式
- java 解释器模式
- 解释器模式
- 解释器模式
- csdn还是"待审核"吗?
- js创建对象和继承
- POJ 1279 Art Gallery
- Java中I/O流
- mysql connector odbc配置注意事项
- 解释器模式
- 浏览器嵌入视频播放器(转载)
- 嵌入式linux多进程编程
- PHP网页游戏学习之Xnova(ogame)源码解读
- C 语言堆栈的实例
- C++ 习题 输出日期时间--友元函数
- mcisendstring打开文件失败
- Binder工作原理与使用
- a标签click和href执行顺序探讨