设计模式之解析器(Interpreter)的C++实现

1、解析模式的提出

在软件开发的过程中,需要实现一种需求,该需求的结构稳定,但是需求的业务内容会频繁变化,如果使用普通语法实现需求,需要经常更新代码,不具有灵活性。可以使用解析器模式解决实现该类需求,解析器是实现一种能够解析该需求结构语法的功能代码,针对不同的业务调用对应的解析规则代码。

2、需求描述

有一个字符串的加减计算,如'a+b+c-d-e',其中a,b,c,d,e分别对应带计算的值。设计一个功能代码,可以实现该功能,且该代码可以适配不定个数的加减数运算。

3、功能实现

(1)UML图如下:

 (2)代码实现如下:

#include <iostream>
#include <map>
#include <stack>

class AbsExpression
{
public:
    bool isVarType = false;
public:
    void   setExpressionType(bool bFlag){isVarType= bFlag;};
    virtual int interpreter(std::map<char,int>var)=0;
    virtual ~AbsExpression(){};
};

//变量表达式
class ValExpression:public AbsExpression
{
private:
    char m_key;
public:
    ValExpression(const char&key)
    {
        std::cout << "ValExpression " << std::endl;
        this->m_key = key;
        setExpressionType(true);
    }

    int interpreter(std::map<char, int> var) override
    {
        return var[m_key];
    }
    ~ValExpression()
    {
     std::cout << "~ValExpression " << std::endl;
    }
};

//符号表达式
class SymbolExpression:public AbsExpression
{
protected:
    AbsExpression* m_left;
    AbsExpression* m_right;

public:
    SymbolExpression(AbsExpression* left,AbsExpression* right):
        m_left(left),m_right(right)
    {
    }
    ~SymbolExpression()
    {
        //left对象是直接取的栈容器的上一个top,故可以显式清理。
        //right的new对象不会直接push进栈容器,而是做了符号实例对象的成员变量。故需要对其进行对象释放
        if(m_right != nullptr)
        {
            delete m_right;
            m_right = nullptr;
        }
        std::cout << "~SymbolExpression" << std::endl;
    }
};

//加法运算符
class AddExpression:public SymbolExpression
{
public:
    AddExpression(AbsExpression* left,AbsExpression* right):
        SymbolExpression(left,right){
        std::cout << "AddExpression " << std::endl;
    }

    int interpreter(std::map<char,int>var)
    {
        return m_left->interpreter(var) + m_right->interpreter(var);
    }
};
//减法运算符
class SubExpression:public SymbolExpression
{
public:
    SubExpression(AbsExpression* left,AbsExpression* right):
        SymbolExpression(left,right){
        std::cout << "SubExpression " << std::endl;
    }

    int interpreter(std::map<char,int>var)
    {
        return m_left->interpreter(var) - m_right->interpreter(var);
    }
};

std::stack<AbsExpression*> analyse(std::string strLanguage){
    std::stack<AbsExpression*>stackExp;
    AbsExpression* left = nullptr;
    AbsExpression* right = nullptr;

    for(size_t i = 0; i < strLanguage.length();i++)
    {
        switch (strLanguage[i]) {
        case '+':
        {
            left = stackExp.top();
            right = new ValExpression(strLanguage[++i]);
            stackExp.push(new AddExpression(left,right));
        }break;
        case '-':
        {   left = stackExp.top();
            right = new ValExpression(strLanguage[++i]);
            stackExp.push(new SubExpression(left,right));

        }break;
        default:
            stackExp.push(new ValExpression(strLanguage[i]));

        }
    }
    return stackExp;
};

void release( std::stack<AbsExpression*> exp)
{
    while (exp.size() > 0) {
       AbsExpression* it =  exp.top();
       delete it;
       it = nullptr;
       exp.pop();
    }
    std::cout << "clear exp finshed " << std::endl;
}
class Client
{
public:
    void doWork()
    {
        std::string str = "a+b+c-d";
        std::map<char,int>mapVar;
        mapVar.insert(std::make_pair('a',1));
        mapVar.insert(std::make_pair('b',2));
        mapVar.insert(std::make_pair('c',3));
        mapVar.insert(std::make_pair('d',4));
        std::stack<AbsExpression*> exp = analyse(str);
        int ret = exp.top()->interpreter(mapVar);

        std::cout << "ret is " << ret << std::endl;
        release(exp);
    }
};

int main()
{
    Client obj;
    obj.doWork();
    return 0;
}

运行结果如下:

注意:解析器适用于比较简单的语法解析,对于复杂的语法,可以使用语法分析生成器工具,具体的语法分析生成器用法可自行搜索查看。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值