zoukankan      html  css  js  c++  java
  • 023 --- 第27章 解释器模式

    简述:

      解释器模式:给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。

      解释器模式包括:上下文类、抽象表达式类、终结符表达式类、非终结符表达式类。

        上下文类:包含解释器之外的一些全局信息。

        抽象表达式类:声明一个抽象的解释操作,这个接口作为抽象语法树中所有的节点共享。

        终结符表达式类:继承自抽象表达式类,实现与文法中的终结符相关联的解释操作。

        非终结符表达式类:继承自抽象表达式类,为文法中的非终结符实现解释操作,对文法中每一条规则R1、R2……RN都需要一个具体的非终结符表达式类。

    解释器模式:

     1 #include <iostream>
     2 #include <list>
     3 using namespace std;
     4 
     5 // 上下文类
     6 class CContext
     7 {
     8 private:
     9     string m_szInput;
    10     string m_szOutPut;
    11 
    12 public:
    13     void SetInput(string szInput) { m_szInput = szInput; }
    14 
    15     string GetInput() { return m_szInput; }
    16 
    17     void SetOutPut(string szOutPut) { m_szOutPut = szOutPut; }
    18 
    19     string GetOutPut() { return m_szOutPut; }
    20 
    21 };
    22 
    23 // 抽象表达式类
    24 class CAbstractExpression
    25 {
    26 public:
    27     virtual void Interpret(CContext* pContext) = 0;
    28 };
    29 
    30 // 终结符表达式类
    31 class CTerminalExpression : public CAbstractExpression
    32 {
    33 public:
    34     virtual void Interpret(CContext* pContext) { cout << "终端解释器" << endl; }
    35 };
    36 
    37 // 非终结符表达式类
    38 class CNonterminalExpression : public CAbstractExpression
    39 {
    40 public:
    41     virtual void Interpret(CContext* pContext) { cout << "非终端解释器" << endl; }
    42 };
    43 
    44 int main()
    45 {
    46     CContext Context;
    47     list<CAbstractExpression*> list;
    48     CTerminalExpression TerminalExpression1;
    49     list.push_back(&TerminalExpression1);
    50     CNonterminalExpression NonterminalExpression;
    51     list.push_back(&NonterminalExpression);
    52     CTerminalExpression TerminalExpression2;
    53     list.push_back(&TerminalExpression2);
    54     CTerminalExpression TerminalExpression3;
    55     list.push_back(&TerminalExpression3);
    56 
    57     for (auto Expression : list)
    58         Expression->Interpret(&Context);
    59 
    60     system("pause");
    61     return 0;
    62 }

    输出结果:

    例:音乐解释器

    代码如下:

      1 #include <iostream>
      2 #include <list>
      3 using namespace std;
      4 
      5 // 演奏内容(上下文类)
      6 class CPlayContext
      7 {
      8 private:
      9     string m_szText; // 演奏文本
     10 
     11 public:
     12     void SetText(string szText) { m_szText = szText; }
     13 
     14     string GetText()
     15     { return m_szText; }
     16 };
     17 
     18 // 抽象表达式类
     19 class CExpression
     20 {
     21 public:
     22     // 解释器
     23     void Interpret(CPlayContext* pContext)
     24     {
     25         if (pContext->GetText().length() == 0)
     26             return;
     27         else
     28         {
     29             string szPlayKey = pContext->GetText().substr(0, 1);
     30             char cKey = szPlayKey[0];
     31             pContext->SetText(pContext->GetText().substr(2));
     32             double fPlayValue = atof(pContext->GetText().substr(0, pContext->GetText().find_first_of(' ')).c_str());
     33             pContext->SetText(pContext->GetText().substr(pContext->GetText().find_first_of(' ') + 1));
     34         
     35             Excute(cKey, fPlayValue);
     36         }
     37     }
     38 
     39     // 执行
     40     virtual void Excute(char szKey, double fValue) = 0;
     41 };
     42 
     43 // 音符类(终结符表达式类)
     44 class CNote : public CExpression
     45 {
     46     void Excute(char cKey, double fValue)
     47     {
     48         int nNote = 0;
     49 
     50         switch (cKey)
     51         {
     52         case 'C':
     53             nNote = 1;
     54             break;
     55         case 'D':
     56             nNote = 2;
     57             break;
     58         case 'E':
     59             nNote = 3;
     60             break;
     61         case 'F':
     62             nNote = 4;
     63             break;
     64         case 'G':
     65             nNote = 5;
     66             break;
     67         case 'A':
     68             nNote = 6;
     69             break;
     70         case 'B':
     71             nNote = 7;
     72             break;
     73         }
     74         cout << nNote << " ";
     75     }
     76 };
     77 
     78 // 音阶类(终结符表达式类)
     79 class CScale : public CExpression
     80 {
     81 public:
     82     void Excute(char cKey, double fValue)
     83     {
     84         string m_szScale;
     85 
     86         switch ((int)fValue)
     87         {
     88         case 1:
     89             m_szScale = "低音";
     90             break;
     91         case 2:
     92             m_szScale = "中音";
     93             break;
     94         case 3:
     95             m_szScale = "高音";
     96             break;
     97         }
     98         cout << m_szScale << " ";
     99     }
    100 };
    101 
    102 // 音速类(终结符表达式类)
    103 class CSpeed : public CExpression
    104 {
    105 public:
    106     void Excute(char cKey, double fValue)
    107     {
    108         string m_szSpeed;
    109 
    110         if (fValue < 500)
    111             m_szSpeed = "快速";
    112         else if(fValue >= 1000)
    113             m_szSpeed = "慢速";
    114         else
    115             m_szSpeed = "中速";
    116 
    117         cout << m_szSpeed << " ";
    118     }
    119 };
    120 
    121 // 缺少非终结符表达式的子类,如果做到不改动客户端,C#可以用简单工厂加反射,C++可以用动态创建对象等技术,之前有写,这里就没有重复写
    122 
    123 int main()
    124 {
    125     CPlayContext Context;
    126     CScale Scale;
    127     CNote Note;
    128     CSpeed Speed;
    129     // 音乐-上海滩
    130     cout << "上海滩:" << endl;
    131     Context.SetText("T 500 O 2 E 0.5 G 0.5 A 3 E 0.5 G 0.5 D 3 E 0.5 G 0.5 A 0.5 O 3 C 1 O 2 A 0.5 G 1 C 0.5 E 0.5 D 3");
    132 
    133     CExpression* pExpression = NULL;
    134     try
    135     {
    136         while (Context.GetText().length() > 0)
    137         {
    138             char c = Context.GetText().substr(0, 1)[0];
    139             switch (c)
    140             {
    141             case 'O':
    142                 pExpression = &Scale;
    143                 break;
    144             case 'T':
    145                 pExpression = &Speed;
    146                 break;
    147             case 'C':
    148             case 'D':
    149             case 'E':
    150             case 'G':
    151             case 'A':
    152             case 'B':
    153             case 'P':
    154                 pExpression = &Note;
    155                 break;
    156             default:
    157                 cout << endl << "播放完成" << endl;
    158                 system("pause");
    159                 return 0;
    160             }
    161             pExpression->Interpret(&Context);
    162         }
    163     }
    164     catch (exception ex)
    165     {
    166         cout << ex.what() << endl; // 第19次取出长度错误,所以报错
    167     }
    168 
    169     system("pause");
    170     return 0;
    171 }

    输出结果:

  • 相关阅读:
    数据统计
    判断文件是否改变
    多列表统计之后的数组排序
    被弃用的php函数以及被那个代替
    curl数据采集
    MySQL教程
    使用多次join数据重复的问题
    ThinkPHP5高阶实战教程 --诠释为API开发而生
    SpringBoot使用thymeleaf模板
    SpringBoot与JPA
  • 原文地址:https://www.cnblogs.com/SmallAndGreat/p/13650267.html
Copyright © 2011-2022 走看看