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/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> 19 20 namespace boost { namespace spirit 21 { 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. 25 26 template <typename Domain, typename Tag, typename Enable = void> 27 struct make_component 28 { 29 template <typename Sig> 30 struct result; 31 32 template <typename This, typename Elements, typename Modifiers> 33 struct result<This(Elements, Modifiers)>; 34 35 template <typename Elements, typename Modifiers> 36 typename result<make_component(Elements, Modifiers)>::type 37 operator()(Elements const& elements, Modifiers const& modifiers) const; 38 }; 39 40 namespace tag 41 { 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. 46 47 struct directive; 48 struct action; 49 } 50 51 template <typename Domain, typename T, typename Enable = void> 52 struct flatten_tree; 53 }} 54 55 namespace boost { namespace spirit { namespace detail 56 { 57 template <typename Expr, typename State, typename Data, typename Domain> 58 struct make_terminal_impl 59 : proto::transform_impl<Expr, State, Data> 60 { 61 typedef typename 62 proto::result_of::value<Expr>::type 63 value; 64 65 typedef typename result_of::make_cons<value>::type elements; 66 67 typedef 68 make_component<Domain, proto::tag::terminal> 69 make_component_; 70 71 typedef typename 72 make_component_::template 73 result<make_component_(elements, Data)>::type 74 result_type; 75 operator ()boost::spirit::detail::make_terminal_impl76 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 80 ) const 81 { 82 return typename make_terminal_impl::make_component_()( 83 detail::make_cons(proto::value(expr)) 84 , data 85 ); 86 } 87 }; 88 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> 92 { 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_; 96 97 typedef typename 98 make_component_::template 99 result<make_component_(elements, Data)>::type 100 result_type; 101 operator ()boost::spirit::detail::make_terminal_impl102 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 106 ) const 107 { 108 return typename make_terminal_impl::make_component_()( 109 detail::make_cons(expr) 110 , data 111 ); 112 } 113 }; 114 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> 118 {}; 119 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> 123 {}; 124 125 template <typename Domain> 126 struct make_terminal : proto::transform<make_terminal<Domain> > 127 { 128 template<typename Expr, typename State, typename Data> 129 struct impl : make_terminal_impl<Expr, State, Data, Domain> {}; 130 }; 131 132 template <typename Domain, typename Tag, typename Grammar> 133 struct make_unary : proto::transform<make_unary<Domain, Tag, Grammar> > 134 { 135 template<typename Expr, typename State, typename Data> 136 struct impl : proto::transform_impl<Expr, State, Data> 137 { 138 typedef typename 139 proto::result_of::child_c<Expr, 0>::type 140 child; 141 142 typedef typename Grammar:: 143 template result<Grammar(child, State, Data)>::type 144 child_component; 145 146 typedef typename 147 result_of::make_cons<child_component>::type 148 elements; 149 150 typedef make_component<Domain, Tag> make_component_; 151 152 typedef typename 153 make_component_::template 154 result<make_component_(elements, Data)>::type 155 result_type; 156 operator ()boost::spirit::detail::make_unary::impl157 result_type operator()( 158 typename impl::expr_param expr 159 , typename impl::state_param state 160 , typename impl::data_param data 161 ) const 162 { 163 return typename impl::make_component_()( 164 detail::make_cons( 165 Grammar()(proto::child(expr), state, data)) 166 , data 167 ); 168 } 169 }; 170 }; 171 172 // un-flattened version 173 template <typename Domain, typename Tag, typename Grammar, 174 bool flatten = flatten_tree<Domain, Tag>::value> 175 struct make_binary 176 { 177 template<typename Expr, typename State, typename Data> 178 struct impl : proto::transform_impl<Expr, State, Data> 179 { 180 typedef typename Grammar:: 181 template result<Grammar( 182 typename proto::result_of::child_c<Expr, 0>::type 183 , State, Data)>::type 184 lhs_component; 185 186 typedef typename Grammar:: 187 template result<Grammar( 188 typename proto::result_of::child_c<Expr, 1>::type 189 , State, Data)>::type 190 rhs_component; 191 192 typedef typename 193 result_of::make_cons< 194 lhs_component 195 , typename result_of::make_cons<rhs_component>::type 196 >::type 197 elements_type; 198 199 typedef make_component<Domain, Tag> make_component_; 200 201 typedef typename 202 make_component_::template 203 result<make_component_(elements_type, Data)>::type 204 result_type; 205 operator ()boost::spirit::detail::make_binary::impl206 result_type operator()( 207 typename impl::expr_param expr 208 , typename impl::state_param state 209 , typename impl::data_param data 210 ) const 211 { 212 elements_type elements = 213 detail::make_cons( 214 Grammar()( 215 proto::child_c<0>(expr), state, data) // LHS 216 , detail::make_cons( 217 Grammar()( 218 proto::child_c<1>(expr), state, data) // RHS 219 ) 220 ); 221 222 return make_component_()(elements, data); 223 } 224 }; 225 }; 226 227 template <typename Grammar> 228 struct make_binary_helper : proto::transform<make_binary_helper<Grammar> > 229 { 230 template<typename Expr, typename State, typename Data> 231 struct impl : proto::transform_impl<Expr, State, Data> 232 { 233 typedef typename Grammar:: 234 template result<Grammar(Expr, State, Data)>::type 235 lhs; 236 237 typedef typename result_of::make_cons<lhs, State>::type result_type; 238 operator ()boost::spirit::detail::make_binary_helper::impl239 result_type operator()( 240 typename impl::expr_param expr 241 , typename impl::state_param state 242 , typename impl::data_param data 243 ) const 244 { 245 return detail::make_cons(Grammar()(expr, state, data), state); 246 } 247 }; 248 }; 249 250 // Flattened version 251 template <typename Domain, typename Tag, typename Grammar> 252 struct make_binary<Domain, Tag, Grammar, true> 253 : proto::transform<make_binary<Domain, Tag, Grammar> > 254 { 255 template<typename Expr, typename State, typename Data> 256 struct impl : proto::transform_impl<Expr, State, Data> 257 { 258 typedef typename 259 proto::reverse_fold_tree< 260 proto::_ 261 , proto::make<fusion::nil_> 262 , make_binary_helper<Grammar> 263 >::template impl<Expr, State, Data> 264 reverse_fold_tree; 265 266 typedef typename reverse_fold_tree::result_type elements; 267 typedef make_component<Domain, Tag> make_component_; 268 269 typedef typename 270 make_component_::template 271 result<make_component_(elements, Data)>::type 272 result_type; 273 operator ()boost::spirit::detail::make_binary::impl274 result_type operator()( 275 typename impl::expr_param expr 276 , typename impl::state_param state 277 , typename impl::data_param data 278 ) const 279 { 280 return make_component_()( 281 reverse_fold_tree()(expr, state, data), data); 282 } 283 }; 284 }; 285 286 template <typename Domain, typename Grammar> 287 struct make_directive : proto::transform<make_directive<Domain, Grammar> > 288 { 289 template<typename Expr, typename State, typename Data> 290 struct impl : proto::transform_impl<Expr, State, Data> 291 { 292 typedef typename 293 proto::result_of::child_c<Expr, 0>::type 294 lhs; 295 296 typedef typename 297 proto::result_of::value<lhs>::type 298 tag_type; 299 300 typedef typename modify<Domain>:: 301 template result<modify<Domain>(tag_type, Data)>::type 302 modifier_type; 303 304 typedef typename Grammar:: 305 template result<Grammar( 306 typename proto::result_of::child_c<Expr, 1>::type 307 , State 308 , modifier_type 309 )>::type 310 rhs_component; 311 312 typedef typename 313 result_of::make_cons< 314 tag_type 315 , typename result_of::make_cons<rhs_component>::type 316 >::type 317 elements_type; 318 319 typedef make_component<Domain, tag::directive> make_component_; 320 321 typedef typename 322 make_component_::template 323 result<make_component_(elements_type, Data)>::type 324 result_type; 325 operator ()boost::spirit::detail::make_directive::impl326 result_type operator()( 327 typename impl::expr_param expr 328 , typename impl::state_param state 329 , typename impl::data_param data 330 ) const 331 { 332 tag_type tag = proto::value(proto::child_c<0>(expr)); 333 typename remove_reference<modifier_type>::type 334 modifier = modify<Domain>()(tag, data); 335 336 elements_type elements = 337 detail::make_cons( 338 tag // LHS 339 , detail::make_cons( 340 Grammar()( 341 proto::child_c<1>(expr) // RHS 342 , state, modifier) 343 ) 344 ); 345 346 return make_component_()(elements, data); 347 } 348 }; 349 }; 350 351 template <typename Domain, typename Grammar> 352 struct make_action : proto::transform<make_action<Domain, Grammar> > 353 { 354 template<typename Expr, typename State, typename Data> 355 struct impl : proto::transform_impl<Expr, State, Data> 356 { 357 typedef typename Grammar:: 358 template result<Grammar( 359 typename proto::result_of::child_c<Expr, 0>::type 360 , State 361 , Data 362 )>::type 363 lhs_component; 364 365 typedef 366 typename mpl::eval_if_c< 367 phoenix::is_actor< 368 typename proto::result_of::child_c<Expr, 1>::type 369 >::type::value 370 , proto::result_of::child_c<Expr, 1> 371 , proto::result_of::value< 372 typename proto::result_of::child_c<Expr, 1>::type 373 > 374 >::type 375 rhs_component; 376 377 typedef typename 378 result_of::make_cons< 379 lhs_component 380 , typename result_of::make_cons<rhs_component>::type 381 >::type 382 elements_type; 383 384 typedef make_component<Domain, tag::action> make_component_; 385 386 typedef typename 387 make_component_::template 388 result<make_component_(elements_type, Data)>::type 389 result_type; 390 operator ()boost::spirit::detail::make_action::impl391 result_type operator()( 392 typename impl::expr_param expr 393 , typename impl::state_param state 394 , typename impl::data_param data 395 ) const 396 { 397 return 398 (*this)( 399 expr 400 , state 401 , data 402 , typename phoenix::is_actor< 403 typename proto::result_of::child_c<Expr, 1>::type 404 >::type() 405 ); 406 } 407 operator ()boost::spirit::detail::make_action::impl408 result_type operator()( 409 typename impl::expr_param expr 410 , typename impl::state_param state 411 , typename impl::data_param data 412 , mpl::false_ 413 ) const 414 { 415 elements_type elements = 416 detail::make_cons( 417 Grammar()( 418 proto::child_c<0>(expr), state, data) // LHS 419 , detail::make_cons( 420 proto::value(proto::child_c<1>(expr))) // RHS 421 ); 422 423 return make_component_()(elements, data); 424 } 425 operator ()boost::spirit::detail::make_action::impl426 result_type operator()( 427 typename impl::expr_param expr 428 , typename impl::state_param state 429 , typename impl::data_param data 430 , mpl::true_ 431 ) const 432 { 433 elements_type elements = 434 detail::make_cons( 435 Grammar()( 436 proto::child_c<0>(expr), state, data) // LHS 437 , detail::make_cons( 438 proto::child_c<1>(expr)) // RHS 439 ); 440 441 return make_component_()(elements, data); 442 } 443 }; 444 }; 445 }}} 446 447 #endif 448