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> // òåìïåðàòóðà 0 ºC const double zero_degree_celsius = 273.15; // K 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 { INPUT, TEMPERATURE, RATE_COMMERCIAL, RATE_VOLUMETRIC, COMPRESSIBILITY, RELATIVE_DENSITY, ROTOR_OUTPUT, ROTOR_RPM, POLYTROPE, RATIO, NOMOGRAM, IMPELLER, COUNT, PLOT, Z_NORM, Z_BB, OUTPUT }; tag_type tag; bool input; struct { double real; long data; std::string text; } value; }; // òåêñòîâîå ïðåäñòàâëåíèå êîìàíäû const char* command::text_cast[] = { "INPUT", "TEMPERATURE", "RATE_COMMERCIAL", "RATE_VOLUMETRIC", "COMPRESSIBILITY", "RELATIVE_DENSITY", "ROTOR_OUTPUT", "ROTOR_RPM", "POLYTROPE", "RATIO", "NOMOGRAM", "IMPELLER", "COUNT", "PLOT", "Z_NORM", "Z_BB", "OUTPUT" }; 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; input %= char_('p')[at_c<0>(_val) = command::INPUT][at_c<1>(_val) = false] >> (double_ [at_c<2>(_val) = _1][at_c<1>(_val) = true] || (lit("at") | lit("MPa")[at_c<2>(_val) *= 10.197162])); temperature %= char_('T')[at_c<0>(_val) = command::TEMPERATURE][at_c<1>(_val) = false] || double_ [at_c<2>(_val) = _1][at_c<1>(_val) = true] || (lit("degC") | lit("degK")[at_c<2>(_val) -= zero_degree_celsius]); rate_commercial %= char_('Q')[at_c<0>(_val) = command::RATE_COMMERCIAL][at_c<1>(_val) = false] || double_ [at_c<2>(_val) = _1][at_c<1>(_val) = true]; rate_volumetric %= char_('q')[at_c<0>(_val) = command::RATE_VOLUMETRIC][at_c<1>(_val) = false] || double_ [at_c<2>(_val) = _1][at_c<1>(_val) = true]; compressibility %= char_('Z')[at_c<0>(_val) = command::COMPRESSIBILITY][at_c<1>(_val) = false] || double_ [at_c<2>(_val) = _1][at_c<1>(_val) = true]; relative_density %= char_('g') >> double_ [at_c<0>(_val) = command::RELATIVE_DENSITY][at_c<2>(_val) = _1][at_c<1>(_val) = true]; rotor_output %= char_('N')[at_c<0>(_val) = command::ROTOR_OUTPUT][at_c<1>(_val) = false] || double_ [at_c<2>(_val) = _1][at_c<1>(_val) = true]; rotor_rpm %= char_('n')[at_c<0>(_val) = command::ROTOR_RPM][at_c<1>(_val) = false] || double_ [at_c<2>(_val) = _1][at_c<1>(_val) = true]; polytrope %= lit("polytrope")[at_c<0>(_val) = command::POLYTROPE][at_c<1>(_val) = false]; 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]; nomogram %= lit("nomogram")[at_c<0>(_val) = command::NOMOGRAM][at_c<1>(_val) = false] || long_ [at_c<3>(_val) = _1][at_c<1>(_val) = true]; quoted_string %= lexeme['"' >> +(char_ - '"') >> '"']; impeller %= lit("impeller")[at_c<0>(_val) = command::IMPELLER][at_c<1>(_val) = false] || quoted_string[at_c<4>(_val) = _1][at_c<1>(_val) = true]; working %= lit("count")[at_c<0>(_val) = command::COUNT][at_c<1>(_val) = false]; plot %= lit("plot")[at_c<0>(_val) = command::PLOT][at_c<1>(_val) = false] >> quoted_string[at_c<4>(_val) = _1][at_c<1>(_val) = true]; output %= char_('P')[at_c<0>(_val) = command::OUTPUT][at_c<1>(_val) = false] || double_ [at_c<2>(_val) = _1][at_c<1>(_val) = true] || (lit("at") | lit("MPa")[at_c<2>(_val) *= 10.197162]); z_norm %= lit("Z_NORM") [at_c<0>(_val) = command::Z_NORM] [at_c<1>(_val) = false]; z_bb %= lit("Z_BB") [at_c<0>(_val) = command::Z_BB] [at_c<1>(_val) = false]; stream = *(plot | working | impeller | nomogram | z_norm | z_bb | input | temperature | rate_commercial | rate_volumetric | compressibility | relative_density | rotor_output | rotor_rpm | polytrope | ratio | output) [push_back(_val, _1)]; } qi::rule<Iterator, std::string(), standard::space_type> quoted_string; // 1. âõîäíîå äàâëåíèå (I) qi::rule<Iterator, command(), standard::space_type> input; // 2. òåìïåðàòóðà (I/O) qi::rule<Iterator, command(), standard::space_type> temperature; // 3. êîììåð÷åñêàÿ ïðîèçâîäèòåëüíîñòü (I/O) qi::rule<Iterator, command(), standard::space_type> rate_commercial; // 4. îáú¸ìíàÿ ïðîèçâîäèòåëüíîñòü (I/O) qi::rule<Iterator, command(), standard::space_type> rate_volumetric; // 5. êîýôôèöèåíò ñâåðõñæèìàåìîñòè (I/O) qi::rule<Iterator, command(), standard::space_type> compressibility; // 6. îòíîñèòåëüíàÿ ïëîòíîñòü ïî âîçäóõó ãàçîâîé ñìåñè (I) qi::rule<Iterator, command(), standard::space_type> relative_density; // 7. ìîùíîñòü íà âàëó ðîòîðà (I/O) qi::rule<Iterator, command(), standard::space_type> rotor_output; // 8. ÷èñëî îáîðîòîâ êîìïðåññîðà (I/O) qi::rule<Iterator, command(), standard::space_type> rotor_rpm; // 9. ïîëèòðîïè÷åñêèé êîýôôèöèåíò (O) qi::rule<Iterator, command(), standard::space_type> polytrope; // 10. ñòåïåíü ñæàòèÿ (I/O) qi::rule<Iterator, command(), standard::space_type> ratio; // 11. èíäåêñ íîìîãðàììû â áàçå äàííûõ (I/O) qi::rule<Iterator, command(), standard::space_type> nomogram; // 12. íàèìåíîâàíèå ÃÏÀ â òàáëèöå aggregate (I/O) qi::rule<Iterator, command(), standard::space_type> impeller; // 13. êîëè÷åñòâî îäíîâðåìåííî ðàáîòàþùèõ ÃÏÀ (O) qi::rule<Iterator, command(), standard::space_type> working; // 14. èìÿ ôàéëà ñ äëÿ âûâîäà ãðàôè÷åñêèõ êîìàíä (I) qi::rule<Iterator, command(), standard::space_type> plot; // 15. âû÷èñëåíèå êîýôôèöèåíòà ñâåðõñæèìàåìîñòè ïî ÎÍÒÏ 51-1-85 (O) qi::rule<Iterator, command(), standard::space_type> z_norm; // 16. âû÷èñëåíèå êîýôôèöèåíòà ñâåðõñæèìàåìîñòè ïî êîðåëëÿöèè Brill-Beggs (O) qi::rule<Iterator, command(), standard::space_type> z_bb; // 17. âûõîäíîå äàâëåíèå (I/O) qi::rule<Iterator, command(), standard::space_type> output; // ïîòîê êîìàíä 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 true; } else { std::cout << str << ": OK\n"; } return false; } int main(int argc, char** argv) { parse_command(std::string(argv[1])); return 0; } |