]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /////////////////////////////////////////////////////////////////////////////// |
2 | // action_matcher.hpp | |
3 | // | |
4 | // Copyright 2008 Eric Niebler. | |
5 | // Copyright 2008 David Jenkins. | |
6 | // | |
7 | // Distributed under the Boost Software License, Version 1.0. (See | |
8 | // accompanying file LICENSE_1_0.txt or copy at | |
9 | // http://www.boost.org/LICENSE_1_0.txt) | |
10 | ||
11 | #ifndef BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_ACTION_MATCHER_HPP_EAN_10_04_2005 | |
12 | #define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_ACTION_MATCHER_HPP_EAN_10_04_2005 | |
13 | ||
14 | // MS compatible compilers support #pragma once | |
15 | #if defined(_MSC_VER) | |
16 | # pragma once | |
17 | #endif | |
18 | ||
19 | #include <boost/config.hpp> | |
20 | #include <boost/version.hpp> | |
21 | #include <boost/ref.hpp> | |
22 | #include <boost/assert.hpp> | |
23 | #include <boost/mpl/if.hpp> | |
24 | #include <boost/throw_exception.hpp> | |
25 | #include <boost/utility/result_of.hpp> | |
26 | #include <boost/type_traits/is_const.hpp> | |
27 | #include <boost/type_traits/remove_reference.hpp> | |
28 | #include <boost/xpressive/detail/detail_fwd.hpp> | |
29 | #include <boost/xpressive/detail/core/quant_style.hpp> | |
30 | #include <boost/xpressive/detail/core/action.hpp> | |
31 | #include <boost/xpressive/detail/core/state.hpp> | |
32 | #include <boost/proto/core.hpp> | |
33 | #include <boost/proto/context.hpp> | |
34 | #include <boost/xpressive/match_results.hpp> // for type_info_less | |
35 | #include <boost/xpressive/detail/static/transforms/as_action.hpp> // for 'read_attr' | |
36 | #if BOOST_VERSION >= 103500 | |
37 | # include <boost/proto/fusion.hpp> | |
38 | # include <boost/fusion/include/transform_view.hpp> | |
39 | # include <boost/fusion/include/invoke.hpp> | |
40 | # include <boost/fusion/include/push_front.hpp> | |
41 | # include <boost/fusion/include/pop_front.hpp> | |
42 | #endif | |
43 | ||
44 | #if BOOST_MSVC | |
45 | #pragma warning(push) | |
46 | #pragma warning(disable : 4510) // default constructor could not be generated | |
47 | #pragma warning(disable : 4512) // assignment operator could not be generated | |
48 | #pragma warning(disable : 4610) // can never be instantiated - user defined constructor required | |
49 | #endif | |
50 | ||
51 | namespace boost { namespace xpressive { namespace detail | |
52 | { | |
53 | ||
54 | #if BOOST_VERSION >= 103500 | |
55 | struct DataMember | |
56 | : proto::mem_ptr<proto::_, proto::terminal<proto::_> > | |
57 | {}; | |
58 | ||
59 | template<typename Expr, long N> | |
60 | struct child_ | |
61 | : remove_reference< | |
62 | typename proto::result_of::child_c<Expr &, N>::type | |
63 | > | |
64 | {}; | |
65 | ||
66 | /////////////////////////////////////////////////////////////////////////////// | |
67 | // mem_ptr_eval | |
68 | // Rewrites expressions of the form x->*foo(a) into foo(x, a) and then | |
69 | // evaluates them. | |
70 | template<typename Expr, typename Context, bool IsDataMember = proto::matches<Expr, DataMember>::value> | |
71 | struct mem_ptr_eval | |
72 | { | |
73 | typedef typename child_<Expr, 0>::type left_type; | |
74 | typedef typename child_<Expr, 1>::type right_type; | |
75 | ||
76 | typedef | |
77 | typename proto::result_of::value< | |
78 | typename proto::result_of::child_c<right_type, 0>::type | |
79 | >::type | |
80 | function_type; | |
81 | ||
82 | typedef | |
83 | fusion::transform_view< | |
84 | typename fusion::result_of::push_front< | |
85 | typename fusion::result_of::pop_front<right_type>::type const | |
86 | , reference_wrapper<left_type> | |
87 | >::type const | |
88 | , proto::eval_fun<Context> | |
89 | > | |
90 | evaluated_args; | |
91 | ||
92 | typedef | |
93 | typename fusion::result_of::invoke<function_type, evaluated_args>::type | |
94 | result_type; | |
95 | ||
96 | result_type operator()(Expr &expr, Context &ctx) const | |
97 | { | |
98 | return fusion::invoke<function_type>( | |
99 | proto::value(proto::child_c<0>(proto::right(expr))) | |
100 | , evaluated_args( | |
101 | fusion::push_front(fusion::pop_front(proto::right(expr)), boost::ref(proto::left(expr))) | |
102 | , proto::eval_fun<Context>(ctx) | |
103 | ) | |
104 | ); | |
105 | } | |
106 | }; | |
107 | ||
108 | /////////////////////////////////////////////////////////////////////////////// | |
109 | // mem_ptr_eval | |
110 | // Rewrites expressions of the form x->*foo into foo(x) and then | |
111 | // evaluates them. | |
112 | template<typename Expr, typename Context> | |
113 | struct mem_ptr_eval<Expr, Context, true> | |
114 | { | |
115 | typedef typename child_<Expr, 0>::type left_type; | |
116 | typedef typename child_<Expr, 1>::type right_type; | |
117 | ||
118 | typedef | |
119 | typename proto::result_of::value<right_type>::type | |
120 | function_type; | |
121 | ||
122 | typedef typename boost::result_of< | |
123 | function_type(typename proto::result_of::eval<left_type, Context>::type) | |
124 | >::type result_type; | |
125 | ||
126 | result_type operator()(Expr &expr, Context &ctx) const | |
127 | { | |
128 | return proto::value(proto::right(expr))( | |
129 | proto::eval(proto::left(expr), ctx) | |
130 | ); | |
131 | } | |
132 | }; | |
133 | #endif | |
134 | ||
135 | struct attr_with_default_tag | |
136 | {}; | |
137 | ||
138 | template<typename T> | |
139 | struct opt; | |
140 | ||
141 | /////////////////////////////////////////////////////////////////////////////// | |
142 | // action_context | |
143 | // | |
144 | struct action_context | |
145 | { | |
146 | explicit action_context(action_args_type *action_args) | |
147 | : action_args_(action_args) | |
148 | {} | |
149 | ||
150 | action_args_type const &args() const | |
151 | { | |
152 | return *this->action_args_; | |
153 | } | |
154 | ||
155 | // eval_terminal | |
156 | template<typename Expr, typename Arg> | |
157 | struct eval_terminal | |
158 | : proto::default_eval<Expr, action_context const> | |
159 | {}; | |
160 | ||
161 | template<typename Expr, typename Arg> | |
162 | struct eval_terminal<Expr, reference_wrapper<Arg> > | |
163 | { | |
164 | typedef Arg &result_type; | |
165 | result_type operator()(Expr &expr, action_context const &) const | |
166 | { | |
167 | return proto::value(expr).get(); | |
168 | } | |
169 | }; | |
170 | ||
171 | template<typename Expr, typename Arg> | |
172 | struct eval_terminal<Expr, opt<Arg> > | |
173 | { | |
174 | typedef Arg const &result_type; | |
175 | result_type operator()(Expr &expr, action_context const &) const | |
176 | { | |
177 | return proto::value(expr); | |
178 | } | |
179 | }; | |
180 | ||
181 | template<typename Expr, typename Type, typename Int> | |
182 | struct eval_terminal<Expr, action_arg<Type, Int> > | |
183 | { | |
184 | typedef typename action_arg<Type, Int>::reference result_type; | |
185 | result_type operator()(Expr &expr, action_context const &ctx) const | |
186 | { | |
187 | action_args_type::const_iterator where_ = ctx.args().find(&typeid(proto::value(expr))); | |
188 | if(where_ == ctx.args().end()) | |
189 | { | |
190 | BOOST_THROW_EXCEPTION( | |
191 | regex_error( | |
192 | regex_constants::error_badarg | |
193 | , "An argument to an action was unspecified" | |
194 | ) | |
195 | ); | |
196 | } | |
197 | return proto::value(expr).cast(where_->second); | |
198 | } | |
199 | }; | |
200 | ||
201 | // eval | |
202 | template<typename Expr, typename Tag = typename Expr::proto_tag> | |
203 | struct eval | |
204 | : proto::default_eval<Expr, action_context const> | |
205 | {}; | |
206 | ||
207 | template<typename Expr> | |
208 | struct eval<Expr, proto::tag::terminal> | |
209 | : eval_terminal<Expr, typename proto::result_of::value<Expr>::type> | |
210 | {}; | |
211 | ||
212 | // Evaluate attributes like a1|42 | |
213 | template<typename Expr> | |
214 | struct eval<Expr, attr_with_default_tag> | |
215 | { | |
216 | typedef | |
217 | typename proto::result_of::value< | |
218 | typename proto::result_of::left< | |
219 | typename proto::result_of::child< | |
220 | Expr | |
221 | >::type | |
222 | >::type | |
223 | >::type | |
224 | temp_type; | |
225 | ||
226 | typedef typename temp_type::type result_type; | |
227 | ||
228 | result_type operator ()(Expr const &expr, action_context const &ctx) const | |
229 | { | |
230 | return proto::value(proto::left(proto::child(expr))).t_ | |
231 | ? *proto::value(proto::left(proto::child(expr))).t_ | |
232 | : proto::eval(proto::right(proto::child(expr)), ctx); | |
233 | } | |
234 | }; | |
235 | ||
236 | #if BOOST_VERSION >= 103500 | |
237 | template<typename Expr> | |
238 | struct eval<Expr, proto::tag::mem_ptr> | |
239 | : mem_ptr_eval<Expr, action_context const> | |
240 | {}; | |
241 | #endif | |
242 | ||
243 | private: | |
244 | action_args_type *action_args_; | |
245 | }; | |
246 | ||
247 | /////////////////////////////////////////////////////////////////////////////// | |
248 | // action | |
249 | // | |
250 | template<typename Actor> | |
251 | struct action | |
252 | : actionable | |
253 | { | |
254 | action(Actor const &actor) | |
255 | : actionable() | |
256 | , actor_(actor) | |
257 | { | |
258 | } | |
259 | ||
260 | virtual void execute(action_args_type *action_args) const | |
261 | { | |
262 | action_context const ctx(action_args); | |
263 | proto::eval(this->actor_, ctx); | |
264 | } | |
265 | ||
266 | private: | |
267 | Actor actor_; | |
268 | }; | |
269 | ||
270 | /////////////////////////////////////////////////////////////////////////////// | |
271 | // subreg_transform | |
272 | // | |
273 | struct subreg_transform : proto::transform<subreg_transform> | |
274 | { | |
275 | template<typename Expr, typename State, typename Data> | |
276 | struct impl : proto::transform_impl<Expr, State, Data> | |
277 | { | |
278 | typedef typename impl::state state_type; | |
279 | ||
280 | typedef | |
281 | typename proto::terminal<sub_match<typename state_type::iterator> >::type | |
282 | result_type; | |
283 | ||
284 | result_type operator ()( | |
285 | typename impl::expr_param | |
286 | , typename impl::state_param state | |
287 | , typename impl::data_param data | |
288 | ) const | |
289 | { | |
290 | return result_type::make(state.sub_matches_[ data ]); | |
291 | } | |
292 | }; | |
293 | }; | |
294 | ||
295 | /////////////////////////////////////////////////////////////////////////////// | |
296 | // mark_transform | |
297 | // | |
298 | struct mark_transform : proto::transform<mark_transform> | |
299 | { | |
300 | template<typename Expr, typename State, typename Data> | |
301 | struct impl : proto::transform_impl<Expr, State, Data> | |
302 | { | |
303 | typedef typename impl::state state_type; | |
304 | typedef | |
305 | typename proto::terminal<sub_match<typename state_type::iterator> >::type | |
306 | result_type; | |
307 | ||
308 | result_type operator ()( | |
309 | typename impl::expr_param expr | |
310 | , typename impl::state_param state | |
311 | , typename impl::data_param | |
312 | ) const | |
313 | { | |
314 | return result_type::make(state.sub_matches_[ proto::value(expr).mark_number_ ]); | |
315 | } | |
316 | }; | |
317 | }; | |
318 | ||
319 | /////////////////////////////////////////////////////////////////////////////// | |
320 | // opt | |
321 | // | |
322 | template<typename T> | |
323 | struct opt | |
324 | { | |
325 | typedef T type; | |
326 | typedef T const &reference; | |
327 | ||
328 | opt(T const *t) | |
329 | : t_(t) | |
330 | {} | |
331 | ||
332 | operator reference() const | |
333 | { | |
334 | BOOST_XPR_ENSURE_(0 != this->t_, regex_constants::error_badattr, "Use of uninitialized regex attribute"); | |
335 | return *this->t_; | |
336 | } | |
337 | ||
338 | T const *t_; | |
339 | }; | |
340 | ||
341 | /////////////////////////////////////////////////////////////////////////////// | |
342 | // attr_transform | |
343 | // | |
344 | struct attr_transform : proto::transform<attr_transform> | |
345 | { | |
346 | template<typename Expr, typename State, typename Data> | |
347 | struct impl : proto::transform_impl<Expr, State, Data> | |
348 | { | |
349 | typedef typename impl::expr expr_type; | |
350 | ||
351 | typedef | |
352 | typename expr_type::proto_child0::matcher_type::value_type::second_type | |
353 | attr_type; | |
354 | ||
355 | typedef | |
356 | typename proto::terminal<opt<attr_type> >::type | |
357 | result_type; | |
358 | ||
359 | result_type operator ()( | |
360 | typename impl::expr_param | |
361 | , typename impl::state_param state | |
362 | , typename impl::data_param | |
363 | ) const | |
364 | { | |
365 | int slot = typename expr_type::proto_child0::nbr_type(); | |
366 | attr_type const *attr = static_cast<attr_type const *>(state.attr_context_.attr_slots_[slot-1]); | |
367 | return result_type::make(opt<attr_type>(attr)); | |
368 | } | |
369 | }; | |
370 | }; | |
371 | ||
372 | /////////////////////////////////////////////////////////////////////////////// | |
373 | // attr_with_default_transform | |
374 | // | |
375 | template<typename Grammar, typename Callable = proto::callable> | |
376 | struct attr_with_default_transform : proto::transform<attr_with_default_transform<Grammar, Callable> > | |
377 | { | |
378 | template<typename Expr, typename State, typename Data> | |
379 | struct impl : proto::transform_impl<Expr, State, Data> | |
380 | { | |
381 | typedef | |
382 | typename proto::unary_expr< | |
383 | attr_with_default_tag | |
384 | , typename Grammar::template impl<Expr, State, Data>::result_type | |
385 | >::type | |
386 | result_type; | |
387 | ||
388 | result_type operator ()( | |
389 | typename impl::expr_param expr | |
390 | , typename impl::state_param state | |
391 | , typename impl::data_param data | |
392 | ) const | |
393 | { | |
394 | result_type that = { | |
395 | typename Grammar::template impl<Expr, State, Data>()(expr, state, data) | |
396 | }; | |
397 | return that; | |
398 | } | |
399 | }; | |
400 | }; | |
401 | ||
402 | /////////////////////////////////////////////////////////////////////////////// | |
403 | // by_ref_transform | |
404 | // | |
405 | struct by_ref_transform : proto::transform<by_ref_transform> | |
406 | { | |
407 | template<typename Expr, typename State, typename Data> | |
408 | struct impl : proto::transform_impl<Expr, State, Data> | |
409 | { | |
410 | typedef | |
411 | typename proto::result_of::value<typename impl::expr_param>::type | |
412 | reference; | |
413 | ||
414 | typedef | |
415 | typename proto::terminal<reference>::type | |
416 | result_type; | |
417 | ||
418 | result_type operator ()( | |
419 | typename impl::expr_param expr | |
420 | , typename impl::state_param | |
421 | , typename impl::data_param | |
422 | ) const | |
423 | { | |
424 | return result_type::make(proto::value(expr)); | |
425 | } | |
426 | }; | |
427 | }; | |
428 | ||
429 | /////////////////////////////////////////////////////////////////////////////// | |
430 | // BindActionArgs | |
431 | // | |
432 | struct BindActionArgs | |
433 | : proto::or_< | |
434 | proto::when<proto::terminal<any_matcher>, subreg_transform> | |
435 | , proto::when<proto::terminal<mark_placeholder>, mark_transform> | |
436 | , proto::when<proto::terminal<read_attr<proto::_, proto::_> >, attr_transform> | |
437 | , proto::when<proto::terminal<proto::_>, by_ref_transform> | |
438 | , proto::when< | |
439 | proto::bitwise_or<proto::terminal<read_attr<proto::_, proto::_> >, BindActionArgs> | |
440 | , attr_with_default_transform<proto::bitwise_or<attr_transform, BindActionArgs> > | |
441 | > | |
442 | , proto::otherwise<proto::nary_expr<proto::_, proto::vararg<BindActionArgs> > > | |
443 | > | |
444 | {}; | |
445 | ||
446 | /////////////////////////////////////////////////////////////////////////////// | |
447 | // action_matcher | |
448 | // | |
449 | template<typename Actor> | |
450 | struct action_matcher | |
451 | : quant_style<quant_none, 0, false> | |
452 | { | |
453 | int sub_; | |
454 | Actor actor_; | |
455 | ||
456 | action_matcher(Actor const &actor, int sub) | |
457 | : sub_(sub) | |
458 | , actor_(actor) | |
459 | { | |
460 | } | |
461 | ||
462 | template<typename BidiIter, typename Next> | |
463 | bool match(match_state<BidiIter> &state, Next const &next) const | |
464 | { | |
465 | // Bind the arguments | |
466 | typedef | |
467 | typename boost::result_of<BindActionArgs( | |
468 | Actor const & | |
469 | , match_state<BidiIter> & | |
470 | , int const & | |
471 | )>::type | |
472 | action_type; | |
473 | ||
474 | action<action_type> actor(BindActionArgs()(this->actor_, state, this->sub_)); | |
475 | ||
476 | // Put the action in the action list | |
477 | actionable const **action_list_tail = state.action_list_tail_; | |
478 | *state.action_list_tail_ = &actor; | |
479 | state.action_list_tail_ = &actor.next; | |
480 | ||
481 | // Match the rest of the pattern | |
482 | if(next.match(state)) | |
483 | { | |
484 | return true; | |
485 | } | |
486 | ||
487 | BOOST_ASSERT(0 == actor.next); | |
488 | // remove action from list | |
489 | *action_list_tail = 0; | |
490 | state.action_list_tail_ = action_list_tail; | |
491 | return false; | |
492 | } | |
493 | }; | |
494 | ||
495 | }}} | |
496 | ||
497 | #if BOOST_MSVC | |
498 | #pragma warning(pop) | |
499 | #endif | |
500 | ||
501 | #endif |