| 1 | /*============================================================================= | 
|---|
| 2 |     Copyright (c) 2001-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 | #include <boost/spirit/core.hpp> | 
|---|
| 11 | #include <boost/spirit/actor/assign_actor.hpp> | 
|---|
| 12 | #include <iostream> | 
|---|
| 13 | #include <assert.h> | 
|---|
| 14 |  | 
|---|
| 15 | using namespace std; | 
|---|
| 16 | using namespace boost::spirit; | 
|---|
| 17 |  | 
|---|
| 18 | template <typename T> | 
|---|
| 19 | struct ts_real_parser_policies : public ureal_parser_policies<T> | 
|---|
| 20 | { | 
|---|
| 21 |     //  These policies can be used to parse thousand separated | 
|---|
| 22 |     //  numbers with at most 2 decimal digits after the decimal | 
|---|
| 23 |     //  point. e.g. 123,456,789.01 | 
|---|
| 24 |  | 
|---|
| 25 |     typedef uint_parser<int, 10, 1, 2>  uint2_t; | 
|---|
| 26 |     typedef uint_parser<T, 10, 1, -1>   uint_parser_t; | 
|---|
| 27 |     typedef int_parser<int, 10, 1, -1>  int_parser_t; | 
|---|
| 28 |  | 
|---|
| 29 |     //////////////////////////////////  2 decimal places Max | 
|---|
| 30 |     template <typename ScannerT> | 
|---|
| 31 |     static typename parser_result<uint2_t, ScannerT>::type | 
|---|
| 32 |     parse_frac_n(ScannerT& scan) | 
|---|
| 33 |     { return uint2_t().parse(scan); } | 
|---|
| 34 |  | 
|---|
| 35 |     //////////////////////////////////  No exponent | 
|---|
| 36 |     template <typename ScannerT> | 
|---|
| 37 |     static typename parser_result<chlit<>, ScannerT>::type | 
|---|
| 38 |     parse_exp(ScannerT& scan) | 
|---|
| 39 |     { return scan.no_match(); } | 
|---|
| 40 |  | 
|---|
| 41 |     //////////////////////////////////  No exponent | 
|---|
| 42 |     template <typename ScannerT> | 
|---|
| 43 |     static typename parser_result<int_parser_t, ScannerT>::type | 
|---|
| 44 |     parse_exp_n(ScannerT& scan) | 
|---|
| 45 |     { return scan.no_match(); } | 
|---|
| 46 |  | 
|---|
| 47 |     //////////////////////////////////  Thousands separated numbers | 
|---|
| 48 |     template <typename ScannerT> | 
|---|
| 49 |     static typename parser_result<uint_parser_t, ScannerT>::type | 
|---|
| 50 |     parse_n(ScannerT& scan) | 
|---|
| 51 |     { | 
|---|
| 52 |         typedef typename parser_result<uint_parser_t, ScannerT>::type RT; | 
|---|
| 53 |         static uint_parser<unsigned, 10, 1, 3> uint3_p; | 
|---|
| 54 |         static uint_parser<unsigned, 10, 3, 3> uint3_3_p; | 
|---|
| 55 |  | 
|---|
| 56 |         if (RT hit = uint3_p.parse(scan)) | 
|---|
| 57 |         { | 
|---|
| 58 |             T n; | 
|---|
| 59 |             typedef typename ScannerT::iterator_t iterator_t; | 
|---|
| 60 |             iterator_t save = scan.first; | 
|---|
| 61 |             while (match<> next = (',' >> uint3_3_p[assign_a(n)]).parse(scan)) | 
|---|
| 62 |             { | 
|---|
| 63 |                 hit.value((hit.value() * 1000) + n); | 
|---|
| 64 |                 scan.concat_match(hit, next); | 
|---|
| 65 |                 save = scan.first; | 
|---|
| 66 |             } | 
|---|
| 67 |             scan.first = save; | 
|---|
| 68 |             return hit; | 
|---|
| 69 |         } | 
|---|
| 70 |         return scan.no_match(); | 
|---|
| 71 |     } | 
|---|
| 72 | }; | 
|---|
| 73 |  | 
|---|
| 74 | real_parser<double, ts_real_parser_policies<double> > const | 
|---|
| 75 |     ts_real_p = real_parser<double, ts_real_parser_policies<double> >(); | 
|---|
| 76 |  | 
|---|
| 77 | template <typename T> | 
|---|
| 78 | struct no_trailing_dot : public real_parser_policies<T> | 
|---|
| 79 | { | 
|---|
| 80 |     static const bool allow_trailing_dot = false; | 
|---|
| 81 | }; | 
|---|
| 82 |  | 
|---|
| 83 | real_parser<double, no_trailing_dot<double> > const | 
|---|
| 84 |     notrdot_real_p = real_parser<double, no_trailing_dot<double> >(); | 
|---|
| 85 |  | 
|---|
| 86 | template <typename T> | 
|---|
| 87 | struct no_leading_dot : public real_parser_policies<T> | 
|---|
| 88 | { | 
|---|
| 89 |     static const bool allow_leading_dot = false; | 
|---|
| 90 | }; | 
|---|
| 91 |  | 
|---|
| 92 | real_parser<double, no_leading_dot<double> > const | 
|---|
| 93 |     nolddot_real_p = real_parser<double, no_leading_dot<double> >(); | 
|---|
| 94 |  | 
|---|
| 95 | /////////////////////////////////////////////////////////////////////////////// | 
|---|
| 96 | int | 
|---|
| 97 | main() | 
|---|
| 98 | { | 
|---|
| 99 |     cout << "/////////////////////////////////////////////////////////\n\n"; | 
|---|
| 100 |     cout << "\t\tNumeric tests...\n\n"; | 
|---|
| 101 |     cout << "/////////////////////////////////////////////////////////\n\n"; | 
|---|
| 102 |  | 
|---|
| 103 |     //  *** The following assumes 32 bit integers. Modify these constant | 
|---|
| 104 |     //  *** strings when appropriate. BEWARE PLATFORM DEPENDENT! | 
|---|
| 105 |  | 
|---|
| 106 |     char const* max_unsigned = "4294967295"; | 
|---|
| 107 |     char const* unsigned_overflow = "4294967296"; | 
|---|
| 108 |     char const* max_int = "2147483647"; | 
|---|
| 109 |     char const* int_overflow = "2147483648"; | 
|---|
| 110 |     char const* min_int = "-2147483648"; | 
|---|
| 111 |     char const* int_underflow = "-2147483649"; | 
|---|
| 112 |     char const* max_binary = "11111111111111111111111111111111"; | 
|---|
| 113 |     char const* binary_overflow = "100000000000000000000000000000000"; | 
|---|
| 114 |     char const* max_octal = "77777777777"; | 
|---|
| 115 |     char const* octal_overflow = "100000000000"; | 
|---|
| 116 |     char const* max_hex = "FFFFFFFF"; | 
|---|
| 117 |     char const* hex_overflow = "100000000"; | 
|---|
| 118 |  | 
|---|
| 119 | #ifdef BOOST_HAS_LONG_LONG | 
|---|
| 120 |  | 
|---|
| 121 |     char const* max_long_long = "9223372036854775807"; | 
|---|
| 122 |     char const* long_long_overflow = "9223372036854775808"; | 
|---|
| 123 |     char const* min_long_long = "-9223372036854775808"; | 
|---|
| 124 |     char const* long_long_underflow = "-9223372036854775809"; | 
|---|
| 125 |  | 
|---|
| 126 | #endif | 
|---|
| 127 |  | 
|---|
| 128 | //  BEGIN TESTS... | 
|---|
| 129 |  | 
|---|
| 130 |     unsigned u; | 
|---|
| 131 |  | 
|---|
| 132 | //  unsigned integer | 
|---|
| 133 |  | 
|---|
| 134 |     parse("123456", uint_p[assign_a(u)]); | 
|---|
| 135 |     assert(u == 123456); | 
|---|
| 136 |  | 
|---|
| 137 |     parse(max_unsigned, uint_p[assign_a(u)]); | 
|---|
| 138 |     assert(u == UINT_MAX); | 
|---|
| 139 |  | 
|---|
| 140 |     assert(!parse(unsigned_overflow, uint_p).full); | 
|---|
| 141 |  | 
|---|
| 142 | //  signed integer | 
|---|
| 143 |  | 
|---|
| 144 |     int i; | 
|---|
| 145 |  | 
|---|
| 146 |     parse("123456", int_p[assign_a(i)]); | 
|---|
| 147 |     assert(i == 123456); | 
|---|
| 148 |  | 
|---|
| 149 |     parse("-123456", int_p[assign_a(i)]); | 
|---|
| 150 |     assert(i == -123456); | 
|---|
| 151 |  | 
|---|
| 152 |     parse(max_int, int_p[assign_a(i)]); | 
|---|
| 153 |     assert(i == INT_MAX); | 
|---|
| 154 |  | 
|---|
| 155 |     parse(min_int, int_p[assign_a(i)]); | 
|---|
| 156 |     assert(i == INT_MIN); | 
|---|
| 157 |  | 
|---|
| 158 |     assert(!parse(int_overflow, int_p).full); | 
|---|
| 159 |     assert(!parse(int_underflow, int_p).full); | 
|---|
| 160 |  | 
|---|
| 161 |     assert(!parse("-", int_p).hit); | 
|---|
| 162 |  | 
|---|
| 163 | //  binary | 
|---|
| 164 |  | 
|---|
| 165 |     parse("11111110", bin_p[assign_a(u)]); | 
|---|
| 166 |     assert(u == 0xFE); | 
|---|
| 167 |  | 
|---|
| 168 |     parse(max_binary, bin_p[assign_a(u)]); | 
|---|
| 169 |     assert(u == UINT_MAX); | 
|---|
| 170 |  | 
|---|
| 171 |     assert(!parse(binary_overflow, bin_p).full); | 
|---|
| 172 |  | 
|---|
| 173 | //  octal | 
|---|
| 174 |  | 
|---|
| 175 |     parse("12545674515", oct_p[assign_a(u)]); | 
|---|
| 176 |     assert(u == 012545674515); | 
|---|
| 177 |  | 
|---|
| 178 |     parse(max_octal, oct_p[assign_a(u)]); | 
|---|
| 179 |     assert(u == UINT_MAX); | 
|---|
| 180 |  | 
|---|
| 181 |     assert(!parse(octal_overflow, oct_p).full); | 
|---|
| 182 |  | 
|---|
| 183 | //  hex | 
|---|
| 184 |  | 
|---|
| 185 |     parse("95BC8DF", hex_p[assign_a(u)]); | 
|---|
| 186 |     assert(u == 0x95BC8DF); | 
|---|
| 187 |  | 
|---|
| 188 |     parse("abcdef12", hex_p[assign_a(u)]); | 
|---|
| 189 |     assert(u == 0xabcdef12); | 
|---|
| 190 |  | 
|---|
| 191 |     parse(max_hex, hex_p[assign_a(u)]); | 
|---|
| 192 |     assert(u == UINT_MAX); | 
|---|
| 193 |  | 
|---|
| 194 |     assert(!parse(hex_overflow, hex_p).full); | 
|---|
| 195 |  | 
|---|
| 196 | //  limited fieldwidth | 
|---|
| 197 |  | 
|---|
| 198 |     uint_parser<unsigned, 10, 1, 3> uint3_p; | 
|---|
| 199 |     parse("123456", uint3_p[assign_a(u)]); | 
|---|
| 200 |     assert(u == 123); | 
|---|
| 201 |  | 
|---|
| 202 |     uint_parser<unsigned, 10, 1, 4> uint4_p; | 
|---|
| 203 |     parse("123456", uint4_p[assign_a(u)]); | 
|---|
| 204 |     assert(u == 1234); | 
|---|
| 205 |  | 
|---|
| 206 |     uint_parser<unsigned, 10, 3, 3> uint3_3_p; | 
|---|
| 207 |  | 
|---|
| 208 | //  thousand separated numbers | 
|---|
| 209 |  | 
|---|
| 210 | #define r (uint3_p >> *(',' >> uint3_3_p)) | 
|---|
| 211 |  | 
|---|
| 212 |     assert(parse("1,234,567,890", r).full);     //  OK | 
|---|
| 213 |     assert(parse("12,345,678,900", r).full);    //  OK | 
|---|
| 214 |     assert(parse("123,456,789,000", r).full);   //  OK | 
|---|
| 215 |     assert(!parse("1000,234,567,890", r).full); //  Bad | 
|---|
| 216 |     assert(!parse("1,234,56,890", r).full);     //  Bad | 
|---|
| 217 |     assert(!parse("1,66", r).full);             //  Bad | 
|---|
| 218 |  | 
|---|
| 219 | //  long long | 
|---|
| 220 |  | 
|---|
| 221 | #ifdef BOOST_HAS_LONG_LONG | 
|---|
| 222 |  | 
|---|
| 223 | // Some compilers have long long, but don't define the | 
|---|
| 224 | // LONG_LONG_MIN and LONG_LONG_MAX macros in limits.h.  This | 
|---|
| 225 | // assumes that long long is 64 bits. | 
|---|
| 226 | #if !defined(LONG_LONG_MIN) && !defined(LONG_LONG_MAX) \ | 
|---|
| 227 |             && !defined(ULONG_LONG_MAX) | 
|---|
| 228 | #define ULONG_LONG_MAX 0xffffffffffffffffLLU | 
|---|
| 229 | #define LONG_LONG_MAX 0x7fffffffffffffffLL | 
|---|
| 230 | #define LONG_LONG_MIN (-LONG_LONG_MAX - 1) | 
|---|
| 231 | #endif | 
|---|
| 232 |  | 
|---|
| 233 |      ::boost::long_long_type ll; | 
|---|
| 234 |     int_parser< ::boost::long_long_type> long_long_p; | 
|---|
| 235 |  | 
|---|
| 236 |     parse("1234567890123456789", long_long_p[assign_a(ll)]); | 
|---|
| 237 |     assert(ll == 1234567890123456789LL); | 
|---|
| 238 |  | 
|---|
| 239 |     parse("-1234567890123456789", long_long_p[assign_a(ll)]); | 
|---|
| 240 |     assert(ll == -1234567890123456789LL); | 
|---|
| 241 |  | 
|---|
| 242 |     parse(max_long_long, long_long_p[assign_a(ll)]); | 
|---|
| 243 |     assert(ll == LONG_LONG_MAX); | 
|---|
| 244 |  | 
|---|
| 245 |     parse(min_long_long, long_long_p[assign_a(ll)]); | 
|---|
| 246 |     assert(ll == LONG_LONG_MIN); | 
|---|
| 247 |  | 
|---|
| 248 | #if defined(__GNUG__) && (__GNUG__ == 3) && (__GNUC_MINOR__ < 3) \ | 
|---|
| 249 |     && !defined(__EDG__) | 
|---|
| 250 |     // gcc 3.2.3 crashes on parse(long_long_overflow, long_long_p) | 
|---|
| 251 |     // wrapping long_long_p into a rule avoids the crash | 
|---|
| 252 |     rule<> gcc_3_2_3_long_long_r = long_long_p; | 
|---|
| 253 |     assert(!parse(long_long_overflow, gcc_3_2_3_long_long_r).full); | 
|---|
| 254 |     assert(!parse(long_long_underflow, gcc_3_2_3_long_long_r).full); | 
|---|
| 255 | #else | 
|---|
| 256 |     assert(!parse(long_long_overflow, long_long_p).full); | 
|---|
| 257 |     assert(!parse(long_long_underflow, long_long_p).full); | 
|---|
| 258 | #endif | 
|---|
| 259 |  | 
|---|
| 260 | #endif | 
|---|
| 261 |  | 
|---|
| 262 | //  real numbers | 
|---|
| 263 |  | 
|---|
| 264 |     double  d; | 
|---|
| 265 |  | 
|---|
| 266 |     assert(parse("1234", ureal_p[assign_a(d)]).full && d == 1234);      //  Good. | 
|---|
| 267 |     assert(parse("1.2e3", ureal_p[assign_a(d)]).full && d == 1.2e3);    //  Good. | 
|---|
| 268 |     assert(parse("1.2e-3", ureal_p[assign_a(d)]).full && d == 1.2e-3);  //  Good. | 
|---|
| 269 |     assert(parse("1.e2", ureal_p[assign_a(d)]).full && d == 1.e2);      //  Good. | 
|---|
| 270 |     assert(parse(".2e3", ureal_p[assign_a(d)]).full && d == .2e3);      //  Good. | 
|---|
| 271 |     assert(parse("2e3", ureal_p[assign_a(d)]).full && d == 2e3);        //  Good. No fraction | 
|---|
| 272 |     assert(!parse("e3", ureal_p).full);                                 //  Bad! No number | 
|---|
| 273 |     assert(!parse("-1.2e3", ureal_p).full);                             //  Bad! Negative number | 
|---|
| 274 |     assert(!parse("+1.2e3", ureal_p).full);                             //  Bad! Positive sign | 
|---|
| 275 |     assert(!parse("1.2e", ureal_p).full);                               //  Bad! No exponent | 
|---|
| 276 |     assert(!parse("-.3", ureal_p).full);                                //  Bad! Negative | 
|---|
| 277 |  | 
|---|
| 278 |     assert(parse("-1234", real_p[assign_a(d)]).full && d == -1234);     //  Good. | 
|---|
| 279 |     assert(parse("-1.2e3", real_p[assign_a(d)]).full && d == -1.2e3);   //  Good. | 
|---|
| 280 |     assert(parse("+1.2e3", real_p[assign_a(d)]).full && d == 1.2e3);    //  Good. | 
|---|
| 281 |     assert(parse("-0.1", real_p[assign_a(d)]).full && d == -0.1);       //  Good. | 
|---|
| 282 |     assert(parse("-1.2e-3", real_p[assign_a(d)]).full && d == -1.2e-3); //  Good. | 
|---|
| 283 |     assert(parse("-1.e2", real_p[assign_a(d)]).full && d == -1.e2);     //  Good. | 
|---|
| 284 |     assert(parse("-.2e3", real_p[assign_a(d)]).full && d == -.2e3);     //  Good. | 
|---|
| 285 |     assert(parse("-2e3", real_p[assign_a(d)]).full && d == -2e3);       //  Good. No fraction | 
|---|
| 286 |     assert(!parse("-e3", real_p).full);                                 //  Bad! No number | 
|---|
| 287 |     assert(!parse("-1.2e", real_p).full);                               //  Bad! No exponent | 
|---|
| 288 |  | 
|---|
| 289 |     assert(!parse("1234", strict_ureal_p[assign_a(d)]).full);           //  Bad. Strict real | 
|---|
| 290 |     assert(parse("1.2", strict_ureal_p[assign_a(d)]).full && d == 1.2); //  Good. | 
|---|
| 291 |     assert(!parse("-1234", strict_real_p[assign_a(d)]).full);           //  Bad. Strict real | 
|---|
| 292 |     assert(parse("123.", strict_real_p[assign_a(d)]).full && d == 123); //  Good. | 
|---|
| 293 |     assert(parse("3.E6", strict_real_p[assign_a(d)]).full && d == 3e6); //  Good. | 
|---|
| 294 |  | 
|---|
| 295 |     assert(!parse("1234.", notrdot_real_p[assign_a(d)]).full);          //  Bad trailing dot | 
|---|
| 296 |     assert(!parse(".1234", nolddot_real_p[assign_a(d)]).full);          //  Bad leading dot | 
|---|
| 297 |  | 
|---|
| 298 | //  Special thousands separated numbers | 
|---|
| 299 |  | 
|---|
| 300 |     assert(parse("123,456,789.01", ts_real_p[assign_a(d)]).full && d == 123456789.01);  //  Good. | 
|---|
| 301 |     assert(parse("12,345,678.90", ts_real_p[assign_a(d)]).full && d == 12345678.90);    //  Good. | 
|---|
| 302 |     assert(parse("1,234,567.89", ts_real_p[assign_a(d)]).full && d == 1234567.89);      //  Good. | 
|---|
| 303 |     assert(!parse("1234,567,890", ts_real_p).full);     //  Bad. | 
|---|
| 304 |     assert(!parse("1,234,5678,9", ts_real_p).full);     //  Bad. | 
|---|
| 305 |     assert(!parse("1,234,567.89e6", ts_real_p).full);   //  Bad. | 
|---|
| 306 |     assert(!parse("1,66", ts_real_p).full);             //  Bad. | 
|---|
| 307 |  | 
|---|
| 308 | //  END TESTS. | 
|---|
| 309 |  | 
|---|
| 310 | ///////////////////////////////////////////////////////////////// | 
|---|
| 311 |     cout << "success!\n"; | 
|---|
| 312 |     return 0; | 
|---|
| 313 | } | 
|---|