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

source code of boost/libs/spirit/include/boost/spirit/home/qi/auto/meta_create.hpp