]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /*============================================================================= |
2 | Copyright (c) 2001-2011 Joel de Guzman | |
3 | Copyright (c) 2011 Bryce Lelbach | |
4 | Copyright (c) 2011 Jan Frederick Eick | |
5 | ||
6 | Distributed under the Boost Software License, Version 1.0. (See accompanying | |
7 | file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
8 | ==============================================================================*/ | |
9 | #if !defined(SPIRIT_UINT_APR_17_2006_0901AM) | |
10 | #define SPIRIT_UINT_APR_17_2006_0901AM | |
11 | ||
12 | #if defined(_MSC_VER) | |
13 | #pragma once | |
14 | #endif | |
15 | ||
16 | #include <boost/spirit/home/qi/skip_over.hpp> | |
17 | #include <boost/spirit/home/qi/detail/enable_lit.hpp> | |
18 | #include <boost/spirit/home/qi/numeric/numeric_utils.hpp> | |
19 | #include <boost/spirit/home/qi/meta_compiler.hpp> | |
20 | #include <boost/spirit/home/qi/parser.hpp> | |
21 | #include <boost/spirit/home/support/common_terminals.hpp> | |
22 | #include <boost/spirit/home/support/info.hpp> | |
23 | #include <boost/spirit/home/support/detail/is_spirit_tag.hpp> | |
24 | #include <boost/mpl/assert.hpp> | |
25 | #include <boost/type_traits/is_same.hpp> | |
26 | ||
27 | namespace boost { namespace spirit | |
28 | { | |
29 | namespace tag | |
30 | { | |
31 | template <typename T, unsigned Radix, unsigned MinDigits | |
32 | , int MaxDigits> | |
33 | struct uint_parser | |
34 | { | |
35 | BOOST_SPIRIT_IS_TAG() | |
36 | }; | |
37 | } | |
38 | ||
39 | namespace qi | |
40 | { | |
41 | /////////////////////////////////////////////////////////////////////// | |
42 | // This one is the class that the user can instantiate directly in | |
43 | // order to create a customized int parser | |
44 | template <typename T = int, unsigned Radix = 10, unsigned MinDigits = 1 | |
45 | , int MaxDigits = -1> | |
46 | struct uint_parser | |
47 | : spirit::terminal<tag::uint_parser<T, Radix, MinDigits, MaxDigits> > | |
48 | {}; | |
49 | } | |
50 | ||
51 | /////////////////////////////////////////////////////////////////////////// | |
52 | // Enablers | |
53 | /////////////////////////////////////////////////////////////////////////// | |
54 | template <> // enables ushort_ | |
55 | struct use_terminal<qi::domain, tag::ushort_> : mpl::true_ {}; | |
56 | ||
57 | template <typename A0> // enables lit(n) | |
58 | struct use_terminal<qi::domain | |
59 | , terminal_ex<tag::lit, fusion::vector1<A0> > | |
60 | , typename enable_if<is_same<A0, unsigned short> >::type> | |
61 | : mpl::true_ {}; | |
62 | ||
63 | template <typename A0> // enables ushort_(n) | |
64 | struct use_terminal<qi::domain | |
65 | , terminal_ex<tag::ushort_, fusion::vector1<A0> > > | |
66 | : is_arithmetic<A0> {}; | |
67 | ||
68 | template <> // enables *lazy* ushort_(n) | |
69 | struct use_lazy_terminal<qi::domain, tag::ushort_, 1> : mpl::true_ {}; | |
70 | ||
71 | /////////////////////////////////////////////////////////////////////////// | |
72 | template <> // enables uint_ | |
73 | struct use_terminal<qi::domain, tag::uint_> : mpl::true_ {}; | |
74 | ||
75 | template <typename A0> // enables lit(n) | |
76 | struct use_terminal<qi::domain | |
77 | , terminal_ex<tag::lit, fusion::vector1<A0> > | |
78 | , typename enable_if<is_same<A0, unsigned> >::type> | |
79 | : mpl::true_ {}; | |
80 | ||
81 | template <typename A0> // enables uint_(n) | |
82 | struct use_terminal<qi::domain | |
83 | , terminal_ex<tag::uint_, fusion::vector1<A0> > > | |
84 | : is_arithmetic<A0> {}; | |
85 | ||
86 | template <> // enables *lazy* uint_(n) | |
87 | struct use_lazy_terminal<qi::domain, tag::uint_, 1> : mpl::true_ {}; | |
88 | ||
89 | /////////////////////////////////////////////////////////////////////////// | |
90 | template <> // enables ulong_ | |
91 | struct use_terminal<qi::domain, tag::ulong_> : mpl::true_ {}; | |
92 | ||
93 | template <typename A0> // enables lit(n) | |
94 | struct use_terminal<qi::domain | |
95 | , terminal_ex<tag::lit, fusion::vector1<A0> > | |
96 | , typename enable_if<is_same<A0, unsigned long> >::type> | |
97 | : mpl::true_ {}; | |
98 | ||
99 | template <typename A0> // enables ulong_(n) | |
100 | struct use_terminal<qi::domain | |
101 | , terminal_ex<tag::ulong_, fusion::vector1<A0> > > | |
102 | : is_arithmetic<A0> {}; | |
103 | ||
104 | template <> // enables *lazy* ulong_(n) | |
105 | struct use_lazy_terminal<qi::domain, tag::ulong_, 1> : mpl::true_ {}; | |
106 | ||
107 | /////////////////////////////////////////////////////////////////////////// | |
108 | #ifdef BOOST_HAS_LONG_LONG | |
109 | template <> // enables ulong_long | |
110 | struct use_terminal<qi::domain, tag::ulong_long> : mpl::true_ {}; | |
111 | ||
112 | template <typename A0> // enables lit(n) | |
113 | struct use_terminal<qi::domain | |
114 | , terminal_ex<tag::lit, fusion::vector1<A0> > | |
115 | , typename enable_if<is_same<A0, boost::ulong_long_type> >::type> | |
116 | : mpl::true_ {}; | |
117 | ||
118 | template <typename A0> // enables ulong_long(n) | |
119 | struct use_terminal<qi::domain | |
120 | , terminal_ex<tag::ulong_long, fusion::vector1<A0> > > | |
121 | : is_arithmetic<A0> {}; | |
122 | ||
123 | template <> // enables *lazy* ulong_long(n) | |
124 | struct use_lazy_terminal<qi::domain, tag::ulong_long, 1> : mpl::true_ {}; | |
125 | #endif | |
126 | ||
127 | /////////////////////////////////////////////////////////////////////////// | |
128 | template <> // enables bin | |
129 | struct use_terminal<qi::domain, tag::bin> : mpl::true_ {}; | |
130 | ||
131 | template <typename A0> // enables bin(n) | |
132 | struct use_terminal<qi::domain | |
133 | , terminal_ex<tag::bin, fusion::vector1<A0> > > | |
134 | : is_arithmetic<A0> {}; | |
135 | ||
136 | template <> // enables *lazy* bin(n) | |
137 | struct use_lazy_terminal<qi::domain, tag::bin, 1> : mpl::true_ {}; | |
138 | ||
139 | /////////////////////////////////////////////////////////////////////////// | |
140 | template <> // enables oct | |
141 | struct use_terminal<qi::domain, tag::oct> : mpl::true_ {}; | |
142 | ||
143 | template <typename A0> // enables oct(n) | |
144 | struct use_terminal<qi::domain | |
145 | , terminal_ex<tag::oct, fusion::vector1<A0> > > | |
146 | : is_arithmetic<A0> {}; | |
147 | ||
148 | template <> // enables *lazy* oct(n) | |
149 | struct use_lazy_terminal<qi::domain, tag::oct, 1> : mpl::true_ {}; | |
150 | ||
151 | /////////////////////////////////////////////////////////////////////////// | |
152 | template <> // enables hex | |
153 | struct use_terminal<qi::domain, tag::hex> : mpl::true_ {}; | |
154 | ||
155 | template <typename A0> // enables hex(n) | |
156 | struct use_terminal<qi::domain | |
157 | , terminal_ex<tag::hex, fusion::vector1<A0> > > | |
158 | : is_arithmetic<A0> {}; | |
159 | ||
160 | template <> // enables *lazy* hex(n) | |
161 | struct use_lazy_terminal<qi::domain, tag::hex, 1> : mpl::true_ {}; | |
162 | ||
163 | /////////////////////////////////////////////////////////////////////////// | |
164 | // enables any custom uint_parser | |
165 | template <typename T, unsigned Radix, unsigned MinDigits | |
166 | , int MaxDigits> | |
167 | struct use_terminal<qi::domain | |
168 | , tag::uint_parser<T, Radix, MinDigits, MaxDigits> > | |
169 | : mpl::true_ {}; | |
170 | ||
171 | // enables any custom uint_parser(n) | |
172 | template <typename T, unsigned Radix, unsigned MinDigits | |
173 | , int MaxDigits, typename A0> | |
174 | struct use_terminal<qi::domain | |
175 | , terminal_ex<tag::uint_parser<T, Radix, MinDigits, MaxDigits> | |
176 | , fusion::vector1<A0> > | |
177 | > : mpl::true_ {}; | |
178 | ||
179 | // enables *lazy* custom uint_parser(n) | |
180 | template <typename T, unsigned Radix, unsigned MinDigits | |
181 | , int MaxDigits> | |
182 | struct use_lazy_terminal<qi::domain | |
183 | , tag::uint_parser<T, Radix, MinDigits, MaxDigits>, 1 | |
184 | > : mpl::true_ {}; | |
185 | }} | |
186 | ||
187 | namespace boost { namespace spirit { namespace qi | |
188 | { | |
189 | #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS | |
190 | using spirit::bin; | |
191 | using spirit::oct; | |
192 | using spirit::hex; | |
193 | ||
194 | using spirit::ushort_; | |
195 | using spirit::uint_; | |
196 | using spirit::ulong_; | |
197 | #ifdef BOOST_HAS_LONG_LONG | |
198 | using spirit::ulong_long; | |
199 | #endif | |
200 | using spirit::lit; // lit(1) is equivalent to 1 | |
201 | #endif | |
202 | ||
203 | using spirit::bin_type; | |
204 | using spirit::oct_type; | |
205 | using spirit::hex_type; | |
206 | ||
207 | using spirit::ushort_type; | |
208 | using spirit::uint_type; | |
209 | using spirit::ulong_type; | |
210 | #ifdef BOOST_HAS_LONG_LONG | |
211 | using spirit::ulong_long_type; | |
212 | #endif | |
213 | using spirit::lit_type; | |
214 | ||
215 | /////////////////////////////////////////////////////////////////////////// | |
216 | // This is the actual uint parser | |
217 | /////////////////////////////////////////////////////////////////////////// | |
218 | template <typename T, unsigned Radix = 10, unsigned MinDigits = 1 | |
219 | , int MaxDigits = -1> | |
220 | struct any_uint_parser | |
221 | : primitive_parser<any_uint_parser<T, Radix, MinDigits, MaxDigits> > | |
222 | { | |
223 | // check template parameter 'Radix' for validity | |
224 | BOOST_SPIRIT_ASSERT_MSG( | |
225 | Radix >= 2 && Radix <= 36, | |
226 | not_supported_radix, ()); | |
227 | ||
228 | template <typename Context, typename Iterator> | |
229 | struct attribute | |
230 | { | |
231 | typedef T type; | |
232 | }; | |
233 | ||
234 | template <typename Iterator, typename Context | |
235 | , typename Skipper, typename Attribute> | |
236 | bool parse(Iterator& first, Iterator const& last | |
237 | , Context& /*context*/, Skipper const& skipper | |
238 | , Attribute& attr_) const | |
239 | { | |
240 | typedef extract_uint<T, Radix, MinDigits, MaxDigits> extract; | |
241 | qi::skip_over(first, last, skipper); | |
242 | return extract::call(first, last, attr_); | |
243 | } | |
244 | ||
245 | template <typename Context> | |
246 | info what(Context& /*context*/) const | |
247 | { | |
248 | return info("unsigned-integer"); | |
249 | } | |
250 | }; | |
251 | //] | |
252 | ||
253 | template <typename T, unsigned Radix = 10, unsigned MinDigits = 1 | |
254 | , int MaxDigits = -1, bool no_attribute = true> | |
255 | struct literal_uint_parser | |
256 | : primitive_parser<literal_uint_parser<T, Radix, MinDigits, MaxDigits | |
257 | , no_attribute> > | |
258 | { | |
259 | // check template parameter 'Radix' for validity | |
260 | BOOST_SPIRIT_ASSERT_MSG( | |
261 | Radix == 2 || Radix == 8 || Radix == 10 || Radix == 16, | |
262 | not_supported_radix, ()); | |
263 | ||
264 | template <typename Value> | |
265 | literal_uint_parser(Value const& n) : n_(n) {} | |
266 | ||
267 | template <typename Context, typename Iterator> | |
268 | struct attribute | |
269 | : mpl::if_c<no_attribute, unused_type, T> | |
270 | {}; | |
271 | ||
272 | template <typename Iterator, typename Context | |
273 | , typename Skipper, typename Attribute> | |
274 | bool parse(Iterator& first, Iterator const& last | |
275 | , Context& /*context*/, Skipper const& skipper | |
276 | , Attribute& attr_param) const | |
277 | { | |
278 | typedef extract_uint<T, Radix, MinDigits, MaxDigits> extract; | |
279 | qi::skip_over(first, last, skipper); | |
280 | ||
281 | Iterator save = first; | |
282 | T attr_; | |
283 | ||
284 | if (extract::call(first, last, attr_) && (attr_ == n_)) | |
285 | { | |
286 | traits::assign_to(attr_, attr_param); | |
287 | return true; | |
288 | } | |
289 | ||
290 | first = save; | |
291 | return false; | |
292 | } | |
293 | ||
294 | template <typename Context> | |
295 | info what(Context& /*context*/) const | |
296 | { | |
297 | return info("unsigned-integer"); | |
298 | } | |
299 | ||
300 | T n_; | |
301 | }; | |
302 | ||
303 | /////////////////////////////////////////////////////////////////////////// | |
304 | // Parser generators: make_xxx function (objects) | |
305 | /////////////////////////////////////////////////////////////////////////// | |
306 | template <typename T, unsigned Radix = 10, unsigned MinDigits = 1 | |
307 | , int MaxDigits = -1> | |
308 | struct make_uint | |
309 | { | |
310 | typedef any_uint_parser<T, Radix, MinDigits, MaxDigits> result_type; | |
311 | result_type operator()(unused_type, unused_type) const | |
312 | { | |
313 | return result_type(); | |
314 | } | |
315 | }; | |
316 | ||
317 | template <typename T, unsigned Radix = 10, unsigned MinDigits = 1 | |
318 | , int MaxDigits = -1> | |
319 | struct make_direct_uint | |
320 | { | |
321 | typedef literal_uint_parser<T, Radix, MinDigits, MaxDigits, false> | |
322 | result_type; | |
323 | template <typename Terminal> | |
324 | result_type operator()(Terminal const& term, unused_type) const | |
325 | { | |
326 | return result_type(fusion::at_c<0>(term.args)); | |
327 | } | |
328 | }; | |
329 | ||
330 | template <typename T, unsigned Radix = 10, unsigned MinDigits = 1 | |
331 | , int MaxDigits = -1> | |
332 | struct make_literal_uint | |
333 | { | |
334 | typedef literal_uint_parser<T, Radix, MinDigits, MaxDigits> result_type; | |
335 | template <typename Terminal> | |
336 | result_type operator()(Terminal const& term, unused_type) const | |
337 | { | |
338 | return result_type(fusion::at_c<0>(term.args)); | |
339 | } | |
340 | }; | |
341 | ||
342 | /////////////////////////////////////////////////////////////////////////// | |
343 | template <typename Modifiers, typename A0> | |
344 | struct make_primitive< | |
345 | terminal_ex<tag::lit, fusion::vector1<A0> > | |
346 | , Modifiers, typename enable_if<is_same<A0, unsigned short> >::type> | |
347 | : make_literal_uint<unsigned short> {}; | |
348 | ||
349 | template <typename Modifiers, typename A0> | |
350 | struct make_primitive< | |
351 | terminal_ex<tag::lit, fusion::vector1<A0> > | |
352 | , Modifiers, typename enable_if<is_same<A0, unsigned> >::type> | |
353 | : make_literal_uint<unsigned> {}; | |
354 | ||
355 | template <typename Modifiers, typename A0> | |
356 | struct make_primitive< | |
357 | terminal_ex<tag::lit, fusion::vector1<A0> > | |
358 | , Modifiers, typename enable_if<is_same<A0, unsigned long> >::type> | |
359 | : make_literal_uint<unsigned long> {}; | |
360 | ||
361 | #ifdef BOOST_HAS_LONG_LONG | |
362 | template <typename Modifiers, typename A0> | |
363 | struct make_primitive< | |
364 | terminal_ex<tag::lit, fusion::vector1<A0> > | |
365 | , Modifiers, typename enable_if<is_same<A0, boost::ulong_long_type> >::type> | |
366 | : make_literal_uint<boost::ulong_long_type> {}; | |
367 | #endif | |
368 | ||
369 | /////////////////////////////////////////////////////////////////////////// | |
370 | template <typename T, unsigned Radix, unsigned MinDigits, int MaxDigits | |
371 | , typename Modifiers> | |
372 | struct make_primitive< | |
373 | tag::uint_parser<T, Radix, MinDigits, MaxDigits> | |
374 | , Modifiers> | |
375 | : make_uint<T, Radix, MinDigits, MaxDigits> {}; | |
376 | ||
377 | template <typename T, unsigned Radix, unsigned MinDigits, int MaxDigits | |
378 | , typename A0, typename Modifiers> | |
379 | struct make_primitive< | |
380 | terminal_ex<tag::uint_parser<T, Radix, MinDigits, MaxDigits> | |
381 | , fusion::vector1<A0> >, Modifiers> | |
382 | : make_direct_uint<T, Radix, MinDigits, MaxDigits> {}; | |
383 | ||
384 | /////////////////////////////////////////////////////////////////////////// | |
385 | template <typename Modifiers> | |
386 | struct make_primitive<tag::bin, Modifiers> | |
387 | : make_uint<unsigned, 2> {}; | |
388 | ||
389 | template <typename Modifiers, typename A0> | |
390 | struct make_primitive< | |
391 | terminal_ex<tag::bin | |
392 | , fusion::vector1<A0> > , Modifiers> | |
393 | : make_direct_uint<unsigned, 2> {}; | |
394 | ||
395 | /////////////////////////////////////////////////////////////////////////// | |
396 | template <typename Modifiers> | |
397 | struct make_primitive<tag::oct, Modifiers> | |
398 | : make_uint<unsigned, 8> {}; | |
399 | ||
400 | template <typename Modifiers, typename A0> | |
401 | struct make_primitive< | |
402 | terminal_ex<tag::oct | |
403 | , fusion::vector1<A0> > , Modifiers> | |
404 | : make_direct_uint<unsigned, 8> {}; | |
405 | ||
406 | /////////////////////////////////////////////////////////////////////////// | |
407 | template <typename Modifiers> | |
408 | struct make_primitive<tag::hex, Modifiers> | |
409 | : make_uint<unsigned, 16> {}; | |
410 | ||
411 | template <typename Modifiers, typename A0> | |
412 | struct make_primitive< | |
413 | terminal_ex<tag::hex | |
414 | , fusion::vector1<A0> > , Modifiers> | |
415 | : make_direct_uint<unsigned, 16> {}; | |
416 | ||
417 | /////////////////////////////////////////////////////////////////////////// | |
418 | template <typename Modifiers> | |
419 | struct make_primitive<tag::ushort_, Modifiers> | |
420 | : make_uint<unsigned short> {}; | |
421 | ||
422 | template <typename Modifiers, typename A0> | |
423 | struct make_primitive< | |
424 | terminal_ex<tag::ushort_ | |
425 | , fusion::vector1<A0> > , Modifiers> | |
426 | : make_direct_uint<unsigned short> {}; | |
427 | ||
428 | /////////////////////////////////////////////////////////////////////////// | |
429 | template <typename Modifiers> | |
430 | struct make_primitive<tag::uint_, Modifiers> | |
431 | : make_uint<unsigned> {}; | |
432 | ||
433 | template <typename Modifiers, typename A0> | |
434 | struct make_primitive< | |
435 | terminal_ex<tag::uint_ | |
436 | , fusion::vector1<A0> > , Modifiers> | |
437 | : make_direct_uint<unsigned> {}; | |
438 | ||
439 | /////////////////////////////////////////////////////////////////////////// | |
440 | template <typename Modifiers> | |
441 | struct make_primitive<tag::ulong_, Modifiers> | |
442 | : make_uint<unsigned long> {}; | |
443 | ||
444 | template <typename Modifiers, typename A0> | |
445 | struct make_primitive< | |
446 | terminal_ex<tag::ulong_ | |
447 | , fusion::vector1<A0> > , Modifiers> | |
448 | : make_direct_uint<unsigned long> {}; | |
449 | ||
450 | /////////////////////////////////////////////////////////////////////////// | |
451 | #ifdef BOOST_HAS_LONG_LONG | |
452 | template <typename Modifiers> | |
453 | struct make_primitive<tag::ulong_long, Modifiers> | |
454 | : make_uint<boost::ulong_long_type> {}; | |
455 | ||
456 | template <typename Modifiers, typename A0> | |
457 | struct make_primitive< | |
458 | terminal_ex<tag::ulong_long | |
459 | , fusion::vector1<A0> > , Modifiers> | |
460 | : make_direct_uint<boost::ulong_long_type> {}; | |
461 | #endif | |
462 | }}} | |
463 | ||
464 | #endif |