1 | /*=============================================================================
|
---|
2 | Copyright (c) 1998-2003 Joel de Guzman
|
---|
3 | Copyright (c) 2001-2003 Hartmut Kaiser
|
---|
4 | http://spirit.sourceforge.net/
|
---|
5 |
|
---|
6 | Use, modification and distribution is subject to the Boost Software
|
---|
7 | License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
---|
8 | http://www.boost.org/LICENSE_1_0.txt)
|
---|
9 | =============================================================================*/
|
---|
10 | #ifndef BOOST_SPIRIT_NUMERICS_HPP
|
---|
11 | #define BOOST_SPIRIT_NUMERICS_HPP
|
---|
12 |
|
---|
13 | #include <boost/config.hpp>
|
---|
14 | #include <boost/spirit/core/parser.hpp>
|
---|
15 | #include <boost/spirit/core/composite/directives.hpp>
|
---|
16 | #include <boost/spirit/core/primitives/impl/numerics.ipp>
|
---|
17 |
|
---|
18 | namespace boost { namespace spirit
|
---|
19 | {
|
---|
20 | ///////////////////////////////////////////////////////////////////////////
|
---|
21 | //
|
---|
22 | // uint_parser class
|
---|
23 | //
|
---|
24 | ///////////////////////////////////////////////////////////////////////////
|
---|
25 | template <
|
---|
26 | typename T = unsigned,
|
---|
27 | int Radix = 10,
|
---|
28 | unsigned MinDigits = 1,
|
---|
29 | int MaxDigits = -1
|
---|
30 | >
|
---|
31 | struct uint_parser : parser<uint_parser<T, Radix, MinDigits, MaxDigits> >
|
---|
32 | {
|
---|
33 | typedef uint_parser<T, Radix, MinDigits, MaxDigits> self_t;
|
---|
34 |
|
---|
35 | template <typename ScannerT>
|
---|
36 | struct result
|
---|
37 | {
|
---|
38 | typedef typename match_result<ScannerT, T>::type type;
|
---|
39 | };
|
---|
40 |
|
---|
41 | template <typename ScannerT>
|
---|
42 | typename parser_result<self_t, ScannerT>::type
|
---|
43 | parse(ScannerT const& scan) const
|
---|
44 | {
|
---|
45 | typedef impl::uint_parser_impl<T, Radix, MinDigits, MaxDigits> impl_t;
|
---|
46 | typedef typename parser_result<impl_t, ScannerT>::type result_t;
|
---|
47 | return impl::contiguous_parser_parse<result_t>(impl_t(), scan, scan);
|
---|
48 | }
|
---|
49 | };
|
---|
50 |
|
---|
51 | ///////////////////////////////////////////////////////////////////////////
|
---|
52 | //
|
---|
53 | // int_parser class
|
---|
54 | //
|
---|
55 | ///////////////////////////////////////////////////////////////////////////
|
---|
56 | template <
|
---|
57 | typename T = unsigned,
|
---|
58 | int Radix = 10,
|
---|
59 | unsigned MinDigits = 1,
|
---|
60 | int MaxDigits = -1
|
---|
61 | >
|
---|
62 | struct int_parser : parser<int_parser<T, Radix, MinDigits, MaxDigits> >
|
---|
63 | {
|
---|
64 | typedef int_parser<T, Radix, MinDigits, MaxDigits> self_t;
|
---|
65 |
|
---|
66 | template <typename ScannerT>
|
---|
67 | struct result
|
---|
68 | {
|
---|
69 | typedef typename match_result<ScannerT, T>::type type;
|
---|
70 | };
|
---|
71 |
|
---|
72 | template <typename ScannerT>
|
---|
73 | typename parser_result<self_t, ScannerT>::type
|
---|
74 | parse(ScannerT const& scan) const
|
---|
75 | {
|
---|
76 | typedef impl::int_parser_impl<T, Radix, MinDigits, MaxDigits> impl_t;
|
---|
77 | typedef typename parser_result<impl_t, ScannerT>::type result_t;
|
---|
78 | return impl::contiguous_parser_parse<result_t>(impl_t(), scan, scan);
|
---|
79 | }
|
---|
80 | };
|
---|
81 |
|
---|
82 | ///////////////////////////////////////////////////////////////////////////
|
---|
83 | //
|
---|
84 | // uint_parser/int_parser instantiations
|
---|
85 | //
|
---|
86 | ///////////////////////////////////////////////////////////////////////////
|
---|
87 | int_parser<int> const
|
---|
88 | int_p = int_parser<int>();
|
---|
89 |
|
---|
90 | uint_parser<unsigned> const
|
---|
91 | uint_p = uint_parser<unsigned>();
|
---|
92 |
|
---|
93 | uint_parser<unsigned, 2> const
|
---|
94 | bin_p = uint_parser<unsigned, 2>();
|
---|
95 |
|
---|
96 | uint_parser<unsigned, 8> const
|
---|
97 | oct_p = uint_parser<unsigned, 8>();
|
---|
98 |
|
---|
99 | uint_parser<unsigned, 16> const
|
---|
100 | hex_p = uint_parser<unsigned, 16>();
|
---|
101 |
|
---|
102 | ///////////////////////////////////////////////////////////////////////////
|
---|
103 | //
|
---|
104 | // sign_parser class
|
---|
105 | //
|
---|
106 | ///////////////////////////////////////////////////////////////////////////
|
---|
107 | namespace impl
|
---|
108 | {
|
---|
109 | // Utility to extract the prefix sign ('-' | '+')
|
---|
110 | template <typename ScannerT>
|
---|
111 | bool extract_sign(ScannerT const& scan, std::size_t& count);
|
---|
112 | }
|
---|
113 |
|
---|
114 | struct sign_parser : public parser<sign_parser>
|
---|
115 | {
|
---|
116 | typedef sign_parser self_t;
|
---|
117 |
|
---|
118 | template <typename ScannerT>
|
---|
119 | struct result
|
---|
120 | {
|
---|
121 | typedef typename match_result<ScannerT, bool>::type type;
|
---|
122 | };
|
---|
123 |
|
---|
124 | sign_parser() {}
|
---|
125 |
|
---|
126 | template <typename ScannerT>
|
---|
127 | typename parser_result<self_t, ScannerT>::type
|
---|
128 | parse(ScannerT const& scan) const
|
---|
129 | {
|
---|
130 | if (!scan.at_end())
|
---|
131 | {
|
---|
132 | std::size_t length;
|
---|
133 | typename ScannerT::iterator_t save(scan.first);
|
---|
134 | bool neg = impl::extract_sign(scan, length);
|
---|
135 | if (length)
|
---|
136 | return scan.create_match(1, neg, save, scan.first);
|
---|
137 | }
|
---|
138 | return scan.no_match();
|
---|
139 | }
|
---|
140 | };
|
---|
141 |
|
---|
142 | sign_parser const sign_p = sign_parser();
|
---|
143 |
|
---|
144 | ///////////////////////////////////////////////////////////////////////////
|
---|
145 | //
|
---|
146 | // default real number policies
|
---|
147 | //
|
---|
148 | ///////////////////////////////////////////////////////////////////////////
|
---|
149 | template <typename T>
|
---|
150 | struct ureal_parser_policies
|
---|
151 | {
|
---|
152 | // trailing dot policy suggested suggested by Gustavo Guerra
|
---|
153 | BOOST_STATIC_CONSTANT(bool, allow_leading_dot = true);
|
---|
154 | BOOST_STATIC_CONSTANT(bool, allow_trailing_dot = true);
|
---|
155 | BOOST_STATIC_CONSTANT(bool, expect_dot = false);
|
---|
156 |
|
---|
157 | typedef uint_parser<T, 10, 1, -1> uint_parser_t;
|
---|
158 | typedef int_parser<T, 10, 1, -1> int_parser_t;
|
---|
159 |
|
---|
160 | template <typename ScannerT>
|
---|
161 | static typename match_result<ScannerT, nil_t>::type
|
---|
162 | parse_sign(ScannerT& scan)
|
---|
163 | {
|
---|
164 | return scan.no_match();
|
---|
165 | }
|
---|
166 |
|
---|
167 | template <typename ScannerT>
|
---|
168 | static typename parser_result<uint_parser_t, ScannerT>::type
|
---|
169 | parse_n(ScannerT& scan)
|
---|
170 | {
|
---|
171 | return uint_parser_t().parse(scan);
|
---|
172 | }
|
---|
173 |
|
---|
174 | template <typename ScannerT>
|
---|
175 | static typename parser_result<chlit<>, ScannerT>::type
|
---|
176 | parse_dot(ScannerT& scan)
|
---|
177 | {
|
---|
178 | return ch_p('.').parse(scan);
|
---|
179 | }
|
---|
180 |
|
---|
181 | template <typename ScannerT>
|
---|
182 | static typename parser_result<uint_parser_t, ScannerT>::type
|
---|
183 | parse_frac_n(ScannerT& scan)
|
---|
184 | {
|
---|
185 | return uint_parser_t().parse(scan);
|
---|
186 | }
|
---|
187 |
|
---|
188 | template <typename ScannerT>
|
---|
189 | static typename parser_result<chlit<>, ScannerT>::type
|
---|
190 | parse_exp(ScannerT& scan)
|
---|
191 | {
|
---|
192 | return as_lower_d['e'].parse(scan);
|
---|
193 | }
|
---|
194 |
|
---|
195 | template <typename ScannerT>
|
---|
196 | static typename parser_result<int_parser_t, ScannerT>::type
|
---|
197 | parse_exp_n(ScannerT& scan)
|
---|
198 | {
|
---|
199 | return int_parser_t().parse(scan);
|
---|
200 | }
|
---|
201 | };
|
---|
202 |
|
---|
203 | template <typename T>
|
---|
204 | struct real_parser_policies : public ureal_parser_policies<T>
|
---|
205 | {
|
---|
206 | template <typename ScannerT>
|
---|
207 | static typename parser_result<sign_parser, ScannerT>::type
|
---|
208 | parse_sign(ScannerT& scan)
|
---|
209 | {
|
---|
210 | return sign_p.parse(scan);
|
---|
211 | }
|
---|
212 | };
|
---|
213 |
|
---|
214 | ///////////////////////////////////////////////////////////////////////////
|
---|
215 | //
|
---|
216 | // real_parser class
|
---|
217 | //
|
---|
218 | ///////////////////////////////////////////////////////////////////////////
|
---|
219 | template <
|
---|
220 | typename T = double,
|
---|
221 | typename RealPoliciesT = ureal_parser_policies<T>
|
---|
222 | >
|
---|
223 | struct real_parser
|
---|
224 | : public parser<real_parser<T, RealPoliciesT> >
|
---|
225 | {
|
---|
226 | typedef real_parser<T, RealPoliciesT> self_t;
|
---|
227 |
|
---|
228 | template <typename ScannerT>
|
---|
229 | struct result
|
---|
230 | {
|
---|
231 | typedef typename match_result<ScannerT, T>::type type;
|
---|
232 | };
|
---|
233 |
|
---|
234 | real_parser() {}
|
---|
235 |
|
---|
236 | template <typename ScannerT>
|
---|
237 | typename parser_result<self_t, ScannerT>::type
|
---|
238 | parse(ScannerT const& scan) const
|
---|
239 | {
|
---|
240 | typedef typename parser_result<self_t, ScannerT>::type result_t;
|
---|
241 | return impl::real_parser_impl<result_t, T, RealPoliciesT>::parse(scan);
|
---|
242 | }
|
---|
243 | };
|
---|
244 |
|
---|
245 | ///////////////////////////////////////////////////////////////////////////
|
---|
246 | //
|
---|
247 | // real_parser instantiations
|
---|
248 | //
|
---|
249 | ///////////////////////////////////////////////////////////////////////////
|
---|
250 | real_parser<double, ureal_parser_policies<double> > const
|
---|
251 | ureal_p = real_parser<double, ureal_parser_policies<double> >();
|
---|
252 |
|
---|
253 | real_parser<double, real_parser_policies<double> > const
|
---|
254 | real_p = real_parser<double, real_parser_policies<double> >();
|
---|
255 |
|
---|
256 | ///////////////////////////////////////////////////////////////////////////
|
---|
257 | //
|
---|
258 | // strict reals (do not allow plain integers (no decimal point))
|
---|
259 | //
|
---|
260 | ///////////////////////////////////////////////////////////////////////////
|
---|
261 | template <typename T>
|
---|
262 | struct strict_ureal_parser_policies : public ureal_parser_policies<T>
|
---|
263 | {
|
---|
264 | BOOST_STATIC_CONSTANT(bool, expect_dot = true);
|
---|
265 | };
|
---|
266 |
|
---|
267 | template <typename T>
|
---|
268 | struct strict_real_parser_policies : public real_parser_policies<T>
|
---|
269 | {
|
---|
270 | BOOST_STATIC_CONSTANT(bool, expect_dot = true);
|
---|
271 | };
|
---|
272 |
|
---|
273 | real_parser<double, strict_ureal_parser_policies<double> > const
|
---|
274 | strict_ureal_p
|
---|
275 | = real_parser<double, strict_ureal_parser_policies<double> >();
|
---|
276 |
|
---|
277 | real_parser<double, strict_real_parser_policies<double> > const
|
---|
278 | strict_real_p
|
---|
279 | = real_parser<double, strict_real_parser_policies<double> >();
|
---|
280 |
|
---|
281 | }} // namespace boost::spirit
|
---|
282 |
|
---|
283 | #endif
|
---|