1 /*=============================================================================
2 Copyright (c) 2001-2011 Joel de Guzman
3 http://spirit.sourceforge.net/
5 Distributed under the Boost Software License, Version 1.0. (See accompanying
6 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 =============================================================================*/
8 #ifndef BOOST_SPIRIT_MAKE_COMPONENT_OCTOBER_16_2008_1250PM
9 #define BOOST_SPIRIT_MAKE_COMPONENT_OCTOBER_16_2008_1250PM
15 #include <boost/spirit/include/phoenix_core.hpp>
16 #include <boost/proto/proto.hpp>
17 #include <boost/spirit/home/support/detail/make_cons.hpp>
18 #include <boost/spirit/home/support/modify.hpp>
20 namespace boost { namespace spirit
22 // There is no real "component" class. Each domain is responsible
23 // for creating its own components. You need to specialize this for
24 // each component in your domain. Use this as a guide.
26 template <typename Domain, typename Tag, typename Enable = void>
29 template <typename Sig>
32 template <typename This, typename Elements, typename Modifiers>
33 struct result<This(Elements, Modifiers)>;
35 template <typename Elements, typename Modifiers>
36 typename result<make_component(Elements, Modifiers)>::type
37 operator()(Elements const& elements, Modifiers const& modifiers) const;
42 // Normally, we use proto tags as-is to distinguish operators.
43 // The special case is proto::tag::subscript. Spirit uses this
44 // as either sementic actions or directives. To distinguish between
45 // the two, we use these special tags below.
51 template <typename Domain, typename T, typename Enable = void>
55 namespace boost { namespace spirit { namespace detail
57 template <typename Expr, typename State, typename Data, typename Domain>
58 struct make_terminal_impl
59 : proto::transform_impl<Expr, State, Data>
62 proto::result_of::value<Expr>::type
65 typedef typename result_of::make_cons<value>::type elements;
68 make_component<Domain, proto::tag::terminal>
72 make_component_::template
73 result<make_component_(elements, Data)>::type
76 result_type operator()(
77 typename make_terminal_impl::expr_param expr
78 , typename make_terminal_impl::state_param /*state*/
79 , typename make_terminal_impl::data_param data
82 return typename make_terminal_impl::make_component_()(
83 detail::make_cons(proto::value(expr))
89 template <typename Expr, typename State, typename Data, typename Domain>
90 struct make_terminal_impl<phoenix::actor<Expr>, State, Data, Domain>
91 : proto::transform_impl<phoenix::actor<Expr>, State, Data>
93 typedef phoenix::actor<Expr> value;
94 typedef typename result_of::make_cons<value>::type elements;
95 typedef make_component<Domain, proto::tag::terminal> make_component_;
98 make_component_::template
99 result<make_component_(elements, Data)>::type
102 result_type operator()(
103 typename make_terminal_impl::expr_param expr
104 , typename make_terminal_impl::state_param /*state*/
105 , typename make_terminal_impl::data_param data
108 return typename make_terminal_impl::make_component_()(
109 detail::make_cons(expr)
115 template <typename Expr, typename State, typename Data, typename Domain>
116 struct make_terminal_impl<phoenix::actor<Expr> &, State, Data, Domain>
117 : make_terminal_impl<phoenix::actor<Expr>, State, Data, Domain>
120 template <typename Expr, typename State, typename Data, typename Domain>
121 struct make_terminal_impl<phoenix::actor<Expr> const &, State, Data, Domain>
122 : make_terminal_impl<phoenix::actor<Expr>, State, Data, Domain>
125 template <typename Domain>
126 struct make_terminal : proto::transform<make_terminal<Domain> >
128 template<typename Expr, typename State, typename Data>
129 struct impl : make_terminal_impl<Expr, State, Data, Domain> {};
132 template <typename Domain, typename Tag, typename Grammar>
133 struct make_unary : proto::transform<make_unary<Domain, Tag, Grammar> >
135 template<typename Expr, typename State, typename Data>
136 struct impl : proto::transform_impl<Expr, State, Data>
139 proto::result_of::child_c<Expr, 0>::type
142 typedef typename Grammar::
143 template result<Grammar(child, State, Data)>::type
147 result_of::make_cons<child_component>::type
150 typedef make_component<Domain, Tag> make_component_;
153 make_component_::template
154 result<make_component_(elements, Data)>::type
157 result_type operator()(
158 typename impl::expr_param expr
159 , typename impl::state_param state
160 , typename impl::data_param data
163 return typename impl::make_component_()(
165 Grammar()(proto::child(expr), state, data))
172 // un-flattened version
173 template <typename Domain, typename Tag, typename Grammar,
174 bool flatten = flatten_tree<Domain, Tag>::value>
177 template<typename Expr, typename State, typename Data>
178 struct impl : proto::transform_impl<Expr, State, Data>
180 typedef typename Grammar::
181 template result<Grammar(
182 typename proto::result_of::child_c<Expr, 0>::type
183 , State, Data)>::type
186 typedef typename Grammar::
187 template result<Grammar(
188 typename proto::result_of::child_c<Expr, 1>::type
189 , State, Data)>::type
193 result_of::make_cons<
195 , typename result_of::make_cons<rhs_component>::type
199 typedef make_component<Domain, Tag> make_component_;
202 make_component_::template
203 result<make_component_(elements_type, Data)>::type
206 result_type operator()(
207 typename impl::expr_param expr
208 , typename impl::state_param state
209 , typename impl::data_param data
212 elements_type elements =
215 proto::child_c<0>(expr), state, data) // LHS
218 proto::child_c<1>(expr), state, data) // RHS
222 return make_component_()(elements, data);
227 template <typename Grammar>
228 struct make_binary_helper : proto::transform<make_binary_helper<Grammar> >
230 template<typename Expr, typename State, typename Data>
231 struct impl : proto::transform_impl<Expr, State, Data>
233 typedef typename Grammar::
234 template result<Grammar(Expr, State, Data)>::type
237 typedef typename result_of::make_cons<lhs, State>::type result_type;
239 result_type operator()(
240 typename impl::expr_param expr
241 , typename impl::state_param state
242 , typename impl::data_param data
245 return detail::make_cons(Grammar()(expr, state, data), state);
251 template <typename Domain, typename Tag, typename Grammar>
252 struct make_binary<Domain, Tag, Grammar, true>
253 : proto::transform<make_binary<Domain, Tag, Grammar> >
255 template<typename Expr, typename State, typename Data>
256 struct impl : proto::transform_impl<Expr, State, Data>
259 proto::reverse_fold_tree<
261 , proto::make<fusion::nil_>
262 , make_binary_helper<Grammar>
263 >::template impl<Expr, State, Data>
266 typedef typename reverse_fold_tree::result_type elements;
267 typedef make_component<Domain, Tag> make_component_;
270 make_component_::template
271 result<make_component_(elements, Data)>::type
274 result_type operator()(
275 typename impl::expr_param expr
276 , typename impl::state_param state
277 , typename impl::data_param data
280 return make_component_()(
281 reverse_fold_tree()(expr, state, data), data);
286 template <typename Domain, typename Grammar>
287 struct make_directive : proto::transform<make_directive<Domain, Grammar> >
289 template<typename Expr, typename State, typename Data>
290 struct impl : proto::transform_impl<Expr, State, Data>
293 proto::result_of::child_c<Expr, 0>::type
297 proto::result_of::value<lhs>::type
300 typedef typename modify<Domain>::
301 template result<modify<Domain>(tag_type, Data)>::type
304 typedef typename Grammar::
305 template result<Grammar(
306 typename proto::result_of::child_c<Expr, 1>::type
313 result_of::make_cons<
315 , typename result_of::make_cons<rhs_component>::type
319 typedef make_component<Domain, tag::directive> make_component_;
322 make_component_::template
323 result<make_component_(elements_type, Data)>::type
326 result_type operator()(
327 typename impl::expr_param expr
328 , typename impl::state_param state
329 , typename impl::data_param data
332 tag_type tag = proto::value(proto::child_c<0>(expr));
333 typename remove_reference<modifier_type>::type
334 modifier = modify<Domain>()(tag, data);
336 elements_type elements =
341 proto::child_c<1>(expr) // RHS
346 return make_component_()(elements, data);
351 template <typename Domain, typename Grammar>
352 struct make_action : proto::transform<make_action<Domain, Grammar> >
354 template<typename Expr, typename State, typename Data>
355 struct impl : proto::transform_impl<Expr, State, Data>
357 typedef typename Grammar::
358 template result<Grammar(
359 typename proto::result_of::child_c<Expr, 0>::type
366 typename mpl::eval_if_c<
368 typename proto::result_of::child_c<Expr, 1>::type
370 , proto::result_of::child_c<Expr, 1>
371 , proto::result_of::value<
372 typename proto::result_of::child_c<Expr, 1>::type
378 result_of::make_cons<
380 , typename result_of::make_cons<rhs_component>::type
384 typedef make_component<Domain, tag::action> make_component_;
387 make_component_::template
388 result<make_component_(elements_type, Data)>::type
391 result_type operator()(
392 typename impl::expr_param expr
393 , typename impl::state_param state
394 , typename impl::data_param data
402 , typename phoenix::is_actor<
403 typename proto::result_of::child_c<Expr, 1>::type
408 result_type operator()(
409 typename impl::expr_param expr
410 , typename impl::state_param state
411 , typename impl::data_param data
415 elements_type elements =
418 proto::child_c<0>(expr), state, data) // LHS
420 proto::value(proto::child_c<1>(expr))) // RHS
423 return make_component_()(elements, data);
426 result_type operator()(
427 typename impl::expr_param expr
428 , typename impl::state_param state
429 , typename impl::data_param data
433 elements_type elements =
436 proto::child_c<0>(expr), state, data) // LHS
438 proto::child_c<1>(expr)) // RHS
441 return make_component_()(elements, data);