123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322 |
- ///////////////////////////////////////////////////////////////////////////////
- // as_action.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_STATIC_TRANSFORMS_AS_ACTION_HPP_EAN_04_05_2007
- #define BOOST_XPRESSIVE_DETAIL_STATIC_TRANSFORMS_AS_ACTION_HPP_EAN_04_05_2007
- // MS compatible compilers support #pragma once
- #if defined(_MSC_VER)
- # pragma once
- #endif
- #include <boost/mpl/sizeof.hpp>
- #include <boost/mpl/min_max.hpp>
- #include <boost/mpl/apply_wrap.hpp>
- #include <boost/xpressive/detail/detail_fwd.hpp>
- #include <boost/xpressive/detail/core/matcher/attr_end_matcher.hpp>
- #include <boost/xpressive/detail/static/static.hpp>
- #include <boost/xpressive/detail/static/transforms/as_quantifier.hpp>
- #include <boost/proto/core.hpp>
- #include <boost/proto/transform/arg.hpp>
- #include <boost/proto/transform/call.hpp>
- #include <boost/proto/transform/make.hpp>
- #include <boost/proto/transform/when.hpp>
- #include <boost/proto/transform/fold.hpp>
- #include <boost/proto/transform/fold_tree.hpp>
- namespace boost { namespace xpressive { namespace detail
- {
- ///////////////////////////////////////////////////////////////////////////////
- // read_attr
- // Placeholder that knows the slot number of an attribute as well as the type
- // of the object stored in it.
- template<typename Nbr, typename Matcher>
- struct read_attr
- {
- typedef Nbr nbr_type;
- typedef Matcher matcher_type;
- static Nbr nbr() { return Nbr(); }
- };
- template<typename Nbr, typename Matcher>
- struct read_attr<Nbr, Matcher &>
- {
- typedef Nbr nbr_type;
- typedef Matcher matcher_type;
- };
- }}}
- namespace boost { namespace xpressive { namespace grammar_detail
- {
- ///////////////////////////////////////////////////////////////////////////////
- // FindAttr
- // Look for patterns like (a1= terminal<RHS>) and return the type of the RHS.
- template<typename Nbr>
- struct FindAttr
- : or_<
- // Ignore nested actions, because attributes are scoped
- when< subscript<_, _>, _state >
- , when< terminal<_>, _state >
- , when< proto::assign<terminal<detail::attribute_placeholder<Nbr> >, _>, call<_value(_right)> >
- , otherwise< fold<_, _state, FindAttr<Nbr> > >
- >
- {};
- ///////////////////////////////////////////////////////////////////////////////
- // as_read_attr
- // For patterns like (a1 = RHS)[ref(i) = a1], transform to
- // (a1 = RHS)[ref(i) = read_attr<1, RHS>] so that when reading the attribute
- // we know what type is stored in the attribute slot.
- struct as_read_attr : proto::transform<as_read_attr>
- {
- template<typename Expr, typename State, typename Data>
- struct impl : proto::transform_impl<Expr, State, Data>
- {
- typedef typename impl::expr expr_type;
- typedef
- typename FindAttr<typename expr_type::proto_child0::nbr_type>::template impl<
- State
- , mpl::void_
- , int
- >::result_type
- attr_type;
- typedef
- typename proto::terminal<
- detail::read_attr<
- typename expr_type::proto_child0::nbr_type
- , BOOST_PROTO_UNCVREF(attr_type)
- >
- >::type
- result_type;
- result_type operator ()(proto::ignore, proto::ignore, proto::ignore) const
- {
- result_type that = {{}};
- return that;
- }
- };
- };
- ///////////////////////////////////////////////////////////////////////////////
- // DeepCopy
- // Turn all refs into values, and also bind all attribute placeholders with
- // the types from which they are being assigned.
- struct DeepCopy
- : or_<
- when< terminal<detail::attribute_placeholder<_> >, as_read_attr>
- , when< terminal<_>, proto::_deep_copy>
- , otherwise< nary_expr<_, vararg<DeepCopy> > >
- >
- {};
- ///////////////////////////////////////////////////////////////////////////////
- // attr_nbr
- // For an attribute placeholder, return the attribute's slot number.
- struct attr_nbr : proto::transform<attr_nbr>
- {
- 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::nbr_type::type result_type;
- };
- };
- struct max_attr;
- ///////////////////////////////////////////////////////////////////////////////
- // MaxAttr
- // In an action (rx)[act], find the largest attribute slot being used.
- struct MaxAttr
- : or_<
- when< terminal<detail::attribute_placeholder<_> >, attr_nbr>
- , when< terminal<_>, make<mpl::int_<0> > >
- // Ignore nested actions, because attributes are scoped:
- , when< subscript<_, _>, make<mpl::int_<0> > >
- , otherwise< fold<_, make<mpl::int_<0> >, max_attr> >
- >
- {};
- ///////////////////////////////////////////////////////////////////////////////
- // max_attr
- // Take the maximum of the current attr slot number and the state.
- struct max_attr : proto::transform<max_attr>
- {
- template<typename Expr, typename State, typename Data>
- struct impl : proto::transform_impl<Expr, State, Data>
- {
- typedef
- typename mpl::max<
- typename impl::state
- , typename MaxAttr::template impl<Expr, State, Data>::result_type
- >::type
- result_type;
- };
- };
- ///////////////////////////////////////////////////////////////////////////////
- // as_attr_matcher
- // turn a1=matcher into attr_matcher<Matcher>(1)
- struct as_attr_matcher : proto::transform<as_attr_matcher>
- {
- template<typename Expr, typename State, typename Data>
- struct impl : proto::transform_impl<Expr, State, Data>
- {
- typedef typename impl::expr expr_type;
- typedef typename impl::data data_type;
- typedef
- detail::attr_matcher<
- typename proto::result_of::value<typename expr_type::proto_child1>::type
- , typename data_type::traits_type
- , typename data_type::icase_type
- >
- result_type;
- result_type operator ()(
- typename impl::expr_param expr
- , typename impl::state_param
- , typename impl::data_param data
- ) const
- {
- return result_type(
- proto::value(proto::left(expr)).nbr()
- , proto::value(proto::right(expr))
- , data.traits()
- );
- }
- };
- };
- ///////////////////////////////////////////////////////////////////////////////
- // add_attrs
- // Wrap an expression in attr_begin_matcher/attr_end_matcher pair
- struct add_attrs : proto::transform<add_attrs>
- {
- template<typename Expr, typename State, typename Data>
- struct impl : proto::transform_impl<Expr, State, Data>
- {
- typedef
- detail::attr_begin_matcher<
- typename MaxAttr::template impl<Expr, mpl::int_<0>, int>::result_type
- >
- begin_type;
- typedef typename impl::expr expr_type;
- typedef
- typename shift_right<
- typename terminal<begin_type>::type
- , typename shift_right<
- Expr
- , terminal<detail::attr_end_matcher>::type
- >::type
- >::type
- result_type;
- result_type operator ()(
- typename impl::expr_param expr
- , typename impl::state_param
- , typename impl::data_param
- ) const
- {
- begin_type begin;
- detail::attr_end_matcher end;
- result_type that = {{begin}, {expr, {end}}};
- return that;
- }
- };
- };
- ///////////////////////////////////////////////////////////////////////////////
- // InsertAttrs
- struct InsertAttrs
- : if_<MaxAttr, add_attrs, _>
- {};
- ///////////////////////////////////////////////////////////////////////////////
- // CheckAssertion
- struct CheckAssertion
- : proto::function<terminal<detail::check_tag>, _>
- {};
- ///////////////////////////////////////////////////////////////////////////////
- // action_transform
- // Turn A[B] into (mark_begin(n) >> A >> mark_end(n) >> action_matcher<B>(n))
- // If A and B use attributes, wrap the above expression in
- // a attr_begin_matcher<Count> / attr_end_matcher pair, where Count is
- // the number of attribute slots used by the pattern/action.
- struct as_action : proto::transform<as_action>
- {
- template<typename Expr, typename State, typename Data>
- struct impl : proto::transform_impl<Expr, State, Data>
- {
- typedef typename proto::result_of::left<Expr>::type expr_type;
- typedef typename proto::result_of::right<Expr>::type action_type;
- typedef
- typename DeepCopy::impl<action_type, expr_type, int>::result_type
- action_copy_type;
- typedef
- typename InsertMark::impl<expr_type, State, Data>::result_type
- marked_expr_type;
- typedef
- typename mpl::if_c<
- proto::matches<action_type, CheckAssertion>::value
- , detail::predicate_matcher<action_copy_type>
- , detail::action_matcher<action_copy_type>
- >::type
- matcher_type;
- typedef
- typename proto::shift_right<
- marked_expr_type
- , typename proto::terminal<matcher_type>::type
- >::type
- no_attr_type;
- typedef
- typename InsertAttrs::impl<no_attr_type, State, Data>::result_type
- result_type;
- result_type operator ()(
- typename impl::expr_param expr
- , typename impl::state_param state
- , typename impl::data_param data
- ) const
- {
- int dummy = 0;
- marked_expr_type marked_expr =
- InsertMark::impl<expr_type, State, Data>()(proto::left(expr), state, data);
- no_attr_type that = {
- marked_expr
- , {
- matcher_type(
- DeepCopy::impl<action_type, expr_type, int>()(
- proto::right(expr)
- , proto::left(expr)
- , dummy
- )
- , proto::value(proto::left(marked_expr)).mark_number_
- )
- }
- };
- return InsertAttrs::impl<no_attr_type, State, Data>()(that, state, data);
- }
- };
- };
- }}}
- #endif
|