[29] | 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 <boost/detail/lightweight_test.hpp> |
---|
| 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 | BOOST_TEST(u == 123456); |
---|
| 136 | |
---|
| 137 | parse(max_unsigned, uint_p[assign_a(u)]); |
---|
| 138 | BOOST_TEST(u == UINT_MAX); |
---|
| 139 | |
---|
| 140 | BOOST_TEST(!parse(unsigned_overflow, uint_p).full); |
---|
| 141 | |
---|
| 142 | // signed integer |
---|
| 143 | |
---|
| 144 | int i; |
---|
| 145 | |
---|
| 146 | parse("123456", int_p[assign_a(i)]); |
---|
| 147 | BOOST_TEST(i == 123456); |
---|
| 148 | |
---|
| 149 | parse("-123456", int_p[assign_a(i)]); |
---|
| 150 | BOOST_TEST(i == -123456); |
---|
| 151 | |
---|
| 152 | parse(max_int, int_p[assign_a(i)]); |
---|
| 153 | BOOST_TEST(i == INT_MAX); |
---|
| 154 | |
---|
| 155 | parse(min_int, int_p[assign_a(i)]); |
---|
| 156 | BOOST_TEST(i == INT_MIN); |
---|
| 157 | |
---|
| 158 | BOOST_TEST(!parse(int_overflow, int_p).full); |
---|
| 159 | BOOST_TEST(!parse(int_underflow, int_p).full); |
---|
| 160 | |
---|
| 161 | BOOST_TEST(!parse("-", int_p).hit); |
---|
| 162 | |
---|
| 163 | // binary |
---|
| 164 | |
---|
| 165 | parse("11111110", bin_p[assign_a(u)]); |
---|
| 166 | BOOST_TEST(u == 0xFE); |
---|
| 167 | |
---|
| 168 | parse(max_binary, bin_p[assign_a(u)]); |
---|
| 169 | BOOST_TEST(u == UINT_MAX); |
---|
| 170 | |
---|
| 171 | BOOST_TEST(!parse(binary_overflow, bin_p).full); |
---|
| 172 | |
---|
| 173 | // octal |
---|
| 174 | |
---|
| 175 | parse("12545674515", oct_p[assign_a(u)]); |
---|
| 176 | BOOST_TEST(u == 012545674515); |
---|
| 177 | |
---|
| 178 | parse(max_octal, oct_p[assign_a(u)]); |
---|
| 179 | BOOST_TEST(u == UINT_MAX); |
---|
| 180 | |
---|
| 181 | BOOST_TEST(!parse(octal_overflow, oct_p).full); |
---|
| 182 | |
---|
| 183 | // hex |
---|
| 184 | |
---|
| 185 | parse("95BC8DF", hex_p[assign_a(u)]); |
---|
| 186 | BOOST_TEST(u == 0x95BC8DF); |
---|
| 187 | |
---|
| 188 | parse("abcdef12", hex_p[assign_a(u)]); |
---|
| 189 | BOOST_TEST(u == 0xabcdef12); |
---|
| 190 | |
---|
| 191 | parse(max_hex, hex_p[assign_a(u)]); |
---|
| 192 | BOOST_TEST(u == UINT_MAX); |
---|
| 193 | |
---|
| 194 | BOOST_TEST(!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 | BOOST_TEST(u == 123); |
---|
| 201 | |
---|
| 202 | uint_parser<unsigned, 10, 1, 4> uint4_p; |
---|
| 203 | parse("123456", uint4_p[assign_a(u)]); |
---|
| 204 | BOOST_TEST(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 | BOOST_TEST(parse("1,234,567,890", r).full); // OK |
---|
| 213 | BOOST_TEST(parse("12,345,678,900", r).full); // OK |
---|
| 214 | BOOST_TEST(parse("123,456,789,000", r).full); // OK |
---|
| 215 | BOOST_TEST(!parse("1000,234,567,890", r).full); // Bad |
---|
| 216 | BOOST_TEST(!parse("1,234,56,890", r).full); // Bad |
---|
| 217 | BOOST_TEST(!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 | BOOST_TEST(ll == 1234567890123456789LL); |
---|
| 238 | |
---|
| 239 | parse("-1234567890123456789", long_long_p[assign_a(ll)]); |
---|
| 240 | BOOST_TEST(ll == -1234567890123456789LL); |
---|
| 241 | |
---|
| 242 | parse(max_long_long, long_long_p[assign_a(ll)]); |
---|
| 243 | BOOST_TEST(ll == LONG_LONG_MAX); |
---|
| 244 | |
---|
| 245 | parse(min_long_long, long_long_p[assign_a(ll)]); |
---|
| 246 | BOOST_TEST(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 | BOOST_TEST(!parse(long_long_overflow, gcc_3_2_3_long_long_r).full); |
---|
| 254 | BOOST_TEST(!parse(long_long_underflow, gcc_3_2_3_long_long_r).full); |
---|
| 255 | #else |
---|
| 256 | BOOST_TEST(!parse(long_long_overflow, long_long_p).full); |
---|
| 257 | BOOST_TEST(!parse(long_long_underflow, long_long_p).full); |
---|
| 258 | #endif |
---|
| 259 | |
---|
| 260 | #endif |
---|
| 261 | |
---|
| 262 | // real numbers |
---|
| 263 | |
---|
| 264 | double d; |
---|
| 265 | |
---|
| 266 | BOOST_TEST(parse("1234", ureal_p[assign_a(d)]).full && d == 1234); // Good. |
---|
| 267 | BOOST_TEST(parse("1.2e3", ureal_p[assign_a(d)]).full && d == 1.2e3); // Good. |
---|
| 268 | BOOST_TEST(parse("1.2e-3", ureal_p[assign_a(d)]).full && d == 1.2e-3); // Good. |
---|
| 269 | BOOST_TEST(parse("1.e2", ureal_p[assign_a(d)]).full && d == 1.e2); // Good. |
---|
| 270 | BOOST_TEST(parse(".2e3", ureal_p[assign_a(d)]).full && d == .2e3); // Good. |
---|
| 271 | BOOST_TEST(parse("2e3", ureal_p[assign_a(d)]).full && d == 2e3); // Good. No fraction |
---|
| 272 | BOOST_TEST(!parse("e3", ureal_p).full); // Bad! No number |
---|
| 273 | BOOST_TEST(!parse("-1.2e3", ureal_p).full); // Bad! Negative number |
---|
| 274 | BOOST_TEST(!parse("+1.2e3", ureal_p).full); // Bad! Positive sign |
---|
| 275 | BOOST_TEST(!parse("1.2e", ureal_p).full); // Bad! No exponent |
---|
| 276 | BOOST_TEST(!parse("-.3", ureal_p).full); // Bad! Negative |
---|
| 277 | |
---|
| 278 | BOOST_TEST(parse("-1234", real_p[assign_a(d)]).full && d == -1234); // Good. |
---|
| 279 | BOOST_TEST(parse("-1.2e3", real_p[assign_a(d)]).full && d == -1.2e3); // Good. |
---|
| 280 | BOOST_TEST(parse("+1.2e3", real_p[assign_a(d)]).full && d == 1.2e3); // Good. |
---|
| 281 | BOOST_TEST(parse("-0.1", real_p[assign_a(d)]).full && d == -0.1); // Good. |
---|
| 282 | BOOST_TEST(parse("-1.2e-3", real_p[assign_a(d)]).full && d == -1.2e-3); // Good. |
---|
| 283 | BOOST_TEST(parse("-1.e2", real_p[assign_a(d)]).full && d == -1.e2); // Good. |
---|
| 284 | BOOST_TEST(parse("-.2e3", real_p[assign_a(d)]).full && d == -.2e3); // Good. |
---|
| 285 | BOOST_TEST(parse("-2e3", real_p[assign_a(d)]).full && d == -2e3); // Good. No fraction |
---|
| 286 | BOOST_TEST(!parse("-e3", real_p).full); // Bad! No number |
---|
| 287 | BOOST_TEST(!parse("-1.2e", real_p).full); // Bad! No exponent |
---|
| 288 | |
---|
| 289 | BOOST_TEST(!parse("1234", strict_ureal_p[assign_a(d)]).full); // Bad. Strict real |
---|
| 290 | BOOST_TEST(parse("1.2", strict_ureal_p[assign_a(d)]).full && d == 1.2); // Good. |
---|
| 291 | BOOST_TEST(!parse("-1234", strict_real_p[assign_a(d)]).full); // Bad. Strict real |
---|
| 292 | BOOST_TEST(parse("123.", strict_real_p[assign_a(d)]).full && d == 123); // Good. |
---|
| 293 | BOOST_TEST(parse("3.E6", strict_real_p[assign_a(d)]).full && d == 3e6); // Good. |
---|
| 294 | |
---|
| 295 | BOOST_TEST(!parse("1234.", notrdot_real_p[assign_a(d)]).full); // Bad trailing dot |
---|
| 296 | BOOST_TEST(!parse(".1234", nolddot_real_p[assign_a(d)]).full); // Bad leading dot |
---|
| 297 | |
---|
| 298 | // Special thousands separated numbers |
---|
| 299 | |
---|
| 300 | BOOST_TEST(parse("123,456,789.01", ts_real_p[assign_a(d)]).full && d == 123456789.01); // Good. |
---|
| 301 | BOOST_TEST(parse("12,345,678.90", ts_real_p[assign_a(d)]).full && d == 12345678.90); // Good. |
---|
| 302 | BOOST_TEST(parse("1,234,567.89", ts_real_p[assign_a(d)]).full && d == 1234567.89); // Good. |
---|
| 303 | BOOST_TEST(!parse("1234,567,890", ts_real_p).full); // Bad. |
---|
| 304 | BOOST_TEST(!parse("1,234,5678,9", ts_real_p).full); // Bad. |
---|
| 305 | BOOST_TEST(!parse("1,234,567.89e6", ts_real_p).full); // Bad. |
---|
| 306 | BOOST_TEST(!parse("1,66", ts_real_p).full); // Bad. |
---|
| 307 | |
---|
| 308 | // END TESTS. |
---|
| 309 | |
---|
| 310 | ///////////////////////////////////////////////////////////////// |
---|
| 311 | return boost::report_errors(); |
---|
| 312 | } |
---|