Chris@16: /*============================================================================= Chris@16: Copyright (c) 2001-2011 Joel de Guzman Chris@16: http://spirit.sourceforge.net/ Chris@16: Chris@16: Distributed under the Boost Software License, Version 1.0. (See accompanying Chris@16: file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@16: =============================================================================*/ Chris@16: #ifndef BOOST_SPIRIT_MAKE_COMPONENT_OCTOBER_16_2008_1250PM Chris@16: #define BOOST_SPIRIT_MAKE_COMPONENT_OCTOBER_16_2008_1250PM Chris@16: Chris@16: #if defined(_MSC_VER) Chris@16: #pragma once Chris@16: #endif Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: namespace boost { namespace spirit Chris@16: { Chris@16: // There is no real "component" class. Each domain is responsible Chris@16: // for creating its own components. You need to specialize this for Chris@16: // each component in your domain. Use this as a guide. Chris@16: Chris@16: template Chris@16: struct make_component Chris@16: { Chris@16: template Chris@16: struct result; Chris@16: Chris@16: template Chris@16: struct result; Chris@16: Chris@16: template Chris@16: typename result::type Chris@16: operator()(Elements const& elements, Modifiers const& modifiers) const; Chris@16: }; Chris@16: Chris@16: namespace tag Chris@16: { Chris@16: // Normally, we use proto tags as-is to distinguish operators. Chris@16: // The special case is proto::tag::subscript. Spirit uses this Chris@16: // as either sementic actions or directives. To distinguish between Chris@16: // the two, we use these special tags below. Chris@16: Chris@16: struct directive; Chris@16: struct action; Chris@16: } Chris@16: Chris@16: template Chris@16: struct flatten_tree; Chris@16: }} Chris@16: Chris@16: namespace boost { namespace spirit { namespace detail Chris@16: { Chris@16: template Chris@16: struct make_terminal_impl Chris@16: : proto::transform_impl Chris@16: { Chris@16: typedef typename Chris@16: proto::result_of::value::type Chris@16: value; Chris@16: Chris@16: typedef typename result_of::make_cons::type elements; Chris@16: Chris@16: typedef Chris@16: make_component Chris@16: make_component_; Chris@16: Chris@16: typedef typename Chris@16: make_component_::template Chris@16: result::type Chris@16: result_type; Chris@16: Chris@16: result_type operator()( Chris@16: typename make_terminal_impl::expr_param expr Chris@16: , typename make_terminal_impl::state_param /*state*/ Chris@16: , typename make_terminal_impl::data_param data Chris@16: ) const Chris@16: { Chris@16: return typename make_terminal_impl::make_component_()( Chris@16: detail::make_cons(proto::value(expr)) Chris@16: , data Chris@16: ); Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: struct make_terminal_impl, State, Data, Domain> Chris@16: : proto::transform_impl, State, Data> Chris@16: { Chris@16: typedef phoenix::actor value; Chris@16: typedef typename result_of::make_cons::type elements; Chris@16: typedef make_component make_component_; Chris@16: Chris@16: typedef typename Chris@16: make_component_::template Chris@16: result::type Chris@16: result_type; Chris@16: Chris@16: result_type operator()( Chris@16: typename make_terminal_impl::expr_param expr Chris@16: , typename make_terminal_impl::state_param /*state*/ Chris@16: , typename make_terminal_impl::data_param data Chris@16: ) const Chris@16: { Chris@16: return typename make_terminal_impl::make_component_()( Chris@16: detail::make_cons(expr) Chris@16: , data Chris@16: ); Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: struct make_terminal_impl &, State, Data, Domain> Chris@16: : make_terminal_impl, State, Data, Domain> Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct make_terminal_impl const &, State, Data, Domain> Chris@16: : make_terminal_impl, State, Data, Domain> Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct make_terminal : proto::transform > Chris@16: { Chris@16: template Chris@16: struct impl : make_terminal_impl {}; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct make_unary : proto::transform > Chris@16: { Chris@16: template Chris@16: struct impl : proto::transform_impl Chris@16: { Chris@16: typedef typename Chris@16: proto::result_of::child_c::type Chris@16: child; Chris@16: Chris@16: typedef typename Grammar:: Chris@16: template result::type Chris@16: child_component; Chris@16: Chris@16: typedef typename Chris@16: result_of::make_cons::type Chris@16: elements; Chris@16: Chris@16: typedef make_component make_component_; Chris@16: Chris@16: typedef typename Chris@16: make_component_::template Chris@16: result::type Chris@16: result_type; Chris@16: Chris@16: result_type operator()( Chris@16: typename impl::expr_param expr Chris@16: , typename impl::state_param state Chris@16: , typename impl::data_param data Chris@16: ) const Chris@16: { Chris@16: return typename impl::make_component_()( Chris@16: detail::make_cons( Chris@16: Grammar()(proto::child(expr), state, data)) Chris@16: , data Chris@16: ); Chris@16: } Chris@16: }; Chris@16: }; Chris@16: Chris@16: // un-flattened version Chris@16: template ::value> Chris@16: struct make_binary Chris@16: { Chris@16: template Chris@16: struct impl : proto::transform_impl Chris@16: { Chris@16: typedef typename Grammar:: Chris@16: template result::type Chris@16: , State, Data)>::type Chris@16: lhs_component; Chris@16: Chris@16: typedef typename Grammar:: Chris@16: template result::type Chris@16: , State, Data)>::type Chris@16: rhs_component; Chris@16: Chris@16: typedef typename Chris@16: result_of::make_cons< Chris@16: lhs_component Chris@16: , typename result_of::make_cons::type Chris@16: >::type Chris@16: elements_type; Chris@16: Chris@16: typedef make_component make_component_; Chris@16: Chris@16: typedef typename Chris@16: make_component_::template Chris@16: result::type Chris@16: result_type; Chris@16: Chris@16: result_type operator()( Chris@16: typename impl::expr_param expr Chris@16: , typename impl::state_param state Chris@16: , typename impl::data_param data Chris@16: ) const Chris@16: { Chris@16: elements_type elements = Chris@16: detail::make_cons( Chris@16: Grammar()( Chris@16: proto::child_c<0>(expr), state, data) // LHS Chris@16: , detail::make_cons( Chris@16: Grammar()( Chris@16: proto::child_c<1>(expr), state, data) // RHS Chris@16: ) Chris@16: ); Chris@16: Chris@16: return make_component_()(elements, data); Chris@16: } Chris@16: }; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct make_binary_helper : proto::transform > Chris@16: { Chris@16: template Chris@16: struct impl : proto::transform_impl Chris@16: { Chris@16: typedef typename Grammar:: Chris@16: template result::type Chris@16: lhs; Chris@16: Chris@16: typedef typename result_of::make_cons::type result_type; Chris@16: Chris@16: result_type operator()( Chris@16: typename impl::expr_param expr Chris@16: , typename impl::state_param state Chris@16: , typename impl::data_param data Chris@16: ) const Chris@16: { Chris@16: return detail::make_cons(Grammar()(expr, state, data), state); Chris@16: } Chris@16: }; Chris@16: }; Chris@16: Chris@16: // Flattened version Chris@16: template Chris@16: struct make_binary Chris@16: : proto::transform > Chris@16: { Chris@16: template Chris@16: struct impl : proto::transform_impl Chris@16: { Chris@16: typedef typename Chris@16: proto::reverse_fold_tree< Chris@16: proto::_ Chris@101: , proto::make Chris@16: , make_binary_helper Chris@16: >::template impl Chris@16: reverse_fold_tree; Chris@16: Chris@16: typedef typename reverse_fold_tree::result_type elements; Chris@16: typedef make_component make_component_; Chris@16: Chris@16: typedef typename Chris@16: make_component_::template Chris@16: result::type Chris@16: result_type; Chris@16: Chris@16: result_type operator()( Chris@16: typename impl::expr_param expr Chris@16: , typename impl::state_param state Chris@16: , typename impl::data_param data Chris@16: ) const Chris@16: { Chris@16: return make_component_()( Chris@16: reverse_fold_tree()(expr, state, data), data); Chris@16: } Chris@16: }; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct make_directive : proto::transform > Chris@16: { Chris@16: template Chris@16: struct impl : proto::transform_impl Chris@16: { Chris@16: typedef typename Chris@16: proto::result_of::child_c::type Chris@16: lhs; Chris@16: Chris@16: typedef typename Chris@16: proto::result_of::value::type Chris@16: tag_type; Chris@16: Chris@16: typedef typename modify:: Chris@16: template result(tag_type, Data)>::type Chris@16: modifier_type; Chris@16: Chris@16: typedef typename Grammar:: Chris@16: template result::type Chris@16: , State Chris@16: , modifier_type Chris@16: )>::type Chris@16: rhs_component; Chris@16: Chris@16: typedef typename Chris@16: result_of::make_cons< Chris@16: tag_type Chris@16: , typename result_of::make_cons::type Chris@16: >::type Chris@16: elements_type; Chris@16: Chris@16: typedef make_component make_component_; Chris@16: Chris@16: typedef typename Chris@16: make_component_::template Chris@16: result::type Chris@16: result_type; Chris@16: Chris@16: result_type operator()( Chris@16: typename impl::expr_param expr Chris@16: , typename impl::state_param state Chris@16: , typename impl::data_param data Chris@16: ) const Chris@16: { Chris@16: tag_type tag = proto::value(proto::child_c<0>(expr)); Chris@16: typename remove_reference::type Chris@16: modifier = modify()(tag, data); Chris@16: Chris@16: elements_type elements = Chris@16: detail::make_cons( Chris@16: tag // LHS Chris@16: , detail::make_cons( Chris@16: Grammar()( Chris@16: proto::child_c<1>(expr) // RHS Chris@16: , state, modifier) Chris@16: ) Chris@16: ); Chris@16: Chris@16: return make_component_()(elements, data); Chris@16: } Chris@16: }; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct make_action : proto::transform > Chris@16: { Chris@16: template Chris@16: struct impl : proto::transform_impl Chris@16: { Chris@16: typedef typename Grammar:: Chris@16: template result::type Chris@16: , State Chris@16: , Data Chris@16: )>::type Chris@16: lhs_component; Chris@16: Chris@16: typedef Chris@16: typename mpl::eval_if_c< Chris@16: phoenix::is_actor< Chris@16: typename proto::result_of::child_c::type Chris@16: >::type::value Chris@16: , proto::result_of::child_c Chris@16: , proto::result_of::value< Chris@16: typename proto::result_of::child_c::type Chris@16: > Chris@16: >::type Chris@16: rhs_component; Chris@16: Chris@16: typedef typename Chris@16: result_of::make_cons< Chris@16: lhs_component Chris@16: , typename result_of::make_cons::type Chris@16: >::type Chris@16: elements_type; Chris@16: Chris@16: typedef make_component make_component_; Chris@16: Chris@16: typedef typename Chris@16: make_component_::template Chris@16: result::type Chris@16: result_type; Chris@16: Chris@16: result_type operator()( Chris@16: typename impl::expr_param expr Chris@16: , typename impl::state_param state Chris@16: , typename impl::data_param data Chris@16: ) const Chris@16: { Chris@16: return Chris@16: (*this)( Chris@16: expr Chris@16: , state Chris@16: , data Chris@16: , typename phoenix::is_actor< Chris@16: typename proto::result_of::child_c::type Chris@16: >::type() Chris@16: ); Chris@16: } Chris@16: Chris@16: result_type operator()( Chris@16: typename impl::expr_param expr Chris@16: , typename impl::state_param state Chris@16: , typename impl::data_param data Chris@16: , mpl::false_ Chris@16: ) const Chris@16: { Chris@16: elements_type elements = Chris@16: detail::make_cons( Chris@16: Grammar()( Chris@16: proto::child_c<0>(expr), state, data) // LHS Chris@16: , detail::make_cons( Chris@16: proto::value(proto::child_c<1>(expr))) // RHS Chris@16: ); Chris@16: Chris@16: return make_component_()(elements, data); Chris@16: } Chris@16: Chris@16: result_type operator()( Chris@16: typename impl::expr_param expr Chris@16: , typename impl::state_param state Chris@16: , typename impl::data_param data Chris@16: , mpl::true_ Chris@16: ) const Chris@16: { Chris@16: elements_type elements = Chris@16: detail::make_cons( Chris@16: Grammar()( Chris@16: proto::child_c<0>(expr), state, data) // LHS Chris@16: , detail::make_cons( Chris@16: proto::child_c<1>(expr)) // RHS Chris@16: ); Chris@16: Chris@16: return make_component_()(elements, data); Chris@16: } Chris@16: }; Chris@16: }; Chris@16: }}} Chris@16: Chris@16: #endif