summaryrefslogtreecommitdiff
path: root/boost/spirit/home/x3/numeric/real_policies.hpp
blob: b8fb38c387dc3d75cbdcd6a311efe11fa8b98ae5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
/*=============================================================================
    Copyright (c) 2001-2014 Joel de Guzman
    Copyright (c) 2001-2011 Hartmut Kaiser

    Distributed under the Boost Software License, Version 1.0. (See accompanying
    file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
==============================================================================*/
#if !defined(SPIRIT_REAL_POLICIES_APRIL_17_2006_1158PM)
#define SPIRIT_REAL_POLICIES_APRIL_17_2006_1158PM

#include <boost/spirit/home/x3/string/detail/string_parse.hpp>
#include <boost/spirit/home/x3/support/numeric_utils/extract_int.hpp>

namespace boost { namespace spirit { namespace x3
{
    ///////////////////////////////////////////////////////////////////////////
    //  Default (unsigned) real number policies
    ///////////////////////////////////////////////////////////////////////////
    template <typename T>
    struct ureal_policies
    {
        // trailing dot policy suggested by Gustavo Guerra
        static bool const allow_leading_dot = true;
        static bool const allow_trailing_dot = true;
        static bool const expect_dot = false;

        template <typename Iterator>
        static bool
        parse_sign(Iterator& /*first*/, Iterator const& /*last*/)
        {
            return false;
        }

        template <typename Iterator, typename Attribute>
        static bool
        parse_n(Iterator& first, Iterator const& last, Attribute& attr_)
        {
            return extract_uint<T, 10, 1, -1>::call(first, last, attr_);
        }

        template <typename Iterator>
        static bool
        parse_dot(Iterator& first, Iterator const& last)
        {
            if (first == last || *first != '.')
                return false;
            ++first;
            return true;
        }

        template <typename Iterator, typename Attribute>
        static bool
        parse_frac_n(Iterator& first, Iterator const& last, Attribute& attr_)
        {
            return extract_uint<T, 10, 1, -1, true>::call(first, last, attr_);
        }

        template <typename Iterator>
        static bool
        parse_exp(Iterator& first, Iterator const& last)
        {
            if (first == last || (*first != 'e' && *first != 'E'))
                return false;
            ++first;
            return true;
        }

        template <typename Iterator>
        static bool
        parse_exp_n(Iterator& first, Iterator const& last, int& attr_)
        {
            return extract_int<int, 10, 1, -1>::call(first, last, attr_);
        }

        ///////////////////////////////////////////////////////////////////////
        //  The parse_nan() and parse_inf() functions get called whenever:
        //
        //    - a number to parse does not start with a digit (after having
        //      successfully parsed an optional sign)
        //
        //  or
        //
        //    - after a floating point number of the value 1 (having no
        //      exponential part and a fractional part value of 0) has been
        //      parsed.
        //
        //  The first call allows to recognize representations of NaN or Inf
        //  starting with a non-digit character (such as NaN, Inf, QNaN etc.).
        //
        //  The second call allows to recognize representation formats starting
        //  with a 1.0 (such as 1.0#NAN or 1.0#INF etc.).
        //
        //  The functions should return true if a Nan or Inf has been found. In
        //  this case the attr should be set to the matched value (NaN or
        //  Inf). The optional sign will be automatically applied afterwards.
        //
        //  The default implementation below recognizes representations of NaN
        //  and Inf as mandated by the C99 Standard and as proposed for
        //  inclusion into the C++0x Standard: nan, nan(...), inf and infinity
        //  (the matching is performed case-insensitively).
        ///////////////////////////////////////////////////////////////////////
        template <typename Iterator, typename Attribute>
        static bool
        parse_nan(Iterator& first, Iterator const& last, Attribute& attr_)
        {
            if (first == last)
                return false;   // end of input reached

            if (*first != 'n' && *first != 'N')
                return false;   // not "nan"

            // nan[(...)] ?
            if (detail::string_parse("nan", "NAN", first, last, unused))
            {
                if (*first == '(')
                {
                    // skip trailing (...) part
                    Iterator i = first;

                    while (++i != last && *i != ')')
                        ;
                    if (i == last)
                        return false;     // no trailing ')' found, give up

                    first = ++i;
                }
                attr_ = std::numeric_limits<T>::quiet_NaN();
                return true;
            }
            return false;
        }

        template <typename Iterator, typename Attribute>
        static bool
        parse_inf(Iterator& first, Iterator const& last, Attribute& attr_)
        {
            if (first == last)
                return false;   // end of input reached

            if (*first != 'i' && *first != 'I')
                return false;   // not "inf"

            // inf or infinity ?
            if (detail::string_parse("inf", "INF", first, last, unused))
            {
                // skip allowed 'inity' part of infinity
                detail::string_parse("inity", "INITY", first, last, unused);
                attr_ = std::numeric_limits<T>::infinity();
                return true;
            }
            return false;
        }
    };

    ///////////////////////////////////////////////////////////////////////////
    //  Default (signed) real number policies
    ///////////////////////////////////////////////////////////////////////////
    template <typename T>
    struct real_policies : ureal_policies<T>
    {
        template <typename Iterator>
        static bool
        parse_sign(Iterator& first, Iterator const& last)
        {
            return extract_sign(first, last);
        }
    };

    template <typename T>
    struct strict_ureal_policies : ureal_policies<T>
    {
        static bool const expect_dot = true;
    };

    template <typename T>
    struct strict_real_policies : real_policies<T>
    {
        static bool const expect_dot = true;
    };
}}}

#endif