简述:
解释器模式:给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
解释器模式包括:上下文类、抽象表达式类、终结符表达式类、非终结符表达式类。
上下文类:包含解释器之外的一些全局信息。
抽象表达式类:声明一个抽象的解释操作,这个接口作为抽象语法树中所有的节点共享。
终结符表达式类:继承自抽象表达式类,实现与文法中的终结符相关联的解释操作。
非终结符表达式类:继承自抽象表达式类,为文法中的非终结符实现解释操作,对文法中每一条规则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 }
输出结果: