You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and dots ('.'), can be up to 35 characters long. Letters must be lowercase.
		
		
		
		
		
			
		
			
				
					
					
						
							474 lines
						
					
					
						
							16 KiB
						
					
					
				
			
		
		
	
	
							474 lines
						
					
					
						
							16 KiB
						
					
					
				| /*============================================================================= | |
|   Copyright (c) 2001-2011 Joel de Guzman | |
|   http://spirit.sourceforge.net/ | |
|  | |
|   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_SPIRIT_MAKE_COMPONENT_OCTOBER_16_2008_1250PM | |
| #define BOOST_SPIRIT_MAKE_COMPONENT_OCTOBER_16_2008_1250PM | |
|  | |
| #if defined(_MSC_VER) | |
| #pragma once | |
| #endif | |
|  | |
| #include <boost/spirit/include/phoenix_core.hpp> | |
| #include <boost/proto/proto.hpp> | |
| #include <boost/spirit/home/support/detail/make_cons.hpp> | |
| #include <boost/spirit/home/support/modify.hpp> | |
|  | |
| namespace boost { namespace spirit | |
| { | |
|     // There is no real "component" class. Each domain is responsible | |
|     // for creating its own components. You need to specialize this for | |
|     // each component in your domain. Use this as a guide. | |
|  | |
|     template <typename Domain, typename Tag, typename Enable = void> | |
|     struct make_component | |
|     { | |
|         template <typename Sig> | |
|         struct result; | |
| 
 | |
|         template <typename This, typename Elements, typename Modifiers> | |
|         struct result<This(Elements, Modifiers)>; | |
| 
 | |
|         template <typename Elements, typename Modifiers> | |
|         typename result<make_component(Elements, Modifiers)>::type | |
|         operator()(Elements const& elements, Modifiers const& modifiers) const; | |
|     }; | |
| 
 | |
|     namespace tag | |
|     { | |
|         // Normally, we use proto tags as-is to distinguish operators. | |
|         // The special case is proto::tag::subscript. Spirit uses this | |
|         // as either sementic actions or directives. To distinguish between | |
|         // the two, we use these special tags below. | |
|  | |
|         struct directive; | |
|         struct action; | |
|     } | |
| 
 | |
|     template <typename Domain, typename T, typename Enable = void> | |
|     struct flatten_tree; | |
| }} | |
| 
 | |
| namespace boost { namespace spirit { namespace detail | |
| { | |
|     template <typename Expr, typename State, typename Data, typename Domain> | |
|     struct make_terminal_impl | |
|       : proto::transform_impl<Expr, State, Data> | |
|     { | |
|         typedef typename | |
|             proto::result_of::value<Expr>::type  | |
|         value; | |
| 
 | |
|         typedef typename result_of::make_cons<value>::type elements; | |
| 
 | |
|         typedef | |
|             make_component<Domain, proto::tag::terminal> | |
|         make_component_; | |
| 
 | |
|         typedef typename | |
|             make_component_::template | |
|                 result<make_component_(elements, Data)>::type | |
|         result_type; | |
| 
 | |
|         result_type operator()( | |
|             typename make_terminal_impl::expr_param expr | |
|           , typename make_terminal_impl::state_param /*state*/ | |
|           , typename make_terminal_impl::data_param data | |
|         ) const | |
|         { | |
|             return typename make_terminal_impl::make_component_()( | |
|                 detail::make_cons(proto::value(expr)) | |
|               , data | |
|             ); | |
|         } | |
|     }; | |
| 
 | |
|     template <typename Expr, typename State, typename Data, typename Domain> | |
|     struct make_terminal_impl<phoenix::actor<Expr>, State, Data, Domain> | |
|       : proto::transform_impl<phoenix::actor<Expr>, State, Data> | |
|     { | |
|         typedef phoenix::actor<Expr> value; | |
|         typedef typename result_of::make_cons<value>::type elements; | |
|         typedef make_component<Domain, proto::tag::terminal> make_component_; | |
| 
 | |
|         typedef typename | |
|             make_component_::template | |
|                 result<make_component_(elements, Data)>::type | |
|         result_type; | |
| 
 | |
|         result_type operator()( | |
|             typename make_terminal_impl::expr_param expr | |
|           , typename make_terminal_impl::state_param /*state*/ | |
|           , typename make_terminal_impl::data_param data | |
|         ) const | |
|         { | |
|             return typename make_terminal_impl::make_component_()( | |
|                 detail::make_cons(expr) | |
|               , data | |
|             ); | |
|         } | |
|     }; | |
| 
 | |
|     template <typename Expr, typename State, typename Data, typename Domain> | |
|     struct make_terminal_impl<phoenix::actor<Expr> &, State, Data, Domain> | |
|         : make_terminal_impl<phoenix::actor<Expr>, State, Data, Domain> | |
|     {}; | |
| 
 | |
|     template <typename Expr, typename State, typename Data, typename Domain> | |
|     struct make_terminal_impl<phoenix::actor<Expr> const &, State, Data, Domain> | |
|         : make_terminal_impl<phoenix::actor<Expr>, State, Data, Domain> | |
|     {}; | |
| 
 | |
|     template <typename Domain> | |
|     struct make_terminal : proto::transform<make_terminal<Domain> > | |
|     { | |
|         template<typename Expr, typename State, typename Data> | |
|         struct impl : make_terminal_impl<Expr, State, Data, Domain> {}; | |
|     }; | |
| 
 | |
|     template <typename Domain, typename Tag, typename Grammar> | |
|     struct make_unary : proto::transform<make_unary<Domain, Tag, Grammar> > | |
|     { | |
|         template<typename Expr, typename State, typename Data> | |
|         struct impl : proto::transform_impl<Expr, State, Data> | |
|         { | |
|             typedef typename | |
|                 proto::result_of::child_c<Expr, 0>::type | |
|             child; | |
| 
 | |
|             typedef typename Grammar:: | |
|                 template result<Grammar(child, State, Data)>::type | |
|             child_component; | |
| 
 | |
|             typedef typename | |
|                 result_of::make_cons<child_component>::type | |
|             elements; | |
| 
 | |
|             typedef make_component<Domain, Tag> make_component_; | |
| 
 | |
|             typedef typename | |
|                 make_component_::template | |
|                     result<make_component_(elements, Data)>::type | |
|             result_type; | |
| 
 | |
|             result_type operator()( | |
|                 typename impl::expr_param expr | |
|               , typename impl::state_param state | |
|               , typename impl::data_param data | |
|             ) const | |
|             { | |
|                 return typename impl::make_component_()( | |
|                     detail::make_cons( | |
|                         Grammar()(proto::child(expr), state, data)) | |
|                   , data | |
|                 ); | |
|             } | |
|         }; | |
|     }; | |
| 
 | |
|     // un-flattened version | |
|     template <typename Domain, typename Tag, typename Grammar, | |
|         bool flatten = flatten_tree<Domain, Tag>::value> | |
|     struct make_binary | |
|     { | |
|         template<typename Expr, typename State, typename Data> | |
|         struct impl : proto::transform_impl<Expr, State, Data> | |
|         { | |
|             typedef typename Grammar:: | |
|                 template result<Grammar( | |
|                     typename proto::result_of::child_c<Expr, 0>::type | |
|                   , State, Data)>::type | |
|             lhs_component; | |
| 
 | |
|             typedef typename Grammar:: | |
|                 template result<Grammar( | |
|                     typename proto::result_of::child_c<Expr, 1>::type | |
|                   , State, Data)>::type | |
|             rhs_component; | |
| 
 | |
|             typedef typename | |
|                 result_of::make_cons< | |
|                     lhs_component | |
|                   , typename result_of::make_cons<rhs_component>::type | |
|                 >::type | |
|             elements_type; | |
| 
 | |
|             typedef make_component<Domain, Tag> make_component_; | |
| 
 | |
|             typedef typename | |
|                 make_component_::template | |
|                     result<make_component_(elements_type, Data)>::type | |
|             result_type; | |
| 
 | |
|             result_type operator()( | |
|                 typename impl::expr_param expr | |
|               , typename impl::state_param state | |
|               , typename impl::data_param data | |
|             ) const | |
|             { | |
|                 elements_type elements = | |
|                     detail::make_cons( | |
|                         Grammar()( | |
|                             proto::child_c<0>(expr), state, data)       // LHS | |
|                       , detail::make_cons( | |
|                             Grammar()( | |
|                                 proto::child_c<1>(expr), state, data)   // RHS | |
|                         ) | |
|                     ); | |
| 
 | |
|                 return make_component_()(elements, data); | |
|             } | |
|         }; | |
|     }; | |
| 
 | |
|     template <typename Grammar> | |
|     struct make_binary_helper : proto::transform<make_binary_helper<Grammar> > | |
|     { | |
|         template<typename Expr, typename State, typename Data> | |
|         struct impl : proto::transform_impl<Expr, State, Data> | |
|         { | |
|             typedef typename Grammar:: | |
|                 template result<Grammar(Expr, State, Data)>::type | |
|             lhs; | |
| 
 | |
|             typedef typename result_of::make_cons<lhs, State>::type result_type; | |
| 
 | |
|             result_type operator()( | |
|                 typename impl::expr_param expr | |
|               , typename impl::state_param state | |
|               , typename impl::data_param data | |
|             ) const | |
|             { | |
|                 return detail::make_cons(Grammar()(expr, state, data), state); | |
|             } | |
|         }; | |
|     }; | |
| 
 | |
|     // Flattened version | |
|     template <typename Domain, typename Tag, typename Grammar> | |
|     struct make_binary<Domain, Tag, Grammar, true> | |
|       : proto::transform<make_binary<Domain, Tag, Grammar> > | |
|     { | |
|         template<typename Expr, typename State, typename Data> | |
|         struct impl : proto::transform_impl<Expr, State, Data> | |
|         { | |
|             typedef typename | |
|                 proto::reverse_fold_tree< | |
|                     proto::_ | |
|                   , proto::make<fusion::nil> | |
|                   , make_binary_helper<Grammar> | |
|                 >::template impl<Expr, State, Data> | |
|             reverse_fold_tree; | |
| 
 | |
|             typedef typename reverse_fold_tree::result_type elements; | |
|             typedef make_component<Domain, Tag> make_component_; | |
| 
 | |
|             typedef typename | |
|                 make_component_::template | |
|                     result<make_component_(elements, Data)>::type | |
|             result_type; | |
| 
 | |
|             result_type operator()( | |
|                 typename impl::expr_param expr | |
|               , typename impl::state_param state | |
|               , typename impl::data_param data | |
|             ) const | |
|             { | |
|                 return make_component_()( | |
|                     reverse_fold_tree()(expr, state, data), data); | |
|             } | |
|         }; | |
|     }; | |
| 
 | |
|     template <typename Domain, typename Grammar> | |
|     struct make_directive : proto::transform<make_directive<Domain, Grammar> > | |
|     { | |
|         template<typename Expr, typename State, typename Data> | |
|         struct impl : proto::transform_impl<Expr, State, Data> | |
|         { | |
|             typedef typename | |
|                 proto::result_of::child_c<Expr, 0>::type | |
|             lhs; | |
| 
 | |
|             typedef typename | |
|                 proto::result_of::value<lhs>::type | |
|             tag_type; | |
| 
 | |
|             typedef typename modify<Domain>:: | |
|                 template result<modify<Domain>(tag_type, Data)>::type | |
|             modifier_type; | |
| 
 | |
|             typedef typename Grammar:: | |
|                 template result<Grammar( | |
|                     typename proto::result_of::child_c<Expr, 1>::type | |
|                   , State | |
|                   , modifier_type | |
|                 )>::type | |
|             rhs_component; | |
| 
 | |
|             typedef typename | |
|                 result_of::make_cons< | |
|                     tag_type | |
|                   , typename result_of::make_cons<rhs_component>::type | |
|                 >::type | |
|             elements_type; | |
| 
 | |
|             typedef make_component<Domain, tag::directive> make_component_; | |
| 
 | |
|             typedef typename | |
|                 make_component_::template | |
|                     result<make_component_(elements_type, Data)>::type | |
|             result_type; | |
| 
 | |
|             result_type operator()( | |
|                 typename impl::expr_param expr | |
|               , typename impl::state_param state | |
|               , typename impl::data_param data | |
|             ) const | |
|             { | |
|                 tag_type tag = proto::value(proto::child_c<0>(expr)); | |
|                 typename remove_reference<modifier_type>::type | |
|                     modifier = modify<Domain>()(tag, data); | |
| 
 | |
|                 elements_type elements = | |
|                     detail::make_cons( | |
|                         tag                                 // LHS | |
|                       , detail::make_cons( | |
|                             Grammar()( | |
|                                 proto::child_c<1>(expr)     // RHS | |
|                               , state, modifier) | |
|                         ) | |
|                     ); | |
| 
 | |
|                 return make_component_()(elements, data); | |
|             } | |
|         }; | |
|     }; | |
| 
 | |
|     template <typename Domain, typename Grammar> | |
|     struct make_action : proto::transform<make_action<Domain, Grammar> > | |
|     { | |
|         template<typename Expr, typename State, typename Data> | |
|         struct impl : proto::transform_impl<Expr, State, Data> | |
|         { | |
|             typedef typename Grammar:: | |
|                 template result<Grammar( | |
|                     typename proto::result_of::child_c<Expr, 0>::type | |
|                   , State | |
|                   , Data | |
|                 )>::type | |
|             lhs_component; | |
| 
 | |
| #ifndef BOOST_SPIRIT_USE_PHOENIX_V3 | |
|             typedef typename | |
|                 proto::result_of::value< | |
|                     typename proto::result_of::child_c<Expr, 1>::type | |
|                 >::type | |
|             rhs_component; | |
| #else | |
|             typedef | |
|                 typename mpl::eval_if_c< | |
|                     phoenix::is_actor< | |
|                         typename proto::result_of::child_c<Expr, 1>::type | |
|                     >::type::value | |
|                   , proto::result_of::child_c<Expr, 1> | |
|                   , proto::result_of::value< | |
|                         typename proto::result_of::child_c<Expr, 1>::type | |
|                     > | |
|                 >::type | |
|                 rhs_component; | |
| #endif | |
|  | |
|             typedef typename | |
|                 result_of::make_cons< | |
|                     lhs_component | |
|                   , typename result_of::make_cons<rhs_component>::type | |
|                 >::type | |
|             elements_type; | |
| 
 | |
|             typedef make_component<Domain, tag::action> make_component_; | |
| 
 | |
|             typedef typename | |
|                 make_component_::template | |
|                     result<make_component_(elements_type, Data)>::type | |
|             result_type; | |
| 
 | |
| #ifndef BOOST_SPIRIT_USE_PHOENIX_V3 | |
|             result_type operator()( | |
|                 typename impl::expr_param expr | |
|               , typename impl::state_param state | |
|               , typename impl::data_param data | |
|             ) const | |
|             { | |
|                 elements_type elements = | |
|                     detail::make_cons( | |
|                         Grammar()( | |
|                             proto::child_c<0>(expr), state, data)   // LHS | |
|                       , detail::make_cons( | |
|                             proto::value(proto::child_c<1>(expr)))  // RHS | |
|                     ); | |
| 
 | |
|                 return make_component_()(elements, data); | |
|             } | |
| #else | |
|             result_type operator()( | |
|                 typename impl::expr_param expr | |
|               , typename impl::state_param state | |
|               , typename impl::data_param data | |
|             ) const | |
|             { | |
|                 return | |
|                     (*this)( | |
|                         expr | |
|                       , state | |
|                       , data | |
|                       , typename phoenix::is_actor< | |
|                             typename proto::result_of::child_c<Expr, 1>::type | |
|                         >::type() | |
|                     ); | |
|             } | |
|              | |
|             result_type operator()( | |
|                 typename impl::expr_param expr | |
|               , typename impl::state_param state | |
|               , typename impl::data_param data | |
|               , mpl::false_ | |
|             ) const | |
|             { | |
|                 elements_type elements = | |
|                     detail::make_cons( | |
|                         Grammar()( | |
|                             proto::child_c<0>(expr), state, data)   // LHS | |
|                       , detail::make_cons( | |
|                             proto::value(proto::child_c<1>(expr)))  // RHS | |
|                     ); | |
| 
 | |
|                 return make_component_()(elements, data); | |
|             } | |
| 
 | |
|             result_type operator()( | |
|                 typename impl::expr_param expr | |
|               , typename impl::state_param state | |
|               , typename impl::data_param data | |
|               , mpl::true_ | |
|             ) const | |
|             { | |
|                 elements_type elements = | |
|                     detail::make_cons( | |
|                         Grammar()( | |
|                             proto::child_c<0>(expr), state, data)   // LHS | |
|                       , detail::make_cons( | |
|                             proto::child_c<1>(expr))               // RHS | |
|                     ); | |
| 
 | |
|                 return make_component_()(elements, data); | |
|             } | |
| #endif | |
|         }; | |
|     }; | |
| }}} | |
| 
 | |
| #endif
 | |
| 
 |