meta_create.hpp 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. // Copyright (c) 2001-2011 Hartmut Kaiser
  2. //
  3. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  4. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. #if !defined(BOOST_SPIRIT_QI_META_CREATE_NOV_21_2009_0432PM)
  6. #define BOOST_SPIRIT_QI_META_CREATE_NOV_21_2009_0432PM
  7. #if defined(_MSC_VER)
  8. #pragma once
  9. #endif
  10. #include <boost/spirit/home/qi/domain.hpp>
  11. #include <boost/spirit/home/support/common_terminals.hpp>
  12. #include <boost/spirit/home/support/auto/meta_create.hpp>
  13. #include <boost/utility/enable_if.hpp>
  14. #include <boost/variant.hpp>
  15. #include <boost/optional.hpp>
  16. #include <boost/config.hpp>
  17. #include <boost/mpl/and.hpp>
  18. #include <boost/mpl/not.hpp>
  19. #include <boost/mpl/fold.hpp>
  20. #include <boost/mpl/vector.hpp>
  21. #include <boost/mpl/push_back.hpp>
  22. #include <boost/proto/tags.hpp>
  23. #include <boost/type_traits/is_same.hpp>
  24. #include <boost/fusion/include/as_vector.hpp>
  25. ///////////////////////////////////////////////////////////////////////////////
  26. namespace boost { namespace spirit { namespace qi
  27. {
  28. ///////////////////////////////////////////////////////////////////////////
  29. // compatible STL containers
  30. template <typename Container>
  31. struct meta_create_container
  32. {
  33. typedef make_unary_proto_expr<
  34. typename Container::value_type
  35. , proto::tag::dereference, qi::domain
  36. > make_proto_expr;
  37. typedef typename make_proto_expr::type type;
  38. static type call()
  39. {
  40. return make_proto_expr::call();
  41. }
  42. };
  43. ///////////////////////////////////////////////////////////////////////////
  44. // Fusion sequences
  45. template <typename Sequence>
  46. struct meta_create_sequence
  47. {
  48. // create a mpl sequence from the given fusion sequence
  49. typedef typename mpl::fold<
  50. typename fusion::result_of::as_vector<Sequence>::type
  51. , mpl::vector<>, mpl::push_back<mpl::_, mpl::_>
  52. >::type sequence_type;
  53. typedef make_nary_proto_expr<
  54. sequence_type, proto::tag::shift_right, qi::domain
  55. > make_proto_expr;
  56. typedef typename make_proto_expr::type type;
  57. static type call()
  58. {
  59. return make_proto_expr::call();
  60. }
  61. };
  62. ///////////////////////////////////////////////////////////////////////////
  63. // the default is to use the standard streaming operator unless it's a
  64. // STL container or a fusion sequence
  65. // The default implementation will be chosen if no predefined mapping of
  66. // the data type T to a Qi component is defined.
  67. struct no_auto_mapping_exists {};
  68. template <typename T, typename Enable = void>
  69. struct meta_create_impl : mpl::identity<no_auto_mapping_exists> {};
  70. template <typename T>
  71. struct meta_create_impl<T
  72. , typename enable_if<mpl::and_<
  73. traits::is_container<T>, mpl::not_<traits::is_string<T> > >
  74. >::type>
  75. : meta_create_container<T> {};
  76. template <typename T>
  77. struct meta_create_impl<T, typename enable_if<
  78. spirit::detail::is_fusion_sequence_but_not_proto_expr<T>
  79. >::type>
  80. : meta_create_sequence<T> {};
  81. template <typename T, typename Enable = void>
  82. struct meta_create : meta_create_impl<T> {};
  83. ///////////////////////////////////////////////////////////////////////////
  84. // optional
  85. template <typename T>
  86. struct meta_create<boost::optional<T> >
  87. {
  88. typedef make_unary_proto_expr<
  89. T, proto::tag::negate, qi::domain
  90. > make_proto_expr;
  91. typedef typename make_proto_expr::type type;
  92. static type call()
  93. {
  94. return make_proto_expr::call();
  95. }
  96. };
  97. ///////////////////////////////////////////////////////////////////////////
  98. // alternatives
  99. template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
  100. struct meta_create<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
  101. {
  102. typedef make_nary_proto_expr<
  103. typename boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>::types
  104. , proto::tag::bitwise_or, qi::domain
  105. > make_proto_expr;
  106. typedef typename make_proto_expr::type type;
  107. static type call()
  108. {
  109. return make_proto_expr::call();
  110. }
  111. };
  112. ///////////////////////////////////////////////////////////////////////////
  113. // predefined specializations for primitive components
  114. // character generator
  115. template <>
  116. struct meta_create<char>
  117. {
  118. typedef spirit::standard::char_type type;
  119. static type call() { return type(); }
  120. };
  121. template <>
  122. struct meta_create<signed char>
  123. {
  124. typedef spirit::standard::char_type type;
  125. static type call() { return type(); }
  126. };
  127. template <>
  128. struct meta_create<wchar_t>
  129. {
  130. typedef spirit::standard_wide::char_type type;
  131. static type call() { return type(); }
  132. };
  133. template <>
  134. struct meta_create<unsigned char>
  135. {
  136. typedef spirit::standard::char_type type;
  137. static type call() { return type(); }
  138. };
  139. // boolean generator
  140. template <>
  141. struct meta_create<bool>
  142. {
  143. typedef spirit::bool_type type;
  144. static type call() { return type(); }
  145. };
  146. // integral generators
  147. template <>
  148. struct meta_create<int>
  149. {
  150. typedef spirit::int_type type;
  151. static type call() { return type(); }
  152. };
  153. template <>
  154. struct meta_create<short>
  155. {
  156. typedef spirit::short_type type;
  157. static type call() { return type(); }
  158. };
  159. template <>
  160. struct meta_create<long>
  161. {
  162. typedef spirit::long_type type;
  163. static type call() { return type(); }
  164. };
  165. template <>
  166. struct meta_create<unsigned int>
  167. {
  168. typedef spirit::uint_type type;
  169. static type call() { return type(); }
  170. };
  171. #if !defined(BOOST_NO_INTRINSIC_WCHAR_T)
  172. template <>
  173. struct meta_create<unsigned short>
  174. {
  175. typedef spirit::ushort_type type;
  176. static type call() { return type(); }
  177. };
  178. #endif
  179. template <>
  180. struct meta_create<unsigned long>
  181. {
  182. typedef spirit::ulong_type type;
  183. static type call() { return type(); }
  184. };
  185. #ifdef BOOST_HAS_LONG_LONG
  186. template <>
  187. struct meta_create<boost::long_long_type>
  188. {
  189. typedef spirit::long_long_type type;
  190. static type call() { return type(); }
  191. };
  192. template <>
  193. struct meta_create<boost::ulong_long_type>
  194. {
  195. typedef spirit::ulong_long_type type;
  196. static type call() { return type(); }
  197. };
  198. #endif
  199. // floating point generators
  200. template <>
  201. struct meta_create<float>
  202. {
  203. typedef spirit::float_type type;
  204. static type call() { return type(); }
  205. };
  206. template <>
  207. struct meta_create<double>
  208. {
  209. typedef spirit::double_type type;
  210. static type call() { return type(); }
  211. };
  212. template <>
  213. struct meta_create<long double>
  214. {
  215. typedef spirit::long_double_type type;
  216. static type call() { return type(); }
  217. };
  218. }}}
  219. ///////////////////////////////////////////////////////////////////////////////
  220. namespace boost { namespace spirit { namespace traits
  221. {
  222. ///////////////////////////////////////////////////////////////////////////
  223. // main customization point for create_parser
  224. template <typename T, typename Enable = void>
  225. struct create_parser : qi::meta_create<T> {};
  226. ///////////////////////////////////////////////////////////////////////////
  227. // dispatch this to the Qi related specializations
  228. template <typename T>
  229. struct meta_create<qi::domain, T>
  230. : create_parser<typename spirit::detail::remove_const_ref<T>::type> {};
  231. ///////////////////////////////////////////////////////////////////////////
  232. // Check whether a valid mapping exits for the given data type to a Qi
  233. // component
  234. template <typename T>
  235. struct meta_create_exists<qi::domain, T>
  236. : mpl::not_<is_same<
  237. qi::no_auto_mapping_exists
  238. , typename meta_create<qi::domain, T>::type
  239. > > {};
  240. }}}
  241. #endif