r17919 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r17918‎ | r17919 | r17920 >
Date:07:23, 25 November 2006
Author:river
Status:old
Tags:
Comment:
expression parser can be vastly simplified using Phoenix
Modified paths:
  • /trunk/willow/src/willow/expr.cc (modified) (history)

Diff [purge]

Index: trunk/willow/src/willow/expr.cc
@@ -21,7 +21,12 @@
2222 #include <stack>
2323 #include <functional>
2424 #include <stdexcept>
 25+
2526 #include <boost/spirit.hpp>
 27+#include <boost/spirit/attribute.hpp>
 28+#include <boost/spirit/phoenix.hpp>
 29+#include <boost/spirit/phoenix/casts.hpp>
 30+#include <boost/spirit/phoenix/closures.hpp>
2631 #include <boost/shared_ptr.hpp>
2732
2833 #include "util.h"
@@ -40,254 +45,125 @@
4146 using boost::spirit::str_p;
4247 using boost::spirit::chset;
4348 using boost::spirit::symbols;
 49+using boost::spirit::closure;
4450 using boost::shared_ptr;
 51+using phoenix::var;
 52+using phoenix::arg1;
 53+using phoenix::arg2;
4554
46 -template<typename T>
47 -struct bitwise_and {
48 - T operator() (T const &a, T const &b) const {
49 - return a & b;
50 - }
 55+struct expr_closure : closure<expr_closure, int64_t> {
 56+ member1 val;
5157 };
5258
53 -template<typename T>
54 -struct bitwise_or {
55 - T operator() (T const &a, T const &b) const {
56 - return a | b;
57 - }
58 -};
 59+struct expression_parser_impl :
 60+ grammar<expression_parser_impl, expr_closure::context_t> {
5961
60 -template<typename T>
61 -struct bitwise_xor {
62 - T operator() (T const &a, T const &b) const {
63 - return a ^ b;
 62+ symbols<int64_t> variables;
 63+
 64+ expression_parser_impl() {
 65+ add_variable("true", 1);
 66+ add_variable("false", 0);
6467 }
65 -};
6668
67 -template<typename T>
68 -struct bitwise_not {
69 - T operator() (T const &a) const {
70 - return ~a;
 69+ void add_variable(string const &name, int64_t val) {
 70+ variables.add(name.begin(), name.end(), val);
7171 }
72 -};
7372
74 -template<typename T>
75 -struct shift_left {
76 - T operator() (T const &a, T const &b) const {
77 - return a << b;
 73+ bool variable_defined(string const &name) const {
 74+ return boost::spirit::find(variables, name.c_str()) != NULL;
7875 }
79 -};
8076
81 -template<typename T>
82 -struct shift_right {
83 - T operator() (T const &a, T const &b) const {
84 - return a >> b;
 77+ int64_t run(string const &str) {
 78+ int64_t n;
 79+ if (!boost::spirit::parse(str.begin(), str.end(),
 80+ (*this)[var(n) = arg1], space_p).full)
 81+ throw expr::syntax_error();
 82+ return n;
8583 }
86 -};
8784
88 -struct expression_parser_impl : public grammar<expression_parser_impl> {
89 - typedef stack<int64_t> stack_t;
90 - struct operation {
91 - virtual ~operation() {}
92 - virtual void execute(stack_t &stack) = 0;
93 - };
 85+ template<typename scanner>
 86+ struct definition {
 87+ rule<scanner>
 88+ const &start(void) const { return top; }
9489
95 - typedef vector<shared_ptr<operation> > program_t;
 90+ rule<scanner, expr_closure::context_t>
 91+ add_expr, atom, mod_expr, eq_expr, neq_expr,
 92+ mul_expr, div_expr, sub_expr, land_expr, lor_expr,
 93+ lt_expr, gt_expr, le_expr, ge_expr, band_expr,
 94+ bxor_expr, bor_expr, lsht_expr, rsht_expr, expr;
 95+ rule<scanner> top, identifier;
9696
97 - template<int64_t value>
98 - struct op_literal : operation {
99 - virtual void execute(stack_t &s) {
100 - s.push(value);
101 - }
 97+ definition(expression_parser_impl const &self) {
 98+identifier = chset<>("a-zA-Z_") >> *chset<>("a-zA-Z0-9_");
10299
103 - struct add {
104 - program_t &_program;
105 - add(program_t &p)
106 - : _program(p)
107 - {}
108 -
109 - void operator() (int64_t) const {
110 - _program.push_back(shared_ptr<operation>(
111 - new op_literal<value>));
112 - }
113 - void operator() (string::const_iterator,
114 - string::const_iterator) const {
115 - _program.push_back(shared_ptr<operation>(
116 - new op_literal<value>));
117 - }
118 - };
119 - };
 100+top = expr[self.val = arg1];
120101
121 - template<typename func>
122 - struct binary_operator : operation {
123 - func _f;
124 - virtual void execute(stack_t &s) {
125 - int64_t a, b, r;
126 - /* note that args are pushed in reverse order -- so
127 - * the first op argument is the second on the stack
128 - */
129 - b = s.top();
130 - s.pop();
131 - a = s.top();
132 - s.pop();
133 - r = _f(a, b);
134 - s.push(r);
135 - }
 102+expr = lor_expr[expr.val = arg1];
136103
137 - struct add {
138 - program_t &_program;
139 - add(program_t &p)
140 - : _program(p)
141 - {}
142 -
143 - void operator() (string::const_iterator,
144 - string::const_iterator) const {
145 - _program.push_back(shared_ptr<operation>(
146 - new binary_operator<func>));
147 - }
148 - };
149 - };
 104+lor_expr = land_expr[lor_expr.val = arg1]
 105+ >> *("||" >> land_expr[lor_expr.val = lor_expr.val || arg1]);
150106
151 - template<typename func>
152 - struct unary_operator : operation {
153 - func _f;
154 - virtual void execute(stack_t &s) {
155 - int64_t v, r;
156 - v = s.top();
157 - s.pop();
158 - r = _f(v);
159 - s.push(r);
160 - }
 107+land_expr = band_expr[land_expr.val = arg1]
 108+ >> *("&&" >> band_expr[land_expr.val = land_expr.val && arg1]);
161109
162 - struct add {
163 - program_t &_program;
164 - add(program_t &p)
165 - : _program(p)
166 - {}
167 -
168 - void operator() (string::const_iterator,
169 - string::const_iterator) const {
170 - _program.push_back(shared_ptr<operation>(
171 - new unary_operator<func>));
172 - }
173 - };
174 - };
 110+band_expr = bxor_expr[band_expr.val = arg1]
 111+ >> *('&' >> bxor_expr[band_expr.val &= arg1]);
175112
176 - struct op_value : operation {
177 - int64_t v;
178 - op_value(int64_t v_) : v(v_) {}
179 - virtual void execute(stack_t &s) {
180 - s.push(v);
181 - }
 113+bxor_expr = bor_expr[bxor_expr.val = arg1]
 114+ >> *('^' >> bor_expr[bxor_expr.val ^= arg1]);
182115
183 - struct add {
184 - program_t &_program;
185 - add(program_t &p)
186 - : _program(p)
187 - {}
188 -
189 - void operator() (int64_t v) const {
190 - _program.push_back(shared_ptr<operation>(
191 - new op_value(v)));
192 - }
193 - };
194 - };
 116+bor_expr = lt_expr[bor_expr.val = arg1]
 117+ >> *('|' >> lt_expr[bor_expr.val |= arg1]);
195118
196 - typedef binary_operator<std::plus <int64_t> > op_add;
197 - typedef binary_operator<std::minus <int64_t> > op_sub;
198 - typedef binary_operator<std::multiplies <int64_t> > op_mul;
199 - typedef binary_operator<std::divides <int64_t> > op_div;
200 - typedef binary_operator<std::modulus <int64_t> > op_mod;
201 - typedef binary_operator<std::logical_and <int64_t> > op_land;
202 - typedef binary_operator<std::logical_or <int64_t> > op_lor;
203 - typedef binary_operator<std::less <int64_t> > op_lt;
204 - typedef binary_operator<std::greater <int64_t> > op_gt;
205 - typedef binary_operator<std::less_equal <int64_t> > op_le;
206 - typedef binary_operator<std::greater_equal <int64_t> > op_ge;
207 - typedef binary_operator<std::equal_to <int64_t> > op_eq;
208 - typedef binary_operator<std::not_equal_to <int64_t> > op_neq;
209 - typedef binary_operator<bitwise_and <int64_t> > op_band;
210 - typedef binary_operator<bitwise_or <int64_t> > op_bor;
211 - typedef binary_operator<bitwise_xor <int64_t> > op_bxor;
212 - typedef binary_operator<shift_left <int64_t> > op_lsht;
213 - typedef binary_operator<shift_right <int64_t> > op_rsht;
 119+lt_expr = gt_expr[lt_expr.val = arg1]
 120+ >> *('<' >> gt_expr[lt_expr.val = lt_expr.val < arg1]);
214121
215 - typedef unary_operator<bitwise_not <int64_t> > op_bnot;
216 - typedef unary_operator<std::negate <int64_t> > op_neg;
217 - typedef unary_operator<std::logical_not <int64_t> > op_not;
218 -
219 - mutable program_t _program;
220 - stack_t stack;
221 - program_t &program(void) const {
222 - return _program;
223 - }
 122+gt_expr = le_expr[gt_expr.val = arg1]
 123+ >> *('>' >> le_expr[gt_expr.val = gt_expr.val > arg1]);
224124
225 - symbols<int64_t> variables;
 125+le_expr = ge_expr[le_expr.val = arg1]
 126+ >> *("<=" >> ge_expr[le_expr.val = le_expr.val <= arg1]);
226127
227 - expression_parser_impl() {
228 - add_variable("true", 1);
229 - add_variable("false", 0);
230 - }
 128+ge_expr = neq_expr[ge_expr.val = arg1]
 129+ >> *(">=" >> neq_expr[ge_expr.val = ge_expr.val >= arg1]);
231130
232 - void add_variable(string const &name, int64_t val) {
233 - variables.add(name.begin(), name.end(), val);
234 - }
 131+neq_expr = eq_expr[neq_expr.val = arg1]
 132+ >> *("!=" >> eq_expr[neq_expr.val = neq_expr.val != arg1]);
235133
236 - bool variable_defined(string const &name) const {
237 - return boost::spirit::find(variables, name.c_str()) != NULL;
238 - }
 134+eq_expr = lsht_expr[eq_expr.val = arg1]
 135+ >> *("==" >> lsht_expr[eq_expr.val = eq_expr.val == arg1]);
239136
240 - int64_t run(string const &str) {
241 - if (!boost::spirit::parse(str.begin(), str.end(), *this, space_p).full)
242 - throw expr::syntax_error();
 137+lsht_expr = rsht_expr[lsht_expr.val = arg1]
 138+ >> *("<<" >> rsht_expr[lsht_expr.val <<= arg1]);
243139
244 - program_t::iterator it = _program.begin(), end = _program.end();
245 - for (; it != end; ++it)
246 - (*it)->execute(stack);
247 - return stack.top();
248 - }
 140+rsht_expr = add_expr[rsht_expr.val = arg1]
 141+ >> *(">>" >> add_expr[rsht_expr.val >>= arg1]);
249142
250 - template<typename scanner>
251 - struct definition {
252 - rule<scanner> const &start(void) const { return expr; }
253 - rule<scanner> add_expr, atom, expr, mod_expr, eq_expr, neq_expr,
254 - mul_expr, div_expr, sub_expr, land_expr, lor_expr,
255 - lt_expr, gt_expr, le_expr, ge_expr, band_expr,
256 - bxor_expr, bor_expr, lsht_expr, rsht_expr, identifier;
 143+add_expr = sub_expr[add_expr.val = arg1]
 144+ >> *('+' >> sub_expr[add_expr.val += arg1]);
257145
258 - definition(expression_parser_impl const &self) {
259 -identifier = chset<>("a-zA-Z_") >> *chset<>("a-zA-Z0-9_");
 146+sub_expr = mul_expr[sub_expr.val = arg1]
 147+ >> *('-' >> mul_expr[sub_expr.val -= arg1]);
260148
261 -expr = lor_expr;
 149+mul_expr = mod_expr[mul_expr.val = arg1]
 150+ >> *('*' >> mod_expr[mul_expr.val *= arg1]);
262151
263 -lor_expr = land_expr >> *(("||" >> land_expr)[ op_lor::add(self.program())]);
264 -land_expr = band_expr >> *(("&&" >> band_expr)[op_land::add(self.program())]);
265 -band_expr = bxor_expr >> *(('&' >> bxor_expr)[op_band::add(self.program())]);
266 -bxor_expr = bor_expr >> *(('^' >> bor_expr)[op_bxor::add(self.program())]);
267 -bor_expr = lt_expr >> *(('|' >> lt_expr)[ op_bor::add(self.program())]);
268 -lt_expr = gt_expr >> *(('<' >> gt_expr)[ op_lt::add(self.program())]);
269 -gt_expr = le_expr >> *(('>' >> le_expr)[ op_gt::add(self.program())]);
270 -le_expr = ge_expr >> *(("<=" >> ge_expr)[ op_le::add(self.program())]);
271 -ge_expr = neq_expr >> *((">=" >> neq_expr)[ op_ge::add(self.program())]);
272 -neq_expr = eq_expr >> *(("!=" >> eq_expr)[ op_neq::add(self.program())]);
273 -eq_expr = lsht_expr >> *(("==" >> lsht_expr)[ op_eq::add(self.program())]);
274 -lsht_expr = rsht_expr >> *(("<<" >> rsht_expr)[op_lsht::add(self.program())]);
275 -rsht_expr = add_expr >> *((">>" >> add_expr)[op_rsht::add(self.program())]);
276 -add_expr = sub_expr >> *(('+' >> sub_expr)[ op_add::add(self.program())]);
277 -sub_expr = mul_expr >> *(('-' >> mul_expr)[ op_sub::add(self.program())]);
278 -mul_expr = mod_expr >> *(('*' >> mod_expr)[ op_mul::add(self.program())]);
279 -mod_expr = div_expr >> *(('%' >> div_expr)[ op_mod::add(self.program())]);
280 -div_expr = atom >> *(('/' >> atom)[ op_div::add(self.program())]);
 152+mod_expr = div_expr[mod_expr.val = arg1]
 153+ >> *('%' >> div_expr[mod_expr.val %= arg1]);
281154
282 -atom = int_p[op_value::add(self.program())]
283 - | ( '(' >> expr >> ')' )
284 - | ( '-' >> expr )[op_neg::add(self.program())]
285 - | ( '!' >> expr )[op_not::add(self.program())]
286 - | ( '~' >> expr )[op_bnot::add(self.program())]
287 - | self.variables[op_value::add(self.program())]
 155+div_expr = atom[div_expr.val = arg1]
 156+ >> *('/' >> atom[div_expr.val /= arg1]);
 157+
 158+atom = int_p[atom.val = arg1]
 159+ | ( '(' >> expr[atom.val = arg1] >> ')' )
 160+ | ( '-' >> expr[atom.val = -arg1])
 161+ | ( '!' >> expr[atom.val = !arg1])
 162+ | ( '~' >> expr[atom.val = ~arg1])
 163+ | self.variables[atom.val = arg1]
288164 | ( str_p("defined") >> '(' >>
289 - self.variables[op_literal<1>::add(self.program())] >> ')' )
 165+ self.variables[atom.val = 1] >> ')' )
290166 | ( str_p("defined") >> '(' >>
291 - identifier[op_literal<0>::add(self.program())] >> ')')
 167+ identifier[atom.val = 0] >> ')')
292168 ;
293169
294170 BOOST_SPIRIT_DEBUG_RULE(identifier);