1 /*=============================================================================
2     Copyright (c) 2001-2011 Joel de Guzman
3     Copyright (c) 2001-2011 Hartmut Kaiser
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(SPIRIT_REAL_POLICIES_APRIL_17_2006_1158PM)
9 #define SPIRIT_REAL_POLICIES_APRIL_17_2006_1158PM
10 
11 #if defined(_MSC_VER)
12 #pragma once
13 #endif
14 
15 #include <boost/spirit/home/qi/numeric/numeric_utils.hpp>
16 #include <boost/spirit/home/qi/detail/string_parse.hpp>
17 
18 namespace boost { namespace spirit { namespace qi
19 {
20     ///////////////////////////////////////////////////////////////////////////
21     //  Default (unsigned) real number policies
22     ///////////////////////////////////////////////////////////////////////////
23     template <typename T>
24     struct ureal_policies
25     {
26         // trailing dot policy suggested by Gustavo Guerra
27         static bool const allow_leading_dot = true;
28         static bool const allow_trailing_dot = true;
29         static bool const expect_dot = false;
30 
31         template <typename Iterator>
32         static bool
parse_signboost::spirit::qi::ureal_policies33         parse_sign(Iterator& /*first*/, Iterator const& /*last*/)
34         {
35             return false;
36         }
37 
38         template <typename Iterator, typename Attribute>
39         static bool
parse_nboost::spirit::qi::ureal_policies40         parse_n(Iterator& first, Iterator const& last, Attribute& attr_)
41         {
42             return extract_uint<Attribute, 10, 1, -1>::call(first, last, attr_);
43         }
44 
45         template <typename Iterator>
46         static bool
parse_dotboost::spirit::qi::ureal_policies47         parse_dot(Iterator& first, Iterator const& last)
48         {
49             if (first == last || *first != '.')
50                 return false;
51             ++first;
52             return true;
53         }
54 
55         template <typename Iterator, typename Attribute>
56         static bool
parse_frac_nboost::spirit::qi::ureal_policies57         parse_frac_n(Iterator& first, Iterator const& last, Attribute& attr_, int& frac_digits)
58         {
59             Iterator savef = first;
60             bool r = extract_uint<Attribute, 10, 1, -1, true, true>::call(first, last, attr_);
61             if (r)
62             {
63                 // Optimization note: don't compute frac_digits if T is
64                 // an unused_type. This should be optimized away by the compiler.
65                 if (!is_same<T, unused_type>::value)
66                     frac_digits =
67                         static_cast<int>(std::distance(savef, first));
68                 // ignore extra (non-significant digits)
69                 extract_uint<unused_type, 10, 1, -1>::call(first, last, unused);
70             }
71             return r;
72         }
73 
74         template <typename Iterator>
75         static bool
parse_expboost::spirit::qi::ureal_policies76         parse_exp(Iterator& first, Iterator const& last)
77         {
78             if (first == last || (*first != 'e' && *first != 'E'))
79                 return false;
80             ++first;
81             return true;
82         }
83 
84         template <typename Iterator>
85         static bool
parse_exp_nboost::spirit::qi::ureal_policies86         parse_exp_n(Iterator& first, Iterator const& last, int& attr_)
87         {
88             return extract_int<int, 10, 1, -1>::call(first, last, attr_);
89         }
90 
91         ///////////////////////////////////////////////////////////////////////
92         //  The parse_nan() and parse_inf() functions get called whenever:
93         //
94         //    - a number to parse does not start with a digit (after having
95         //      successfully parsed an optional sign)
96         //
97         //  or
98         //
99         //    - after a floating point number of the value 1 (having no
100         //      exponential part and a fractional part value of 0) has been
101         //      parsed.
102         //
103         //  The first call allows to recognize representations of NaN or Inf
104         //  starting with a non-digit character (such as NaN, Inf, QNaN etc.).
105         //
106         //  The second call allows to recognize representation formats starting
107         //  with a 1.0 (such as 1.0#NAN or 1.0#INF etc.).
108         //
109         //  The functions should return true if a Nan or Inf has been found. In
110         //  this case the attr should be set to the matched value (NaN or
111         //  Inf). The optional sign will be automatically applied afterwards.
112         //
113         //  The default implementation below recognizes representations of NaN
114         //  and Inf as mandated by the C99 Standard and as proposed for
115         //  inclusion into the C++0x Standard: nan, nan(...), inf and infinity
116         //  (the matching is performed case-insensitively).
117         ///////////////////////////////////////////////////////////////////////
118         template <typename Iterator, typename Attribute>
119         static bool
parse_nanboost::spirit::qi::ureal_policies120         parse_nan(Iterator& first, Iterator const& last, Attribute& attr_)
121         {
122             if (first == last)
123                 return false;   // end of input reached
124 
125             if (*first != 'n' && *first != 'N')
126                 return false;   // not "nan"
127 
128             // nan[(...)] ?
129             if (detail::string_parse("nan", "NAN", first, last, unused))
130             {
131                 if (first != last && *first == '(')
132                 {
133                     // skip trailing (...) part
134                     Iterator i = first;
135 
136                     while (++i != last && *i != ')')
137                         ;
138                     if (i == last)
139                         return false;     // no trailing ')' found, give up
140 
141                     first = ++i;
142                 }
143                 attr_ = std::numeric_limits<T>::quiet_NaN();
144                 return true;
145             }
146             return false;
147         }
148 
149         template <typename Iterator, typename Attribute>
150         static bool
parse_infboost::spirit::qi::ureal_policies151         parse_inf(Iterator& first, Iterator const& last, Attribute& attr_)
152         {
153             if (first == last)
154                 return false;   // end of input reached
155 
156             if (*first != 'i' && *first != 'I')
157                 return false;   // not "inf"
158 
159             // inf or infinity ?
160             if (detail::string_parse("inf", "INF", first, last, unused))
161             {
162                 // skip allowed 'inity' part of infinity
163                 detail::string_parse("inity", "INITY", first, last, unused);
164                 attr_ = std::numeric_limits<T>::infinity();
165                 return true;
166             }
167             return false;
168         }
169     };
170 
171     ///////////////////////////////////////////////////////////////////////////
172     //  Default (signed) real number policies
173     ///////////////////////////////////////////////////////////////////////////
174     template <typename T>
175     struct real_policies : ureal_policies<T>
176     {
177         template <typename Iterator>
178         static bool
parse_signboost::spirit::qi::real_policies179         parse_sign(Iterator& first, Iterator const& last)
180         {
181             return extract_sign(first, last);
182         }
183     };
184 
185     template <typename T>
186     struct strict_ureal_policies : ureal_policies<T>
187     {
188         static bool const expect_dot = true;
189     };
190 
191     template <typename T>
192     struct strict_real_policies : real_policies<T>
193     {
194         static bool const expect_dot = true;
195     };
196 }}}
197 
198 #endif
199