设计模式之解析器模式

INTERPRETER(解释器)

声明:本文概念为《设计模式》GOF 中的定义,详细请查看对应书籍

1. 意图
给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。

2. 动机
如果一种特定类型的问题发生的频率足够高 , 那么可能就值得将该问题的各个实例表述为一个简单语言中的句子。这样就可以构建一个解释器 , 该解释器通过解释这些句子来解决该问题。

3. 适用性
当有一个语言需要解释执行 , 并且你可将该语言中的句子表示为一个抽象语法树时,可使用解释器模式。而当存在以下情况时该模式效果最好:
• 该文法简单对于复杂的文法 , 文法的类层次变得庞大而无法管理。此时语法分析程序生成器这样的工具是更好的选择。它们无需构建抽象语法树即可解释表达式 , 这样可以节省空间而且还可能节省时间。
• 效率不是一个关键问题最高效的解释器通常不是通过直接解释语法分析树实现的 , 而是首先将它们转换成另一种形式。例如,正则表达式通常被转换成状态机。但即使在这种情况下, 转换器仍可用解释器模式实现, 该模式仍是有用的。

 

4.类图

代码:

声明:代码参考:https://blog.csdn.net/Bing_Lee/article/details/103672683

#pragma once
#include "stdafx.h"

//抽象表达式
class AbstractNode
{
public:
	virtual ~AbstractNode() = default;
	virtual string interpret() = 0;
protected:
	AbstractNode() = default;
};

//方向解释器
class DirectionNode : public AbstractNode
{
public:
	explicit DirectionNode(const string &direction)
	{
		this->direction = direction;
		cout << "DirectionNode  say  hi,pkqbp  = "<< this->direction << endl;
	}
	~DirectionNode()
	{
		cout << "DirectionNode  say  Bye,pkqbp  = " << this->direction << endl;
	}

	string interpret() override
	{
		if (direction == "up")
		{
			return "向上";
		}
		else if (direction == "down")
		{
			return "向下";
		}
		else if (direction == "left") {
			return "向左";
		}
		else if (direction == "right") {
			return "向右";
		}
		else {
			return "无效指令";
		}		
	}
private:
	string direction;
};

//动作解释器
class ActionNode : public AbstractNode
{
public:
	explicit ActionNode(const string & action)
	{
		this->action = action;
		cout << "ActionNode hello. Action = " << this->action << endl;
	}
	~ActionNode() override
	{
		cout << "ActionNode Bye.  Action = " << this->action << endl;
	}

	string interpret() override
	{
		if (action == "move") {
			return "移动";
		}
		else if (action == "run") {
			return "快速移动";
		}
		else {
			return "无效指令";
		}
	}
private:
	string action;
};

//距离解释:终结符表达式
class DistanceNode : public AbstractNode
{
public:
	explicit DistanceNode(const string & distance)
	{
		this->distance = distance;
		cout << "DistanceNode, Hello. Distance = " << this->distance << endl;
	}
	~DistanceNode() override
	{
		cout << "DistanceNode, Bye. Distance = " << this->distance << endl;
	}
	string interpret() override
	{
		return distance;
	}
private:
	string distance;
};

//And解释:非终结符表达式

class AndNode : public AbstractNode
{
public:
	AndNode(AbstractNode *left, AbstractNode *right)
	{
		this->left = left;
		this->right = right;
		cout << "AndNode, Hello." << "left = " << this->left
			<< " right = " << this->right << endl;
	}
	~AndNode() override
	{
		cout << "AndNode, Bye." << "left = " << this->left
			<< " right = " << this->right << endl;
		delete left;
		delete right;
	}
	string interpret() override {
		return left->interpret() + "再" + right->interpret();
	}
private:
	AbstractNode *left;  //And的左表达式
	AbstractNode *right; //And的右表达式
};

//简单句子解释:非终结符表达式
class SentenceNode : public AbstractNode
{
public:
	SentenceNode(AbstractNode *direction, AbstractNode *action, AbstractNode *distance)
	{
		this->direction = direction;
		this->action = action;
		this->distance = distance;
		cout << "SentenceNode, Hello." << "direction = " << this->direction
			<< " action = " << this->action << " distance = " << this->distance << endl;
	}
	~SentenceNode() override {
		cout << "SentenceNode, Bye." << "direction = " << this->direction
			<< " action = " << this->action << " distance = " << this->distance << endl;
		delete direction;
		delete action;
		delete distance;
	}
	string interpret() override {
		return direction->interpret() + action->interpret() + distance->interpret();
	}
private:
	AbstractNode *direction; // 移动方向
	AbstractNode *action; // 移动方式
	AbstractNode *distance; // 移动距离
};


//Context(环境类):Handler  (指令处理类工具类)
class Handler
{
public:
	explicit Handler(const std::string &input) {
		expression = input;
		finalExp = nullptr;
		std::cout << "Handler , Hello: " << expression << std::endl;
	}
	~Handler() {
		std::cout << "Handler , Bye: " << expression << std::endl;
		delete finalExp;
	}
	void handle() {
		AbstractNode *left = nullptr, *right = nullptr;
		AbstractNode *direction = nullptr, *action = nullptr, *distance = nullptr;

		// 分割 expression 这里 借助strtok实现split, 其他方式自行百度
		char* inputCh = const_cast<char *>(expression.c_str());
		char *token = strtok(inputCh, " ");
		while (token != nullptr) {
			expVector.emplace_back(token);
			token = strtok(nullptr, " ");
		}
		for (int i = 0; i < expVector.size(); i++) {
			// 如果遇到and则将其后的三个单词连成一个简单句子(Sentence)作为"and"的右表达式,而将栈顶弹出的表达式作为"and"的左表达式,最后将新的And表达式压入栈中
			if ("and" == expVector[i]) { //
										 //从弹出栈顶作为and的左表达式
				left = stackExp.top();
				stackExp.pop();

				string dir = expVector[++i]; // i 先 +1
				direction = new DirectionNode(dir);
				string act = expVector[++i];
				action = new ActionNode(act);
				string dis = expVector[++i];
				distance = new DistanceNode(dis);

				//组成一个简单表达式作为And的右表达式
				right = new SentenceNode(direction, action, distance);

				//生成And表达式,并压入栈中
				stackExp.push(new AndNode(left, right));
			}
			else {
				//如果不是and表达式,就从头开始进行解释,将前3个单词作为Sentence的三个操作数,生成简单表达式解析器后压入栈中
				string dir = expVector[i];
				direction = new DirectionNode(dir);
				string act = expVector[++i]; // i 先 +1
				action = new ActionNode(act);
				string dis = expVector[++i];
				distance = new DistanceNode(dis);

				//组成一个简单表达式作为And的右表达式
				stackExp.push(new SentenceNode(direction, action, distance));
			}
		}
		/// 最后 解释成一条表达式语句并存放在 栈 stackExp中
		if (!stackExp.empty()) {
			finalExp = stackExp.top();
			stackExp.pop();
		}
		else {
			finalExp = nullptr;
		}
	}

	string output() {
		return finalExp == nullptr ? "**empty**" : finalExp->interpret();
	}
private:
	stack<AbstractNode *> stackExp; //存储表达式的栈
	vector<string> expVector;  //按空格分隔后,存储vector
	string expression;  //表达
	AbstractNode * finalExp;
};


void process()
{
	cout << "test 1 start" << endl;
	string  instruction = "up move 5 and down run 10 and left move 5"; //指令
	Handler hander(instruction);
	hander.handle();
	cout << "输入指令:" << instruction << endl;
	cout << "输出结果:" << hander.output() << endl;
}

输出结果:

test 1 start
Handler , Hello: up move 5 and down run 10 and left move 5
DirectionNode  say  hi,pkqbp  = up
ActionNode hello. Action = move
DistanceNode, Hello. Distance = 5
SentenceNode, Hello.direction = 0089B030 action = 0089B350 distance = 0089B5D0
DirectionNode  say  hi,pkqbp  = down
ActionNode hello. Action = run
DistanceNode, Hello. Distance = 10
SentenceNode, Hello.direction = 0089B3F0 action = 0089B440 distance = 0089B4E0
AndNode, Hello.left = 008969C8 right = 0089FE08
DirectionNode  say  hi,pkqbp  = left
ActionNode hello. Action = move
DistanceNode, Hello. Distance = 5
SentenceNode, Hello.direction = 0089AEF0 action = 0089B530 distance = 0089B580
AndNode, Hello.left = 008A01F0 right = 0089FE48
输入指令:up move 5 and down run 10 and left move 5
输出结果:向上移动5再向下快速移动10再向左移动5
Handler , Bye: up move 5 and down run 10 and left move 5
AndNode, Bye.left = 008A01F0 right = 0089FE48
AndNode, Bye.left = 008969C8 right = 0089FE08
SentenceNode, Bye.direction = 0089B030 action = 0089B350 distance = 0089B5D0
DirectionNode  say  Bye,pkqbp  = up
ActionNode Bye.  Action = move
DistanceNode, Bye. Distance = 5
SentenceNode, Bye.direction = 0089B3F0 action = 0089B440 distance = 0089B4E0
DirectionNode  say  Bye,pkqbp  = down
ActionNode Bye.  Action = run
DistanceNode, Bye. Distance = 10
SentenceNode, Bye.direction = 0089AEF0 action = 0089B530 distance = 0089B580
DirectionNode  say  Bye,pkqbp  = left
ActionNode Bye.  Action = move
DistanceNode, Bye. Distance = 5

这就是设计模式之解析器模式,十分的有趣呢。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值