码迷,mamicode.com
首页 > 其他好文 > 详细

第27章解释器模式

时间:2019-07-11 11:10:45      阅读:114      评论:0      收藏:0      [点我收藏+]

标签:iss   logs   details   string   const   expr   ||   stat   表达式   

一 概念

  • 解释器模式,给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
  • 解释器要解决的问题是,如果一种特定类型的问题发生的频率足够高,那么可能就值得将该问题的各个实例表述为一个简单语言中的句子,这样就可以构建一个解释器,该解释器通过解释这些句子来解决该问题。

二 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》

第27章解释器模式

标签:iss   logs   details   string   const   expr   ||   stat   表达式   

原文地址:https://www.cnblogs.com/Manual-Linux/p/11162086.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!