简介
给定⼀个语⾔,定义它的⽂法的⼀种表示,并定义 ⼀个解释器,这个解释器使⽤该表示来解释语⾔中的句⼦。
解释器模式的动机
- 搜索匹配⼀个模式的字符串是⼀个常见问题。
- 正则表达式是描述字符串模式的⼀种标准语⾔。
- 使⽤⼀种通⽤的搜索算法来解释执⾏⼀个正则表达式,该正则表达式定义了待匹配字符串的集合。
- 解释器模式描述了如何为简单的语⾔定义⼀个⽂法,如何在该语⾔中表示⼀个句⼦,以及如何解释这些句⼦。
结构
解释器模式主要包含如下几个角色
- AbstractExpression: 抽象表达式。声明一个抽象的解释操作,该接口为抽象语法树中所有的节点共享。
- TerminalExpression: 终结符表达式。实现与文法中的终结符相关的解释操作。实现抽象表达式中所要求的方法。文法中每一个终结符都有一个具体的终结表达式与之相对应。
- NonterminalExpression: 非终结符表达式。为文法中的非终结符相关的解释操作。
- Context: 环境类。包含解释器之外的一些全局信息。
- Client: 客户类。
抽象语法树描述了如何构成一个复杂的句子,通过对抽象语法树的分析,可以识别出语言中的终结符和非终结符类。 在解释器模式中由于每一种终结符表达式、非终结符表达式都会有一个具体的实例与之相对应,所以系统的扩展性比较好。
实例
利用解释器模式,打印并计算实现浮点数的四则运算。
例如,对于如下表达式:
3+((4*6)-(7/2))
输出:
3+((4*6)-(7/2))=23.5
实验UML图
代码
为了使表达式显示出来需要增加一个括号类。最高的抽象接口是Expression,加减乘除括号变量常量均继承自Expression类。
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 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 |
#include<iostream> #include<vector> #include<map> using namespace std; class Context; class Variable; class Expression{ private: public: virtual double interpret(Context *con) = 0; virtual void display(Context *con) = 0; }; class Bracket :public Expression{ public: Bracket(Expression * n){ exp = n; } double interpret(Context *con){ return exp->interpret(con); } void display(Context *con){ cout << "("; exp->display(con); cout << ")"; } private: Expression * exp; }; class Context{ private: map<Variable*, double> valueMap; public: void addValue(Variable *x, double y){ double yi = y; valueMap[x] = yi; } double LookupValue(Variable *x){ double i = valueMap[x]; return i; } }; class Variable : public Expression{ public: void display(Context *con){ cout<<con->LookupValue(this); } double interpret(Context *con){ return con->LookupValue(this); } }; class Add : public Expression{ private: Expression *left, *right; public: Add(Expression *leftx, Expression *rightx){ left = leftx; right = rightx; } void display(Context *con){ left->display(con); cout<<" + "; right->display(con); } double interpret(Context *con){ return left->interpret(con) + right->interpret(con); } }; class Substract : public Expression{ private: Expression *left, *right; public: Substract(Expression *leftx, Expression *rightx){ left = leftx; right = rightx; } void display(Context *con){ left->display(con); cout<<" - "; right->display(con); } double interpret(Context *con){ return left->interpret(con) - right->interpret(con); } }; class Multiply : public Expression{ private: Expression *left, *right; public: Multiply(Expression *leftx, Expression *rightx){ left = leftx; right = rightx; } void display(Context *con){ left->display(con); cout<<" * "; right->display(con); } double interpret(Context *con){ return left->interpret(con) * right->interpret(con); } }; class Division : public Expression{ private: Expression *left, *right; public: Division(Expression *leftx, Expression *rightx){ left = leftx; right = rightx; } void display(Context *con){ left->display(con); cout<<" / "; right->display(con); } double interpret(Context *con){ return left->interpret(con) / right->interpret(con); } }; class Constant : public Expression{ private: int i; public: Constant(int a){ i = a; } double interpret(Context *con){ return i; } }; //3 + ((4*6) - (7/2)) int main(){ Expression *ex; Context *con = new Context(); Variable *a = new Variable(); Variable *b = new Variable(); Variable *c = new Variable(); Variable *d = new Variable(); Variable *e = new Variable(); con->addValue(a, 3); con->addValue(b, 4); con->addValue(c, 6); con->addValue(d, 7); con->addValue(e, 2); ex = new Add(a, new Bracket(new Substract(new Bracket(new Multiply(b, c)), new Bracket(new Division(d, e))))); ex->display(con); cout<<" = "<<ex->interpret(con)<<endl; return 0; } |
结果
总结
Context在本次实验中可以不用——除了上述用于表示表达式的类以外,通常在解释器模式中还提供了一个环境类Context,用于存储一些全局信息,通常在Context中包含了一个HashMap或ArrayList等类型的集合对象(也可以直接由HashMap等集合类充当环境类),存储一系列公共信息,如变量名与值的映射关系(key/value)等,用于在进行具体的解释操作时从中获取相关信息。
多态很有意思。
但是这个不能算解释器的哦~嘿嘿
这是设计模式中的解释器模式。