1 /*=============================================================================
2 Copyright (c) 2001-2011 Joel de Guzman
3 Copyright (c) 2011 Bryce Lelbach
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(BOOST_SPIRIT_INT_APR_17_2006_0830AM)
9 #define BOOST_SPIRIT_INT_APR_17_2006_0830AM
15 #include <boost/spirit/home/qi/skip_over.hpp>
16 #include <boost/spirit/home/qi/detail/enable_lit.hpp>
17 #include <boost/spirit/home/qi/numeric/numeric_utils.hpp>
18 #include <boost/spirit/home/qi/meta_compiler.hpp>
19 #include <boost/spirit/home/qi/parser.hpp>
20 #include <boost/spirit/home/support/common_terminals.hpp>
21 #include <boost/spirit/home/support/info.hpp>
22 #include <boost/spirit/home/support/detail/is_spirit_tag.hpp>
23 #include <boost/mpl/assert.hpp>
24 #include <boost/type_traits/is_same.hpp>
26 namespace boost { namespace spirit
30 template <typename T, unsigned Radix, unsigned MinDigits
40 ///////////////////////////////////////////////////////////////////////
41 // This one is the class that the user can instantiate directly in
42 // order to create a customized int parser
43 template <typename T = int, unsigned Radix = 10, unsigned MinDigits = 1
46 : spirit::terminal<tag::int_parser<T, Radix, MinDigits, MaxDigits> >
50 ///////////////////////////////////////////////////////////////////////////
52 ///////////////////////////////////////////////////////////////////////////
53 //[primitive_parsers_enable_short
54 template <> // enables short_
55 struct use_terminal<qi::domain, tag::short_> : mpl::true_ {};
58 template <typename A0> // enables lit(n)
59 struct use_terminal<qi::domain
60 , terminal_ex<tag::lit, fusion::vector1<A0> >
61 , typename enable_if<is_same<A0, signed short> >::type>
64 template <typename A0> // enables short_(n)
65 struct use_terminal<qi::domain
66 , terminal_ex<tag::short_, fusion::vector1<A0> > >
67 : is_arithmetic<A0> {};
69 template <> // enables *lazy* short_(n)
70 struct use_lazy_terminal<qi::domain, tag::short_, 1> : mpl::true_ {};
72 ///////////////////////////////////////////////////////////////////////////
73 //[primitive_parsers_enable_int
74 template <> // enables int_
75 struct use_terminal<qi::domain, tag::int_> : mpl::true_ {};
78 template <typename A0> // enables lit(n)
79 struct use_terminal<qi::domain
80 , terminal_ex<tag::lit, fusion::vector1<A0> >
81 , typename enable_if<is_same<A0, signed> >::type>
84 template <typename A0> // enables int_(n)
85 struct use_terminal<qi::domain
86 , terminal_ex<tag::int_, fusion::vector1<A0> > >
87 : is_arithmetic<A0> {};
89 template <> // enables *lazy* int_(n)
90 struct use_lazy_terminal<qi::domain, tag::int_, 1> : mpl::true_ {};
92 ///////////////////////////////////////////////////////////////////////////
93 //[primitive_parsers_enable_long
94 template <> // enables long_
95 struct use_terminal<qi::domain, tag::long_> : mpl::true_ {};
98 template <typename A0> // enables lit(n)
99 struct use_terminal<qi::domain
100 , terminal_ex<tag::lit, fusion::vector1<A0> >
101 , typename enable_if<is_same<A0, signed long> >::type>
104 template <typename A0> // enables long_(n)
105 struct use_terminal<qi::domain
106 , terminal_ex<tag::long_, fusion::vector1<A0> > >
107 : is_arithmetic<A0> {};
109 template <> // enables *lazy* long_(n)
110 struct use_lazy_terminal<qi::domain, tag::long_, 1> : mpl::true_ {};
112 ///////////////////////////////////////////////////////////////////////////
113 #ifdef BOOST_HAS_LONG_LONG
114 //[primitive_parsers_enable_long_long
115 template <> // enables long_long
116 struct use_terminal<qi::domain, tag::long_long> : mpl::true_ {};
119 template <typename A0> // enables lit(n)
120 struct use_terminal<qi::domain
121 , terminal_ex<tag::lit, fusion::vector1<A0> >
122 , typename enable_if<is_same<A0, boost::long_long_type> >::type>
125 template <typename A0> // enables long_long(n)
126 struct use_terminal<qi::domain
127 , terminal_ex<tag::long_long, fusion::vector1<A0> > >
128 : is_arithmetic<A0> {};
130 template <> // enables *lazy* long_long(n)
131 struct use_lazy_terminal<qi::domain, tag::long_long, 1> : mpl::true_ {};
134 ///////////////////////////////////////////////////////////////////////////
135 // enables any custom int_parser
136 template <typename T, unsigned Radix, unsigned MinDigits
138 struct use_terminal<qi::domain
139 , tag::int_parser<T, Radix, MinDigits, MaxDigits> >
142 // enables any custom int_parser(n)
143 template <typename T, unsigned Radix, unsigned MinDigits
144 , int MaxDigits, typename A0>
145 struct use_terminal<qi::domain
146 , terminal_ex<tag::int_parser<T, Radix, MinDigits, MaxDigits>
147 , fusion::vector1<A0> >
150 // enables *lazy* custom int_parser(n)
151 template <typename T, unsigned Radix, unsigned MinDigits
153 struct use_lazy_terminal<qi::domain
154 , tag::int_parser<T, Radix, MinDigits, MaxDigits>, 1
158 namespace boost { namespace spirit { namespace qi
160 #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
161 using spirit::short_;
164 #ifdef BOOST_HAS_LONG_LONG
165 using spirit::long_long;
167 using spirit::lit; // lit(1) is equivalent to 1
169 using spirit::short_type;
170 using spirit::int_type;
171 using spirit::long_type;
172 using spirit::lit_type;
173 #ifdef BOOST_HAS_LONG_LONG
174 using spirit::long_long_type;
176 using spirit::lit_type;
178 ///////////////////////////////////////////////////////////////////////////
179 // This is the actual int parser
180 ///////////////////////////////////////////////////////////////////////////
181 //[primitive_parsers_int_parser
184 , unsigned Radix = 10
185 , unsigned MinDigits = 1
186 , int MaxDigits = -1>
187 struct any_int_parser
188 : primitive_parser<any_int_parser<T, Radix, MinDigits, MaxDigits> >
190 // check template parameter 'Radix' for validity
191 BOOST_SPIRIT_ASSERT_MSG(
192 Radix == 2 || Radix == 8 || Radix == 10 || Radix == 16,
193 not_supported_radix, ());
195 template <typename Context, typename Iterator>
201 template <typename Iterator, typename Context
202 , typename Skipper, typename Attribute>
203 bool parse(Iterator& first, Iterator const& last
204 , Context& /*context*/, Skipper const& skipper
205 , Attribute& attr_) const
207 typedef extract_int<T, Radix, MinDigits, MaxDigits> extract;
208 qi::skip_over(first, last, skipper);
209 return extract::call(first, last, attr_);
212 template <typename Context>
213 info what(Context& /*context*/) const
215 return info("integer");
220 template <typename T, unsigned Radix = 10, unsigned MinDigits = 1
221 , int MaxDigits = -1, bool no_attribute = true>
222 struct literal_int_parser
223 : primitive_parser<literal_int_parser<T, Radix, MinDigits, MaxDigits
226 // check template parameter 'Radix' for validity
227 BOOST_SPIRIT_ASSERT_MSG(
228 Radix == 2 || Radix == 8 || Radix == 10 || Radix == 16,
229 not_supported_radix, ());
231 template <typename Value>
232 literal_int_parser(Value const& n) : n_(n) {}
234 template <typename Context, typename Iterator>
236 : mpl::if_c<no_attribute, unused_type, T>
239 template <typename Iterator, typename Context
240 , typename Skipper, typename Attribute>
241 bool parse(Iterator& first, Iterator const& last
242 , Context& /*context*/, Skipper const& skipper
243 , Attribute& attr_param) const
245 typedef extract_int<T, Radix, MinDigits, MaxDigits> extract;
246 qi::skip_over(first, last, skipper);
248 Iterator save = first;
251 if (extract::call(first, last, attr_) && (attr_ == n_))
253 traits::assign_to(attr_, attr_param);
261 template <typename Context>
262 info what(Context& /*context*/) const
264 return info("integer");
270 ///////////////////////////////////////////////////////////////////////////
271 // Parser generators: make_xxx function (objects)
272 ///////////////////////////////////////////////////////////////////////////
273 //[primitive_parsers_make_int
276 , unsigned Radix = 10
277 , unsigned MinDigits = 1
278 , int MaxDigits = -1>
281 typedef any_int_parser<T, Radix, MinDigits, MaxDigits> result_type;
282 result_type operator()(unused_type, unused_type) const
284 return result_type();
289 template <typename T, unsigned Radix = 10, unsigned MinDigits = 1
290 , int MaxDigits = -1>
291 struct make_direct_int
293 typedef literal_int_parser<T, Radix, MinDigits, MaxDigits, false>
295 template <typename Terminal>
296 result_type operator()(Terminal const& term, unused_type) const
298 return result_type(fusion::at_c<0>(term.args));
302 template <typename T, unsigned Radix = 10, unsigned MinDigits = 1
303 , int MaxDigits = -1>
304 struct make_literal_int
306 typedef literal_int_parser<T, Radix, MinDigits, MaxDigits> result_type;
307 template <typename Terminal>
308 result_type operator()(Terminal const& term, unused_type) const
310 return result_type(fusion::at_c<0>(term.args));
314 ///////////////////////////////////////////////////////////////////////////
315 template <typename Modifiers, typename A0>
316 struct make_primitive<
317 terminal_ex<tag::lit, fusion::vector1<A0> >
318 , Modifiers, typename enable_if<is_same<A0, signed short> >::type>
319 : make_literal_int<signed short> {};
321 template <typename Modifiers, typename A0>
322 struct make_primitive<
323 terminal_ex<tag::lit, fusion::vector1<A0> >
324 , Modifiers, typename enable_if<is_same<A0, signed> >::type>
325 : make_literal_int<signed> {};
327 template <typename Modifiers, typename A0>
328 struct make_primitive<
329 terminal_ex<tag::lit, fusion::vector1<A0> >
330 , Modifiers, typename enable_if<is_same<A0, signed long> >::type>
331 : make_literal_int<signed long> {};
333 #ifdef BOOST_HAS_LONG_LONG
334 template <typename Modifiers, typename A0>
335 struct make_primitive<
336 terminal_ex<tag::lit, fusion::vector1<A0> >
337 , Modifiers, typename enable_if<is_same<A0, boost::long_long_type> >::type>
338 : make_literal_int<boost::long_long_type> {};
341 ///////////////////////////////////////////////////////////////////////////
342 template <typename T, unsigned Radix, unsigned MinDigits, int MaxDigits
343 , typename Modifiers>
344 struct make_primitive<
345 tag::int_parser<T, Radix, MinDigits, MaxDigits>
347 : make_int<T, Radix, MinDigits, MaxDigits> {};
349 template <typename T, unsigned Radix, unsigned MinDigits, int MaxDigits
350 , typename A0, typename Modifiers>
351 struct make_primitive<
352 terminal_ex<tag::int_parser<T, Radix, MinDigits, MaxDigits>
353 , fusion::vector1<A0> >, Modifiers>
354 : make_direct_int<T, Radix, MinDigits, MaxDigits> {};
356 ///////////////////////////////////////////////////////////////////////////
357 //[primitive_parsers_short_primitive
358 template <typename Modifiers>
359 struct make_primitive<tag::short_, Modifiers>
360 : make_int<short> {};
363 template <typename Modifiers, typename A0>
364 struct make_primitive<
365 terminal_ex<tag::short_
366 , fusion::vector1<A0> > , Modifiers>
367 : make_direct_int<short> {};
369 ///////////////////////////////////////////////////////////////////////////
370 //[primitive_parsers_int_primitive
371 template <typename Modifiers>
372 struct make_primitive<tag::int_, Modifiers>
376 template <typename Modifiers, typename A0>
377 struct make_primitive<
378 terminal_ex<tag::int_
379 , fusion::vector1<A0> > , Modifiers>
380 : make_direct_int<int> {};
382 ///////////////////////////////////////////////////////////////////////////
383 //[primitive_parsers_long_primitive
384 template <typename Modifiers>
385 struct make_primitive<tag::long_, Modifiers>
389 template <typename Modifiers, typename A0>
390 struct make_primitive<
391 terminal_ex<tag::long_
392 , fusion::vector1<A0> > , Modifiers>
393 : make_direct_int<long> {};
395 ///////////////////////////////////////////////////////////////////////////
396 #ifdef BOOST_HAS_LONG_LONG
397 //[primitive_parsers_long_long_primitive
398 template <typename Modifiers>
399 struct make_primitive<tag::long_long, Modifiers>
400 : make_int<boost::long_long_type> {};
403 template <typename Modifiers, typename A0>
404 struct make_primitive<
405 terminal_ex<tag::long_long
406 , fusion::vector1<A0> > , Modifiers>
407 : make_direct_int<boost::long_long_type> {};