#include <boost/config/warning_disable.hpp> #include <boost/spirit/include/qi.hpp> #include <boost/spirit/include/phoenix_core.hpp> #include <boost/spirit/include/phoenix_operator.hpp> #include <boost/spirit/include/phoenix_fusion.hpp> #include <boost/spirit/include/phoenix_stl.hpp> #include <boost/spirit/include/phoenix_object.hpp> #include <boost/fusion/include/adapt_struct.hpp> #include <boost/fusion/include/io.hpp> #include <iostream> #include <string> #include <list> #include <limits> #include <valarray> #include <sstream> namespace client { namespace fusion = boost::fusion; namespace phoenix = boost::phoenix; namespace qi = boost::spirit::qi; namespace standard = boost::spirit::standard; struct command { static const char* text_cast[]; enum tag_type { RATIO }; tag_type tag; bool input; struct { double real; long data; std::string text; } value; }; // текстовое представление команды const char* command::text_cast[] = { "RATIO" }; class command_stream: public std::list<command> { public: typedef std::list<command_stream> response_list; command* get_last_of(command::tag_type tag, bool input); }; } BOOST_FUSION_ADAPT_STRUCT( client::command, (client::command::tag_type, tag) (bool, input) (double, value.real) (long, value.data) (std::string, value.text) ) namespace client { template <typename Iterator> struct command_grammar : qi::grammar<Iterator, command_stream(), standard::space_type> { command_grammar(): command_grammar::base_type(stream) { using qi::double_; using qi::phrase_parse; using qi::lexeme; using standard::space; using standard::char_; using qi::long_; using qi::lit; using qi::eps; using boost::spirit::qi::_1; using boost::phoenix::ref; using namespace qi::labels; using phoenix::at_c; using phoenix::push_back; ratio %= lit("ratio")[at_c<0>(_val) = command::RATIO][at_c<1>(_val) = false] || double_ [at_c<2>(_val) = _1][at_c<1>(_val) = true]; stream = *(ratio) [push_back(_val, _1)]; } qi::rule<Iterator, command(), standard::space_type> ratio; qi::rule<Iterator, command_stream(), standard::space_type> stream; }; command* command_stream::get_last_of(client::command::tag_type tag, bool input) { for (reverse_iterator it = rbegin(); it != rend(); ++it) { if (it->input == input && it->tag == tag) { return &(*it); } } return ((command*) 0); } } bool parse_command(std::string str) { typedef client::command_grammar<std::string::const_iterator> command_grammar; command_grammar g; client::command_stream input; using boost::spirit::standard::space; std::string::const_iterator it = str.begin(); std::string::const_iterator end = str.end(); bool result = phrase_parse(it, end, g, space, input); if (!result || it != end) { std::cerr << str << ": FAILED\n"; return false; } std::cout << str << ": OK\n"; return true; } int main(int argc, char** argv) { parse_command(std::string(argv[1])); return 0; } |