1、解析模式的提出
在软件开发的过程中,需要实现一种需求,该需求的结构稳定,但是需求的业务内容会频繁变化,如果使用普通语法实现需求,需要经常更新代码,不具有灵活性。可以使用解析器模式解决实现该类需求,解析器是实现一种能够解析该需求结构语法的功能代码,针对不同的业务调用对应的解析规则代码。
2、需求描述
有一个字符串的加减计算,如'a+b+c-d-e',其中a,b,c,d,e分别对应带计算的值。设计一个功能代码,可以实现该功能,且该代码可以适配不定个数的加减数运算。
3、功能实现
(1)UML图如下:
(2)代码实现如下:
#include <iostream>
#include <map>
#include <stack>
class AbsExpression
{
public:
bool isVarType = false;
public:
void setExpressionType(bool bFlag){isVarType= bFlag;};
virtual int interpreter(std::map<char,int>var)=0;
virtual ~AbsExpression(){};
};
//变量表达式
class ValExpression:public AbsExpression
{
private:
char m_key;
public:
ValExpression(const char&key)
{
std::cout << "ValExpression " << std::endl;
this->m_key = key;
setExpressionType(true);
}
int interpreter(std::map<char, int> var) override
{
return var[m_key];
}
~ValExpression()
{
std::cout << "~ValExpression " << std::endl;
}
};
//符号表达式
class SymbolExpression:public AbsExpression
{
protected:
AbsExpression* m_left;
AbsExpression* m_right;
public:
SymbolExpression(AbsExpression* left,AbsExpression* right):
m_left(left),m_right(right)
{
}
~SymbolExpression()
{
//left对象是直接取的栈容器的上一个top,故可以显式清理。
//right的new对象不会直接push进栈容器,而是做了符号实例对象的成员变量。故需要对其进行对象释放
if(m_right != nullptr)
{
delete m_right;
m_right = nullptr;
}
std::cout << "~SymbolExpression" << std::endl;
}
};
//加法运算符
class AddExpression:public SymbolExpression
{
public:
AddExpression(AbsExpression* left,AbsExpression* right):
SymbolExpression(left,right){
std::cout << "AddExpression " << std::endl;
}
int interpreter(std::map<char,int>var)
{
return m_left->interpreter(var) + m_right->interpreter(var);
}
};
//减法运算符
class SubExpression:public SymbolExpression
{
public:
SubExpression(AbsExpression* left,AbsExpression* right):
SymbolExpression(left,right){
std::cout << "SubExpression " << std::endl;
}
int interpreter(std::map<char,int>var)
{
return m_left->interpreter(var) - m_right->interpreter(var);
}
};
std::stack<AbsExpression*> analyse(std::string strLanguage){
std::stack<AbsExpression*>stackExp;
AbsExpression* left = nullptr;
AbsExpression* right = nullptr;
for(size_t i = 0; i < strLanguage.length();i++)
{
switch (strLanguage[i]) {
case '+':
{
left = stackExp.top();
right = new ValExpression(strLanguage[++i]);
stackExp.push(new AddExpression(left,right));
}break;
case '-':
{ left = stackExp.top();
right = new ValExpression(strLanguage[++i]);
stackExp.push(new SubExpression(left,right));
}break;
default:
stackExp.push(new ValExpression(strLanguage[i]));
}
}
return stackExp;
};
void release( std::stack<AbsExpression*> exp)
{
while (exp.size() > 0) {
AbsExpression* it = exp.top();
delete it;
it = nullptr;
exp.pop();
}
std::cout << "clear exp finshed " << std::endl;
}
class Client
{
public:
void doWork()
{
std::string str = "a+b+c-d";
std::map<char,int>mapVar;
mapVar.insert(std::make_pair('a',1));
mapVar.insert(std::make_pair('b',2));
mapVar.insert(std::make_pair('c',3));
mapVar.insert(std::make_pair('d',4));
std::stack<AbsExpression*> exp = analyse(str);
int ret = exp.top()->interpreter(mapVar);
std::cout << "ret is " << ret << std::endl;
release(exp);
}
};
int main()
{
Client obj;
obj.doWork();
return 0;
}
运行结果如下:
注意:解析器适用于比较简单的语法解析,对于复杂的语法,可以使用语法分析生成器工具,具体的语法分析生成器用法可自行搜索查看。