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