注意:复现代码时,确保 VS2022 使用 C++17/20 标准以支持现代特性。
自定义语法的解析引擎
1. 模式定义与用途
核心思想
- 解释器模式:定义一种语言的语法表示,并提供解释器来解析和执行该语言。
- 关键用途:
1.领域特定语言(DSL):为特定场景设计专用语法(如数据查询、规则引擎)。
2.动态解析逻辑:允许运行时根据输入表达式调整行为(如动态过滤条件)。
经典场景
- 数学表达式解析(如计算器)。
- SQL的WHERE条件解析与执行。
- 正则表达式引擎。
2. 模式结构解析
UML类图
+---------------------+ +---------------------+
| AbstractExpression| | Context |
+---------------------+ +---------------------+
| + interpret(c: Context)| | - variables: map |
+---------------------+ +---------------------+
^ ^
| |
+---------------------+ +--------------------------------+
| TerminalExpression | | NonTerminalExpression |
+---------------------+ +--------------------------------+
| + interpret() | | + interpret() |
+---------------------+ +--------------------------------+
角色说明
AbstractExpression:抽象表达式接口,定义interpret()方法。-
TerminalExpression:终结符表达式(如变量、常量)。 NonTerminalExpression:非终结符表达式(如运算符、组合逻辑)。Context:上下文环境,存储变量值或中间结果。
3. 现代C++实现示例
场景:自定义布尔逻辑表达式解析
步骤1:定义上下文与表达式接口
#include <iostream>
#include <string>
#include <unordered_map>
#include <memory>
// 上下文:存储变量值
class Context {
public:
void setVariable(const std::string& var, bool value) {
variables_[var] = value;
}
bool getVariable(const std::string& var) const {
auto it = variables_.find(var);
return it != variables_.end() ? it->second : false;
}
private:
std::unordered_map<std::string, bool> variables_;
};
// 抽象表达式接口
class Expression {
public:
virtual ~Expression() = default;
virtual bool interpret(const Context& context) = 0;
};
步骤2:实现终结符表达式(变量)
// 终结符:变量
class VariableExpression : public Expression {
public:
VariableExpression(const std::string& name) : name_(name) {}
bool interpret(const Context& context) override {
return context.getVariable(name_);
}
private:
std::string name_;
};
步骤3:实现非终结符表达式(逻辑运算符)
// 非终结符:逻辑与
class AndExpression : public Expression {
public:
AndExpression(std::shared_ptr<Expression> left, std::shared_ptr<Expression> right)
: left_(std::move(left)), right_(std::move(right)) {}
bool interpret(const Context& context) override {
return left_->interpret(context) && right_->interpret(context);
}
private:
std::shared_ptr<Expression> left_, right_;
};
// 非终结符:逻辑或
class OrExpression : public Expression {
public:
OrExpression(std::shared_ptr<Expression> left, std::shared_ptr<Expression> right)
: left_(std::move(left)), right_(std::move(right)) {}
bool interpret(const Context& context) override {
return left_->interpret(context) || right_->interpret(context);
}
private:
std::shared_ptr<Expression> left_, right_;
};
// 非终结符:逻辑非
class NotExpression : public Expression {
public:
NotExpression(std::shared_ptr<Expression> expr)
: expr_(std::move(expr)) {}
bool interpret(const Context& context) override {
return !expr_->interpret(context);
}
private:
std::shared_ptr<Expression> expr_;
};
步骤4:客户端代码(解析并执行表达式)
// 构造表达式:(A && B) || !C
int main() {
Context context;
context.setVariable("A", true);
context.setVariable("B", false);
context.setVariable("C", true);
auto exprA = std::make_shared<VariableExpression>("A");
auto exprB = std::make_shared<VariableExpression>("B");
auto exprC = std::make_shared<VariableExpression>("C");
auto andExpr = std::make_shared<AndExpression>(exprA, exprB);
auto notExpr = std::make_shared<NotExpression>(exprC);
auto finalExpr = std::make_shared<OrExpression>(andExpr, notExpr);
bool result = finalExpr->interpret(context);
std::cout << "表达式结果: " << std::boolalpha << result << "\n";
// 输出:表达式结果: false(因为 A&&B=false,!C=false,整体为false)
}
4. 应用场景示例
场景1:动态SQL条件过滤
class SQLFilter : public Expression {
public:
SQLFilter(const std::string& condition) {
// 解析条件字符串为表达式树(示例简化)
// 例如:"age > 25 AND (city = 'NY' OR city = 'SF')"
}
bool interpret(const Context& context) override {
// 转换为实际SQL查询
return true;
}
};
场景2:数学表达式计算器
class NumberExpression : public Expression {
public:
NumberExpression(int value) : value_(value) {}
int interpret(const Context&) override { return value_; }
private:
int value_;
};
class AddExpression : public Expression {
public:
AddExpression(std::shared_ptr<Expression> left, std::shared_ptr<Expression> right)
: left_(left), right_(right) {}
int interpret(const Context& context) override {
return left_->interpret(context) + right_->interpret(context);
}
};
5. 优缺点分析
| 优点 | 缺点 |
|---|---|
| 灵活扩展语法规则 | 复杂语法导致类数量爆炸(需组合表达式) |
| 易于实现简单DSL | 性能较低(递归解析开销大) |
| 分离语法定义与解析逻辑 | 难以维护复杂文法(需结合解析器生成器) |
6. 调试与优化策略
调试技巧(VS2022)
1. 跟踪表达式树解析:
- 在interpret()方法内设置断点,逐层查看表达式计算过程。
2. 验证上下文变量:
- 使用 内存窗口 检查Context中的变量值是否正确。
性能优化
1. 预编译表达式树:
class PrecompiledExpression {
public:
PrecompiledExpression(std::shared_ptr<Expression> expr) : expr_(expr) {}
bool execute(const Context& context) {
return expr_->interpret(context);
}
private:
std::shared_ptr<Expression> expr_;
};
2. 缓存重复表达式:
class ExpressionCache {
public:
std::shared_ptr<Expression> parse(const std::string& expr) {
if (auto it = cache_.find(expr); it != cache_.end()) {
return it->second;
}
auto parsedExpr = buildExpressionTree(expr);
cache_[expr] = parsedExpr;
return parsedExpr;
}
private:
std::unordered_map<std::string, std::shared_ptr<Expression>> cache_;
};
1385

被折叠的 条评论
为什么被折叠?



