023 --- 第27章 解释器模式

简述:

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

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

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

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

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

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

 

应用场景:定义一种语言,定义一种解释其文法的解释器,将复杂问题简单化

 

注:开发环境调整为VS2017,操作系统win11

解释器模式:

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

 

输出结果:

 

posted @ 2020-09-11 10:32  二是一种不三不亖的范  阅读(127)  评论(0编辑  收藏  举报