123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501 |
- ///////////////////////////////////////////////////////////////////////////////
- // action_matcher.hpp
- //
- // Copyright 2008 Eric Niebler.
- // Copyright 2008 David Jenkins.
- //
- // Distributed under the Boost Software License, Version 1.0. (See
- // accompanying file LICENSE_1_0.txt or copy at
- // http://www.boost.org/LICENSE_1_0.txt)
- #ifndef BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_ACTION_MATCHER_HPP_EAN_10_04_2005
- #define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_ACTION_MATCHER_HPP_EAN_10_04_2005
- // MS compatible compilers support #pragma once
- #if defined(_MSC_VER)
- # pragma once
- #endif
- #include <boost/config.hpp>
- #include <boost/version.hpp>
- #include <boost/ref.hpp>
- #include <boost/assert.hpp>
- #include <boost/mpl/if.hpp>
- #include <boost/throw_exception.hpp>
- #include <boost/utility/result_of.hpp>
- #include <boost/type_traits/is_const.hpp>
- #include <boost/type_traits/remove_reference.hpp>
- #include <boost/xpressive/detail/detail_fwd.hpp>
- #include <boost/xpressive/detail/core/quant_style.hpp>
- #include <boost/xpressive/detail/core/action.hpp>
- #include <boost/xpressive/detail/core/state.hpp>
- #include <boost/proto/core.hpp>
- #include <boost/proto/context.hpp>
- #include <boost/xpressive/match_results.hpp> // for type_info_less
- #include <boost/xpressive/detail/static/transforms/as_action.hpp> // for 'read_attr'
- #if BOOST_VERSION >= 103500
- # include <boost/proto/fusion.hpp>
- # include <boost/fusion/include/transform_view.hpp>
- # include <boost/fusion/include/invoke.hpp>
- # include <boost/fusion/include/push_front.hpp>
- # include <boost/fusion/include/pop_front.hpp>
- #endif
- #if BOOST_MSVC
- #pragma warning(push)
- #pragma warning(disable : 4510) // default constructor could not be generated
- #pragma warning(disable : 4512) // assignment operator could not be generated
- #pragma warning(disable : 4610) // can never be instantiated - user defined constructor required
- #endif
- namespace boost { namespace xpressive { namespace detail
- {
- #if BOOST_VERSION >= 103500
- struct DataMember
- : proto::mem_ptr<proto::_, proto::terminal<proto::_> >
- {};
- template<typename Expr, long N>
- struct child_
- : remove_reference<
- typename proto::result_of::child_c<Expr &, N>::type
- >
- {};
- ///////////////////////////////////////////////////////////////////////////////
- // mem_ptr_eval
- // Rewrites expressions of the form x->*foo(a) into foo(x, a) and then
- // evaluates them.
- template<typename Expr, typename Context, bool IsDataMember = proto::matches<Expr, DataMember>::value>
- struct mem_ptr_eval
- {
- typedef typename child_<Expr, 0>::type left_type;
- typedef typename child_<Expr, 1>::type right_type;
- typedef
- typename proto::result_of::value<
- typename proto::result_of::child_c<right_type, 0>::type
- >::type
- function_type;
- typedef
- fusion::transform_view<
- typename fusion::result_of::push_front<
- typename fusion::result_of::pop_front<right_type>::type const
- , reference_wrapper<left_type>
- >::type const
- , proto::eval_fun<Context>
- >
- evaluated_args;
- typedef
- typename fusion::result_of::invoke<function_type, evaluated_args>::type
- result_type;
- result_type operator()(Expr &expr, Context &ctx) const
- {
- return fusion::invoke<function_type>(
- proto::value(proto::child_c<0>(proto::right(expr)))
- , evaluated_args(
- fusion::push_front(fusion::pop_front(proto::right(expr)), boost::ref(proto::left(expr)))
- , proto::eval_fun<Context>(ctx)
- )
- );
- }
- };
- ///////////////////////////////////////////////////////////////////////////////
- // mem_ptr_eval
- // Rewrites expressions of the form x->*foo into foo(x) and then
- // evaluates them.
- template<typename Expr, typename Context>
- struct mem_ptr_eval<Expr, Context, true>
- {
- typedef typename child_<Expr, 0>::type left_type;
- typedef typename child_<Expr, 1>::type right_type;
- typedef
- typename proto::result_of::value<right_type>::type
- function_type;
- typedef typename boost::result_of<
- function_type(typename proto::result_of::eval<left_type, Context>::type)
- >::type result_type;
- result_type operator()(Expr &expr, Context &ctx) const
- {
- return proto::value(proto::right(expr))(
- proto::eval(proto::left(expr), ctx)
- );
- }
- };
- #endif
- struct attr_with_default_tag
- {};
- template<typename T>
- struct opt;
- ///////////////////////////////////////////////////////////////////////////////
- // action_context
- //
- struct action_context
- {
- explicit action_context(action_args_type *action_args)
- : action_args_(action_args)
- {}
- action_args_type const &args() const
- {
- return *this->action_args_;
- }
- // eval_terminal
- template<typename Expr, typename Arg>
- struct eval_terminal
- : proto::default_eval<Expr, action_context const>
- {};
- template<typename Expr, typename Arg>
- struct eval_terminal<Expr, reference_wrapper<Arg> >
- {
- typedef Arg &result_type;
- result_type operator()(Expr &expr, action_context const &) const
- {
- return proto::value(expr).get();
- }
- };
- template<typename Expr, typename Arg>
- struct eval_terminal<Expr, opt<Arg> >
- {
- typedef Arg const &result_type;
- result_type operator()(Expr &expr, action_context const &) const
- {
- return proto::value(expr);
- }
- };
- template<typename Expr, typename Type, typename Int>
- struct eval_terminal<Expr, action_arg<Type, Int> >
- {
- typedef typename action_arg<Type, Int>::reference result_type;
- result_type operator()(Expr &expr, action_context const &ctx) const
- {
- action_args_type::const_iterator where_ = ctx.args().find(&typeid(proto::value(expr)));
- if(where_ == ctx.args().end())
- {
- BOOST_THROW_EXCEPTION(
- regex_error(
- regex_constants::error_badarg
- , "An argument to an action was unspecified"
- )
- );
- }
- return proto::value(expr).cast(where_->second);
- }
- };
- // eval
- template<typename Expr, typename Tag = typename Expr::proto_tag>
- struct eval
- : proto::default_eval<Expr, action_context const>
- {};
- template<typename Expr>
- struct eval<Expr, proto::tag::terminal>
- : eval_terminal<Expr, typename proto::result_of::value<Expr>::type>
- {};
- // Evaluate attributes like a1|42
- template<typename Expr>
- struct eval<Expr, attr_with_default_tag>
- {
- typedef
- typename proto::result_of::value<
- typename proto::result_of::left<
- typename proto::result_of::child<
- Expr
- >::type
- >::type
- >::type
- temp_type;
- typedef typename temp_type::type result_type;
- result_type operator ()(Expr const &expr, action_context const &ctx) const
- {
- return proto::value(proto::left(proto::child(expr))).t_
- ? *proto::value(proto::left(proto::child(expr))).t_
- : proto::eval(proto::right(proto::child(expr)), ctx);
- }
- };
- #if BOOST_VERSION >= 103500
- template<typename Expr>
- struct eval<Expr, proto::tag::mem_ptr>
- : mem_ptr_eval<Expr, action_context const>
- {};
- #endif
- private:
- action_args_type *action_args_;
- };
- ///////////////////////////////////////////////////////////////////////////////
- // action
- //
- template<typename Actor>
- struct action
- : actionable
- {
- action(Actor const &actor)
- : actionable()
- , actor_(actor)
- {
- }
- virtual void execute(action_args_type *action_args) const
- {
- action_context const ctx(action_args);
- proto::eval(this->actor_, ctx);
- }
- private:
- Actor actor_;
- };
- ///////////////////////////////////////////////////////////////////////////////
- // subreg_transform
- //
- struct subreg_transform : proto::transform<subreg_transform>
- {
- template<typename Expr, typename State, typename Data>
- struct impl : proto::transform_impl<Expr, State, Data>
- {
- typedef typename impl::state state_type;
- typedef
- typename proto::terminal<sub_match<typename state_type::iterator> >::type
- result_type;
- result_type operator ()(
- typename impl::expr_param
- , typename impl::state_param state
- , typename impl::data_param data
- ) const
- {
- return result_type::make(state.sub_matches_[ data ]);
- }
- };
- };
- ///////////////////////////////////////////////////////////////////////////////
- // mark_transform
- //
- struct mark_transform : proto::transform<mark_transform>
- {
- template<typename Expr, typename State, typename Data>
- struct impl : proto::transform_impl<Expr, State, Data>
- {
- typedef typename impl::state state_type;
- typedef
- typename proto::terminal<sub_match<typename state_type::iterator> >::type
- result_type;
- result_type operator ()(
- typename impl::expr_param expr
- , typename impl::state_param state
- , typename impl::data_param
- ) const
- {
- return result_type::make(state.sub_matches_[ proto::value(expr).mark_number_ ]);
- }
- };
- };
- ///////////////////////////////////////////////////////////////////////////////
- // opt
- //
- template<typename T>
- struct opt
- {
- typedef T type;
- typedef T const &reference;
- opt(T const *t)
- : t_(t)
- {}
- operator reference() const
- {
- BOOST_XPR_ENSURE_(0 != this->t_, regex_constants::error_badattr, "Use of uninitialized regex attribute");
- return *this->t_;
- }
- T const *t_;
- };
- ///////////////////////////////////////////////////////////////////////////////
- // attr_transform
- //
- struct attr_transform : proto::transform<attr_transform>
- {
- template<typename Expr, typename State, typename Data>
- struct impl : proto::transform_impl<Expr, State, Data>
- {
- typedef typename impl::expr expr_type;
- typedef
- typename expr_type::proto_child0::matcher_type::value_type::second_type
- attr_type;
- typedef
- typename proto::terminal<opt<attr_type> >::type
- result_type;
- result_type operator ()(
- typename impl::expr_param
- , typename impl::state_param state
- , typename impl::data_param
- ) const
- {
- int slot = typename expr_type::proto_child0::nbr_type();
- attr_type const *attr = static_cast<attr_type const *>(state.attr_context_.attr_slots_[slot-1]);
- return result_type::make(opt<attr_type>(attr));
- }
- };
- };
- ///////////////////////////////////////////////////////////////////////////////
- // attr_with_default_transform
- //
- template<typename Grammar, typename Callable = proto::callable>
- struct attr_with_default_transform : proto::transform<attr_with_default_transform<Grammar, Callable> >
- {
- template<typename Expr, typename State, typename Data>
- struct impl : proto::transform_impl<Expr, State, Data>
- {
- typedef
- typename proto::unary_expr<
- attr_with_default_tag
- , typename Grammar::template impl<Expr, State, Data>::result_type
- >::type
- result_type;
- result_type operator ()(
- typename impl::expr_param expr
- , typename impl::state_param state
- , typename impl::data_param data
- ) const
- {
- result_type that = {
- typename Grammar::template impl<Expr, State, Data>()(expr, state, data)
- };
- return that;
- }
- };
- };
- ///////////////////////////////////////////////////////////////////////////////
- // by_ref_transform
- //
- struct by_ref_transform : proto::transform<by_ref_transform>
- {
- template<typename Expr, typename State, typename Data>
- struct impl : proto::transform_impl<Expr, State, Data>
- {
- typedef
- typename proto::result_of::value<typename impl::expr_param>::type
- reference;
- typedef
- typename proto::terminal<reference>::type
- result_type;
- result_type operator ()(
- typename impl::expr_param expr
- , typename impl::state_param
- , typename impl::data_param
- ) const
- {
- return result_type::make(proto::value(expr));
- }
- };
- };
- ///////////////////////////////////////////////////////////////////////////////
- // BindActionArgs
- //
- struct BindActionArgs
- : proto::or_<
- proto::when<proto::terminal<any_matcher>, subreg_transform>
- , proto::when<proto::terminal<mark_placeholder>, mark_transform>
- , proto::when<proto::terminal<read_attr<proto::_, proto::_> >, attr_transform>
- , proto::when<proto::terminal<proto::_>, by_ref_transform>
- , proto::when<
- proto::bitwise_or<proto::terminal<read_attr<proto::_, proto::_> >, BindActionArgs>
- , attr_with_default_transform<proto::bitwise_or<attr_transform, BindActionArgs> >
- >
- , proto::otherwise<proto::nary_expr<proto::_, proto::vararg<BindActionArgs> > >
- >
- {};
- ///////////////////////////////////////////////////////////////////////////////
- // action_matcher
- //
- template<typename Actor>
- struct action_matcher
- : quant_style<quant_none, 0, false>
- {
- int sub_;
- Actor actor_;
- action_matcher(Actor const &actor, int sub)
- : sub_(sub)
- , actor_(actor)
- {
- }
- template<typename BidiIter, typename Next>
- bool match(match_state<BidiIter> &state, Next const &next) const
- {
- // Bind the arguments
- typedef
- typename boost::result_of<BindActionArgs(
- Actor const &
- , match_state<BidiIter> &
- , int const &
- )>::type
- action_type;
- action<action_type> actor(BindActionArgs()(this->actor_, state, this->sub_));
- // Put the action in the action list
- actionable const **action_list_tail = state.action_list_tail_;
- *state.action_list_tail_ = &actor;
- state.action_list_tail_ = &actor.next;
- // Match the rest of the pattern
- if(next.match(state))
- {
- return true;
- }
- BOOST_ASSERT(0 == actor.next);
- // remove action from list
- *action_list_tail = 0;
- state.action_list_tail_ = action_list_tail;
- return false;
- }
- };
- }}}
- #if BOOST_MSVC
- #pragma warning(pop)
- #endif
- #endif
|