在软件开发的过程中,需要实现一种需求,该需求的结构稳定,但是需求的业务内容会频繁变化,如果使用普通语法实现需求,需要经常更新代码,不具有灵活性。可以使用解析器模式解决实现该类需求,解析器是实现一种能够解析该需求结构语法的功能代码,针对不同的业务调用对应的解析规则代码。
有一个字符串的加减计算,如'a+b+c-d-e',其中a,b,c,d,e分别对应带计算的值。设计一个功能代码,可以实现该功能,且该代码可以适配不定个数的加减数运算。
(1)UML图如下:
(2)代码实现如下:
- #include
- #include
- #include
-
- 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
analyse(std::string strLanguage) { - std::stack
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
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
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;
- }
运行结果如下:
注意:解析器适用于比较简单的语法解析,对于复杂的语法,可以使用语法分析生成器工具,具体的语法分析生成器用法可自行搜索查看。