Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:53:48

0001 ///////////////////////////////////////////////////////////////////////////////
0002 // action_matcher.hpp
0003 //
0004 //  Copyright 2008 Eric Niebler.
0005 //  Copyright 2008 David Jenkins.
0006 //
0007 //  Distributed under the Boost Software License, Version 1.0. (See
0008 //  accompanying file LICENSE_1_0.txt or copy at
0009 //  http://www.boost.org/LICENSE_1_0.txt)
0010 
0011 #ifndef BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_ACTION_MATCHER_HPP_EAN_10_04_2005
0012 #define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_ACTION_MATCHER_HPP_EAN_10_04_2005
0013 
0014 // MS compatible compilers support #pragma once
0015 #if defined(_MSC_VER)
0016 # pragma once
0017 #endif
0018 
0019 #include <boost/config.hpp>
0020 #include <boost/version.hpp>
0021 #include <boost/ref.hpp>
0022 #include <boost/assert.hpp>
0023 #include <boost/mpl/if.hpp>
0024 #include <boost/throw_exception.hpp>
0025 #include <boost/utility/result_of.hpp>
0026 #include <boost/type_traits/is_const.hpp>
0027 #include <boost/type_traits/remove_reference.hpp>
0028 #include <boost/xpressive/detail/detail_fwd.hpp>
0029 #include <boost/xpressive/detail/core/quant_style.hpp>
0030 #include <boost/xpressive/detail/core/action.hpp>
0031 #include <boost/xpressive/detail/core/state.hpp>
0032 #include <boost/proto/core.hpp>
0033 #include <boost/proto/context.hpp>
0034 #include <boost/xpressive/match_results.hpp> // for type_info_less
0035 #include <boost/xpressive/detail/static/transforms/as_action.hpp> // for 'read_attr'
0036 #if BOOST_VERSION >= 103500
0037 # include <boost/proto/fusion.hpp>
0038 # include <boost/fusion/include/transform_view.hpp>
0039 # include <boost/fusion/include/invoke.hpp>
0040 # include <boost/fusion/include/push_front.hpp>
0041 # include <boost/fusion/include/pop_front.hpp>
0042 #endif
0043 
0044 #if BOOST_MSVC
0045 #pragma warning(push)
0046 #pragma warning(disable : 4510) // default constructor could not be generated
0047 #pragma warning(disable : 4512) // assignment operator could not be generated
0048 #pragma warning(disable : 4610) // can never be instantiated - user defined constructor required
0049 #endif
0050 
0051 namespace boost { namespace xpressive { namespace detail
0052 {
0053 
0054     #if BOOST_VERSION >= 103500
0055     struct DataMember
0056       : proto::mem_ptr<proto::_, proto::terminal<proto::_> >
0057     {};
0058 
0059     template<typename Expr, long N>
0060     struct child_
0061       : remove_reference<
0062             typename proto::result_of::child_c<Expr &, N>::type
0063         >
0064     {};
0065 
0066     ///////////////////////////////////////////////////////////////////////////////
0067     // mem_ptr_eval
0068     //  Rewrites expressions of the form x->*foo(a) into foo(x, a) and then
0069     //  evaluates them.
0070     template<typename Expr, typename Context, bool IsDataMember = proto::matches<Expr, DataMember>::value>
0071     struct mem_ptr_eval
0072     {
0073         typedef typename child_<Expr, 0>::type left_type;
0074         typedef typename child_<Expr, 1>::type right_type;
0075 
0076         typedef
0077             typename proto::result_of::value<
0078                 typename proto::result_of::child_c<right_type, 0>::type
0079             >::type
0080         function_type;
0081 
0082         typedef
0083             fusion::transform_view<
0084                 typename fusion::result_of::push_front<
0085                     typename fusion::result_of::pop_front<right_type>::type const
0086                   , reference_wrapper<left_type>
0087                 >::type const
0088               , proto::eval_fun<Context>
0089             >
0090         evaluated_args;
0091 
0092         typedef
0093             typename fusion::result_of::invoke<function_type, evaluated_args>::type
0094         result_type;
0095 
0096         result_type operator()(Expr &expr, Context &ctx) const
0097         {
0098             return fusion::invoke<function_type>(
0099                 proto::value(proto::child_c<0>(proto::right(expr)))
0100               , evaluated_args(
0101                     fusion::push_front(fusion::pop_front(proto::right(expr)), boost::ref(proto::left(expr)))
0102                   , proto::eval_fun<Context>(ctx)
0103                 )
0104             );
0105         }
0106     };
0107 
0108     ///////////////////////////////////////////////////////////////////////////////
0109     // mem_ptr_eval
0110     //  Rewrites expressions of the form x->*foo into foo(x) and then
0111     //  evaluates them.
0112     template<typename Expr, typename Context>
0113     struct mem_ptr_eval<Expr, Context, true>
0114     {
0115         typedef typename child_<Expr, 0>::type left_type;
0116         typedef typename child_<Expr, 1>::type right_type;
0117 
0118         typedef
0119             typename proto::result_of::value<right_type>::type
0120         function_type;
0121 
0122         typedef typename boost::result_of<
0123             function_type(typename proto::result_of::eval<left_type, Context>::type)
0124         >::type result_type;
0125 
0126         result_type operator()(Expr &expr, Context &ctx) const
0127         {
0128             return proto::value(proto::right(expr))(
0129                 proto::eval(proto::left(expr), ctx)
0130             );
0131         }
0132     };
0133     #endif
0134 
0135     struct attr_with_default_tag
0136     {};
0137 
0138     template<typename T>
0139     struct opt;
0140 
0141     ///////////////////////////////////////////////////////////////////////////////
0142     // action_context
0143     //
0144     struct action_context
0145     {
0146         explicit action_context(action_args_type *action_args)
0147           : action_args_(action_args)
0148         {}
0149 
0150         action_args_type const &args() const
0151         {
0152             return *this->action_args_;
0153         }
0154 
0155         // eval_terminal
0156         template<typename Expr, typename Arg>
0157         struct eval_terminal
0158           : proto::default_eval<Expr, action_context const>
0159         {};
0160 
0161         template<typename Expr, typename Arg>
0162         struct eval_terminal<Expr, reference_wrapper<Arg> >
0163         {
0164             typedef Arg &result_type;
0165             result_type operator()(Expr &expr, action_context const &) const
0166             {
0167                 return proto::value(expr).get();
0168             }
0169         };
0170 
0171         template<typename Expr, typename Arg>
0172         struct eval_terminal<Expr, opt<Arg> >
0173         {
0174             typedef Arg const &result_type;
0175             result_type operator()(Expr &expr, action_context const &) const
0176             {
0177                 return proto::value(expr);
0178             }
0179         };
0180 
0181         template<typename Expr, typename Type, typename Int>
0182         struct eval_terminal<Expr, action_arg<Type, Int> >
0183         {
0184             typedef typename action_arg<Type, Int>::reference result_type;
0185             result_type operator()(Expr &expr, action_context const &ctx) const
0186             {
0187                 action_args_type::const_iterator where_ = ctx.args().find(&typeid(proto::value(expr)));
0188                 if(where_ == ctx.args().end())
0189                 {
0190                     BOOST_THROW_EXCEPTION(
0191                         regex_error(
0192                             regex_constants::error_badarg
0193                           , "An argument to an action was unspecified"
0194                         )
0195                     );
0196                 }
0197                 return proto::value(expr).cast(where_->second);
0198             }
0199         };
0200 
0201         // eval
0202         template<typename Expr, typename Tag = typename Expr::proto_tag>
0203         struct eval
0204           : proto::default_eval<Expr, action_context const>
0205         {};
0206 
0207         template<typename Expr>
0208         struct eval<Expr, proto::tag::terminal>
0209           : eval_terminal<Expr, typename proto::result_of::value<Expr>::type>
0210         {};
0211 
0212         // Evaluate attributes like a1|42
0213         template<typename Expr>
0214         struct eval<Expr, attr_with_default_tag>
0215         {
0216             typedef
0217                 typename proto::result_of::value<
0218                     typename proto::result_of::left<
0219                         typename proto::result_of::child<
0220                             Expr
0221                         >::type
0222                     >::type
0223                 >::type
0224             temp_type;
0225 
0226             typedef typename temp_type::type result_type;
0227 
0228             result_type operator ()(Expr const &expr, action_context const &ctx) const
0229             {
0230                 return proto::value(proto::left(proto::child(expr))).t_
0231                     ? *proto::value(proto::left(proto::child(expr))).t_
0232                     :  proto::eval(proto::right(proto::child(expr)), ctx);
0233             }
0234         };
0235 
0236         #if BOOST_VERSION >= 103500
0237         template<typename Expr>
0238         struct eval<Expr, proto::tag::mem_ptr>
0239           : mem_ptr_eval<Expr, action_context const>
0240         {};
0241         #endif
0242 
0243     private:
0244         action_args_type *action_args_;
0245     };
0246 
0247     ///////////////////////////////////////////////////////////////////////////////
0248     // action
0249     //
0250     template<typename Actor>
0251     struct action
0252       : actionable
0253     {
0254         action(Actor const &actor)
0255           : actionable()
0256           , actor_(actor)
0257         {
0258         }
0259 
0260         virtual void execute(action_args_type *action_args) const
0261         {
0262             action_context const ctx(action_args);
0263             proto::eval(this->actor_, ctx);
0264         }
0265 
0266     private:
0267         Actor actor_;
0268     };
0269 
0270     ///////////////////////////////////////////////////////////////////////////////
0271     // subreg_transform
0272     //
0273     struct subreg_transform : proto::transform<subreg_transform>
0274     {
0275         template<typename Expr, typename State, typename Data>
0276         struct impl : proto::transform_impl<Expr, State, Data>
0277         {
0278             typedef typename impl::state state_type;
0279 
0280             typedef
0281                 typename proto::terminal<sub_match<typename state_type::iterator> >::type
0282             result_type;
0283 
0284             result_type operator ()(
0285                 typename impl::expr_param
0286               , typename impl::state_param state
0287               , typename impl::data_param data
0288             ) const
0289             {
0290                 return result_type::make(state.sub_matches_[ data ]);
0291             }
0292         };
0293     };
0294 
0295     ///////////////////////////////////////////////////////////////////////////////
0296     // mark_transform
0297     //
0298     struct mark_transform : proto::transform<mark_transform>
0299     {
0300         template<typename Expr, typename State, typename Data>
0301         struct impl : proto::transform_impl<Expr, State, Data>
0302         {
0303             typedef typename impl::state state_type;
0304             typedef
0305                 typename proto::terminal<sub_match<typename state_type::iterator> >::type
0306             result_type;
0307 
0308             result_type operator ()(
0309                 typename impl::expr_param expr
0310               , typename impl::state_param state
0311               , typename impl::data_param
0312             ) const
0313             {
0314                 return result_type::make(state.sub_matches_[ proto::value(expr).mark_number_ ]);
0315             }
0316         };
0317     };
0318 
0319     ///////////////////////////////////////////////////////////////////////////////
0320     // opt
0321     //
0322     template<typename T>
0323     struct opt
0324     {
0325         typedef T type;
0326         typedef T const &reference;
0327 
0328         opt(T const *t)
0329           : t_(t)
0330         {}
0331 
0332         operator reference() const
0333         {
0334             BOOST_XPR_ENSURE_(0 != this->t_, regex_constants::error_badattr, "Use of uninitialized regex attribute");
0335             return *this->t_;
0336         }
0337 
0338         T const *t_;
0339     };
0340 
0341     ///////////////////////////////////////////////////////////////////////////////
0342     // attr_transform
0343     //
0344     struct attr_transform : proto::transform<attr_transform>
0345     {
0346         template<typename Expr, typename State, typename Data>
0347         struct impl : proto::transform_impl<Expr, State, Data>
0348         {
0349             typedef typename impl::expr expr_type;
0350 
0351             typedef
0352                 typename expr_type::proto_child0::matcher_type::value_type::second_type
0353             attr_type;
0354 
0355             typedef
0356                 typename proto::terminal<opt<attr_type> >::type
0357             result_type;
0358 
0359             result_type operator ()(
0360                 typename impl::expr_param
0361               , typename impl::state_param state
0362               , typename impl::data_param
0363             ) const
0364             {
0365                 int slot = typename expr_type::proto_child0::nbr_type();
0366                 attr_type const *attr = static_cast<attr_type const *>(state.attr_context_.attr_slots_[slot-1]);
0367                 return result_type::make(opt<attr_type>(attr));
0368             }
0369         };
0370     };
0371 
0372     ///////////////////////////////////////////////////////////////////////////////
0373     // attr_with_default_transform
0374     //
0375     template<typename Grammar, typename Callable = proto::callable>
0376     struct attr_with_default_transform : proto::transform<attr_with_default_transform<Grammar, Callable> >
0377     {
0378         template<typename Expr, typename State, typename Data>
0379         struct impl : proto::transform_impl<Expr, State, Data>
0380         {
0381             typedef
0382                 typename proto::unary_expr<
0383                     attr_with_default_tag
0384                   , typename Grammar::template impl<Expr, State, Data>::result_type
0385                 >::type
0386             result_type;
0387 
0388             result_type operator ()(
0389                 typename impl::expr_param expr
0390               , typename impl::state_param state
0391               , typename impl::data_param data
0392             ) const
0393             {
0394                 result_type that = {
0395                     typename Grammar::template impl<Expr, State, Data>()(expr, state, data)
0396                 };
0397                 return that;
0398             }
0399         };
0400     };
0401 
0402     ///////////////////////////////////////////////////////////////////////////////
0403     // by_ref_transform
0404     //
0405     struct by_ref_transform : proto::transform<by_ref_transform>
0406     {
0407         template<typename Expr, typename State, typename Data>
0408         struct impl : proto::transform_impl<Expr, State, Data>
0409         {
0410             typedef
0411                 typename proto::result_of::value<typename impl::expr_param>::type
0412             reference;
0413 
0414             typedef
0415                 typename proto::terminal<reference>::type
0416             result_type;
0417 
0418             result_type operator ()(
0419                 typename impl::expr_param expr
0420               , typename impl::state_param
0421               , typename impl::data_param
0422             ) const
0423             {
0424                 return result_type::make(proto::value(expr));
0425             }
0426         };
0427     };
0428 
0429     ///////////////////////////////////////////////////////////////////////////////
0430     // BindActionArgs
0431     //
0432     struct BindActionArgs
0433       : proto::or_<
0434             proto::when<proto::terminal<any_matcher>,                      subreg_transform>
0435           , proto::when<proto::terminal<mark_placeholder>,                 mark_transform>
0436           , proto::when<proto::terminal<read_attr<proto::_, proto::_> >,   attr_transform>
0437           , proto::when<proto::terminal<proto::_>,                         by_ref_transform>
0438           , proto::when<
0439                 proto::bitwise_or<proto::terminal<read_attr<proto::_, proto::_> >, BindActionArgs>
0440               , attr_with_default_transform<proto::bitwise_or<attr_transform, BindActionArgs> >
0441             >
0442           , proto::otherwise<proto::nary_expr<proto::_, proto::vararg<BindActionArgs> > >
0443         >
0444     {};
0445 
0446     ///////////////////////////////////////////////////////////////////////////////
0447     // action_matcher
0448     //
0449     template<typename Actor>
0450     struct action_matcher
0451       : quant_style<quant_none, 0, false>
0452     {
0453         int sub_;
0454         Actor actor_;
0455 
0456         action_matcher(Actor const &actor, int sub)
0457           : sub_(sub)
0458           , actor_(actor)
0459         {
0460         }
0461 
0462         template<typename BidiIter, typename Next>
0463         bool match(match_state<BidiIter> &state, Next const &next) const
0464         {
0465             // Bind the arguments
0466             typedef
0467                 typename boost::result_of<BindActionArgs(
0468                     Actor const &
0469                   , match_state<BidiIter> &
0470                   , int const &
0471                 )>::type
0472             action_type;
0473 
0474             action<action_type> actor(BindActionArgs()(this->actor_, state, this->sub_));
0475 
0476             // Put the action in the action list
0477             actionable const **action_list_tail = state.action_list_tail_;
0478             *state.action_list_tail_ = &actor;
0479             state.action_list_tail_ = &actor.next;
0480 
0481             // Match the rest of the pattern
0482             if(next.match(state))
0483             {
0484                 return true;
0485             }
0486 
0487             BOOST_ASSERT(0 == actor.next);
0488             // remove action from list
0489             *action_list_tail = 0;
0490             state.action_list_tail_ = action_list_tail;
0491             return false;
0492         }
0493     };
0494 
0495 }}}
0496 
0497 #if BOOST_MSVC
0498 #pragma warning(pop)
0499 #endif
0500 
0501 #endif