]> git.sesse.net Git - casparcg/blob - dependencies/boost/boost/xpressive/detail/core/matcher/action_matcher.hpp
Manually merged pull request #222
[casparcg] / dependencies / boost / boost / xpressive / detail / core / matcher / action_matcher.hpp
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) && (_MSC_VER >= 1020)
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