解释器模式
Posted manual-linux
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了解释器模式相关的知识,希望对你有一定的参考价值。
一 概念
- 解释器模式,给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
- 解释器要解决的问题是,如果一种特定类型的问题发生的频率足够高,那么可能就值得将该问题的各个实例表述为一个简单语言中的句子,这样就可以构建一个解释器,该解释器通过解释这些句子来解决该问题。
二 UML图
- Context 包含解释器之外的一些全局信息,对全局的一些内容进行描述
- AbstractExpression 抽象表达式,声明一个抽象的解释操作,这个接口为抽象语法树中所有的节点所共享。
- TerminalExpression 终结符表达式,实现与文法中的终结符相关联的解释操作。
- NonterminalExpression 非终结符表达式,为文法中的非终结符实现解释操作,对文法中每一条规则R1,R2,。。。Rn都需要一个具体的非终结符表达式类。
三 C++代码实现
#include "pch.h"
#include <iostream>
#include <string>
#include <vector>
#include <sstream>
using namespace std;
template <typename elemType>
elemType stringToNum(const string& str)
istringstream iss(str);
elemType num;
iss >> num;
return num;
//包含解释器之外的一些全局信息
class PlayContext
public:
void SetPlayContext(const string text)
this->str_text = text;
string GetPlayContext() const
return this->str_text;
private:
string str_text;
;
//表达式类 AbstractExpression
//抽象表达式,声明一个抽象的解释操作,这个接口为抽象语法树中所有的节点所共享
class Expression
public:
virtual void Interpret(PlayContext* context)
string buf;
string s2;
if (context->GetPlayContext().size() == 0)
return;
else
vector<string> vec;
stringstream ss(context->GetPlayContext());
while (ss >> buf)
vec.push_back(buf);
//这里是C++的字符串处理
string playKey = vec[0];
double playValue = stringToNum<double>(vec[1]);
this->Excute(playKey, playValue);
vec.erase(vec.begin(), vec.begin() + 2);
vector<string>::iterator it;
for (it = vec.begin(); it != vec.end(); it++)
s2 += *it;
if (it != vec.end() - 1)
s2 += " ";
context->SetPlayContext(s2);
virtual void Excute(string key, double value) = 0;
;
//音符类
//TerminalExpression 终结符表达式,实现与文法中的终结符相关联的解释操作
class Note : public Expression
void Excute(string key, double value) override
string note = "";
switch (key[0])
case 'C':
note = "1";
break;
case 'D':
note = "2";
break;
case 'E':
note = "3";
break;
case 'F':
note = "4";
break;
case 'G':
note = "5";
break;
case 'A':
note = "6";
break;
case 'B':
note = "7";
break;
default:
break;
cout << note << " ";
;
class Scale : public Expression
public:
void Excute(string key, double value) override
string scale = "";
switch (static_cast<int>(value))
case 1:
scale = "低音";
break;
case 2:
scale = "中音";
break;
case 3:
scale = "高音";
break;
default:
break;
cout << scale << " ";
;
int main()
PlayContext* context = new PlayContext();
cout << "上海滩: " << endl;
context->SetPlayContext("O 2 E 0.5 G 0.5 A 3 E 0.5 G 0.5 D 3 E 0.5 G 0.5 A 0.5 O 3 C 1 O 2 A 0.5 G 1 C 0.5 E 0.5 D 3 ");
while (context->GetPlayContext().size() > 0)
Expression* expression = nullptr;
char c = context->GetPlayContext()[0];
switch (c)
case 'O':
//当首字段是O时,则表达式实例化为音阶
expression = new Scale();
break;
case 'C':
case 'D':
case 'E':
case 'F':
case 'G':
case 'A':
case 'B':
case 'P':
//当首字母是CDEFGAB,以及休止符P时,则实例化为音符
expression = new Note();
break;
expression->Interpret(context);
delete expression;
system("pause");
补充的另外一个例子
- 一个简单加减法运算器的实例
//一个简单加减法运算器的实例
#include "pch.h"
#include <iostream>
#include <string>
#include <vector>
using namespace std;
//抽象的表达式对象以及Context对象
//用于保存计算的中间结果以及当前执行的操作符
class Context
public:
Context()
:m_value(0), m_operator('\\0')
void SetOperator(char type)
this->m_operator = type;
char GetOperator() const
return this->m_operator;
void SetValue(int number)
this->m_value = number;
int GetValue() const
return this->m_value;
private:
int m_value;
char m_operator;
;
//表示所有表达式的抽象接口
class IExpression
public:
virtual void Eval(Context* p) = 0;
;
//拆分表达式的元素
class Operator : public IExpression
public:
Operator(char op)
this->m_op = op;
void Eval(Context* pContext) override
pContext->SetOperator(this->m_op);
private:
char m_op;
;
//拆分操作数
class Operand : public IExpression
public:
Operand(int number)
this->m_num = number;
void Eval(Context* pContext) override
switch (pContext->GetOperator())
case '\\0':
pContext->SetValue(this->m_num);
break;
case '+':
pContext->SetValue(this->m_num + pContext->GetValue());
break;
case '-':
pContext->SetValue(pContext->GetValue() - this->m_num);
break;
default:
break;
private:
int m_num;
;
class Calculator
public:
Calculator()
int Calc(string expression)
Context* pContext = new Context;
vector<IExpression*> tree; //语法解析树
for (int ix = 0; ix < expression.size(); ++ix)
if (expression[ix] == '+' || expression[ix] == '-')
tree.push_back(new Operator(expression[ix]));
cout << "第" << ix << "次压入的符号是" << expression[ix] << endl;
else
tree.push_back(new Operand(static_cast<int>(expression[ix] - 48)));
cout << "第" << ix << "次压入的数字是" << static_cast<int>(expression[ix] - 48) << endl;
for (vector<IExpression*>::iterator iter = tree.begin(); iter != tree.end(); ++iter)
(*iter)->Eval(pContext);
return pContext->GetValue();
;
int main()
Calculator* pc = new Calculator();
cout << "1+4-2+6+9-5-2-1+1+2= " << pc->Calc("1+4-2+6-9-5-2-1+1+2") << endl;
system("pause");
return 0;
运行结果
参考资料:
1 https://blog.csdn.net/xiqingnian/article/details/42222369 《大话设计模式C++实现-第27章-解释器模式》
2 https://www.cnblogs.com/hjj-fighting/p/10514935.html 《c++ string 转double》
以上是关于解释器模式的主要内容,如果未能解决你的问题,请参考以下文章