Przetwarzaj cytowane ciągi za pomocą boost :: spirit
Chciałbym przeanalizować zdanie, w którym niektóre ciągi mogą być niecytowane, cytowane lub cytowane. Poniższy kod prawie działa - ale nie pasuje do cytatów zamykających. Zgaduję, że to z powodu odniesienia qq. W kodzie komentuje się modyfikację, modyfikacja zmienia się w „cytowany” lub „cytowany”, a także analizuje i pomaga pokazać, że pierwotny problem dotyczy cytatu zamykającego. Kod opisuje również dokładną gramatykę.
Aby być całkowicie jasnym: nienotowane ciągi znaków są analizowane. Cytowany ciąg jak'hello'
przeanalizuje otwarty cytat'
, wszystkie postaciehello
, ale potem nie uda się przeanalizować ostatecznego cytatu'
.
Podjąłem kolejną próbę, podobnie jak pasujące znaczniki początku / końca wzwiększ tutoriale, ale bez powodzenia.
<code>template <typename Iterator> struct test_parser : qi::grammar<Iterator, dectest::Test(), ascii::space_type> { test_parser() : test_parser::base_type(test, "test") { using qi::fail; using qi::on_error; using qi::lit; using qi::lexeme; using ascii::char_; using qi::repeat; using namespace qi::labels; using boost::phoenix::construct; using boost::phoenix::at_c; using boost::phoenix::push_back; using boost::phoenix::val; using boost::phoenix::ref; using qi::space; char qq; arrow = lit("->"); open_quote = (char_('\'') | char_('"')) [ref(qq) = _1]; // Remember what the opening quote was close_quote = lit(val(qq)); // Close must match the open // close_quote = (char_('\'') | char_('"')); // Enable this line to get code 'almost' working quoted_string = open_quote >> +ascii::alnum >> close_quote; unquoted_string %= +ascii::alnum; any_string %= (quoted_string | unquoted_string); test = unquoted_string [at_c<0>(_val) = _1] > unquoted_string [at_c<1>(_val) = _1] > repeat(1,3)[any_string] [at_c<2>(_val) = _1] > arrow > any_string [at_c<3>(_val) = _1] ; // .. <snip>set rule names on_error<fail>(/* <snip> */); // debug rules } qi::rule<Iterator> arrow; qi::rule<Iterator> open_quote; qi::rule<Iterator> close_quote; qi::rule<Iterator, std::string()> quoted_string; qi::rule<Iterator, std::string()> unquoted_string; qi::rule<Iterator, std::string()> any_string; // A quoted or unquoted string qi::rule<Iterator, dectest::Test(), ascii::space_type> test; }; // main() // This example should fail at the very end // (ie not parse "str3' because of the mismatched quote // However, it fails to parse the closing quote of str1 typedef boost::tuple<string, string, vector<string>, string> DataT; DataT data; std::string str("addx001 add 'str1' \"str2\" -> \"str3'"); std::string::const_iterator iter = str.begin(); const std::string::const_iterator end = str.end(); bool r = phrase_parse(iter, end, grammar, boost::spirit::ascii::space, data); </code>
W przypadku kredytu premiowego: rozwiązanie, które pozwala uniknąć lokalnego członka danych (npchar qq
w powyższym przykładzie byłoby preferowane, ale z praktycznego punktu widzenia użyję wszystkiego, co działa!