C++25设计模式之解释器模式

在这里插入图片描述
图片引用于百度

简介:给定一个语言,定义它的文法表示,并定义一个解释器,这个解释器使用该标识来解释语言中的句子

优点:扩展性、灵活性比较好,易于实现简单文法

缺点:可利用场景的比较少,对于复杂的文法比较难维护并且会引起类膨胀

例子背景:解释一段汇编加减乘除代码

解释器模式代码:

  • 上下文类:
#pragma once
#include <string>
#include <iostream>
#include <list>
#include <map>
using namespace std;

using StringList = list<string>;

class Context
{
private:
        StringList m_lstStatements;
public:
        Context(const string& str) : m_lstStatements(split(str))
        {
                
        }
        ~Context() {}
public:
        string NextStatement()
        {
                auto str = m_lstStatements.front();
                m_lstStatements.pop_front();
                return str;
        }
        bool HasNext()
        {
                return !m_lstStatements.empty();
        }
private:
        StringList split(const string& txt)
        {
                char* str = const_cast<char*>(txt.c_str());
                string tmp;
                StringList tmpLst;
                while (*str != '\0')
                {
                        if( *str != '\n')
                        {
                                tmp.push_back(*str);
                        }
                        else
                        {
                                tmpLst.push_back(tmp);
                                tmp.clear();
                        }
                        str++;
                }
                tmpLst.push_back(tmp);
                return tmpLst;
        }
};
  • 抽象解释器类:
#pragma once
#include "Context.h"

class AbstractExpression
{
public:
        AbstractExpression() = default;
        virtual ~AbstractExpression() = default;
public:
        virtual void interpret(Context* text) = 0;
        virtual int execute() = 0;
};
  • 具体解释器类:
#pragma once
#include "AbstractExpression.h"

class MovExpression : public AbstractExpression
{
private:
        int m_num = 0;
public:
        MovExpression(const int& num) : m_num(num) {}
public:
        virtual void interpret(Context* text)
        {
                (text);
        }
        virtual int execute()
        {
                return m_num;
        }
};

class AddExpression : public AbstractExpression
{
private:
        AbstractExpression* m_mov = nullptr;
        int m_num = 0;
public:
        AddExpression(AbstractExpression* mov, const int& num) : m_mov(mov), m_num(num) {}
        ~AddExpression()
        {
                delete m_mov;
        }
public:
        virtual void interpret(Context* text)
        {
                (text);
        }
        virtual int execute()
        {
                return m_mov->execute() + m_num;
        }
};

class SubExpression : public AbstractExpression
{
private:
        AbstractExpression* m_mov = nullptr;
        int m_num = 0;
public:
        SubExpression(AbstractExpression* mov, const int& num) : m_mov(mov), m_num(num) {}
        ~SubExpression()
        {
                delete m_mov;
        }
public:
        virtual void interpret(Context* text)
        {
                (text);
        }
        virtual int execute()
        {
                return m_mov->execute() - m_num;
        }
};

class MulExpression : public AbstractExpression
{
private:
        AbstractExpression* m_mov = nullptr;
        int m_num = 0;
public:
        MulExpression(AbstractExpression* mov, const int& num) : m_mov(mov), m_num(num) {}
        ~MulExpression()
        {
                delete m_mov;
        }
public:
        virtual void interpret(Context* text)
        {
                (text);
        }
        virtual int execute()
        {
                return m_mov->execute() * m_num;
        }
};

class IdivExpression : public AbstractExpression
{
private:
        AbstractExpression* m_mov = nullptr;
        int m_num = 0;
public:
        IdivExpression(AbstractExpression* mov, const int& num) : m_mov(mov), m_num(num) {}
        ~IdivExpression()
        {
                delete m_mov;
        }
public:
        virtual void interpret(Context* text)
        {
                (text);
        }
        virtual int execute()
        {
                return m_mov->execute() / m_num;
        }
};

class ExplainStatement : public AbstractExpression
{
private:
        map<string, AbstractExpression*> m_lstExpression;
        AbstractExpression* m_execute = nullptr;
        bool m_isError = false;
public:
        ExplainStatement() {}
        ~ExplainStatement()
        {
                delete m_execute;
        }
private:
        bool isNumber(const string& str)
        {
                return (str.at(0) >= 0x30 && str.at(0) < 0x40);
        }
        void judgeCommand(const string& statement)
        {
                int replace = static_cast<int>(statement.find(" "));
                auto command = statement.substr(0, replace);
                int replace1 = static_cast<int>(statement.find(",", replace));
                string theRegister = statement.substr(replace+1, replace1-replace-1);
                string numStr = statement.substr(replace1+2, statement.size()-replace1-2);
                bool isNum = isNumber(numStr);

                int num = atoi(numStr.c_str());
                if (command == "mov")
                {
                        m_lstExpression.insert(make_pair(theRegister, new MovExpression(num)));
                }
                else 
                {
                        AbstractExpression* nextCommand = m_lstExpression[theRegister];
                        if (!nextCommand) throw "寄存器:" + theRegister + "不存在!";
                        if (!isNum)
                        {
                                auto numExp = m_lstExpression[numStr];
                                if (!numExp) throw "寄存器:" + numStr + "不存在!";
                                else num = numExp->execute();
                        }

                        if (command == "add")
                        {
                                m_execute = new AddExpression(nextCommand, num);
                        }
                        else if (command == "sub")
                        {
                                m_execute = new SubExpression(nextCommand, num);

                        }
                        else if (command == "mul")
                        {
                                m_execute = new MulExpression(nextCommand, num);

                        }
                        else if (command == "idiv")
                        {
                                m_execute = new IdivExpression(nextCommand, num);

                        }
                        m_lstExpression[theRegister] = m_execute;
                }
        }
public:
        virtual void interpret(Context* text)
        {
                while (text->HasNext())
                {
                        try
                        {
                                judgeCommand(text->NextStatement());
                        }
                        catch (string& str)
                        {
                                cout << str << endl;
                                m_isError = true;
                                break;
                        }
                }
        }
        virtual int execute()
        {
                return (m_isError ? 0 : m_execute->execute());
        }
};
  • 引用:
#include "Expressions.h"

int main()
{
        string text("mov eax, 12\nmov ebx, 15\nadd eax, 20\nsub eax, ebx\nmul eax, ebx\nidiv eax, 5");
        //string text("mov eax, 0\nadd eax, ebx\nadd eax, 12\nsub eax, 10");
        Context* context = new Context(text);
        ExplainStatement* es = new ExplainStatement;
        es->interpret(context);
        cout << "result:" << es->execute() << endl;

        getchar();
        return 0;
}

总结:
解释器模式(Interpreter):可以用于解释一些自定义的数据结构,常用于编译器、规则引擎、正则表达式等,这个设计模式的本质就是解释、解析

作者:丶梦爱
博客:https://blog.csdn.net/u014732297(转载请说明出处)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值