/*============================================================================= 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 #include #include #include /////////////////////////////////////////////////////////////////////////////// using namespace std; using namespace BOOST_SPIRIT_CLASSIC_NS; template struct ts_real_parser_policies : public ureal_parser_policies { // 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 uint2_t; typedef uint_parser uint_parser_t; typedef int_parser int_parser_t; ////////////////////////////////// 2 decimal places Max template static typename parser_result::type parse_frac_n(ScannerT& scan) { return uint2_t().parse(scan); } ////////////////////////////////// No exponent template static typename parser_result, ScannerT>::type parse_exp(ScannerT& scan) { return scan.no_match(); } ////////////////////////////////// No exponent template static typename parser_result::type parse_exp_n(ScannerT& scan) { return scan.no_match(); } ////////////////////////////////// Thousands separated numbers template static typename parser_result::type parse_n(ScannerT& scan) { typedef typename parser_result::type RT; static uint_parser uint3_p; static uint_parser 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 > const ts_real_p = real_parser >(); //////////////////////////////////////////////////////////////////////////// // // 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; }