1 // Copyright (c) 2001-2011 Hartmut Kaiser
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)
6 #if !defined(BOOST_SPIRIT_QI_META_CREATE_NOV_21_2009_0432PM)
7 #define BOOST_SPIRIT_QI_META_CREATE_NOV_21_2009_0432PM
13 #include <boost/spirit/home/qi/domain.hpp>
14 #include <boost/spirit/home/support/common_terminals.hpp>
15 #include <boost/spirit/home/support/auto/meta_create.hpp>
17 #include <boost/utility/enable_if.hpp>
18 #include <boost/variant.hpp>
19 #include <boost/optional.hpp>
20 #include <boost/config.hpp>
21 #include <boost/mpl/and.hpp>
22 #include <boost/mpl/not.hpp>
23 #include <boost/mpl/fold.hpp>
24 #include <boost/mpl/vector.hpp>
25 #include <boost/mpl/push_back.hpp>
26 #include <boost/type_traits/is_same.hpp>
27 #include <boost/fusion/include/as_vector.hpp>
29 ///////////////////////////////////////////////////////////////////////////////
30 namespace boost { namespace spirit { namespace qi
32 ///////////////////////////////////////////////////////////////////////////
33 // compatible STL containers
34 template <typename Container>
35 struct meta_create_container
37 typedef make_unary_proto_expr<
38 typename Container::value_type
39 , proto::tag::dereference, qi::domain
42 typedef typename make_proto_expr::type type;
46 return make_proto_expr::call();
50 ///////////////////////////////////////////////////////////////////////////
52 template <typename Sequence>
53 struct meta_create_sequence
55 // create a mpl sequence from the given fusion sequence
56 typedef typename mpl::fold<
57 typename fusion::result_of::as_vector<Sequence>::type
58 , mpl::vector<>, mpl::push_back<mpl::_, mpl::_>
59 >::type sequence_type;
61 typedef make_nary_proto_expr<
62 sequence_type, proto::tag::shift_right, qi::domain
65 typedef typename make_proto_expr::type type;
69 return make_proto_expr::call();
73 ///////////////////////////////////////////////////////////////////////////
74 // the default is to use the standard streaming operator unless it's a
75 // STL container or a fusion sequence
77 // The default implementation will be chosen if no predefined mapping of
78 // the data type T to a Qi component is defined.
79 struct no_auto_mapping_exists {};
81 template <typename T, typename Enable = void>
82 struct meta_create_impl : mpl::identity<no_auto_mapping_exists> {};
85 struct meta_create_impl<T
86 , typename enable_if<mpl::and_<
87 traits::is_container<T>, mpl::not_<traits::is_string<T> > >
89 : meta_create_container<T> {};
92 struct meta_create_impl<T, typename enable_if<
93 spirit::detail::is_fusion_sequence_but_not_proto_expr<T>
95 : meta_create_sequence<T> {};
97 template <typename T, typename Enable = void>
98 struct meta_create : meta_create_impl<T> {};
100 ///////////////////////////////////////////////////////////////////////////
102 template <typename T>
103 struct meta_create<boost::optional<T> >
105 typedef make_unary_proto_expr<
106 T, proto::tag::negate, qi::domain
109 typedef typename make_proto_expr::type type;
113 return make_proto_expr::call();
117 ///////////////////////////////////////////////////////////////////////////
119 template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
120 struct meta_create<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
122 typedef make_nary_proto_expr<
123 typename boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>::types
124 , proto::tag::bitwise_or, qi::domain
127 typedef typename make_proto_expr::type type;
131 return make_proto_expr::call();
135 ///////////////////////////////////////////////////////////////////////////
136 // predefined specializations for primitive components
138 // character generator
140 struct meta_create<char>
142 typedef spirit::standard::char_type type;
143 static type call() { return type(); }
146 struct meta_create<signed char>
148 typedef spirit::standard::char_type type;
149 static type call() { return type(); }
152 struct meta_create<wchar_t>
154 typedef spirit::standard_wide::char_type type;
155 static type call() { return type(); }
159 struct meta_create<unsigned char>
161 typedef spirit::standard::char_type type;
162 static type call() { return type(); }
167 struct meta_create<bool>
169 typedef spirit::bool_type type;
170 static type call() { return type(); }
173 // integral generators
175 struct meta_create<int>
177 typedef spirit::int_type type;
178 static type call() { return type(); }
181 struct meta_create<short>
183 typedef spirit::short_type type;
184 static type call() { return type(); }
187 struct meta_create<long>
189 typedef spirit::long_type type;
190 static type call() { return type(); }
193 struct meta_create<unsigned int>
195 typedef spirit::uint_type type;
196 static type call() { return type(); }
198 #if !defined(BOOST_NO_INTRINSIC_WCHAR_T)
200 struct meta_create<unsigned short>
202 typedef spirit::ushort_type type;
203 static type call() { return type(); }
207 struct meta_create<unsigned long>
209 typedef spirit::ulong_type type;
210 static type call() { return type(); }
213 #ifdef BOOST_HAS_LONG_LONG
215 struct meta_create<boost::long_long_type>
217 typedef spirit::long_long_type type;
218 static type call() { return type(); }
221 struct meta_create<boost::ulong_long_type>
223 typedef spirit::ulong_long_type type;
224 static type call() { return type(); }
228 // floating point generators
230 struct meta_create<float>
232 typedef spirit::float_type type;
233 static type call() { return type(); }
236 struct meta_create<double>
238 typedef spirit::double_type type;
239 static type call() { return type(); }
242 struct meta_create<long double>
244 typedef spirit::long_double_type type;
245 static type call() { return type(); }
249 ///////////////////////////////////////////////////////////////////////////////
250 namespace boost { namespace spirit { namespace traits
252 ///////////////////////////////////////////////////////////////////////////
253 // main customization point for create_parser
254 template <typename T, typename Enable = void>
255 struct create_parser : qi::meta_create<T> {};
257 ///////////////////////////////////////////////////////////////////////////
258 // dispatch this to the Qi related specializations
259 template <typename T>
260 struct meta_create<qi::domain, T>
261 : create_parser<typename spirit::detail::remove_const_ref<T>::type> {};
263 ///////////////////////////////////////////////////////////////////////////
264 // Check whether a valid mapping exits for the given data type to a Qi
266 template <typename T>
267 struct meta_create_exists<qi::domain, T>
269 qi::no_auto_mapping_exists
270 , typename meta_create<qi::domain, T>::type