1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
|
/*=============================================================================
Copyright (c) 2002-2003 Joel de Guzman
http://spirit.sourceforge.net/
Use, modification and distribution is subject to the Boost Software
License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
=============================================================================*/
///////////////////////////////////////////////////////////////////////////////
//
// A parser for a real number parser that parses thousands separated numbers
// with at most two decimal places and no exponent. This is discussed in the
// "Numerics" chapter in the Spirit User's Guide.
//
// [ JDG 12/16/2003 ]
//
///////////////////////////////////////////////////////////////////////////////
#include <boost/spirit/include/classic_core.hpp>
#include <boost/spirit/include/classic_assign_actor.hpp>
#include <iostream>
#include <string>
///////////////////////////////////////////////////////////////////////////////
using namespace std;
using namespace BOOST_SPIRIT_CLASSIC_NS;
template <typename T>
struct ts_real_parser_policies : public ureal_parser_policies<T>
{
// These policies can be used to parse thousand separated
// numbers with at most 2 decimal digits after the decimal
// point. e.g. 123,456,789.01
typedef uint_parser<int, 10, 1, 2> uint2_t;
typedef uint_parser<T, 10, 1, -1> uint_parser_t;
typedef int_parser<int, 10, 1, -1> int_parser_t;
////////////////////////////////// 2 decimal places Max
template <typename ScannerT>
static typename parser_result<uint2_t, ScannerT>::type
parse_frac_n(ScannerT& scan)
{ return uint2_t().parse(scan); }
////////////////////////////////// No exponent
template <typename ScannerT>
static typename parser_result<chlit<>, ScannerT>::type
parse_exp(ScannerT& scan)
{ return scan.no_match(); }
////////////////////////////////// No exponent
template <typename ScannerT>
static typename parser_result<int_parser_t, ScannerT>::type
parse_exp_n(ScannerT& scan)
{ return scan.no_match(); }
////////////////////////////////// Thousands separated numbers
template <typename ScannerT>
static typename parser_result<uint_parser_t, ScannerT>::type
parse_n(ScannerT& scan)
{
typedef typename parser_result<uint_parser_t, ScannerT>::type RT;
static uint_parser<unsigned, 10, 1, 3> uint3_p;
static uint_parser<unsigned, 10, 3, 3> uint3_3_p;
if (RT hit = uint3_p.parse(scan))
{
T n;
typedef typename ScannerT::iterator_t iterator_t;
iterator_t save = scan.first;
while (match<> next = (',' >> uint3_3_p[assign_a(n)]).parse(scan))
{
hit.value((hit.value() * 1000) + n);
scan.concat_match(hit, next);
save = scan.first;
}
scan.first = save;
return hit;
// Note: On erroneous input such as "123,45", the result should
// be a partial match "123". 'save' is used to makes sure that
// the scanner position is placed at the last *valid* parse
// position.
}
return scan.no_match();
}
};
real_parser<double, ts_real_parser_policies<double> > const
ts_real_p = real_parser<double, ts_real_parser_policies<double> >();
////////////////////////////////////////////////////////////////////////////
//
// Main program
//
////////////////////////////////////////////////////////////////////////////
int
main()
{
cout << "/////////////////////////////////////////////////////////\n\n";
cout << "\t\tA real number parser that parses thousands separated\n";
cout << "\t\tnumbers with at most two decimal places and no exponent...\n\n";
cout << "/////////////////////////////////////////////////////////\n\n";
cout << "Give me a number.\n";
cout << "Type [q or Q] to quit\n\n";
string str;
double n;
while (getline(cin, str))
{
if (str.empty() || str[0] == 'q' || str[0] == 'Q')
break;
if (parse(str.c_str(), ts_real_p[assign_a(n)]).full)
{
cout << "-------------------------\n";
cout << "Parsing succeeded\n";
cout << str << " Parses OK: " << endl;
cout << "n=" << n << endl;
cout << "-------------------------\n";
}
else
{
cout << "-------------------------\n";
cout << "Parsing failed\n";
cout << "-------------------------\n";
}
}
cout << "Bye... :-) \n\n";
return 0;
}
|