Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_33_1/libs/spirit/test/numerics_tests.cpp @ 12

Last change on this file since 12 was 12, checked in by landauf, 17 years ago

added boost

File size: 11.0 KB
Line 
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
15using namespace std;
16using namespace boost::spirit;
17
18template <typename T>
19struct 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
74real_parser<double, ts_real_parser_policies<double> > const
75    ts_real_p = real_parser<double, ts_real_parser_policies<double> >();
76
77template <typename T>
78struct no_trailing_dot : public real_parser_policies<T>
79{
80    static const bool allow_trailing_dot = false;
81};
82
83real_parser<double, no_trailing_dot<double> > const
84    notrdot_real_p = real_parser<double, no_trailing_dot<double> >();
85
86template <typename T>
87struct no_leading_dot : public real_parser_policies<T>
88{
89    static const bool allow_leading_dot = false;
90};
91
92real_parser<double, no_leading_dot<double> > const
93    nolddot_real_p = real_parser<double, no_leading_dot<double> >();
94
95///////////////////////////////////////////////////////////////////////////////
96int
97main()
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}
Note: See TracBrowser for help on using the repository browser.