• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 ///////////////////////////////////////////////////////////////////////////////
31 namespace 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 
callboost::spirit::qi::meta_create_container45         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 
callboost::spirit::qi::meta_create_sequence68         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 
callboost::spirit::qi::meta_create112         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 
callboost::spirit::qi::meta_create130         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;
callboost::spirit::qi::meta_create144         static type call() { return type(); }
145     };
146     template <>
147     struct meta_create<signed char>
148     {
149         typedef spirit::standard::char_type type;
callboost::spirit::qi::meta_create150         static type call() { return type(); }
151     };
152     template <>
153     struct meta_create<wchar_t>
154     {
155         typedef spirit::standard_wide::char_type type;
callboost::spirit::qi::meta_create156         static type call() { return type(); }
157     };
158 
159     template <>
160     struct meta_create<unsigned char>
161     {
162         typedef spirit::standard::char_type type;
callboost::spirit::qi::meta_create163         static type call() { return type(); }
164     };
165 
166     // boolean generator
167     template <>
168     struct meta_create<bool>
169     {
170         typedef spirit::bool_type type;
callboost::spirit::qi::meta_create171         static type call() { return type(); }
172     };
173 
174     // integral generators
175     template <>
176     struct meta_create<int>
177     {
178         typedef spirit::int_type type;
callboost::spirit::qi::meta_create179         static type call() { return type(); }
180     };
181     template <>
182     struct meta_create<short>
183     {
184         typedef spirit::short_type type;
callboost::spirit::qi::meta_create185         static type call() { return type(); }
186     };
187     template <>
188     struct meta_create<long>
189     {
190         typedef spirit::long_type type;
callboost::spirit::qi::meta_create191         static type call() { return type(); }
192     };
193     template <>
194     struct meta_create<unsigned int>
195     {
196         typedef spirit::uint_type type;
callboost::spirit::qi::meta_create197         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;
callboost::spirit::qi::meta_create204         static type call() { return type(); }
205     };
206 #endif
207     template <>
208     struct meta_create<unsigned long>
209     {
210         typedef spirit::ulong_type type;
callboost::spirit::qi::meta_create211         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;
callboost::spirit::qi::meta_create219         static type call() { return type(); }
220     };
221     template <>
222     struct meta_create<boost::ulong_long_type>
223     {
224         typedef spirit::ulong_long_type type;
callboost::spirit::qi::meta_create225         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;
callboost::spirit::qi::meta_create234         static type call() { return type(); }
235     };
236     template <>
237     struct meta_create<double>
238     {
239         typedef spirit::double_type type;
callboost::spirit::qi::meta_create240         static type call() { return type(); }
241     };
242     template <>
243     struct meta_create<long double>
244     {
245         typedef spirit::long_double_type type;
callboost::spirit::qi::meta_create246         static type call() { return type(); }
247     };
248 }}}
249 
250 ///////////////////////////////////////////////////////////////////////////////
251 namespace 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