Analysieren Sie zitierte Zeichenfolgen mit boost :: spirit
Ich möchte einen Satz analysieren, in dem einige Zeichenfolgen nicht in Anführungszeichen, "Anführungszeichen" oder "Anführungszeichen" stehen. Der folgende Code funktioniert fast - entspricht jedoch nicht den schließenden Anführungszeichen. Ich vermute, das liegt an der qq-Referenz. Eine Änderung wird im Code kommentiert, die Änderung führt dazu, dass "quoted" oder "quoted" ebenfalls analysiert wird, und zeigt, dass das ursprüngliche Problem im schließenden Anführungszeichen liegt. Der Code beschreibt auch die genaue Grammatik.
Um ganz klar zu sein: Nicht zitierte Zeichenfolgen werden analysiert. Eine zitierte Zeichenfolge wie'hello'
wird das offene Zitat analysieren'
alle Zeichenhello
, aber dann nicht das endgültige Zitat zu analysieren'
.
Ich habe einen weiteren Versuch unternommen, ähnlich wie beim Start / Ende-TagBoost-Tutorials, aber ohne Erfolg.
<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>
Für Bonusguthaben: Eine Lösung, die ein lokales Datenmitglied vermeidet (wie zchar qq
in obigem Beispiel) wäre vorzuziehen, aber aus praktischer Sicht verwende ich alles, was funktioniert!