1 /*=============================================================================
2     Copyright (c) 2001-2014 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 #include <boost/spirit/home/x3/string/detail/string_parse.hpp>
12 #include <boost/spirit/home/x3/support/numeric_utils/extract_int.hpp>
13 
14 namespace boost { namespace spirit { namespace x3
15 {
16     ///////////////////////////////////////////////////////////////////////////
17     //  Default (unsigned) real number policies
18     ///////////////////////////////////////////////////////////////////////////
19     template <typename T>
20     struct ureal_policies
21     {
22         // trailing dot policy suggested by Gustavo Guerra
23         static bool const allow_leading_dot = true;
24         static bool const allow_trailing_dot = true;
25         static bool const expect_dot = false;
26 
27         template <typename Iterator>
28         static bool
parse_signboost::spirit::x3::ureal_policies29         parse_sign(Iterator& /*first*/, Iterator const& /*last*/)
30         {
31             return false;
32         }
33 
34         template <typename Iterator, typename Attribute>
35         static bool
parse_nboost::spirit::x3::ureal_policies36         parse_n(Iterator& first, Iterator const& last, Attribute& attr_)
37         {
38             return extract_uint<T, 10, 1, -1>::call(first, last, attr_);
39         }
40 
41         template <typename Iterator>
42         static bool
parse_dotboost::spirit::x3::ureal_policies43         parse_dot(Iterator& first, Iterator const& last)
44         {
45             if (first == last || *first != '.')
46                 return false;
47             ++first;
48             return true;
49         }
50 
51         template <typename Iterator, typename Attribute>
52         static bool
parse_frac_nboost::spirit::x3::ureal_policies53         parse_frac_n(Iterator& first, Iterator const& last, Attribute& attr_)
54         {
55             return extract_uint<T, 10, 1, -1, true>::call(first, last, attr_);
56         }
57 
58         template <typename Iterator>
59         static bool
parse_expboost::spirit::x3::ureal_policies60         parse_exp(Iterator& first, Iterator const& last)
61         {
62             if (first == last || (*first != 'e' && *first != 'E'))
63                 return false;
64             ++first;
65             return true;
66         }
67 
68         template <typename Iterator>
69         static bool
parse_exp_nboost::spirit::x3::ureal_policies70         parse_exp_n(Iterator& first, Iterator const& last, int& attr_)
71         {
72             return extract_int<int, 10, 1, -1>::call(first, last, attr_);
73         }
74 
75         ///////////////////////////////////////////////////////////////////////
76         //  The parse_nan() and parse_inf() functions get called whenever:
77         //
78         //    - a number to parse does not start with a digit (after having
79         //      successfully parsed an optional sign)
80         //
81         //  or
82         //
83         //    - after a floating point number of the value 1 (having no
84         //      exponential part and a fractional part value of 0) has been
85         //      parsed.
86         //
87         //  The first call allows to recognize representations of NaN or Inf
88         //  starting with a non-digit character (such as NaN, Inf, QNaN etc.).
89         //
90         //  The second call allows to recognize representation formats starting
91         //  with a 1.0 (such as 1.0#NAN or 1.0#INF etc.).
92         //
93         //  The functions should return true if a Nan or Inf has been found. In
94         //  this case the attr should be set to the matched value (NaN or
95         //  Inf). The optional sign will be automatically applied afterwards.
96         //
97         //  The default implementation below recognizes representations of NaN
98         //  and Inf as mandated by the C99 Standard and as proposed for
99         //  inclusion into the C++0x Standard: nan, nan(...), inf and infinity
100         //  (the matching is performed case-insensitively).
101         ///////////////////////////////////////////////////////////////////////
102         template <typename Iterator, typename Attribute>
103         static bool
parse_nanboost::spirit::x3::ureal_policies104         parse_nan(Iterator& first, Iterator const& last, Attribute& attr_)
105         {
106             if (first == last)
107                 return false;   // end of input reached
108 
109             if (*first != 'n' && *first != 'N')
110                 return false;   // not "nan"
111 
112             // nan[(...)] ?
113             if (detail::string_parse("nan", "NAN", first, last, unused))
114             {
115                 if (*first == '(')
116                 {
117                     // skip trailing (...) part
118                     Iterator i = first;
119 
120                     while (++i != last && *i != ')')
121                         ;
122                     if (i == last)
123                         return false;     // no trailing ')' found, give up
124 
125                     first = ++i;
126                 }
127                 attr_ = std::numeric_limits<T>::quiet_NaN();
128                 return true;
129             }
130             return false;
131         }
132 
133         template <typename Iterator, typename Attribute>
134         static bool
parse_infboost::spirit::x3::ureal_policies135         parse_inf(Iterator& first, Iterator const& last, Attribute& attr_)
136         {
137             if (first == last)
138                 return false;   // end of input reached
139 
140             if (*first != 'i' && *first != 'I')
141                 return false;   // not "inf"
142 
143             // inf or infinity ?
144             if (detail::string_parse("inf", "INF", first, last, unused))
145             {
146                 // skip allowed 'inity' part of infinity
147                 detail::string_parse("inity", "INITY", first, last, unused);
148                 attr_ = std::numeric_limits<T>::infinity();
149                 return true;
150             }
151             return false;
152         }
153     };
154 
155     ///////////////////////////////////////////////////////////////////////////
156     //  Default (signed) real number policies
157     ///////////////////////////////////////////////////////////////////////////
158     template <typename T>
159     struct real_policies : ureal_policies<T>
160     {
161         template <typename Iterator>
162         static bool
parse_signboost::spirit::x3::real_policies163         parse_sign(Iterator& first, Iterator const& last)
164         {
165             return extract_sign(first, last);
166         }
167     };
168 
169     template <typename T>
170     struct strict_ureal_policies : ureal_policies<T>
171     {
172         static bool const expect_dot = true;
173     };
174 
175     template <typename T>
176     struct strict_real_policies : real_policies<T>
177     {
178         static bool const expect_dot = true;
179     };
180 }}}
181 
182 #endif
183