1.定义
给定一个语言,定义它的文法的一种表示,并定义一个解释器。比如加减乘除在代码里是一种表示,我们需要翻译成可以阅读的数学公式,并且可以供用户输入数字得到输出结果。
2.组成结构
- 抽象表达式(Abstract Expression):定义解释器的接口,约定解释器的解释操作,主要包含解释方法 interpret()。
- 终结符表达式(Terminal Expression):是抽象表达式的子类,用来实现文法中与终结符相关的操作,文法中的每一个终结符都有一个具体终结表达式与之相对应。
- 非终结符表达式(Nonterminal Expression):也是抽象表达式的子类,用来实现文法中与非终结符相关的操作,文法中的每条规则都对应于一个非终结符表达式。
- 上下文(Context):通常包含各个解释器需要的数据或是公共的功能,一般用来传递被所有解释器共享的数据,后面的解释器可以从这里获取这些值。
我们将用示例代码来解释各个组成部分的意义。
3.示例代码
cpp
#include <iostream>
#include <map>
using namespace std;
#define DELETE(pointer) delete pointer; pointer=nullptr
const string key1 = string("s1");
const string key2 = string("s2");
const string key3 = string("s3");
const string key4 = string("s4");
class Context
{
public:
Context() {
datas[key1] = 1;
datas[key2] = 2;
datas[key3] = 3;
datas[key4] = 4;
}
int getValue(string key) {
if (!datas.count(key))
{
return 0;
}
return datas[key];
}
private:
std::map<string, int> datas;
};
class Expression
{
public:
Expression(Expression* left, Expression* right) :left(left), right(right) { }
virtual ~Expression() {
if (left != nullptr)
{
DELETE(left);
}
if (right != nullptr)
{
DELETE(right);
}
}
virtual int interpreter(Context* context) = 0;
protected:
Expression* left;
Expression* right;
};
class MultiExpression : public Expression
{
public:
MultiExpression(Expression* left, Expression* right) : Expression(left, right) { }
int interpreter(Context* context) override {
if ((left == nullptr) || (right == nullptr))
{
return 0;
}
return left->interpreter(context) * right->interpreter(context);
}
};
class DivisionExpression : public Expression
{
public:
DivisionExpression(Expression* left, Expression* right) : Expression(left, right) { }
int interpreter(Context* context) override {
if ((left == nullptr) || (right == nullptr))
{
return 0;
}
return left->interpreter(context) / right->interpreter(context);
}
};
class TerminalExpression : public Expression
{
public:
TerminalExpression(int value) : value(value), Expression(nullptr, nullptr) { }
int interpreter(Context* context) {
return value;
}
private:
int value;
};
void doInterpreter() // 客户端client
{
/* 3*4/2==6 对应语法树如下:
/ (除法)
/ \
* 2
/ \
3 4
*/
Context context;
MultiExpression* multiExpression = new MultiExpression(new TerminalExpression(context.getValue(key3))
, new TerminalExpression(context.getValue(key4))); // 终止节点作为叶子结点,非终止节点作为非叶子节点
int mutil = multiExpression->interpreter(&context);
cout << "mutil==" << mutil << endl;
DivisionExpression* divisionExpression = new DivisionExpression(multiExpression
, new TerminalExpression(context.getValue(key2))); // 乘法表达式作为左子树 / 右子树
int division = divisionExpression->interpreter(&context); // 运行解释器
cout << "division==" << division << endl;
DELETE(divisionExpression);
// 这里注意,不能第二次释放divisionExpression,因为此时它是divisionExpression的左子树
//,divisionExpression释放的时候会自动释放左右子树,也就是递归释放,最终只需要释放最后一次嵌套调用的就行
}
int main()
{
doInterpreter();
system("pause");
return 1;
}
引用
C++设计模式------解释器模式(interpreter pattern)_c++interpreter模式-CSDN博客