1 /*============================================================================= 2 Copyright (c) 2001-2011 Joel de Guzman 3 Copyright (c) 2011 Bryce Lelbach 4 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 10 11 #if defined(_MSC_VER) 12 #pragma once 13 #endif 14 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> 25 26 namespace boost { namespace spirit 27 { 28 namespace tag 29 { 30 template <typename T, unsigned Radix, unsigned MinDigits 31 , int MaxDigits> 32 struct int_parser 33 { 34 BOOST_SPIRIT_IS_TAG() 35 }; 36 } 37 38 namespace qi 39 { 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 44 , int MaxDigits = -1> 45 struct int_parser 46 : spirit::terminal<tag::int_parser<T, Radix, MinDigits, MaxDigits> > 47 {}; 48 } 49 50 /////////////////////////////////////////////////////////////////////////// 51 // Enablers 52 /////////////////////////////////////////////////////////////////////////// 53 //[primitive_parsers_enable_short 54 template <> // enables short_ 55 struct use_terminal<qi::domain, tag::short_> : mpl::true_ {}; 56 //] 57 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> 62 : mpl::true_ {}; 63 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> {}; 68 69 template <> // enables *lazy* short_(n) 70 struct use_lazy_terminal<qi::domain, tag::short_, 1> : mpl::true_ {}; 71 72 /////////////////////////////////////////////////////////////////////////// 73 //[primitive_parsers_enable_int 74 template <> // enables int_ 75 struct use_terminal<qi::domain, tag::int_> : mpl::true_ {}; 76 //] 77 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> 82 : mpl::true_ {}; 83 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> {}; 88 89 template <> // enables *lazy* int_(n) 90 struct use_lazy_terminal<qi::domain, tag::int_, 1> : mpl::true_ {}; 91 92 /////////////////////////////////////////////////////////////////////////// 93 //[primitive_parsers_enable_long 94 template <> // enables long_ 95 struct use_terminal<qi::domain, tag::long_> : mpl::true_ {}; 96 //] 97 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> 102 : mpl::true_ {}; 103 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> {}; 108 109 template <> // enables *lazy* long_(n) 110 struct use_lazy_terminal<qi::domain, tag::long_, 1> : mpl::true_ {}; 111 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_ {}; 117 //] 118 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> 123 : mpl::true_ {}; 124 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> {}; 129 130 template <> // enables *lazy* long_long(n) 131 struct use_lazy_terminal<qi::domain, tag::long_long, 1> : mpl::true_ {}; 132 #endif 133 134 /////////////////////////////////////////////////////////////////////////// 135 // enables any custom int_parser 136 template <typename T, unsigned Radix, unsigned MinDigits 137 , int MaxDigits> 138 struct use_terminal<qi::domain 139 , tag::int_parser<T, Radix, MinDigits, MaxDigits> > 140 : mpl::true_ {}; 141 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> > 148 > : mpl::true_ {}; 149 150 // enables *lazy* custom int_parser(n) 151 template <typename T, unsigned Radix, unsigned MinDigits 152 , int MaxDigits> 153 struct use_lazy_terminal<qi::domain 154 , tag::int_parser<T, Radix, MinDigits, MaxDigits>, 1 155 > : mpl::true_ {}; 156 }} 157 158 namespace boost { namespace spirit { namespace qi 159 { 160 #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS 161 using spirit::short_; 162 using spirit::int_; 163 using spirit::long_; 164 #ifdef BOOST_HAS_LONG_LONG 165 using spirit::long_long; 166 #endif 167 using spirit::lit; // lit(1) is equivalent to 1 168 #endif 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; 175 #endif 176 using spirit::lit_type; 177 178 /////////////////////////////////////////////////////////////////////////// 179 // This is the actual int parser 180 /////////////////////////////////////////////////////////////////////////// 181 //[primitive_parsers_int_parser 182 template < 183 typename T 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> > 189 { 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, ()); 194 195 template <typename Context, typename Iterator> 196 struct attribute 197 { 198 typedef T type; 199 }; 200 201 template <typename Iterator, typename Context 202 , typename Skipper, typename Attribute> parseboost::spirit::qi::any_int_parser203 bool parse(Iterator& first, Iterator const& last 204 , Context& /*context*/, Skipper const& skipper 205 , Attribute& attr_) const 206 { 207 typedef extract_int<T, Radix, MinDigits, MaxDigits> extract; 208 qi::skip_over(first, last, skipper); 209 return extract::call(first, last, attr_); 210 } 211 212 template <typename Context> whatboost::spirit::qi::any_int_parser213 info what(Context& /*context*/) const 214 { 215 return info("integer"); 216 } 217 }; 218 //] 219 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 224 , no_attribute> > 225 { 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, ()); 230 231 template <typename Value> literal_int_parserboost::spirit::qi::literal_int_parser232 literal_int_parser(Value const& n) : n_(n) {} 233 234 template <typename Context, typename Iterator> 235 struct attribute 236 : mpl::if_c<no_attribute, unused_type, T> 237 {}; 238 239 template <typename Iterator, typename Context 240 , typename Skipper, typename Attribute> parseboost::spirit::qi::literal_int_parser241 bool parse(Iterator& first, Iterator const& last 242 , Context& /*context*/, Skipper const& skipper 243 , Attribute& attr_param) const 244 { 245 typedef extract_int<T, Radix, MinDigits, MaxDigits> extract; 246 qi::skip_over(first, last, skipper); 247 248 Iterator save = first; 249 T attr_; 250 251 if (extract::call(first, last, attr_) && (attr_ == n_)) 252 { 253 traits::assign_to(attr_, attr_param); 254 return true; 255 } 256 257 first = save; 258 return false; 259 } 260 261 template <typename Context> whatboost::spirit::qi::literal_int_parser262 info what(Context& /*context*/) const 263 { 264 return info("integer"); 265 } 266 267 T n_; 268 }; 269 270 /////////////////////////////////////////////////////////////////////////// 271 // Parser generators: make_xxx function (objects) 272 /////////////////////////////////////////////////////////////////////////// 273 //[primitive_parsers_make_int 274 template < 275 typename T 276 , unsigned Radix = 10 277 , unsigned MinDigits = 1 278 , int MaxDigits = -1> 279 struct make_int 280 { 281 typedef any_int_parser<T, Radix, MinDigits, MaxDigits> result_type; operator ()boost::spirit::qi::make_int282 result_type operator()(unused_type, unused_type) const 283 { 284 return result_type(); 285 } 286 }; 287 //] 288 289 template <typename T, unsigned Radix = 10, unsigned MinDigits = 1 290 , int MaxDigits = -1> 291 struct make_direct_int 292 { 293 typedef literal_int_parser<T, Radix, MinDigits, MaxDigits, false> 294 result_type; 295 template <typename Terminal> operator ()boost::spirit::qi::make_direct_int296 result_type operator()(Terminal const& term, unused_type) const 297 { 298 return result_type(fusion::at_c<0>(term.args)); 299 } 300 }; 301 302 template <typename T, unsigned Radix = 10, unsigned MinDigits = 1 303 , int MaxDigits = -1> 304 struct make_literal_int 305 { 306 typedef literal_int_parser<T, Radix, MinDigits, MaxDigits> result_type; 307 template <typename Terminal> operator ()boost::spirit::qi::make_literal_int308 result_type operator()(Terminal const& term, unused_type) const 309 { 310 return result_type(fusion::at_c<0>(term.args)); 311 } 312 }; 313 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> {}; 320 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> {}; 326 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> {}; 332 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> {}; 339 #endif 340 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> 346 , Modifiers> 347 : make_int<T, Radix, MinDigits, MaxDigits> {}; 348 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> {}; 355 356 /////////////////////////////////////////////////////////////////////////// 357 //[primitive_parsers_short_primitive 358 template <typename Modifiers> 359 struct make_primitive<tag::short_, Modifiers> 360 : make_int<short> {}; 361 //] 362 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> {}; 368 369 /////////////////////////////////////////////////////////////////////////// 370 //[primitive_parsers_int_primitive 371 template <typename Modifiers> 372 struct make_primitive<tag::int_, Modifiers> 373 : make_int<int> {}; 374 //] 375 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> {}; 381 382 /////////////////////////////////////////////////////////////////////////// 383 //[primitive_parsers_long_primitive 384 template <typename Modifiers> 385 struct make_primitive<tag::long_, Modifiers> 386 : make_int<long> {}; 387 //] 388 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> {}; 394 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> {}; 401 //] 402 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> {}; 408 #endif 409 }}} 410 411 #endif 412