解释器模式是一种行为设计模式,它定义了一种语言的文法表示,并提供一个解释器来解释该语言中的句子。这种模式常用于需要解释执行特定领域语言的场景。
解释器模式核心结构
解释器模式包含以下主要角色:
AbstractExpression(抽象表达式):声明一个抽象的解释操作
TerminalExpression(终结符表达式):实现与文法中的终结符相关的解释操作
NonterminalExpression(非终结符表达式):实现文法规则的解释操作
Context(上下文):包含解释器之外的一些全局信息
Client(客户端):构建语法树并调用解释操作
解释器模式典型应用场景
正则表达式引擎
SQL查询解析器
数学表达式计算器
编译器语法分析
业务规则引擎
配置文件解析器
C++实现示例
1. 简单数学表达式计算器
#include <iostream>
#include <string>
#include <unordered_map>
#include <memory>
#include <stack>
#include <stdexcept>
// 抽象表达式
class Expression {
public:
virtual ~Expression() = default;
virtual int interpret(std::unordered_map<char, int>& context) = 0;
};
// 终结符表达式:变量
class Variable : public Expression {
public:
explicit Variable(char name) : name(name) {}
int interpret(std::unordered_map<char, int>& context) override {
return context[name];
}
private:
char name;
};
// 终结符表达式:数字常量
class Number : public Expression {
public:
explicit Number(int value) : value(value) {}
int interpret(std::unordered_map<char, int>&) override {
return value;
}
private:
int value;
};
// 非终结符表达式:加法
class Add : public Expression {
public:
Add(std::unique_ptr<Expression> left, std::unique_ptr<Expression> right)
: left(std::move(left)), right(std::move(right)) {}
int interpret(std::unordered_map<char, int>& context) override {
return left->interpret(context) + right->interpret(context);
}
private:
std::unique_ptr<Expression> left;
std::unique_ptr<Expression> right;
};
// 非终结符表达式:减法
class Subtract : public Expression {
public:
Subtract(std::unique_ptr<Expression> left, std::unique_ptr<Expression> right)
: left(std::move(left)), right(std::move(right)) {}
int interpret(std::unordered_map<char, int>& context) override {
return left->interpret(context) - right->interpret(context);
}
private:
std::unique_ptr<Expression> left;
std::unique_ptr<Expression> right;
};
// 非终结符表达式:乘法
class Multiply : public Expression {
public:
Multiply(std::unique_ptr<Expression> left, std::unique_ptr<Expression> right)
: left(std::move(left)), right(std::move(right)) {}
int interpret(std::unordered_map<char, int>& context) override {
return left->interpret(context) * right->interpret(context);
}
private:
std::unique_ptr<Expression> left;
std::unique_ptr<Expression> right;
};
// 表达式解析器
class Parser {
public:
std::unique_ptr<Expression> parse(const std::string& expr) {
std::stack<std::unique_ptr<Expression>> stack;
for (size_t i = 0; i < expr.size(); ++i) {
char c = expr[i];
if (isdigit(c)) {
int num = 0;
while (i < expr.size() && isdigit(expr[i])) {
num = num * 10 + (expr[i++] - '0');
}
--i;
stack.push(std::make_unique<Number>(num));
}
else if (isalpha(c)) {
stack.push(std::make_unique<Variable>(c));
}
else if (c == '+' || c == '-' || c == '*') {
if (stack.size() < 2) {
throw std::runtime_error("Invalid expression");
}
auto right = std::move(stack.top()); stack.pop();
auto left = std::move(stack.top()); stack.pop();
switch (c) {
case '+':
stack.push(std::make_unique<Add>(std::move(left), std::move(right)));
break;
case '-':
stack.push(std::make_unique<Subtract>(std::move(left), std::move(right)));
break;
case '*':
stack.push(std::make_unique<Multiply>(std::move(left), std::move(right)));
break;
}
}
}
if (stack.size() != 1) {
throw std::runtime_error("Invalid expression");
}
return std::move(stack.top());
}
};
int main() {
// 上下文:变量值
std::unordered_map<char, int> context = {
{'a', 5},
{'b', 10},
{'c', 2}
};
Parser parser;
// 解析并计算表达式
try {
// 计算 a + b * c
auto expr1 = parser.parse("a b c * +");
std::cout << "a + b * c = " << expr1->interpret(context) << std::endl;
// 计算 (a + b) * c
auto expr2 = parser.parse("a b + c *");
std::cout << "(a + b) * c = " << expr2->interpret(context) << std::endl;
// 计算 100 - a * b
auto expr3 = parser.parse("100 a b * -");
std::cout << "100 - a * b = " << expr3->interpret(context) << std::endl;
}
catch (const std::exception& e) {
std::cerr << "Error: " << e.what() << std::endl;
}
return 0;
}
2. 简单SQL WHERE条件解析器
#include <iostream>
#include <string>
#include <vector>
#include <memory>
#include <unordered_map>
#include <stdexcept>
// 数据库记录类型
using Record = std::unordered_map<std::string, std::string>;
// 抽象表达式
class SQLExpression {
public:
virtual ~SQLExpression() = default;
virtual bool evaluate(const Record& record) const = 0;
};
// 终结符表达式:等于比较
class Equals : public SQLExpression {
public:
Equals(const std::string& field, const std::string& value)
: field(field), value(value) {}
bool evaluate(const Record& record) const override {
auto it = record.find(field);
return it != record.end() && it->second == value;
}
private:
std::string field;
std::string value;
};
// 终结符表达式:大于比较
class GreaterThan : public SQLExpression {
public:
GreaterThan(const std::string& field, const std::string& value)
: field(field), value(value) {}
bool evaluate(const Record& record) const override {
auto it = record.find(field);
return it != record.end() && it->second > value;
}
private:
std::string field;
std::string value;
};
// 非终结符表达式:AND逻辑
class And : public SQLExpression {
public:
And(std::unique_ptr<SQLExpression> left, std::unique_ptr<SQLExpression> right)
: left(std::move(left)), right(std::move(right)) {}
bool evaluate(const Record& record) const override {
return left->evaluate(record) && right->evaluate(record);
}
private:
std::unique_ptr<SQLExpression> left;
std::unique_ptr<SQLExpression> right;
};
// 非终结符表达式:OR逻辑
class Or : public SQLExpression {
public:
Or(std::unique_ptr<SQLExpression> left, std::unique_ptr<SQLExpression> right)
: left(std::move(left)), right(std::move(right)) {}
bool evaluate(const Record& record) const override {
return left->evaluate(record) || right->evaluate(record);
}
private:
std::unique_ptr<SQLExpression> left;
std::unique_ptr<SQLExpression> right;
};
// 非终结符表达式:NOT逻辑
class Not : public SQLExpression {
public:
explicit Not(std::unique_ptr<SQLExpression> expr)
: expr(std::move(expr)) {}
bool evaluate(const Record& record) const override {
return !expr->evaluate(record);
}
private:
std::unique_ptr<SQLExpression> expr;
};
// SQL解析器(简化版)
class SQLParser {
public:
std::unique_ptr<SQLExpression> parse(const std::string& condition) {
// 这里简化了解析过程,实际应用中需要更复杂的解析器
if (condition.find("AND") != std::string::npos) {
size_t pos = condition.find(" AND ");
auto left = parse(condition.substr(0, pos));
auto right = parse(condition.substr(pos + 5));
return std::make_unique<And>(std::move(left), std::move(right));
}
else if (condition.find("OR") != std::string::npos) {
size_t pos = condition.find(" OR ");
auto left = parse(condition.substr(0, pos));
auto right = parse(condition.substr(pos + 4));
return std::make_unique<Or>(std::move(left), std::move(right));
}
else if (condition.find("NOT") != std::string::npos) {
size_t pos = condition.find("NOT ");
auto expr = parse(condition.substr(pos + 4));
return std::make_unique<Not>(std::move(expr));
}
else if (condition.find("=") != std::string::npos) {
size_t pos = condition.find("=");
std::string field = condition.substr(0, pos);
std::string value = condition.substr(pos + 1);
trim(field);
trim(value);
return std::make_unique<Equals>(field, value);
}
else if (condition.find(">") != std::string::npos) {
size_t pos = condition.find(">");
std::string field = condition.substr(0, pos);
std::string value = condition.substr(pos + 1);
trim(field);
trim(value);
return std::make_unique<GreaterThan>(field, value);
}
throw std::runtime_error("Invalid SQL condition: " + condition);
}
private:
void trim(std::string& s) {
s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](int ch) {
return !std::isspace(ch);
}));
s.erase(std::find_if(s.rbegin(), s.rend(), [](int ch) {
return !std::isspace(ch);
}).base(), s.end());
}
};
int main() {
// 模拟数据库记录
std::vector<Record> database = {
{{"name", "Alice"}, {"age", "30"}, {"salary", "50000"}},
{{"name", "Bob"}, {"age", "25"}, {"salary", "45000"}},
{{"name", "Charlie"}, {"age", "35"}, {"salary", "60000"}},
{{"name", "David"}, {"age", "28"}, {"salary", "55000"}}
};
SQLParser parser;
try {
// 解析WHERE条件
auto condition1 = parser.parse("age > 28 AND salary > 50000");
auto condition2 = parser.parse("name = Bob OR name = Alice");
auto condition3 = parser.parse("NOT age > 30");
// 筛选记录
std::cout << "Records where age > 28 AND salary > 50000:\n";
for (const auto& record : database) {
if (condition1->evaluate(record)) {
std::cout << record.at("name") << " (age: " << record.at("age")
<< ", salary: " << record.at("salary") << ")\n";
}
}
std::cout << "\nRecords where name = Bob OR name = Alice:\n";
for (const auto& record : database) {
if (condition2->evaluate(record)) {
std::cout << record.at("name") << "\n";
}
}
std::cout << "\nRecords where NOT age > 30:\n";
for (const auto& record : database) {
if (condition3->evaluate(record)) {
std::cout << record.at("name") << " (age: " << record.at("age") << ")\n";
}
}
}
catch (const std::exception& e) {
std::cerr << "Error: " << e.what() << std::endl;
}
return 0;
}
解释器模式的特点
优点:
易于扩展文法:添加新的表达式类即可扩展语言
实现文法简单:每个文法规则都可以表示为一个类
易于改变和扩展解释过程:可以通过继承或组合来改变解释行为
缺点:
复杂的文法难以维护:文法规则很多时,类层次结构会变得庞大
执行效率较低:解释器模式通常使用递归调用,效率不如命令式代码
难以调试:复杂的解释逻辑可能难以调试
解释器模式适用场景
需要解释执行的语言:当有一个语言需要解释执行,并且可以将该语言中的句子表示为一个抽象语法树时
简单文法:文法较为简单时(复杂文法需要大量的类来表示规则)
效率不是关键问题:当效率不是关键问题时(解释器模式通常比编译型语言慢)
实际应用中的变体
使用访问者模式遍历语法树:将操作与语法树结构分离
使用生成器模式构建语法树:简化复杂语法树的构建过程
共享终结符:使用享元模式共享终结符表达式实例
解释器模式在需要实现简单语言解释器时非常有用,但需要注意控制文法的复杂度,避免类爆炸问题。在实际应用中,通常会结合其他模式(如访问者模式)来提高灵活性和可维护性。