Index: trunk/willow/src/willow/expr.cc |
— | — | @@ -21,7 +21,12 @@ |
22 | 22 | #include <stack> |
23 | 23 | #include <functional> |
24 | 24 | #include <stdexcept> |
| 25 | + |
25 | 26 | #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> |
26 | 31 | #include <boost/shared_ptr.hpp> |
27 | 32 | |
28 | 33 | #include "util.h" |
— | — | @@ -40,254 +45,125 @@ |
41 | 46 | using boost::spirit::str_p; |
42 | 47 | using boost::spirit::chset; |
43 | 48 | using boost::spirit::symbols; |
| 49 | +using boost::spirit::closure; |
44 | 50 | using boost::shared_ptr; |
| 51 | +using phoenix::var; |
| 52 | +using phoenix::arg1; |
| 53 | +using phoenix::arg2; |
45 | 54 | |
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; |
51 | 57 | }; |
52 | 58 | |
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> { |
59 | 61 | |
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); |
64 | 67 | } |
65 | | -}; |
66 | 68 | |
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); |
71 | 71 | } |
72 | | -}; |
73 | 72 | |
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; |
78 | 75 | } |
79 | | -}; |
80 | 76 | |
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; |
85 | 83 | } |
86 | | -}; |
87 | 84 | |
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; } |
94 | 89 | |
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; |
96 | 96 | |
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_"); |
102 | 99 | |
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]; |
120 | 101 | |
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]; |
136 | 103 | |
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]); |
150 | 106 | |
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]); |
161 | 109 | |
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]); |
175 | 112 | |
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]); |
182 | 115 | |
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]); |
195 | 118 | |
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]); |
214 | 121 | |
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]); |
224 | 124 | |
225 | | - symbols<int64_t> variables; |
| 125 | +le_expr = ge_expr[le_expr.val = arg1] |
| 126 | + >> *("<=" >> ge_expr[le_expr.val = le_expr.val <= arg1]); |
226 | 127 | |
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]); |
231 | 130 | |
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]); |
235 | 133 | |
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]); |
239 | 136 | |
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]); |
243 | 139 | |
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]); |
249 | 142 | |
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]); |
257 | 145 | |
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]); |
260 | 148 | |
261 | | -expr = lor_expr; |
| 149 | +mul_expr = mod_expr[mul_expr.val = arg1] |
| 150 | + >> *('*' >> mod_expr[mul_expr.val *= arg1]); |
262 | 151 | |
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]); |
281 | 154 | |
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] |
288 | 164 | | ( str_p("defined") >> '(' >> |
289 | | - self.variables[op_literal<1>::add(self.program())] >> ')' ) |
| 165 | + self.variables[atom.val = 1] >> ')' ) |
290 | 166 | | ( str_p("defined") >> '(' >> |
291 | | - identifier[op_literal<0>::add(self.program())] >> ')') |
| 167 | + identifier[atom.val = 0] >> ')') |
292 | 168 | ; |
293 | 169 | |
294 | 170 | BOOST_SPIRIT_DEBUG_RULE(identifier); |