meta_compiler.hpp 12 KB

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