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

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

前言

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

实现举例

  1. 场景描述
    输入一个四则运算的字符串,比如:a-10+b*(c+5) ,解析并返回计算结果。
  2. 表达式抽象基类
#include 
#include 
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 
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 
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 
#include 
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. 客户端调用
    设计模式的 C++ 实现---解释器模式_第1张图片
#include "calculator.h"

#include 
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();
}

你可能感兴趣的:(设计模式,设计模式,c++,字符串)