给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
a1 定义数据转换类Context,定义获取数据接口函数getValue(),以及定义转换数据map
a2 定义表达式类Expression,定义一个解释器抽象接口函数int interpreter(Context*)=0,同时定义一个左右子树指针Expression left,Expression right;
a3 定义具体非终结符表达式类,比如乘法类MultiExpression,重写接口函数int interpreter(Context);
a4 定义具体非终结符表达式类,比如除法类DivisionExpression,重写接口函数int interpreter(Context);
a5 定义具体终结符表达式类,比如TerminalExpression,重写接口函数int interpreter(Context*)终止递归调用,同时定义成员变量(转换后的值,也就是键值对的值)int value;
代码主要功能是实现一个乘法和除法运算,即 3*4/2==6.
#include
#include
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 Context1
{
public:
Context1(){
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);
cout << "delete left" << endl;
}
if (right != nullptr)
{
DELETE(right);
cout << "delete right" << endl;
}
}
virtual int interpreter(Context1* context) = 0;
protected:
Expression *left;
Expression *right;
};
class MultiExpression : public Expression
{
public:
MultiExpression(Expression *left, Expression *right) : Expression(left, right) { }
int interpreter(Context1* 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(Context1* 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(Context1* context) {
return value;
}
private:
int value;
};
void doInterpreter() // 客户端client
{
/* 3*4/2==6 对应语法树如下:
/ (除法)
/ \
* 2
/ \
3 4
*/
Context1 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释放的时候会自动释放左右子树,也就是递归释放,最终只需要释放最后一次嵌套调用的就行
}
#include
using namespace std;
extern void doInterpreter();
int main()
{
doInterpreter();
system("pause");
return 1;
}
在本次乘除法代码实现中,解释器模式的核心思想是用叶子节点(也就是终止符类)作为值,而把非叶子节点(也就是非终止类)作为符号运行,综合起来形成一个表达式,然后进行计算int interpreter(Context *)。
设计模式C++实现(20)——解释器模式
设计模式C++实现-解释器模式
C++设计模式之解释器模式
陈建忠设计模式(参考:哔哩哔哩C++设计模式!!!)
Erich Gamma,Richard Helm.《设计模式 可复用面向对象软件的基础》[M].机械工业出版社,2019: