c++实现解释器模式(附带源码)
·
解释器模式(Interpreter Pattern)
解释器模式是一种行为型设计模式,主要用于为特定语言构建解释器。解释器模式定义了一个语言的文法规则,并且使用一个解释器来解释输入的文法字符串。该模式通常用于构建基于规则或表达式的解析器,例如:正则表达式、SQL查询解析器、数学表达式求值等。
关键角色
- Expression(抽象表达式):这是所有具体表达式的共同接口,定义了
interpret()方法,所有具体表达式都会实现这个方法。 - TerminalExpression(终结符表达式):表示文法中的终结符,通常与文法中的基本元素对应,如数字、字母等。
- NonTerminalExpression(非终结符表达式):表示文法中的非终结符,通常由多个终结符或其他非终结符组合而成,表示更复杂的规则。
- Context(上下文):用于存储解释过程中的信息,通常用于保存输入的文本等。
项目实现思路
- 抽象表达式(Expression):定义所有表达式的基本接口
interpret(),该方法将负责解释具体的表达式。 - 终结符表达式(TerminalExpression):表示语法中的最基本的元素,如数字或字母,直接与输入内容匹配。
- 非终结符表达式(NonTerminalExpression):表示由多个终结符或其他非终结符组成的复杂规则。
- 上下文(Context):存储解释过程中的信息,并为表达式提供上下文支持。
C++实现代码
#include <iostream>
#include <string>
#include <map>
#include <memory>
// 抽象表达式
class Expression {
public:
virtual ~Expression() = default;
virtual int interpret() const = 0; // 解释方法
};
// 终结符表达式
class NumberExpression : public Expression {
public:
explicit NumberExpression(int value) : value_(value) {}
int interpret() const override {
return value_;
}
private:
int value_; // 存储数字值
};
// 非终结符表达式:加法表达式
class AddExpression : public Expression {
public:
AddExpression(std::shared_ptr<Expression> left, std::shared_ptr<Expression> right)
: left_(std::move(left)), right_(std::move(right)) {}
int interpret() const override {
return left_->interpret() + right_->interpret(); // 返回两个表达式的和
}
private:
std::shared_ptr<Expression> left_, right_;
};
// 非终结符表达式:减法表达式
class SubtractExpression : public Expression {
public:
SubtractExpression(std::shared_ptr<Expression> left, std::shared_ptr<Expression> right)
: left_(std::move(left)), right_(std::move(right)) {}
int interpret() const override {
return left_->interpret() - right_->interpret(); // 返回两个表达式的差
}
private:
std::shared_ptr<Expression> left_, right_;
};
// 上下文类:用于存储变量和提供变量的值
class Context {
public:
void assignVariable(const std::string& name, int value) {
variables_[name] = value;
}
int getVariableValue(const std::string& name) const {
auto it = variables_.find(name);
if (it != variables_.end()) {
return it->second;
}
throw std::invalid_argument("Variable not found.");
}
private:
std::map<std::string, int> variables_; // 存储变量和它们的值
};
int main() {
// 示例:构造数学表达式 "5 + (3 - 2)"
std::shared_ptr<Expression> five = std::make_shared<NumberExpression>(5);
std::shared_ptr<Expression> three = std::make_shared<NumberExpression>(3);
std::shared_ptr<Expression> two = std::make_shared<NumberExpression>(2);
std::shared_ptr<Expression> subtract = std::make_shared<SubtractExpression>(three, two);
std::shared_ptr<Expression> add = std::make_shared<AddExpression>(five, subtract);
// 计算表达式的结果
std::cout << "Result of '5 + (3 - 2)' is: " << add->interpret() << std::endl;
// 上下文处理示例:使用变量
Context context;
context.assignVariable("x", 10);
context.assignVariable("y", 5);
std::cout << "Value of x: " << context.getVariableValue("x") << std::endl;
std::cout << "Value of y: " << context.getVariableValue("y") << std::endl;
return 0;
}
代码解读
-
抽象表达式(Expression):
Expression是一个抽象类,定义了interpret()方法。所有的具体表达式类都需要实现这个方法,用来解释表达式。
-
终结符表达式(NumberExpression):
NumberExpression是Expression的一个子类,表示文法中的终结符。在本例中,它表示一个常量数字。interpret()方法直接返回存储的数字值。
-
非终结符表达式(AddExpression、SubtractExpression):
AddExpression和SubtractExpression是非终结符类,表示加法和减法运算。- 它们都持有两个
Expression对象,并通过interpret()方法计算出它们的和或差。 interpret()方法递归调用子表达式的interpret(),从而实现了更复杂的表达式计算。
-
上下文(Context):
Context类用于存储和管理变量的值,提供assignVariable()方法来为变量赋值,提供getVariableValue()方法来获取变量的值。- 在本例中,它可以存储表达式中的变量值,方便在复杂表达式中使用。
-
客户端(Main函数):
- 在
main()函数中,我们首先构建了一个数学表达式5 + (3 - 2),并计算了它的值。 - 然后展示了如何在上下文中存储和访问变量的值,演示了如何为变量赋值和获取值。
- 在
总结
解释器模式非常适用于表达式求值或规则解析的场景,特别是当需要处理一个复杂的语言或数据结构时。它通过定义文法规则,递归地解释各个组成部分,从而实现对复杂结构的解析。
优点:
- 易于扩展:通过定义不同的终结符和非终结符表达式,可以方便地扩展新的语法规则和操作。
- 清晰的语法表示:使用解释器模式可以清晰地定义语言的文法规则,并能直接用于解析。
- 可维护性:由于每个表达式都是独立的类,修改和扩展某个规则时不需要修改其他部分,维护性较高。
缺点:
- 性能问题:解释器模式通常会涉及到递归和较多的对象创建,可能会导致性能问题。
- 实现复杂:如果文法规则过于复杂,解释器的实现会变得很复杂,尤其是涉及到多个非终结符和嵌套规则时。
总结来说,解释器模式非常适合用于语言解析、表达式计算等场景,在构建计算器、SQL查询解析器、正则表达式解析等项目中具有广泛的应用。
更多推荐
所有评论(0)