设计模式的 C++ 实现---解释器模式

前文回顾
单例模式(一)
单例模式(二)
观察者模式
简单工厂模式
工厂方法模式(一)
工厂方法模式(二)
抽象工厂模式(一)
抽象工厂模式(二)
原型模式
外观模式
中介者模式
代理模式
装饰者模式
策略模式
状态模式
命令模式
建造者模式
桥接模式

前言

解释器模式的本质就是把一个依据确定规则组成的一个字符串翻译为计算机可执行的语句。

实现举例

  1. 场景描述
    输入一个四则运算的字符串,比如:a-10+b*(c+5) ,解析并返回计算结果。
  2. 表达式抽象基类
#include <string>
#include <iostream>
using namespace std;
class Context;
class Expression
{
public:
    virtual ~Expression(){}
    virtual double interpret(Context *ctx) = 0;
    virtual void display(Context *ctx) = 0;
};
  1. 变量表达式
#include "expression.h"

class Variable : public Expression
{
public:
    Variable(const string &m_name):virname(m_name){}
    virtual double interpret(Context *ctx) override;
    string getName() const { return  virname ;}
    void display(Context *ctx) override;

private:
    string virname;//变量名称
};

#include "variable.h"
#include "context.h"

double Variable::interpret(Context *ctx)
{
    return ctx->lookUpValue(this->virname);
}

void Variable::display(Context *ctx)
{
    cout << ctx->lookUpValue(this->virname);
}

  1. 解析字典类
#include "variable.h"
#include <map>
using namespace std;

class Context
{
public:
    void registerVariable(string var,double value)
    {
        m_map.insert(make_pair(var,value));
    }
    double lookUpValue(string var )
    {
        auto iter = m_map.find(var);
        if( iter != m_map.end() )
        {
            return  iter->second;
        }
        return  0;
    }
    bool findVariable(string var)
    {
        auto iter = m_map.find(var);
        if( iter != m_map.end() )
        {
            return  true;
        }
        return  false;
    }
private:
    map<string ,double> m_map;
};

  1. 常量表达式
#include "expression.h"

class Constant : public Expression
{
public:
    Constant(double value):m_value(value){}
    double interpret(Context *) override
    {
        return  m_value;
    }
    void display(Context *) override
    {
        cout << m_value;
    }
private:
    double m_value;
};
  1. 二元表达式
    ①.二元表达式基类
#include "expression.h"
#include "memory"
using namespace std;

class BinaryExpression : public Expression
{
public:
    BinaryExpression(shared_ptr<Expression> left,shared_ptr<Expression> right):leftExpression(left),rightExpression(right){}
protected:
    shared_ptr<Expression> leftExpression;
    shared_ptr<Expression> rightExpression;
};

②.加法表达式类

#include "binaryexpression.h"

class AddBinaryExpression : public BinaryExpression
{
public:
    using BinaryExpression::BinaryExpression;
    double interpret(Context *ctx) override
    {
        return leftExpression->interpret(ctx) + rightExpression->interpret(ctx);
    }
    void display(Context * ctx) override
    {
        leftExpression->display(ctx);
        cout << "+";
        rightExpression->display(ctx);
    }
};

③.减法表达式类

#include "binaryexpression.h"

class SubBinaryExpression : public BinaryExpression
{
public:
    using BinaryExpression::BinaryExpression;
    double interpret(Context *ctx) override
    {
        return leftExpression->interpret(ctx) - rightExpression->interpret(ctx);
    }
    void display(Context * ctx) override
    {
        leftExpression->display(ctx);
        cout << "-";
        rightExpression->display(ctx);
    }
};

④.乘法表达式类

#include "binaryexpression.h"


class MulBinaryExpression : public BinaryExpression
{
public:
    using BinaryExpression::BinaryExpression;
    double interpret(Context *ctx) override
    {
        return leftExpression->interpret(ctx) * rightExpression->interpret(ctx);
    }
    void display(Context * ctx) override
    {
        leftExpression->display(ctx);
        cout << "*";
        rightExpression->display(ctx);
    }
};

⑤.除法表达式类

#include "binaryexpression.h"

class DivBinaryExpression : public BinaryExpression
{
public:
    using BinaryExpression::BinaryExpression;
    double interpret(Context *ctx) override
    {
        return leftExpression->interpret(ctx) / rightExpression->interpret(ctx);
    }
    void display(Context * ctx) override
    {
        leftExpression->display(ctx);
        cout << "/";
        rightExpression->display(ctx);
    }
};

  1. 一元表达式
    ①.一元表达式基类
#include "expression.h"
#include <memory>
using namespace std;

class UnaryExpression : public Expression
{
public:
    UnaryExpression(shared_ptr<Expression> expression):mExpression(expression){}
protected:
    shared_ptr<Expression> mExpression;
};

②.正运算类

#include "unaryexpression.h"

class PositiveUnaryExpression : public UnaryExpression
{
public:
    using UnaryExpression::UnaryExpression;
    double interpret(Context *ctx) override
    {
        return  mExpression->interpret(ctx);
    }
    void display(Context * ctx) override
    {
        cout << "+";
        mExpression->display(ctx);
    }
};

③.负运算类

#include "unaryexpression.h"


class NegativeUnaryExpression : public UnaryExpression
{
public:
    using UnaryExpression::UnaryExpression;
    double interpret(Context *ctx) override
    {
        return - mExpression->interpret(ctx);
    }
    void display(Context * ctx) override
    {
        cout << "-";
        mExpression->display(ctx);
    }
};

  1. 解析类
#include "context.h"
#include <string>
#include <memory>
using namespace std;

class Expression;
class Calculator
{
public:
    Calculator(const string &expression,shared_ptr<Context> &contex):m_expression(expression),m_contex(contex){}
    bool  getCalculatorResult(double &result,string &error);


private:
    string m_expression;//要解析的表达式
    int curIndex =0;//当前解析到的位置
    shared_ptr<Context> m_contex;//解析字典

    bool ReadConstant(shared_ptr<Expression> &exp);//读取一个常量数字
    bool ReadVariable(shared_ptr<Expression> &exp);//读取一个变量
    bool ReadOperator(const char & oper);//读取一个操作符
    bool ReadExpression(shared_ptr<Expression> &exp,string &error);//读取一个表达式
    bool ReadFactor(shared_ptr<Expression> &exp,string &error);//读取一个优先计算的独立表达式
    bool ReadIterm(shared_ptr<Expression> &exp,string &error);//读取一个独立项


};

#include "calculator.h"
#include "expression.h"
#include "addbinaryexpression.h"
#include "subbinaryexpression.h"
#include "mulbinaryexpression.h"
#include "divbinaryexpression.h"
#include "positiveunaryexpression.h"
#include "negativeunaryexpression.h"
#include "constant.h"
#include "variable.h"


bool Calculator:: getCalculatorResult(double &result,string &error)
{
    //删除开头空格
    m_expression.erase(0,m_expression.find_first_not_of(" "));

    shared_ptr<Expression> exp;
    if( ReadExpression(exp,error))
    {
       cout << "表达式解析为:";
       exp->display(m_contex.get()) ;
       cout << endl;
       result = exp->interpret(m_contex.get());
       return  true;
    }
    return false;
}

bool Calculator::ReadConstant(shared_ptr<Expression> &exp)
{
    bool readNum = false;
    bool readPoint = false;
    string resDouble = "";
    for( ;curIndex< (int)m_expression.size();++curIndex)
    {
        if( m_expression[curIndex] >= '0' && m_expression[curIndex] <= '9')
        {
            readNum = true;
            resDouble.push_back(m_expression[curIndex]);
        }
        else if( m_expression[curIndex] == '.')
        {
            if(readNum && !readPoint)
            {
                readPoint = true;
                resDouble.push_back(m_expression[curIndex]);
            }
            else
                break;
        }
        else
        {
            break;
        }
    }
    if( resDouble != "")
    {
        exp = make_shared<Constant>(atof(resDouble.c_str()));
        return true;
    }
    return false;
}

bool Calculator::ReadExpression(shared_ptr<Expression> &resultFactor,string &error)
{
    shared_ptr<Expression> nextFactor;
    bool isok = true;
    if( ReadFactor(resultFactor,error))//读取到了一个优先计算的独立表达式
    {
        while(true)//循环读取
        {
            if(curIndex < (int)m_expression.size() )
            {
                if( ReadOperator('+'))
                {
                    if( ReadFactor(nextFactor,error))
                        resultFactor = make_shared<AddBinaryExpression>(resultFactor,nextFactor);
                    else//读取下一项失败
                    {
                        isok = false;
                        break;
                    }
                }
                else  if( ReadOperator('-'))
                {
                    if( ReadFactor(nextFactor,error))
                        resultFactor = make_shared<SubBinaryExpression>(resultFactor,nextFactor);
                    else//读取下一项失败
                    {
                        isok = false;
                        break;
                    }
                }
                else break;
            }
            else break;
        }
    }
    else//读取失败
    {
        isok = false;
    }
    return isok;

}

bool Calculator::ReadFactor(shared_ptr<Expression> &resultIterm,string &error)
{
    shared_ptr<Expression> nextIterm;
    bool isok = true;
    if( ReadIterm(resultIterm,error))
    {
        while(true)
        {
            if(curIndex < (int)m_expression.size() )
            {
                if(ReadOperator('*'))
                {
                    if(ReadIterm(nextIterm,error))
                        resultIterm = make_shared<MulBinaryExpression>(resultIterm,nextIterm);
                    else
                    {
                        isok = false;
                        break;
                    }
                }
                else if(ReadOperator('/'))
                {
                    if(ReadIterm(nextIterm,error))
                        resultIterm = make_shared<DivBinaryExpression>(resultIterm,nextIterm);
                    else
                    {
                        isok = false;
                        break;
                    }
                }
                else  break;
            }
            else break;
        }
    }
    else
    {
        isok = false;
    }
    return  isok;
}

bool Calculator::ReadIterm(shared_ptr<Expression> &exp,string &error)
{
    bool isok = true;
    if(ReadConstant(exp)) {} //读取到一个常量数字
    else if ( ReadVariable(exp)) { }
    else if( ReadOperator('('))//读到左括号
    {
        if(  ReadExpression(exp,error) )
        {
            if(!ReadOperator(')'))
            {
                error = "解析失败:在位置:"+to_string(curIndex)+" 没有解析到右括号";
                isok = false;
            }
        }
        else
            isok = false;
    }
    else if( ReadOperator('+'))
    {
        shared_ptr<Expression> nextFactor;
        if( ReadFactor(nextFactor,error))
        {
            exp = make_shared<PositiveUnaryExpression>(nextFactor);
        }
        else
            isok = false;
    }
    else if(ReadOperator('-'))
    {
        shared_ptr<Expression> nextFactor;
        if( ReadFactor(nextFactor,error))
        {
            exp = make_shared<NegativeUnaryExpression>(nextFactor);
        }
        else
            isok = false;
    }
    else
    {
        isok = false;
        error = "解析失败:位置:"+to_string(curIndex)+" 无法解析";
    }
    return isok;
}

bool Calculator::ReadVariable(shared_ptr<Expression> &exp)
{
    string temp;
    temp.push_back(m_expression[curIndex]);
    shared_ptr<Variable> var(new Variable(temp));
    if(m_contex->findVariable(temp))
    {
        exp = var;
        curIndex++;
        return true;
    }
    return  false;
}

bool Calculator::ReadOperator(const char &oper)
{
    if( m_expression[curIndex] == oper)
    {
        curIndex++;
    }
    else
    {
        return  false;
    }
    return true;
}

  1. 客户端调用
    在这里插入图片描述
#include "calculator.h"

#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    string expression = "a-10+b*(c+5)";

    shared_ptr<Context> context(new Context() );

    context->registerVariable("a",10);
    context->registerVariable("b",200);
    context->registerVariable("c",5);
    context->registerVariable("d",20);

    Calculator * calculator = new  Calculator(expression,context);
    string error;
    double result;
    calculator->getCalculatorResult(result,error);
    cout << "计算结果为:"<<result;


    return a.exec();
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值