解析器模式提供了评估语言的语法或表达式的方式。这种模式实现了一个表达式接口,该接口解释一个特定的上下文,这种模式被用在SQL解析、符号处理引擎等。
1. 介绍
意图:给定一个怨言,定义它的文法表示,并定义一个解析器,这个解析器使用该标识来解析语言中的句子。
主要解决:对于一些固定文法构建一个解析句子的解析器。
何时使用:如果一种特定类型的额问题发生的评率足够高,那么可能就值得将该问题的各个实例表述为一个简单语言中的句子。这样就可以构建一个解析器,该解析器通过解析这些句子来解决问题。
如何解决:构建语法书,定义终结符和非终结符。
关键代码:构建环境类,包含解析器之外的一些全局信息,一般是hashmap。
应用实例:编译器、运算表达式计算。
优点:1、可扩展性比较好,灵活。 2、增加了新的解释表达式的方式。 3、易于实现简单文法。
缺点: 1、可利用场景比较少。 2、对于复杂的文法比较难维护。 3、解释器模式会引起类膨胀。 4、解释器模式采用递归调用方法。
使用场景: 1、可以将一个需要解释执行的语言中的句子表示为一个抽象语法树。 2、一些重复出现的问题可以用一种简单的语言来进行表达。 3、一个简单语法需要解释的场景。
注意事项:可利用场景比较少,JAVA 中如果碰到可以用 expression4J 代替。
2. 实例
2.1. C++实现
using std::string;
using std::stack;
class DPExpression {
public:
virtual int interpret(string value) = 0;
};
// 变量解析:就是把 "1111" --> 1111
class DPValExpression : public DPExpression {
string _value;
public:
DPValExpression(string value);
public:
int interpret(string value);
};
/*
下面两个就是计算符号的解析
*/
class DPAddExpression : public DPExpression {
DPExpression* _leftExpression;
DPExpression* _rightExpression;
public:
DPAddExpression(DPExpression* leftExpression, DPExpression* rightExpression);
virtual int interpret(string value);
};
class DPSubExpression : public DPExpression {
DPExpression* _leftExpression;
DPExpression* _rightExpression;
public:
DPSubExpression(DPExpression* leftExpression, DPExpression* rightExpression);
virtual int interpret(string value);
};
class DPExpressionProduct {
stack<DPExpression*> expressionStack;
void splitString(string inValue, string* outValue, size_t* index);
public:
DPExpression* ctrateExpression(string value);
};
int main() {
string value = "1000+100+10+1-111";
DPExpressionProduct product;
DPExpression* expression = product.ctrateExpression(value);
int res = expression->interpret(value); // 完成计算
return 0;
}
加减法解析器
#include <iostream>
#include <map>
#include <stack>
using namespace std;
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* left, Expression* right):
left(left),right(right){
}
};
//加法运算
class AddExpression : public SymbolExpression {
public:
AddExpression(Expression* left, Expression* right):
SymbolExpression(left,right){
}
int interpreter(map<char, int> var) override {
return left->interpreter(var) + right->interpreter(var);
}
};
//减法运算
class SubExpression : public SymbolExpression {
public:
SubExpression(Expression* left, Expression* right):
SymbolExpression(left,right){
}
int interpreter(map<char, int> var) override {
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 SubExpression(left, right));
break;
default:
// 变量表达式
expStack.push(new VarExpression(expStr[i]));
}
}
Expression* expression = expStack.top();
return expression;
}
void release(Expression* expression){
//释放表达式树的节点内存...
}
int main(int argc, const char * argv[]) {
string expStr = "a+b-c+d-e";
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));
var.insert(make_pair('e',10));
Expression* expression= analyse(expStr);
int result=expression->interpreter(var);
cout<<result<<endl;
release(expression);
return 0;
}