• 设计模式之解析器(Interpreter)的C++实现


    1、解析模式的提出

    在软件开发的过程中,需要实现一种需求,该需求的结构稳定,但是需求的业务内容会频繁变化,如果使用普通语法实现需求,需要经常更新代码,不具有灵活性。可以使用解析器模式解决实现该类需求,解析器是实现一种能够解析该需求结构语法的功能代码,针对不同的业务调用对应的解析规则代码。

    2、需求描述

    有一个字符串的加减计算,如'a+b+c-d-e',其中a,b,c,d,e分别对应带计算的值。设计一个功能代码,可以实现该功能,且该代码可以适配不定个数的加减数运算。

    3、功能实现

    (1)UML图如下:

     (2)代码实现如下:

    1. #include
    2. #include
    3. #include
    4. class AbsExpression
    5. {
    6. public:
    7. bool isVarType = false;
    8. public:
    9. void setExpressionType(bool bFlag){isVarType= bFlag;};
    10. virtual int interpreter(std::map<char,int>var)=0;
    11. virtual ~AbsExpression(){};
    12. };
    13. //变量表达式
    14. class ValExpression:public AbsExpression
    15. {
    16. private:
    17. char m_key;
    18. public:
    19. ValExpression(const char&key)
    20. {
    21. std::cout << "ValExpression " << std::endl;
    22. this->m_key = key;
    23. setExpressionType(true);
    24. }
    25. int interpreter(std::map<char, int> var) override
    26. {
    27. return var[m_key];
    28. }
    29. ~ValExpression()
    30. {
    31. std::cout << "~ValExpression " << std::endl;
    32. }
    33. };
    34. //符号表达式
    35. class SymbolExpression:public AbsExpression
    36. {
    37. protected:
    38. AbsExpression* m_left;
    39. AbsExpression* m_right;
    40. public:
    41. SymbolExpression(AbsExpression* left,AbsExpression* right):
    42. m_left(left),m_right(right)
    43. {
    44. }
    45. ~SymbolExpression()
    46. {
    47. //left对象是直接取的栈容器的上一个top,故可以显式清理。
    48. //right的new对象不会直接push进栈容器,而是做了符号实例对象的成员变量。故需要对其进行对象释放
    49. if(m_right != nullptr)
    50. {
    51. delete m_right;
    52. m_right = nullptr;
    53. }
    54. std::cout << "~SymbolExpression" << std::endl;
    55. }
    56. };
    57. //加法运算符
    58. class AddExpression:public SymbolExpression
    59. {
    60. public:
    61. AddExpression(AbsExpression* left,AbsExpression* right):
    62. SymbolExpression(left,right){
    63. std::cout << "AddExpression " << std::endl;
    64. }
    65. int interpreter(std::map<char,int>var)
    66. {
    67. return m_left->interpreter(var) + m_right->interpreter(var);
    68. }
    69. };
    70. //减法运算符
    71. class SubExpression:public SymbolExpression
    72. {
    73. public:
    74. SubExpression(AbsExpression* left,AbsExpression* right):
    75. SymbolExpression(left,right){
    76. std::cout << "SubExpression " << std::endl;
    77. }
    78. int interpreter(std::map<char,int>var)
    79. {
    80. return m_left->interpreter(var) - m_right->interpreter(var);
    81. }
    82. };
    83. std::stack analyse(std::string strLanguage){
    84. std::stackstackExp;
    85. AbsExpression* left = nullptr;
    86. AbsExpression* right = nullptr;
    87. for(size_t i = 0; i < strLanguage.length();i++)
    88. {
    89. switch (strLanguage[i]) {
    90. case '+':
    91. {
    92. left = stackExp.top();
    93. right = new ValExpression(strLanguage[++i]);
    94. stackExp.push(new AddExpression(left,right));
    95. }break;
    96. case '-':
    97. { left = stackExp.top();
    98. right = new ValExpression(strLanguage[++i]);
    99. stackExp.push(new SubExpression(left,right));
    100. }break;
    101. default:
    102. stackExp.push(new ValExpression(strLanguage[i]));
    103. }
    104. }
    105. return stackExp;
    106. };
    107. void release( std::stack exp)
    108. {
    109. while (exp.size() > 0) {
    110. AbsExpression* it = exp.top();
    111. delete it;
    112. it = nullptr;
    113. exp.pop();
    114. }
    115. std::cout << "clear exp finshed " << std::endl;
    116. }
    117. class Client
    118. {
    119. public:
    120. void doWork()
    121. {
    122. std::string str = "a+b+c-d";
    123. std::map<char,int>mapVar;
    124. mapVar.insert(std::make_pair('a',1));
    125. mapVar.insert(std::make_pair('b',2));
    126. mapVar.insert(std::make_pair('c',3));
    127. mapVar.insert(std::make_pair('d',4));
    128. std::stack exp = analyse(str);
    129. int ret = exp.top()->interpreter(mapVar);
    130. std::cout << "ret is " << ret << std::endl;
    131. release(exp);
    132. }
    133. };
    134. int main()
    135. {
    136. Client obj;
    137. obj.doWork();
    138. return 0;
    139. }

    运行结果如下:

    注意:解析器适用于比较简单的语法解析,对于复杂的语法,可以使用语法分析生成器工具,具体的语法分析生成器用法可自行搜索查看。

  • 相关阅读:
    高级数据结构:最小生成树及普里姆算法
    06-kafka及异步通知文章上下架
    c语言实现数据结构中的带头双向循环链表
    2017年亚太杯APMCM数学建模大赛B题喷雾轨迹规划问题求解全过程文档及程序
    【2022国赛模拟】相似序列问题——DFA(DP套DP)
    Nginx搭建RTMP流媒体服务器(Ubuntu18.04)
    Minecraft 1.18.1、1.18.2模组开发 22.狙击枪(Sniper Rifle)
    .NET开源的一个小而快并且功能强大的 Windows 动态桌面软件 - DreamScene2
    【Proteus】:LCD1602仿真实验基于STM32CubeMX
    (标签-机器学习|关键词-set)
  • 原文地址:https://blog.csdn.net/hanxiaoyong_/article/details/132940807