make_component.hpp 15 KB

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