meta_compiler.hpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  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_META_COMPILER_OCTOBER_16_2008_1258PM
  8. #define BOOST_SPIRIT_META_COMPILER_OCTOBER_16_2008_1258PM
  9. #if defined(_MSC_VER)
  10. #pragma once
  11. #endif
  12. #include <boost/config.hpp>
  13. #include <boost/spirit/include/phoenix_limits.hpp>
  14. #include <boost/detail/workaround.hpp>
  15. #include <boost/spirit/include/phoenix_limits.hpp> // needs to be included before proto
  16. #include <boost/proto/proto.hpp>
  17. #include <boost/spirit/home/support/make_component.hpp>
  18. #include <boost/spirit/home/support/modify.hpp>
  19. #include <boost/spirit/home/support/detail/make_cons.hpp>
  20. #include <boost/spirit/home/support/unused.hpp>
  21. #include <boost/spirit/home/support/assert_msg.hpp>
  22. #include <boost/utility/enable_if.hpp>
  23. #include <boost/type_traits/remove_reference.hpp>
  24. namespace boost { namespace spirit
  25. {
  26. // Some defaults...
  27. template <typename Domain, typename Tag, typename Enable = void>
  28. struct use_operator : mpl::false_ {};
  29. template <typename Domain, typename T, typename Enable = void>
  30. struct use_function : mpl::false_ {};
  31. template <typename Domain, typename T, typename Enable = void>
  32. struct use_directive : mpl::false_ {};
  33. template <typename Domain, typename T, typename Enable /* = void */>
  34. struct is_modifier_directive : mpl::false_ {};
  35. template <typename Domain, typename T, typename Enable = void>
  36. struct use_terminal : mpl::false_ {};
  37. template <typename Domain, typename T, typename Enable /*= void*/>
  38. struct flatten_tree : mpl::false_ {};
  39. // Our meta-compiler. This is the main engine that hooks Spirit
  40. // to the proto expression template engine.
  41. template <typename Domain>
  42. struct meta_compiler
  43. {
  44. struct meta_grammar;
  45. BOOST_SPIRIT_ASSERT_MSG((
  46. !use_operator<Domain, proto::tag::subscript>::value
  47. ), error_proto_tag_subscript_cannot_be_used, ());
  48. #if !BOOST_WORKAROUND(BOOST_MSVC, < 1400)
  49. // this is the non-broken part for compilers properly supporting
  50. // partial template specialization (VC7.1 does not)
  51. struct cases
  52. {
  53. template <typename Tag, typename Enable = void>
  54. struct case_
  55. : proto::not_<proto::_>
  56. {};
  57. ///////////////////////////////////////////////////////////////////
  58. // terminals
  59. ///////////////////////////////////////////////////////////////////
  60. template <typename Enable>
  61. struct case_<proto::tag::terminal, Enable>
  62. : proto::when<
  63. proto::if_<use_terminal<Domain, proto::_value>()>,
  64. detail::make_terminal<Domain>
  65. >
  66. {};
  67. template <typename Tag>
  68. struct case_<Tag, typename enable_if<use_operator<Domain, Tag> >::type>
  69. : proto::or_<
  70. ///////////////////////////////////////////////////////////////////
  71. // binary operators
  72. ///////////////////////////////////////////////////////////////////
  73. proto::when<proto::binary_expr<Tag, meta_grammar, meta_grammar>,
  74. detail::make_binary<Domain, Tag, meta_grammar>
  75. >,
  76. ///////////////////////////////////////////////////////////////////
  77. // unary operators
  78. ///////////////////////////////////////////////////////////////////
  79. proto::when<proto::unary_expr<Tag, meta_grammar>,
  80. detail::make_unary<Domain, Tag, meta_grammar>
  81. >
  82. >
  83. {};
  84. template <typename Enable>
  85. struct case_<proto::tag::subscript, Enable>
  86. : proto::or_<
  87. ///////////////////////////////////////////////////////////////////
  88. // directives
  89. ///////////////////////////////////////////////////////////////////
  90. proto::when<proto::binary_expr<proto::tag::subscript
  91. , proto::and_<
  92. proto::terminal<proto::_>
  93. , proto::if_<use_directive<Domain, proto::_value >()> >
  94. , meta_grammar>,
  95. detail::make_directive<Domain, meta_grammar>
  96. >,
  97. ///////////////////////////////////////////////////////////////////
  98. // semantic actions
  99. ///////////////////////////////////////////////////////////////////
  100. proto::when<proto::binary_expr<proto::tag::subscript
  101. , meta_grammar, proto::_>,
  102. detail::make_action<Domain, meta_grammar>
  103. >
  104. >
  105. {};
  106. };
  107. #else
  108. // this part actually constitutes invalid C++ code, but it allows us to
  109. // convince VC7.1 to do what we want
  110. struct cases
  111. {
  112. template <typename Tag, typename Enable = void>
  113. struct case_
  114. : proto::not_<proto::_>
  115. {};
  116. ///////////////////////////////////////////////////////////////////
  117. // terminals
  118. ///////////////////////////////////////////////////////////////////
  119. template <>
  120. struct case_<proto::tag::terminal>
  121. : proto::when<
  122. proto::if_<use_terminal<Domain, proto::_value>()>,
  123. detail::make_terminal<Domain>
  124. >
  125. {};
  126. template <typename Tag>
  127. struct case_<Tag>
  128. : proto::or_<
  129. ///////////////////////////////////////////////////////////////////
  130. // binary operators
  131. ///////////////////////////////////////////////////////////////////
  132. proto::when<proto::binary_expr<
  133. typename enable_if<use_operator<Domain, Tag>, Tag>::type
  134. , meta_grammar, meta_grammar>
  135. , detail::make_binary<Domain, Tag, meta_grammar>
  136. >,
  137. ///////////////////////////////////////////////////////////////////
  138. // unary operators
  139. ///////////////////////////////////////////////////////////////////
  140. proto::when<proto::unary_expr<
  141. typename enable_if<use_operator<Domain, Tag>, Tag>::type
  142. , meta_grammar>
  143. , detail::make_unary<Domain, Tag, meta_grammar>
  144. >
  145. >
  146. {};
  147. template <>
  148. struct case_<proto::tag::subscript>
  149. : proto::or_<
  150. ///////////////////////////////////////////////////////////////////
  151. // directives
  152. ///////////////////////////////////////////////////////////////////
  153. proto::when<proto::binary_expr<proto::tag::subscript
  154. , proto::and_<
  155. proto::terminal<proto::_>
  156. , proto::if_<use_directive<Domain, proto::_value >()> >
  157. , meta_grammar>,
  158. detail::make_directive<Domain, meta_grammar>
  159. >,
  160. ///////////////////////////////////////////////////////////////////
  161. // semantic actions
  162. ///////////////////////////////////////////////////////////////////
  163. proto::when<proto::binary_expr<proto::tag::subscript
  164. , meta_grammar, proto::_>,
  165. detail::make_action<Domain, meta_grammar>
  166. >
  167. >
  168. {};
  169. };
  170. #endif
  171. struct meta_grammar
  172. : proto::switch_<cases>
  173. {};
  174. };
  175. namespace result_of
  176. {
  177. // Default case
  178. template <typename Domain, typename Expr
  179. , typename Modifiers = unused_type, typename Enable = void>
  180. struct compile
  181. {
  182. typedef typename meta_compiler<Domain>::meta_grammar meta_grammar;
  183. typedef typename meta_grammar::
  184. template result<meta_grammar(Expr, mpl::void_, Modifiers)>::type
  185. type;
  186. };
  187. // If Expr is not a proto expression, make it a terminal
  188. template <typename Domain, typename Expr, typename Modifiers>
  189. struct compile<Domain, Expr, Modifiers,
  190. typename disable_if<proto::is_expr<Expr> >::type>
  191. : compile<Domain, typename proto::terminal<Expr>::type, Modifiers> {};
  192. }
  193. namespace traits
  194. {
  195. // Check if Expr matches the domain's grammar
  196. template <typename Domain, typename Expr>
  197. struct matches :
  198. proto::matches<
  199. typename proto::result_of::as_expr<
  200. typename remove_reference<Expr>::type>::type,
  201. typename meta_compiler<Domain>::meta_grammar
  202. >
  203. {
  204. };
  205. }
  206. namespace detail
  207. {
  208. template <typename Domain>
  209. struct compiler
  210. {
  211. // Default case
  212. template <typename Expr, typename Modifiers>
  213. static typename spirit::result_of::compile<Domain, Expr, Modifiers>::type
  214. compile(Expr const& expr, Modifiers modifiers, mpl::true_)
  215. {
  216. typename meta_compiler<Domain>::meta_grammar compiler;
  217. return compiler(expr, mpl::void_(), modifiers);
  218. }
  219. // If Expr is not a proto expression, make it a terminal
  220. template <typename Expr, typename Modifiers>
  221. static typename spirit::result_of::compile<Domain, Expr, Modifiers>::type
  222. compile(Expr const& expr, Modifiers modifiers, mpl::false_)
  223. {
  224. typename meta_compiler<Domain>::meta_grammar compiler;
  225. typedef typename detail::as_meta_element<Expr>::type expr_;
  226. typename proto::terminal<expr_>::type term = {expr};
  227. return compiler(term, mpl::void_(), modifiers);
  228. }
  229. };
  230. }
  231. template <typename Domain, typename Expr>
  232. inline typename result_of::compile<Domain, Expr, unused_type>::type
  233. compile(Expr const& expr)
  234. {
  235. typedef typename proto::is_expr<Expr>::type is_expr;
  236. return detail::compiler<Domain>::compile(expr, unused, is_expr());
  237. }
  238. template <typename Domain, typename Expr, typename Modifiers>
  239. inline typename result_of::compile<Domain, Expr, Modifiers>::type
  240. compile(Expr const& expr, Modifiers modifiers)
  241. {
  242. typedef typename proto::is_expr<Expr>::type is_expr;
  243. return detail::compiler<Domain>::compile(expr, modifiers, is_expr());
  244. }
  245. ///////////////////////////////////////////////////////////////////////////
  246. template <typename Elements, template <typename Subject> class generator>
  247. struct make_unary_composite
  248. {
  249. typedef typename
  250. fusion::result_of::value_at_c<Elements, 0>::type
  251. element_type;
  252. typedef generator<element_type> result_type;
  253. result_type operator()(Elements const& elements, unused_type) const
  254. {
  255. return result_type(fusion::at_c<0>(elements));
  256. }
  257. };
  258. template <typename Elements, template <typename Left, typename Right> class generator>
  259. struct make_binary_composite
  260. {
  261. typedef typename
  262. fusion::result_of::value_at_c<Elements, 0>::type
  263. left_type;
  264. typedef typename
  265. fusion::result_of::value_at_c<Elements, 1>::type
  266. right_type;
  267. typedef generator<left_type, right_type> result_type;
  268. result_type operator()(Elements const& elements, unused_type) const
  269. {
  270. return result_type(
  271. fusion::at_c<0>(elements)
  272. , fusion::at_c<1>(elements)
  273. );
  274. }
  275. };
  276. template <typename Elements, template <typename Elements_> class generator>
  277. struct make_nary_composite
  278. {
  279. typedef generator<Elements> result_type;
  280. result_type operator()(Elements const& elements, unused_type) const
  281. {
  282. return result_type(elements);
  283. }
  284. };
  285. }}
  286. #endif