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

C++二十三种设计模式之解释器模式

C++二十三种设计模式之解释器模式

  • 一、组成
  • 二、特点
  • 三、目的
  • 四、缺点
  • 五、示例代码

一、组成

抽象表达式类:声明解释接口。
终结符表达式类:实现解释接口,代表语言中的终结符(数字、变量)。
抽象非终结符表达式类:实现非终结符获取左表达式和获取右表达式接口。
具体非终结符表达式类:实现非终结符的解释接口,代表语言中的非终结符。
解析函数:使用表达式类解析表达式字符串。

二、特点

1、解析函数充当表达式类的使用者身份。
2、解析函数使用表达式栈来存储逐步解析的表达式。
3、解释器模式逐步解析得到的是一个个表达式。

三、目的

提供解释器,根据语言的语法规则,将表达式表示为一个抽象的语法树来解析。

四、缺点

1、性能问题,复杂语句包含大量的循环和递归时会影响系统的性能。
2、类膨胀问题,语言文法规则复杂时,需要大量的表达式类,会导致类急剧膨胀。

五、示例代码

#include<iostream>
#include <vector>
#include <list>
#include <string>
#include <mutex>
#include <map>
#include<stack>

using namespace std;

class Expression;//抽象表达式类
class VarExpression;//终结符表达式类
class SymbolExpression;//抽象非终结符表达式类
class AddExpression;//具体非终结符表达式类
class SubExpression;//具体非终结符表达式类
Expression* analyse(string strExp);//解析函数

class Expression {
public:
	Expression(int num, char sign) : m_num_dbg(num), m_sign_dbg(sign) {}
	virtual int interpret(map <char, int> var) = 0;
	virtual ~Expression() {};
	int m_num_dbg;
	char m_sign_dbg;
};

class VarExpression : public Expression {
public:
	VarExpression(const char& key, int num, char sign) : Expression(num, sign), m_key(key) {}
	int interpret(map <char, int> var) {
		return var[m_key];
	};
	~VarExpression() {
		cout << "delete VarExpression num:" << m_num_dbg << " sign:" << m_sign_dbg << endl;
	};
private:
	char m_key;
};

class SymbolExpression : public Expression {
public:
	SymbolExpression(Expression* left, Expression* right, int num, char sign) : Expression(num, sign), m_left(left), m_right(right) {}
	Expression* GetLeft() {
		return m_left;
	};
	Expression* GetRight() {
		return m_right;
	};
	~SymbolExpression() {
		delete m_left;
		delete m_right;
		cout << "delete SymbolExpression num:" << m_num_dbg << " sign:" << m_sign_dbg << endl;
	}
protected:
	Expression* m_left;
	Expression* m_right;
};

class AddExpression : public SymbolExpression {
public:
	AddExpression(Expression* left, Expression* right, int num, char sign) : SymbolExpression(left, right, num, sign) {}
	int interpret(map <char, int> var) {
		int value1 = m_left->interpret(var);
		int value2 = m_right->interpret(var);
		int result = value1 + value2;
		return result;
	};
	~AddExpression() {};
};

class SubExpression : public SymbolExpression {
public:
	SubExpression(Expression* left, Expression* right, int num, char sign) : SymbolExpression(left, right, num, sign) {}
	int interpret(map <char, int> var) {
		int value1 = m_left->interpret(var);
		int value2 = m_right->interpret(var);
		int result = value1 - value2;
		return result;
	};
};

Expression* analyse(string strExp) {
	stack<Expression*> expStack;
	Expression* left;
	Expression* right;
	int iCount = 0;
	for (size_t i = 0; i < strExp.size(); i++) {
		switch (strExp[i]) {
		case '+':
			left = expStack.top();
			++i;
			right = new VarExpression(strExp[i], iCount++, 'v');
			expStack.push(new AddExpression(left, right, iCount++, '+'));
			break;
		case '-':
			left = expStack.top();
			++i;
			right = new VarExpression(strExp[i], iCount++, 'v');
			expStack.push(new SubExpression(left, right, iCount++, '-'));
			break;
		default:
			expStack.push(new VarExpression(strExp[i], iCount++, 'v'));
			break;
		}
	}
	return expStack.top();
}
int main() {

	string expStr = "a+b-c";
	map<char, int> var;
	var.insert({ 'a',1 });
	var.insert({ 'b',3 });
	var.insert({ 'c',2 });
	unique_ptr<Expression> exp(analyse(expStr));
	int result = (exp)->interpret(var);
	for (auto iter = var.begin(); iter != var.end(); iter++) {
		cout << iter->first << ":" << iter->second << endl;
	}
	cout << expStr << "=" << result << endl;
}

http://www.kler.cn/a/488329.html

相关文章:

  • Jmeter-压测时接口如何按照顺序执行
  • 智慧公厕大数据驱动下的公共卫生管理与优化
  • 00000008_C并发编程与多线程
  • Python中的可变对象与不可变对象;Python中的六大标准数据类型哪些属于可变对象,哪些属于不可变对象
  • C#语言的网络编程
  • 3D机器视觉的类型、应用和未来趋势
  • 【c++实战项目】负载均衡式在线OJ
  • C#里使用libxl读取EXCEL文件的例子
  • 在Ubuntu中使用systemd设置后台自启动服务
  • ffmpeg7.0 aac转pcm
  • Docker入门篇[SpringBoot之Docker实战系列] - 第534篇
  • 商品详情API接口数据解析,API接口系列(示例返回数据(JSON格式))
  • THB6128安森美步进电机驱动芯片
  • leetcode 面试经典 150 题:两数之和
  • 算法题(31):两数之和-输入有序数组
  • 2025年新出炉的MySQL面试题
  • 基于http协议的天气爬虫
  • 计算机视觉算法实战——YOLOv7在姿态识别上的应用
  • 【IDEA】快捷键篇
  • 麦田物语学习笔记:创建DragItem实现物品的拖拽跟随显示
  • 【Flutter】使用ScrollController配合EasyRefresh实现列表预加载:在还未滑动到底部时加载下一页数据
  • 图像传感器的视觉演变与创新
  • Unity自定义编辑器:基于枚举类型动态显示属性
  • sql 函数
  • 联邦大语言模型典型系统: FATE - LLM、FedLLM、FederatedScope - LLM、PrimiHub
  • 【Flink】flink或java异常日志输出不完整问题解决