C++解释器模式

意图

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

适用性

  • 当有一个语言需要解释执行, 并且你可将该语言中的句子表示为一个抽象语法树时,可使用解释器模式。而当存在以下情况时该模式效果最好:
  • 该文法简单对于复杂的文法, 文法的类层次变得庞大而无法管理。此时语法分析程序生成
    器这样的工具是更好的选择。它们无需构建抽象语法树即可解释表达式, 这样可以节省空间而且还可能节省时间。
  • 效率不是一个关键问题最高效的解释器通常不是通过直接解释语法分析树实现的, 而是首先将它们转换成另一种形式。例如,正则表达式通常被转换成状态机。但即使在这种情况下, 转换器仍可用解释器模式实现, 该模式仍是有用的。

模式结构

  • 抽象表达式(Abstract Expression):定义解释器的接口,约定解释器的解释操作,主要包含解释方法 interpret()。

  • 终结符表达式(Terminal Expression):是抽象表达式的子类,用来实现文法中与终结符相关的操作,文法中的每一个终结符都有一个具体终结表达式与之相对应。

  • 非终结符表达式(Nonterminal Expression):也是抽象表达式的子类,用来实现文法中与非终结符相关的操作,文法中的每条规则都对应于一个非终结符表达式。

  • 上下文(Context):通常包含各个解释器需要的数据或是公共的功能,一般用来传递被所有解释器共享的数据,后面的解释器可以从这里获取这些值。

示意性代码

#include <iostream>
#include <stack>
#include <string>
#include <unordered_map>
#include <vector>
#include <algorithm>
using namespace std;

// 抽象表达式类
class Expression {
public: 
    virtual ~Expression() { }
    virtual double interpreter(unordered_map<string, double> var) = 0;
};

// 变量解析器
class VarExpression : public Expression {
public:
    VarExpression(string key) : m_key(key) { }

    double interpreter(unordered_map<string, double> var) override {
        return var[m_key];
    }

private:
    string m_key;
};

// 抽象运算符号解析器
class SymbolExpression : public Expression {
public:
    SymbolExpression(Expression* left, Expression* right)
        : m_left(left), m_right(right) { }

    virtual double interpreter(unordered_map<string, double>) = 0;

protected:
    Expression* m_left;
    Expression* m_right;
};

// 加法解析器
class AddExpression : public SymbolExpression {
public:
    AddExpression(Expression* left, Expression* right)
        : SymbolExpression(left, right) { }

    double interpreter(unordered_map<string, double> var) override {
        return m_left->interpreter(var) + m_right->interpreter(var);
    }
};

// 减法解析器
class SubExpression : public SymbolExpression {
public:
    SubExpression(Expression* left, Expression* right)
        : SymbolExpression(left, right) { }

    double interpreter(unordered_map<string, double> var) override {
        return m_left->interpreter(var) - m_right->interpreter(var);
    }
};

// 解析器封装类
class Calculator {
public:
    Calculator(vector<string> expStr) {
        stack<Expression*> stack;
        Expression* left;
        Expression* right;
        
        for (int i = 0; i < expStr.size(); ++i) {
            if (expStr[i] == "+") { // 加法
                left = stack.top(), stack.pop();
                right = new VarExpression(expStr[++i]);
                stack.push(new AddExpression(left, right));
            } else if (expStr[i] == "-") { // 减法
                left = stack.top(), stack.pop();
                right = new VarExpression(expStr[++i]);
                stack.push(new SubExpression(left, right));
            } else { // 变量
                stack.push(new VarExpression(expStr[i]));
            }
        }

        this->m_expression = stack.top();
    }

    double run(unordered_map<string, double> var) {
        return this->m_expression->interpreter(var);
    }

private:
    // 定义表达式
    Expression* m_expression;
};

// 客户端

// 获得表达式
void getExpStr(vector<string>& expStr) {
    cout << "请输入表达式:" << endl;
    string str;
    int currentIndex = 0;
    getline(cin, str);
    string temp;
    int len = 0;
    for (int i = 0; i < str.size(); ++i) {
        switch (str[i]) {
            case '+' : 
                len = i - currentIndex;
                temp = str.substr(currentIndex, len);
                // 清楚多余的空格
                temp.erase(remove(temp.begin(), temp.end(), ' '), temp.end());
                expStr.push_back(temp);
                expStr.push_back("+");
                currentIndex = i + 1;
                break;
            case '-' :
                len = i - currentIndex;
                temp = str.substr(currentIndex, len);
                temp.erase(remove(temp.begin(), temp.end(), ' '), temp.end());
                expStr.push_back(temp);
                expStr.push_back("-");
                currentIndex = i + 1;
                break;
        }
    }
    temp = str.substr(currentIndex);
    temp.erase(remove(temp.begin(), temp.end(), ' '), temp.end());
    expStr.push_back(temp);
}

void getValue(unordered_map<string, double>& var, vector<string>& expStr) {
    for (const auto& key : expStr) {
        if (key != "+" && key != "-") {
            if (var.find(key) == var.end()) {
                cout << "请输入 " << key << " 的值:" << endl;
                cin >> var[key]; 
            }
        }
    }
}

string vector_to_string(vector<string>& expStr) {
    string str;
    for (const auto& expstr : expStr) {
        str.append(expstr);
        str.append(" ");
    }
    str.pop_back();
    return str;
}

int main() {
    vector<string> expStr;
    unordered_map<string, double> var;
    getExpStr(expStr);
    getValue(var, expStr);

    Calculator* calcutor = new Calculator(expStr);

    cout << "运算结果:" << vector_to_string(expStr) 
         << " = " << calcutor->run(var) << endl;
}

img

参考

  1. 看完就明白的解释器模式
  2. 简说设计模式——解释器模式
posted @ 2022-08-05 14:37  岁月飞扬  阅读(252)  评论(0编辑  收藏  举报