1 /*============================================================================= 2 Copyright (c) 2001-2011 Joel de Guzman 3 http://spirit.sourceforge.net/ 4 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 10 11 #if defined(_MSC_VER) 12 #pragma once 13 #endif 14 15 #include <boost/spirit/home/support/detail/make_cons.hpp> 16 #include <boost/spirit/home/support/modify.hpp> 17 #include <boost/phoenix/core/actor.hpp> 18 #include <boost/phoenix/core/is_actor.hpp> 19 #include <boost/proto/tags.hpp> 20 #include <boost/proto/traits.hpp> 21 #include <boost/proto/transform.hpp> 22 23 namespace boost { namespace spirit 24 { 25 // There is no real "component" class. Each domain is responsible 26 // for creating its own components. You need to specialize this for 27 // each component in your domain. Use this as a guide. 28 29 template <typename Domain, typename Tag, typename Enable = void> 30 struct make_component 31 { 32 template <typename Sig> 33 struct result; 34 35 template <typename This, typename Elements, typename Modifiers> 36 struct result<This(Elements, Modifiers)>; 37 38 template <typename Elements, typename Modifiers> 39 typename result<make_component(Elements, Modifiers)>::type 40 operator()(Elements const& elements, Modifiers const& modifiers) const; 41 }; 42 43 namespace tag 44 { 45 // Normally, we use proto tags as-is to distinguish operators. 46 // The special case is proto::tag::subscript. Spirit uses this 47 // as either sementic actions or directives. To distinguish between 48 // the two, we use these special tags below. 49 50 struct directive; 51 struct action; 52 } 53 54 template <typename Domain, typename T, typename Enable = void> 55 struct flatten_tree; 56 }} 57 58 namespace boost { namespace spirit { namespace detail 59 { 60 template <typename Expr, typename State, typename Data, typename Domain> 61 struct make_terminal_impl 62 : proto::transform_impl<Expr, State, Data> 63 { 64 typedef typename 65 proto::result_of::value<Expr>::type 66 value; 67 68 typedef typename result_of::make_cons<value>::type elements; 69 70 typedef 71 make_component<Domain, proto::tag::terminal> 72 make_component_; 73 74 typedef typename 75 make_component_::template 76 result<make_component_(elements, Data)>::type 77 result_type; 78 operator ()boost::spirit::detail::make_terminal_impl79 result_type operator()( 80 typename make_terminal_impl::expr_param expr 81 , typename make_terminal_impl::state_param /*state*/ 82 , typename make_terminal_impl::data_param data 83 ) const 84 { 85 return typename make_terminal_impl::make_component_()( 86 detail::make_cons(proto::value(expr)) 87 , data 88 ); 89 } 90 }; 91 92 template <typename Expr, typename State, typename Data, typename Domain> 93 struct make_terminal_impl<phoenix::actor<Expr>, State, Data, Domain> 94 : proto::transform_impl<phoenix::actor<Expr>, State, Data> 95 { 96 typedef phoenix::actor<Expr> value; 97 typedef typename result_of::make_cons<value>::type elements; 98 typedef make_component<Domain, proto::tag::terminal> make_component_; 99 100 typedef typename 101 make_component_::template 102 result<make_component_(elements, Data)>::type 103 result_type; 104 operator ()boost::spirit::detail::make_terminal_impl105 result_type operator()( 106 typename make_terminal_impl::expr_param expr 107 , typename make_terminal_impl::state_param /*state*/ 108 , typename make_terminal_impl::data_param data 109 ) const 110 { 111 return typename make_terminal_impl::make_component_()( 112 detail::make_cons(expr) 113 , data 114 ); 115 } 116 }; 117 118 template <typename Expr, typename State, typename Data, typename Domain> 119 struct make_terminal_impl<phoenix::actor<Expr> &, State, Data, Domain> 120 : make_terminal_impl<phoenix::actor<Expr>, State, Data, Domain> 121 {}; 122 123 template <typename Expr, typename State, typename Data, typename Domain> 124 struct make_terminal_impl<phoenix::actor<Expr> const &, State, Data, Domain> 125 : make_terminal_impl<phoenix::actor<Expr>, State, Data, Domain> 126 {}; 127 128 template <typename Domain> 129 struct make_terminal : proto::transform<make_terminal<Domain> > 130 { 131 template<typename Expr, typename State, typename Data> 132 struct impl : make_terminal_impl<Expr, State, Data, Domain> {}; 133 }; 134 135 template <typename Domain, typename Tag, typename Grammar> 136 struct make_unary : proto::transform<make_unary<Domain, Tag, Grammar> > 137 { 138 template<typename Expr, typename State, typename Data> 139 struct impl : proto::transform_impl<Expr, State, Data> 140 { 141 typedef typename 142 proto::result_of::child_c<Expr, 0>::type 143 child; 144 145 typedef typename Grammar:: 146 template result<Grammar(child, State, Data)>::type 147 child_component; 148 149 typedef typename 150 result_of::make_cons<child_component>::type 151 elements; 152 153 typedef make_component<Domain, Tag> make_component_; 154 155 typedef typename 156 make_component_::template 157 result<make_component_(elements, Data)>::type 158 result_type; 159 operator ()boost::spirit::detail::make_unary::impl160 result_type operator()( 161 typename impl::expr_param expr 162 , typename impl::state_param state 163 , typename impl::data_param data 164 ) const 165 { 166 return typename impl::make_component_()( 167 detail::make_cons( 168 Grammar()(proto::child(expr), state, data)) 169 , data 170 ); 171 } 172 }; 173 }; 174 175 // un-flattened version 176 template <typename Domain, typename Tag, typename Grammar, 177 bool flatten = flatten_tree<Domain, Tag>::value> 178 struct make_binary 179 { 180 template<typename Expr, typename State, typename Data> 181 struct impl : proto::transform_impl<Expr, State, Data> 182 { 183 typedef typename Grammar:: 184 template result<Grammar( 185 typename proto::result_of::child_c<Expr, 0>::type 186 , State, Data)>::type 187 lhs_component; 188 189 typedef typename Grammar:: 190 template result<Grammar( 191 typename proto::result_of::child_c<Expr, 1>::type 192 , State, Data)>::type 193 rhs_component; 194 195 typedef typename 196 result_of::make_cons< 197 lhs_component 198 , typename result_of::make_cons<rhs_component>::type 199 >::type 200 elements_type; 201 202 typedef make_component<Domain, Tag> make_component_; 203 204 typedef typename 205 make_component_::template 206 result<make_component_(elements_type, Data)>::type 207 result_type; 208 operator ()boost::spirit::detail::make_binary::impl209 result_type operator()( 210 typename impl::expr_param expr 211 , typename impl::state_param state 212 , typename impl::data_param data 213 ) const 214 { 215 elements_type elements = 216 detail::make_cons( 217 Grammar()( 218 proto::child_c<0>(expr), state, data) // LHS 219 , detail::make_cons( 220 Grammar()( 221 proto::child_c<1>(expr), state, data) // RHS 222 ) 223 ); 224 225 return make_component_()(elements, data); 226 } 227 }; 228 }; 229 230 template <typename Grammar> 231 struct make_binary_helper : proto::transform<make_binary_helper<Grammar> > 232 { 233 template<typename Expr, typename State, typename Data> 234 struct impl : proto::transform_impl<Expr, State, Data> 235 { 236 typedef typename Grammar:: 237 template result<Grammar(Expr, State, Data)>::type 238 lhs; 239 240 typedef typename result_of::make_cons<lhs, State>::type result_type; 241 operator ()boost::spirit::detail::make_binary_helper::impl242 result_type operator()( 243 typename impl::expr_param expr 244 , typename impl::state_param state 245 , typename impl::data_param data 246 ) const 247 { 248 return detail::make_cons(Grammar()(expr, state, data), state); 249 } 250 }; 251 }; 252 253 // Flattened version 254 template <typename Domain, typename Tag, typename Grammar> 255 struct make_binary<Domain, Tag, Grammar, true> 256 : proto::transform<make_binary<Domain, Tag, Grammar> > 257 { 258 template<typename Expr, typename State, typename Data> 259 struct impl : proto::transform_impl<Expr, State, Data> 260 { 261 typedef typename 262 proto::reverse_fold_tree< 263 proto::_ 264 , proto::make<fusion::nil_> 265 , make_binary_helper<Grammar> 266 >::template impl<Expr, State, Data> 267 reverse_fold_tree; 268 269 typedef typename reverse_fold_tree::result_type elements; 270 typedef make_component<Domain, Tag> make_component_; 271 272 typedef typename 273 make_component_::template 274 result<make_component_(elements, Data)>::type 275 result_type; 276 operator ()boost::spirit::detail::make_binary::impl277 result_type operator()( 278 typename impl::expr_param expr 279 , typename impl::state_param state 280 , typename impl::data_param data 281 ) const 282 { 283 return make_component_()( 284 reverse_fold_tree()(expr, state, data), data); 285 } 286 }; 287 }; 288 289 template <typename Domain, typename Grammar> 290 struct make_directive : proto::transform<make_directive<Domain, Grammar> > 291 { 292 template<typename Expr, typename State, typename Data> 293 struct impl : proto::transform_impl<Expr, State, Data> 294 { 295 typedef typename 296 proto::result_of::child_c<Expr, 0>::type 297 lhs; 298 299 typedef typename 300 proto::result_of::value<lhs>::type 301 tag_type; 302 303 typedef typename modify<Domain>:: 304 template result<modify<Domain>(tag_type, Data)>::type 305 modifier_type; 306 307 typedef typename Grammar:: 308 template result<Grammar( 309 typename proto::result_of::child_c<Expr, 1>::type 310 , State 311 , modifier_type 312 )>::type 313 rhs_component; 314 315 typedef typename 316 result_of::make_cons< 317 tag_type 318 , typename result_of::make_cons<rhs_component>::type 319 >::type 320 elements_type; 321 322 typedef make_component<Domain, tag::directive> make_component_; 323 324 typedef typename 325 make_component_::template 326 result<make_component_(elements_type, Data)>::type 327 result_type; 328 operator ()boost::spirit::detail::make_directive::impl329 result_type operator()( 330 typename impl::expr_param expr 331 , typename impl::state_param state 332 , typename impl::data_param data 333 ) const 334 { 335 tag_type tag = proto::value(proto::child_c<0>(expr)); 336 typename remove_reference<modifier_type>::type 337 modifier = modify<Domain>()(tag, data); 338 339 elements_type elements = 340 detail::make_cons( 341 tag // LHS 342 , detail::make_cons( 343 Grammar()( 344 proto::child_c<1>(expr) // RHS 345 , state, modifier) 346 ) 347 ); 348 349 return make_component_()(elements, data); 350 } 351 }; 352 }; 353 354 template <typename Domain, typename Grammar> 355 struct make_action : proto::transform<make_action<Domain, Grammar> > 356 { 357 template<typename Expr, typename State, typename Data> 358 struct impl : proto::transform_impl<Expr, State, Data> 359 { 360 typedef typename Grammar:: 361 template result<Grammar( 362 typename proto::result_of::child_c<Expr, 0>::type 363 , State 364 , Data 365 )>::type 366 lhs_component; 367 368 typedef 369 typename mpl::eval_if_c< 370 phoenix::is_actor< 371 typename proto::result_of::child_c<Expr, 1>::type 372 >::type::value 373 , proto::result_of::child_c<Expr, 1> 374 , proto::result_of::value< 375 typename proto::result_of::child_c<Expr, 1>::type 376 > 377 >::type 378 rhs_component; 379 380 typedef typename 381 result_of::make_cons< 382 lhs_component 383 , typename result_of::make_cons<rhs_component>::type 384 >::type 385 elements_type; 386 387 typedef make_component<Domain, tag::action> make_component_; 388 389 typedef typename 390 make_component_::template 391 result<make_component_(elements_type, Data)>::type 392 result_type; 393 operator ()boost::spirit::detail::make_action::impl394 result_type operator()( 395 typename impl::expr_param expr 396 , typename impl::state_param state 397 , typename impl::data_param data 398 ) const 399 { 400 return 401 (*this)( 402 expr 403 , state 404 , data 405 , typename phoenix::is_actor< 406 typename proto::result_of::child_c<Expr, 1>::type 407 >::type() 408 ); 409 } 410 operator ()boost::spirit::detail::make_action::impl411 result_type operator()( 412 typename impl::expr_param expr 413 , typename impl::state_param state 414 , typename impl::data_param data 415 , mpl::false_ 416 ) const 417 { 418 elements_type elements = 419 detail::make_cons( 420 Grammar()( 421 proto::child_c<0>(expr), state, data) // LHS 422 , detail::make_cons( 423 proto::value(proto::child_c<1>(expr))) // RHS 424 ); 425 426 return make_component_()(elements, data); 427 } 428 operator ()boost::spirit::detail::make_action::impl429 result_type operator()( 430 typename impl::expr_param expr 431 , typename impl::state_param state 432 , typename impl::data_param data 433 , mpl::true_ 434 ) const 435 { 436 elements_type elements = 437 detail::make_cons( 438 Grammar()( 439 proto::child_c<0>(expr), state, data) // LHS 440 , detail::make_cons( 441 proto::child_c<1>(expr)) // RHS 442 ); 443 444 return make_component_()(elements, data); 445 } 446 }; 447 }; 448 }}} 449 450 #endif 451