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 }
输出结果: