spirit/classic/example/fundamental/thousand_separated.cpp
2008-04-13 16:28:27 +00:00

134 lines
4.6 KiB
C++

/*=============================================================================
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;
}