解释器模式是一种行为型设计模式,它给定一门语言,定义其文法的一种表示,并定义一个解释器来解释语言中的句子。在C++中,我们可以通过类层次结构来映射文法规则,使每一条规则对应一个表达式类,从而完成对自定义语言的解释执行。

解释器模式的核心角色
在C++实现中,通常包含以下几个部分:
- 抽象表达式类:声明解释操作的接口,一般包含interpret方法。
- 终结符表达式:对应文法中的基本元素,如变量或常量。
- 非终结符表达式:对应文法中的组合规则,如加法、循环等。
- 上下文环境:保存解释过程中需要的全局信息或变量表。
- 客户端:负责构建语法树并触发解释。
定义简单的加法与变量文法
假设我们要支持形如 (a + b) + 3 的表达式语言,其中a和b是变量,数字是常量。我们先定义上下文与抽象表达式。
#include <iostream>
#include <string>
#include <map>
// 上下文,保存变量的值
class Context {
public:
void setVariable(const std::string& name, int value) {
variables[name] = value;
}
int getVariable(const std::string& name) {
return variables[name];
}
private:
std::map<std::string, int> variables;
};
// 抽象表达式
class Expression {
public:
virtual ~Expression() {}
virtual int interpret(Context& ctx) = 0;
};
实现终结符与非终结符表达式
终结符包括变量和常量,非终结符对应加法操作。代码如下:
// 变量终结符
class Variable : public Expression {
public:
Variable(const std::string& n) : name(n) {}
int interpret(Context& ctx) override {
return ctx.getVariable(name);
}
private:
std::string name;
};
// 常量终结符
class Number : public Expression {
public:
Number(int v) : value(v) {}
int interpret(Context& ctx) override {
return value;
}
private:
int value;
};
// 加法非终结符
class Add : public Expression {
public:
Add(Expression* l, Expression* r) : left(l), right(r) {}
~Add() {
delete left;
delete right;
}
int interpret(Context& ctx) override {
return left->interpret(ctx) + right->interpret(ctx);
}
private:
Expression* left;
Expression* right;
};
客户端构建语法树并解释
我们在main函数中组装语法树,相当于写出了 (a + b) + 5 的抽象表示,并设置变量值后解释执行。
int main() {
Context ctx;
ctx.setVariable("a", 10);
ctx.setVariable("b", 20);
// 构建 (a + b) + 5
Expression* expr = new Add(
new Add(new Variable("a"), new Variable("b")),
new Number(5)
);
int result = expr->interpret(ctx);
std::cout << "结果: " << result << std::endl; // 输出 35
delete expr;
return 0;
}
扩展与注意事项
如果需要支持更多运算,只需增加对应的非终结符类,例如减法、乘法。当文法变复杂时,建议先用词法分析和语法分析工具生成语法树,再将树节点适配为解释器模式的类。解释器模式的优点是易扩展文法,缺点是类数量会随着规则增多而膨胀,且递归解释可能影响性能,适合中小型语言处理场景。
小结
在C++中实现解释器模式,关键是把文法规则映射为表达式类,利用多态完成解释。通过上下文管理状态,客户端负责组装语法树。这样即可为项目定制轻量级的解释型小语言。