解释器模式

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》

以上是关于解释器模式的主要内容,如果未能解决你的问题,请参考以下文章

设计模式----解释器模式

设计模式解释器模式 ( 简介 | 适用场景 | 优缺点 | 代码示例 )

大话设计模式Python实现-解释器模式

设计模式之解释器模式

设计模式——23.解释器模式

Java进阶篇设计模式之九----- 解释器模式和迭代器模式