领域规则模式(解析器)

领域规则模式
在特定领域中,某些变化虽然频繁,但可以抽象为某种规则。这时候,结合特定领域,将问题抽象为语法规则,从而给出在该领域下的一般性解决方案。
属于领域规则模式的有Interpreter

class Expression{
public:
    virtual int interpreter(map<char, int> var) = 0;
    virtual ~Expression() {}
};

// 变量表达式
class VarExpression : public Expression{
    char key;
public:
    VarExpression(const char &key){
        this->key = key;
    }

    int interpreter(map<char, int> var) override{
        return var[key];
    }
}

// 符号表达式
class SymbolExpression : public Expression{
protected:
    Expression *left;
    Expression *right;

public:
    SymbolExpression(Expression *x, Expression *y) : left(x), right(y) {}
}

class AddExpression : public SymbolExpression {
public:
    AddExpression(Expression *x, Expression *y) : SymbolExpression(x,y) {}

    int interpreter(map<char, int> var){
        return left->interpreter(var) + right->interpreter(var);
    }
}

class SubExpression : public SymbolExpression{
public:
    SubExpression(Expression *x, Expression *y) : SymbolExpression(x,y) {}

    int interpreter(map<char, int> var){
        return left->interpreter(var) - right->interpreter(var);
    }
};

Expression *analyse(string expStr){
    stack<Expression *> expStack; // 这里的栈操作属实没什么意义,只要保留一份最顶上的元素即可。
    Expression *left = nullptr;
    Expression *right = nullptr;
    for(int i = 0; i < expStr.size(); ++i){
        switch( expStr[i] ){
            case '+':
                left = expStack.top();
                right = new VarExpression(expStr[++i]);
                expStack.push(new AddExpression(left, right) );
                break;
            case '-':
                left = expStack.top();
                right = new VarExpression(expStr[++i]);
                expStack.push(new SubExpressionn(left, right) );
                break;
            default:
                expStack.push(new VarExpression(expStr[i]));
        }
    }
    Expression *expression = expStack.top();
    return expression;
}

void release(Expression *exp){
    // 释放表达式树的节点内存
}

int main(){
    string expStr = "a+b-c+d"; // 这个可以任意加减下去 
    map<char, int> var;
    var.insert(make_pair('a', 5) );
    var.insert(make_pair('b', 2) );
    var.insert(make_pair('c', 1) );
    var.insert(make_pair('d', 6) );

    Expression *expression = analyse(expStr);   // 构建表达式树,并返回根节点
    int result = expression->interpreter(var);  // 根节点开始解析,会使用后序遍历的方式计算结果。
    cout << result << endl;
}

要点总结:
– Interpreter模式的应用场合是Interpreter模式应用中的难点,只有满足“业务规则频繁变化,且类似的结构不断重复出现,并且容易抽象为语法规则的问题”才适合使用Interpreter模式
– 使用Interpreter模式来表示文法规则,从而可以使用面向对象技巧来方便地“扩展”文法
– Interpreter模式比较适合简单的文法表示,对于复杂的文法表示,Interpreter模式会产生比较大的类层次结构,需要求助于语法分析生成器这样的标准工具

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注