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 #ifndef BOOST_SPIRIT_QI_NUMERIC_UINT_HPP 10 #define BOOST_SPIRIT_QI_NUMERIC_UINT_HPP 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> parseboost::spirit::qi::any_uint_parser236 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> whatboost::spirit::qi::any_uint_parser246 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> literal_uint_parserboost::spirit::qi::literal_uint_parser265 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> parseboost::spirit::qi::literal_uint_parser274 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> whatboost::spirit::qi::literal_uint_parser295 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; operator ()boost::spirit::qi::make_uint311 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> operator ()boost::spirit::qi::make_direct_uint324 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> operator ()boost::spirit::qi::make_literal_uint336 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 465