Understanding Boost.spirit String Parsing

#include <iostream> #include <boost/spirit/include/qi.hpp> namespace qi = boost::spirit::qi; int main () { using qi::string; std::string input("a"); std::string::iterator strbegin = input.begin(); std::string p; bool ok = qi::phrase_parse(strbegin, input.end(), ((string("a") >> string("a")) | string("a")), qi::space, p); if (ok && strbegin == input.end()) { std::cout << p << std::endl; std::cout << p.size() << std::endl; } else { std::cout << "fail" << std::endl; std::cout << std::string(strbegin, input.end()) << std::endl; } } 

This program displays aa . How is this possible? Input line a . The parser must match aa or a . I wrote string("a") just for testing statements.

The same thing happens when using char_ instead of string .

+6
source share
1 answer

This is not a string match. This is [attribute distribution] + [backlink] in action.

The string attribute is a container attribute, and many elements can be assigned to it by various parser subexpressions. Now, for reasons of efficiency, Spirit does not roll back the values โ€‹โ€‹of the emitted attributes upon return.

Often this is not a problem, but as you can see, the โ€œaโ€ from the failed first branch of the alternative sticks.

Rename or use the "big gun" qi::hold[] directive:

 (qi::hold [ string("a") >> string("a") ] | string("a")), 

The entry may look like this:

 qi::string("a") >> -qi::string("a"), 

Also, if you are really trying to match specific text strings, consider:

 (qi::raw [ qi::lit("aa") | "a" ]), // or even just qi::string("aa") | qi::string("a"), 

Now, which one works best depends on your grammar.

+6
source

All Articles