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