解析器模式(Interpreter)定义
给定一个语言,定义它的文法的一种表示,并定义一种解释器,这个解释器使用该表示来解析语言中的句子。
解析器模式结构图
示例代码
#include <map>
#include <stack>
#include <iostream>
using namespace std;
//AbstractExpression 定义一个抽象表达式
class Expression
{
public:
virtual int Interpreter(std::map<char, int>) = 0; //运算操作接口
virtual ~Expression() {}
};
//变量表达式
class VarExpression : public Expression
{
public:
VarExpression(const char& key)
{
this->sKey = key;
}
int Interpreter(std::map<char, int> var)
{
return var[sKey];
}
private:
char sKey;
};
//符号表达式
class SymbolExpression : public Expression
{
protected:
Expression* m_left = nullptr;
Expression* m_right = nullptr;
public:
SymbolExpression(Expression* left, Expression* right) :
m_left(left), m_right(right)
{
}
};
//加法运算
class AddExpression : public SymbolExpression
{
public:
AddExpression(Expression* left, Expression* right) :
SymbolExpression(left, right)
{
}
int Interpreter(std::map<char, int> var)
{
return m_left->Interpreter(var) + m_right->Interpreter(var);
}
};
//减法运算
class SubExpression : public SymbolExpression
{
public:
SubExpression(Expression* left, Expression* right) :
SymbolExpression(left, right)
{
}
int Interpreter(std::map<char, int> var)
{
return m_left->Interpreter(var) - m_right->Interpreter(var);
}
};
//表达式解析
Expression* analyse(std::string expStr)
{
stack<Expression*> sk;
Expression* left = nullptr;
Expression* right = nullptr;
for (int i = 0; i < (int)expStr.size(); i++)
{
switch (expStr[i])
{
case '+':
{
left = sk.top();
right = new VarExpression(expStr[++i]);
sk.push(new AddExpression(left, right));
}
break;
case '-':
{
left = sk.top();
right = new VarExpression(expStr[++i]);
sk.push(new SubExpression(left, right));
}
break;
default:
sk.push(new VarExpression(expStr[i]));
break;
}
}
Expression* expression = sk.top();
return expression;
}
int main()
{
std::string str = "a+b-c";
std::map<char, int> var;
var.insert(std::make_pair('a', 7));
var.insert(std::make_pair('b', 3));
var.insert(std::make_pair('c', 6));
Expression* expression = analyse(str);
int i = expression->Interpreter(var);
cout << i << endl;
//作释放操作
system("pause");
return 0;
}
输出结果:
4
个人总结
1) 可以将一个需要执行语言中的句子表示为一个抽象的语法树;
2) 用于表示语法规则,可以使面向对象技巧来方便的扩展文法。对于复杂的文法,需要借助语法分析生成器;
解释器模式缺点
由于大量使用了循环和递归,使得复杂语句的执行效率比较慢,操作起来比较复杂。