meta_create.hpp 7.9 KB

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