/////////////////////////////////////////////////////////////////////////////// // // A parser based on dynamic parser statements that parses a decimal integer // // [ JCAB 7/26/2002 ] // /////////////////////////////////////////////////////////////////////////////// #include <boost/spirit/core.hpp> #include <boost/spirit/utility/functor_parser.hpp> #include <iostream> #include <vector> #include <string> /////////////////////////////////////////////////////////////////////////////// // // Implementation // TODO: Move this into the Spirit library // /////////////////////////////////////////////////////////////////////////////// #if !defined(SPIRIT_COMPOSITE_HPP) #include "boost/spirit/core/impl/composite.ipp" #endif namespace spirit { ////////////////////////////////// template <typename ParserT_true, typename ParserT_false, typename CondT> struct if_else_parser : public binary< ParserT_true, ParserT_false, parser<if_else_parser<ParserT_true, ParserT_false, CondT> > > { CondT cond; typedef if_else_parser<ParserT_true, ParserT_false, CondT> self_t; if_else_parser( ParserT_true const& p_true, ParserT_false const& p_false, CondT const& cond_ ) : binary<ParserT_true, ParserT_false, parser <self_t> >(p_true, p_false), cond(cond_) { } template <typename ScannerT> struct result { typedef typename match_result<ScannerT, nil_t>::type type; }; template <typename ScannerT> typename parser_result<self_t, ScannerT>::type parse(ScannerT const& scan) const { if (cond()) { return this->left().parse(scan); } else { return this->right().parse(scan); } } }; ////////////////////////////////// template <typename ParserT_true, typename CondT> struct if_else_parser_gen { if_else_parser_gen(ParserT_true const& p_true_, CondT const& cond_) : p_true(p_true_), cond(cond_) {} template <typename ParserT_false> if_else_parser<ParserT_true, ParserT_false, CondT> operator[](parser<ParserT_false> const& subject) const { return if_else_parser<ParserT_true, ParserT_false, CondT> (p_true, subject.derived(), cond); } ParserT_true p_true; CondT cond; }; ////////////////////////////////// template <typename ParserT, typename CondT> struct if_parser : public unary<ParserT, parser<if_parser<ParserT, CondT> > > { CondT cond; typedef if_parser<ParserT, CondT> self_t; if_parser(ParserT const& p, CondT const& cond_) : unary<ParserT, parser <self_t> >(p), cond(cond_), else_p(p, cond) {} template <typename ScannerT> struct result { typedef typename match_result<ScannerT, nil_t>::type type; }; template <typename ScannerT> typename parser_result<self_t, ScannerT>::type parse(ScannerT const& scan) const { if (cond()) { return this->subject().parse(scan); } return scan.no_match(); } if_else_parser_gen<ParserT, CondT> else_p; }; ////////////////////////////////// template <typename CondT> struct if_parser_gen { if_parser_gen(CondT const& cond_) : cond(cond_) {} template <typename ParserT> if_parser<ParserT, CondT> operator[](parser<ParserT> const& subject) const { return if_parser<ParserT, CondT>(subject.derived(), cond); } CondT cond; }; ////////////////////////////////// struct cond_boolref { bool const& ref; cond_boolref(bool const& ref_): ref(ref_) {} bool operator()() const { return ref; } }; ////////////////////////////////// #if !defined(BOOST_MSVC) || (_MSC_VER >= 1300) template <typename CondT> if_parser_gen<CondT> if_p(CondT const& cond) { return if_parser_gen<CondT>(cond); } if_parser_gen<cond_boolref> if_p(bool const& cond) { return if_parser_gen<cond_boolref>(cond_boolref(cond)); } #else // if_p implementation for VC6 template <typename CondT> struct if_p_rt { typedef bool_t<boost::is_same<CondT,bool>::value> is_bool; typedef typename if_t < is_bool , cond_boolref , CondT >::type type; }; template <typename CondT> if_parser_gen<if_p_rt<CondT>::type> if_p(CondT const& cond) { return if_parser_gen<if_p_rt<CondT>::type >(cond); } #endif } // namespace spirit /////////////////////////////////////////////////////////////////////////////// // // End of implementation // /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// using namespace std; using namespace spirit; /////////////////////////////////////////////////////////////////////////////// // // Our parser functor // /////////////////////////////////////////////////////////////////////////////// struct number_parser { typedef int result_t; template <typename ScannerT> int operator()(ScannerT const& scan, result_t& result) const { if (scan.at_end()) { return -1; } char ch = *scan; if (ch < '0' || ch > '9') { return -1; } result = 0; int len = 0; do { result = result*10 + int(ch - '0'); ++len; ++scan; } while (!scan.at_end() && (ch = *scan, ch >= '0' && ch <= '9')); return len; } }; functor_parser<number_parser> number_parser_p; /////////////////////////////////////////////////////////////////////////////// // // Our number parser function // /////////////////////////////////////////////////////////////////////////////// bool parse_numbers(char const* str, std::vector<int>& n, bool many) { return parse(str, lexeme_d[number_parser_p[append(n)]] >> if_p (many) [ *(',' >> lexeme_d[number_parser_p[append(n)]]) ] .else_p [ epsilon_p ], space_p ).full; } //////////////////////////////////////////////////////////////////////////// // // Main program // //////////////////////////////////////////////////////////////////////////// int main() { cout << "/////////////////////////////////////////////////////////\n\n"; cout << "\t\tA number parser implemented as a functor for Spirit...\n\n"; cout << "/////////////////////////////////////////////////////////\n\n"; cout << "Give me an integer number command\n"; cout << "Commands:\n"; cout << " A <num> --> parses a single number\n"; cout << " B <num>, <num>, ... --> parses a series of numbers " "separated by commas\n"; cout << " Q --> quit\n\n"; for (;;) { string str; getline(cin, str); if (str[0] == 'q' || str[0] == 'Q') { break; } else if (str[0] == 'a' || str[0] == 'A') { std::vector<int> n; if (parse_numbers(str.c_str()+1, n, false)) { cout << "-------------------------\n"; cout << "Parsing succeeded\n"; cout << str << " Parses OK: " << n[0] << endl; cout << "-------------------------\n"; } else { cout << "-------------------------\n"; cout << "Parsing failed\n"; cout << "-------------------------\n"; } } else if (str[0] == 'b' || str[0] == 'B') { std::vector<int> n; if (parse_numbers(str.c_str()+1, n, true)) { cout << "-------------------------\n"; cout << "Parsing succeeded\n"; int size = n.size(); cout << str << " Parses OK: " << size << " number(s): " << n[0]; for (int i = 1; i < size; ++i) { cout << ", " << n[i]; } cout << endl; cout << "-------------------------\n"; } else { cout << "-------------------------\n"; cout << "Parsing failed\n"; cout << "-------------------------\n"; } } else { cout << "-------------------------\n"; cout << "Unrecognized command!!"; cout << "-------------------------\n"; } } cout << "Bye... :-) \n\n"; return 0; }