解释器模式
理论
解释器模式(interpreter),给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
解释器模式的应用场景:
当有一个语言需要解释执行,并且可将该语言中的句子表示为一个抽象语法树时,可使用解释器模式。
解释器模式的优点:
1. 可以很容易地改变和扩展文法,因为该模式使用类来表示文法规则,可使用继承来改变和扩展该文法。
2. 也比较容易实现文法,因为定义抽象语法树中各个节点地类地实现大体类似,这些类都易于直接编写。
解释器模式的缺点:
解释器模式为文法中地每一条规则至少定义了一个类,因此包含许多规则地文法可能难以管理和维护。建议当文法非常复杂时,使用其他技术如语法分析程序或编译器生成器来处理。
实例
实现音乐解释器,定义一套规则:
T表示速度,以毫秒为单位;
O 表示音阶, O1 表示低音阶, O2 表示中音阶, O3 表示高音阶;
P 表示休止符;
C D E F G A B 表示 “Do-Re-Mi-Fa-So-La-Ti”;
音符长度1表示一拍,2表示二拍,0.5表示半拍,0.25表示四分之一拍;
所有字母和数字都要用半角空格分开。
UML类图
代码实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 | #include <iostream> #include <sstream> #include <vector> using namespace std; //演奏内容类 class PlayContext { public : void SetText(string _text) { text = _text; } string GetText() { return text; } private : string text; }; //抽象表达式类 class Expression { public : virtual void Excute(string key, string value) = 0; void Interpret(PlayContext* context) { if (context->GetText().length() == 0) return ; else { vector<string> vs; stringstream ss(context->GetText()); //使用字符串构造一个stringstream //按空格分割字符串 string buf; while (ss >> buf) vs.push_back(buf); //解释前两个字符串 Excute(vs[0], vs[1]); //拼接剩下的字符串 string tmp; vs.erase(vs.begin(), vs.begin() + 2); for (vector<string>::iterator it = vs.begin(); it != vs.end(); it++) { tmp += *it; if (it < vs.end() - 1) tmp += " " ; } //更新字符串 context->SetText(tmp); } } }; //音符类 class Note : public Expression { public : void Excute(string key, string value) { string note = " " ; switch (key[0]) { case 'C' : note = "1" ; break ; case 'D' : note = "2" ; break ; case 'E' : note = "3" ; break ; case 'F' : note = "4" ; break ; case 'G' : note = "5" ; break ; case 'A' : note = "6" ; break ; case 'B' : note = "7" ; break ; default : break ; } cout << note << " " ; } }; //音阶类 class Scale : public Expression { public : virtual void Excute(string key, string value) { string scale = " " ; switch (value[0]) { case '1' : scale = "低音" ; break ; case '2' : scale = "中音" ; break ; case '3' : scale = "高音" ; break ; default : break ; } cout << scale << " " ; } }; //音速类 class Speed : public Expression { public : void Excute(string key, string value) { int v = stoi(value); if (v < 500) cout << "快速 " ; else if (v > 1000) cout << "慢速 " ; else cout << "中速 " ; } }; int main() { PlayContext context; cout << "上海滩: " << endl; context.SetText( "T 600 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" ); Expression* expression = NULL; while (context.GetText().length() > 0) { char str = context.GetText()[0]; switch (str) { case 'O' : expression = new Scale; break ; case 'T' : expression = new Speed; break ; case 'C' : case 'D' : case 'E' : case 'F' : case 'G' : case 'A' : case 'B' : case 'P' : expression = new Note; break ; default : break ; } expression->Interpret(&context); delete expression; } cout << endl; return 0; } |
运行结果:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧