1 /*=============================================================================
2     Copyright (c) 2001-2011 Joel de Guzman
3     Copyright (c) 2011      Bryce Lelbach
4 
5     Distributed under the Boost Software License, Version 1.0. (See accompanying
6     file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 ==============================================================================*/
8 #if !defined(BOOST_SPIRIT_REAL_APRIL_18_2006_0850AM)
9 #define BOOST_SPIRIT_REAL_APRIL_18_2006_0850AM
10 
11 #if defined(_MSC_VER)
12 #pragma once
13 #endif
14 
15 #include <boost/spirit/home/qi/skip_over.hpp>
16 #include <boost/spirit/home/qi/detail/enable_lit.hpp>
17 #include <boost/spirit/home/qi/meta_compiler.hpp>
18 #include <boost/spirit/home/qi/parser.hpp>
19 #include <boost/spirit/home/qi/numeric/real_policies.hpp>
20 #include <boost/spirit/home/qi/numeric/numeric_utils.hpp>
21 #include <boost/spirit/home/qi/numeric/detail/real_impl.hpp>
22 #include <boost/spirit/home/support/common_terminals.hpp>
23 #include <boost/type_traits/is_same.hpp>
24 
25 namespace boost { namespace spirit
26 {
27     namespace qi
28     {
29         ///////////////////////////////////////////////////////////////////////
30         // forward declaration only
31         template <typename T>
32         struct real_policies;
33 
34         ///////////////////////////////////////////////////////////////////////
35         // This is the class that the user can instantiate directly in
36         // order to create a customized real parser
37         template <typename T = double, typename Policies = real_policies<T> >
38         struct real_parser
39           : spirit::terminal<tag::stateful_tag<Policies, tag::double_, T> >
40         {
41             typedef tag::stateful_tag<Policies, tag::double_, T> tag_type;
42 
real_parserboost::spirit::qi::real_parser43             real_parser() {}
real_parserboost::spirit::qi::real_parser44             real_parser(Policies const& p)
45               : spirit::terminal<tag_type>(p) {}
46         };
47     }
48 
49     ///////////////////////////////////////////////////////////////////////////
50     // Enablers
51     ///////////////////////////////////////////////////////////////////////////
52     template <> // enables float_
53     struct use_terminal<qi::domain, tag::float_>
54       : mpl::true_ {};
55 
56     template <> // enables double_
57     struct use_terminal<qi::domain, tag::double_>
58       : mpl::true_ {};
59 
60     template <> // enables long_double
61     struct use_terminal<qi::domain, tag::long_double>
62       : mpl::true_ {};
63 
64     ///////////////////////////////////////////////////////////////////////////
65     template <typename A0> // enables lit(n)
66     struct use_terminal<qi::domain
67         , terminal_ex<tag::lit, fusion::vector1<A0> >
68         , typename enable_if<is_same<A0, float> >::type>
69       : mpl::true_ {};
70 
71     template <typename A0> // enables lit(n)
72     struct use_terminal<qi::domain
73         , terminal_ex<tag::lit, fusion::vector1<A0> >
74         , typename enable_if<is_same<A0, double> >::type>
75       : mpl::true_ {};
76 
77     template <typename A0> // enables lit(n)
78     struct use_terminal<qi::domain
79         , terminal_ex<tag::lit, fusion::vector1<A0> >
80         , typename enable_if<is_same<A0, long double> >::type>
81       : mpl::true_ {};
82 
83     ///////////////////////////////////////////////////////////////////////////
84     template <typename A0> // enables float_(...)
85     struct use_terminal<qi::domain
86       , terminal_ex<tag::float_, fusion::vector1<A0> >
87     > : mpl::true_ {};
88 
89     template <typename A0> // enables double_(...)
90     struct use_terminal<qi::domain
91       , terminal_ex<tag::double_, fusion::vector1<A0> >
92     > : mpl::true_ {};
93 
94     template <typename A0> // enables long_double(...)
95     struct use_terminal<qi::domain
96       , terminal_ex<tag::long_double, fusion::vector1<A0> >
97     > : mpl::true_ {};
98 
99     template <> // enables *lazy* float_(...)
100     struct use_lazy_terminal<qi::domain, tag::float_, 1>
101       : mpl::true_ {};
102 
103     template <> // enables *lazy* double_(...)
104     struct use_lazy_terminal<qi::domain, tag::double_, 1>
105       : mpl::true_ {};
106 
107     template <> // enables *lazy* long_double_(...)
108     struct use_lazy_terminal<qi::domain, tag::long_double, 1>
109       : mpl::true_ {};
110 
111     ///////////////////////////////////////////////////////////////////////////
112     // enables custom real_parser
113     template <typename T, typename Policies>
114     struct use_terminal<qi::domain
115         , tag::stateful_tag<Policies, tag::double_, T> >
116       : mpl::true_ {};
117 
118     // enables custom real_parser(...)
119     template <typename T, typename Policies, typename A0>
120     struct use_terminal<qi::domain
121         , terminal_ex<tag::stateful_tag<Policies, tag::double_, T>
122         , fusion::vector1<A0> > >
123       : mpl::true_ {};
124 
125     // enables *lazy* custom real_parser(...)
126     template <typename T, typename Policies>
127     struct use_lazy_terminal<
128         qi::domain
129       , tag::stateful_tag<Policies, tag::double_, T>
130       , 1 // arity
131     > : mpl::true_ {};
132 }}
133 
134 namespace boost { namespace spirit { namespace qi
135 {
136 #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
137     using spirit::float_;
138     using spirit::double_;
139     using spirit::long_double;
140     using spirit::lit; // lit(1.0) is equivalent to 1.0
141 #endif
142 
143     using spirit::float_type;
144     using spirit::double_type;
145     using spirit::long_double_type;
146     using spirit::lit_type;
147 
148     ///////////////////////////////////////////////////////////////////////////
149     // This is the actual real number parser
150     ///////////////////////////////////////////////////////////////////////////
151     template <typename T, typename RealPolicies = real_policies<T> >
152     struct any_real_parser
153       : primitive_parser<any_real_parser<T, RealPolicies> >
154     {
155         template <typename Context, typename Iterator>
156         struct attribute
157         {
158             typedef T type;
159         };
160 
161         template <typename Iterator, typename Context, typename Skipper>
parseboost::spirit::qi::any_real_parser162         bool parse(Iterator& first, Iterator const& last
163           , Context& /*context*/, Skipper const& skipper
164           , T& attr_) const
165         {
166             typedef detail::real_impl<T, RealPolicies> extract;
167             qi::skip_over(first, last, skipper);
168             return extract::parse(first, last, attr_, RealPolicies());
169         }
170 
171         template <typename Iterator, typename Context
172           , typename Skipper, typename Attribute>
parseboost::spirit::qi::any_real_parser173         bool parse(Iterator& first, Iterator const& last
174           , Context& context, Skipper const& skipper
175           , Attribute& attr_param) const
176         {
177             // this case is called when Attribute is not T
178             T attr_;
179             if (parse(first, last, context, skipper, attr_))
180             {
181                 traits::assign_to(attr_, attr_param);
182                 return true;
183             }
184             return false;
185         }
186 
187         template <typename Context>
whatboost::spirit::qi::any_real_parser188         info what(Context& /*context*/) const
189         {
190             return info("real");
191         }
192     };
193 
194     template <typename T, typename RealPolicies = real_policies<T>
195             , bool no_attribute = true>
196     struct literal_real_parser
197       : primitive_parser<literal_real_parser<T, RealPolicies, no_attribute> >
198     {
199         template <typename Value>
literal_real_parserboost::spirit::qi::literal_real_parser200         literal_real_parser(Value const& n) : n_(n) {}
201 
202         template <typename Context, typename Iterator>
203         struct attribute
204           : mpl::if_c<no_attribute, unused_type, T>
205         {};
206 
207         template <typename Iterator, typename Context
208           , typename Skipper, typename Attribute>
parseboost::spirit::qi::literal_real_parser209         bool parse(Iterator& first, Iterator const& last
210           , Context&, Skipper const& skipper
211           , Attribute& attr_param) const
212         {
213             typedef detail::real_impl<T, RealPolicies> extract;
214             qi::skip_over(first, last, skipper);
215 
216             Iterator save = first;
217             T attr_;
218 
219             if (extract::parse(first, last, attr_, RealPolicies()) &&
220                 (attr_ == n_))
221             {
222                 traits::assign_to(attr_, attr_param);
223                 return true;
224             }
225 
226             first = save;
227             return false;
228         }
229 
230         template <typename Context>
whatboost::spirit::qi::literal_real_parser231         info what(Context& /*context*/) const
232         {
233             return info("real");
234         }
235 
236         T n_;
237     };
238 
239     ///////////////////////////////////////////////////////////////////////////
240     // Parser generators: make_xxx function (objects)
241     ///////////////////////////////////////////////////////////////////////////
242     template <typename T, typename Policies = real_policies<T> >
243     struct make_real
244     {
245         typedef any_real_parser<T, Policies> result_type;
246 
operator ()boost::spirit::qi::make_real247         result_type operator()(unused_type, unused_type) const
248         {
249             return result_type();
250         }
251     };
252 
253     template <typename T, typename Policies = real_policies<T> >
254     struct make_direct_real
255     {
256         typedef literal_real_parser<T, Policies, false> result_type;
257 
258         template <typename Terminal>
operator ()boost::spirit::qi::make_direct_real259         result_type operator()(Terminal const& term, unused_type) const
260         {
261             return result_type(T(fusion::at_c<0>(term.args)));
262         }
263     };
264 
265     template <typename T, typename Policies = real_policies<T> >
266     struct make_literal_real
267     {
268         typedef literal_real_parser<T, Policies> result_type;
269 
270         template <typename Terminal>
operator ()boost::spirit::qi::make_literal_real271         result_type operator()(Terminal const& term, unused_type) const
272         {
273             return result_type(fusion::at_c<0>(term.args));
274         }
275     };
276 
277     ///////////////////////////////////////////////////////////////////////////
278     template <typename Modifiers, typename A0>
279     struct make_primitive<
280           terminal_ex<tag::lit, fusion::vector1<A0> >
281         , Modifiers, typename enable_if<is_same<A0, float> >::type>
282       : make_literal_real<float> {};
283 
284     template <typename Modifiers, typename A0>
285     struct make_primitive<
286           terminal_ex<tag::lit, fusion::vector1<A0> >
287         , Modifiers, typename enable_if<is_same<A0, double> >::type>
288       : make_literal_real<double> {};
289 
290     template <typename Modifiers, typename A0>
291     struct make_primitive<
292           terminal_ex<tag::lit, fusion::vector1<A0> >
293         , Modifiers, typename enable_if<is_same<A0, long double> >::type>
294       : make_literal_real<long double> {};
295 
296     ///////////////////////////////////////////////////////////////////////////
297     template <typename T, typename Policies, typename Modifiers>
298     struct make_primitive<
299         tag::stateful_tag<Policies, tag::double_, T>, Modifiers>
300       : make_real<T, Policies> {};
301 
302     template <typename T, typename Policies, typename A0, typename Modifiers>
303     struct make_primitive<
304         terminal_ex<tag::stateful_tag<Policies, tag::double_, T>
305       , fusion::vector1<A0> >, Modifiers>
306       : make_direct_real<T, Policies> {};
307 
308     ///////////////////////////////////////////////////////////////////////////
309     template <typename Modifiers>
310     struct make_primitive<tag::float_, Modifiers>
311       : make_real<float> {};
312 
313     template <typename Modifiers, typename A0>
314     struct make_primitive<
315         terminal_ex<tag::float_
316       , fusion::vector1<A0> >, Modifiers>
317       : make_direct_real<float> {};
318 
319     ///////////////////////////////////////////////////////////////////////////
320     template <typename Modifiers>
321     struct make_primitive<tag::double_, Modifiers>
322       : make_real<double> {};
323 
324     template <typename Modifiers, typename A0>
325     struct make_primitive<
326         terminal_ex<tag::double_
327       , fusion::vector1<A0> >, Modifiers>
328       : make_direct_real<double> {};
329 
330     ///////////////////////////////////////////////////////////////////////////
331     template <typename Modifiers>
332     struct make_primitive<tag::long_double, Modifiers>
333       : make_real<long double> {};
334 
335     template <typename Modifiers, typename A0>
336     struct make_primitive<
337         terminal_ex<tag::long_double
338       , fusion::vector1<A0> >, Modifiers>
339       : make_direct_real<long double> {};
340 }}}
341 
342 #endif
343