当前位置: 首页 > news >正文

解释器模式C++

解释器模式(Interpreter Pattern)是一种行为型设计模式,它用于定义一种语言的语法规则,并构建一个解释器来解释该语言中的句子。这种模式适用于需要处理固定语法规则的场景,如表达式解析、配置文件解析等。

解释器模式的核心角色

  1. AbstractExpression(抽象表达式):声明解释操作的接口,通常包含一个interpret()方法
  2. TerminalExpression(终结符表达式):实现与语法规则中终结符相关的解释操作
  3. NonterminalExpression(非终结符表达式):实现与语法规则中非终结符相关的解释操作,通常包含其他表达式
  4. Context(上下文):包含解释器之外的一些全局信息
  5. Client(客户端):构建表示特定句子的抽象语法树,调用解释操作

C++实现示例

以下以"简单算术表达式解析"为例实现解释器模式,支持加法、减法运算和数字解析:

#include <iostream>
#include <string>
#include <memory>
#include <map>
#include <cctype>
#include <stdexcept>// 前向声明
class Expression;// 上下文:存储变量值和表达式字符串
class Context {
private:std::map<std::string, int> variables;  // 变量映射表std::string expression;                // 表达式字符串size_t position;                       // 当前解析位置public:Context(std::string expr) : expression(std::move(expr)), position(0) {}// 设置变量值void setVariable(const std::string& name, int value) {variables[name] = value;}// 获取变量值int getVariable(const std::string& name) const {auto it = variables.find(name);if (it != variables.end()) {return it->second;}throw std::runtime_error("变量未定义: " + name);}// 获取当前字符char currentChar() const {if (position < expression.size()) {return expression[position];}return '\0';}// 移动到下一个字符void nextChar() {if (position < expression.size()) {position++;}}// 跳过空白字符void skipWhitespace() {while (std::isspace(currentChar())) {nextChar();}}// 解析标识符(变量名)std::string parseIdentifier() {std::string id;skipWhitespace();if (!std::isalpha(currentChar())) {throw std::runtime_error("无效的标识符");}while (std::isalnum(currentChar())) {id += currentChar();nextChar();}skipWhitespace();return id;}// 解析数字int parseNumber() {int num = 0;skipWhitespace();if (!std::isdigit(currentChar())) {throw std::runtime_error("无效的数字");}while (std::isdigit(currentChar())) {num = num * 10 + (currentChar() - '0');nextChar();}skipWhitespace();return num;}// 获取当前位置size_t getPosition() const {return position;}// 设置当前位置void setPosition(size_t pos) {position = pos;}
};// 抽象表达式
class Expression {
public:virtual ~Expression() = default;virtual int interpret(Context& context) const = 0;
};// 终结符表达式:数字
class NumberExpression : public Expression {
private:int number;public:explicit NumberExpression(int num) : number(num) {}int interpret(Context& /*context*/) const override {return number;}
};// 终结符表达式:变量
class VariableExpression : public Expression {
private:std::string name;public:explicit VariableExpression(std::string varName) : name(std::move(varName)) {}int interpret(Context& context) const override {return context.getVariable(name);}
};// 非终结符表达式:加法
class AddExpression : public Expression {
private:std::unique_ptr<Expression> left;std::unique_ptr<Expression> right;public:AddExpression(std::unique_ptr<Expression> l, std::unique_ptr<Expression> r): left(std::move(l)), right(std::move(r)) {}int interpret(Context& context) const override {return left->interpret(context) + right->interpret(context);}
};// 非终结符表达式:减法
class SubtractExpression : public Expression {
private:std::unique_ptr<Expression> left;std::unique_ptr<Expression> right;public:SubtractExpression(std::unique_ptr<Expression> l, std::unique_ptr<Expression> r): left(std::move(l)), right(std::move(r)) {}int interpret(Context& context) const override {return left->interpret(context) - right->interpret(context);}
};// 解析器:构建抽象语法树
class Parser {
private:// 解析因子(数字或变量)std::unique_ptr<Expression> parseFactor(Context& context) {char c = context.currentChar();if (c == '(') {context.nextChar();  // 跳过 '('auto expr = parseExpression(context);if (context.currentChar() != ')') {throw std::runtime_error("缺少右括号");}context.nextChar();  // 跳过 ')'return expr;} else if (std::isalpha(c)) {// 变量std::string varName = context.parseIdentifier();return std::make_unique<VariableExpression>(varName);} else if (std::isdigit(c)) {// 数字int num = context.parseNumber();return std::make_unique<NumberExpression>(num);}throw std::runtime_error("语法错误: 意外字符 '" + std::string(1, c) + "'");}// 解析项(处理乘法和除法,这里简化只处理加减)std::unique_ptr<Expression> parseTerm(Context& context) {auto expr = parseFactor(context);while (true) {char c = context.currentChar();if (c != '+' && c != '-') {break;}context.nextChar();  // 跳过运算符auto rhs = parseFactor(context);if (c == '+') {expr = std::make_unique<AddExpression>(std::move(expr), std::move(rhs));} else {expr = std::make_unique<SubtractExpression>(std::move(expr), std::move(rhs));}}return expr;}public:// 解析表达式std::unique_ptr<Expression> parseExpression(Context& context) {return parseTerm(context);}
};// 客户端代码
int main() {try {// 测试1:纯数字表达式Context context1("10 + 20 - 5");Parser parser;auto expr1 = parser.parseExpression(context1);std::cout << "10 + 20 - 5 = " << expr1->interpret(context1) << std::endl;// 测试2:带变量的表达式Context context2("a + b - c");context2.setVariable("a", 15);context2.setVariable("b", 30);context2.setVariable("c", 10);auto expr2 = parser.parseExpression(context2);std::cout << "a + b - c = " << expr2->interpret(context2) << std::endl;// 测试3:带括号的表达式Context context3("(x + y) - (z + 5)");context3.setVariable("x", 20);context3.setVariable("y", 10);context3.setVariable("z", 5);auto expr3 = parser.parseExpression(context3);std::cout << "(x + y) - (z + 5) = " << expr3->interpret(context3) << std::endl;} catch (const std::exception& e) {std::cerr << "错误: " << e.what() << std::endl;}return 0;
}

代码解析

  1. 抽象表达式(Expression

    • 定义了interpret()方法作为解释操作的接口
    • 所有具体表达式都必须实现这个方法
  2. 终结符表达式

    • NumberExpression:解释数字常量,直接返回存储的数值
    • VariableExpression:解释变量,从上下文获取变量值
  3. 非终结符表达式

    • AddExpression:解释加法运算,计算左右两个表达式的和
    • SubtractExpression:解释减法运算,计算左右两个表达式的差
  4. 上下文(Context

    • 存储表达式字符串、当前解析位置和变量映射表
    • 提供解析辅助方法(如跳过空白、解析标识符和数字)
  5. 解析器(Parser

    • 负责将输入的表达式字符串转换为抽象语法树(由各种表达式对象组成)
    • 使用递归下降法解析,支持数字、变量、加减运算和括号

解释器模式的优缺点

优点

  • 易于扩展新的语法规则,只需添加新的表达式类
  • 语法规则清晰地体现在表达式类的层次结构中
  • 便于实现简单的语法解释器,逻辑明确

缺点

  • 对于复杂语法,表达式类的数量会急剧增加,导致系统庞大
  • 复杂语法的解释效率可能较低
  • 难以维护复杂的语法规则

适用场景

  • 当需要处理简单的语法规则时(如配置文件解析、简单表达式计算)
  • 当语法规则可以表示为抽象语法树时
  • 当需要频繁添加新的语法规则时

常见应用:

  • 表达式计算器(如数学表达式、布尔表达式)
  • 配置文件解析器
  • 简单的脚本语言解释器
  • 正则表达式引擎

解释器模式通过将语法规则分解为一系列表达式对象,实现了语法的灵活解析。但对于复杂语法,通常会选择更专业的解析工具(如ANTLR),而非手动实现解释器模式。

http://www.lryc.cn/news/621957.html

相关文章:

  • EN 61547照明产品的电磁兼容抗干扰标准
  • 图数据库如何构筑 Web3 风控防线 聚焦批量注册与链上盗转 悦数图数据库
  • eBPF技术介绍
  • 【Java】HashMap的详细介绍
  • YAML:锚点深度解析,告别重复,拥抱优雅的配置艺术
  • 【Java Web 快速入门】十、AOP
  • 「 CentOS7 安装部署k8s」
  • 水环境遥感分析!R语言编程+多源遥感数据预处理;水体指数计算、水深回归分析、水温SVM预测、水质神经网络建模及科研级可视化制图
  • 关于simplifyweibo_4_moods数据集的分类问题
  • 云原生俱乐部-k8s知识点归纳(3)
  • 2025年中国AI算力基础设施发展趋势洞察
  • MySQL 全面指南:从入门到精通——深入解析安装、配置、操作与优化
  • Linux 进程、线程与 exec/系统调用详解
  • 力扣top100(day04-06)--贪心算法
  • 自动处理考勤表——如何使用Power Query,步步为营,一点点探索自定义函数
  • 陪伴,是挫折教育最暖的底色
  • Java 中使用阿里云日志服务(SLS)完整指南
  • Hologres实战:路径分析函数
  • 【开发语言】Groovy语言:Java生态中的动态力量
  • 1.2. qemu命令起虚拟机增加网络配置
  • [git] 当GitHub宕机时,我们如何协作?| github同步gitee的部署方法
  • uniApp App 端日志本地存储方案:实现可靠的日志记录功能
  • Flutter 自定义组件开发指南
  • Wi-Fi 与蜂窝网络(手机网络)的核心区别,以及 Wi-Fi 技术未来的发展方向
  • css变量的妙用(setProperty()的使用)
  • MySQL的学习笔记
  • 前端性能优化工具Performance面板实战指南
  • w484扶贫助农系统设计与实现
  • Android项目中Ktor的引入与使用实践
  • @[TOC](计算机是如何⼯作的) JavaEE==网站开发