Boost Spirit newcomer here.
I have a string in the form of "Key:Value\r\nKey2:Value2\r\n" that I'm trying to parse. In that specific form, it's trivial to parse with Boost Spirit. However, in order to be more robust, I also need to handle cases such as this one:
" My Key : Value \r\n My2ndKey : Long<4 spaces>Value \r\n"
In this case, I need to trim leading and trailing spaces before and after the key/value separators so that I get the following map:
"My Key", "Value"
"My2ndKey", "Long<4 spaces>Value"
I played with qi::hold to achieve this but I get compile errors because of unsupported boost::multi_pass iterator with the embedded parser I was trying to use. There has to be a simple way to achieve this.
I read the following articles (and many others on the subject):
http://boost-spirit.com/home/articles/qi-example/parsing-a-list-of-key-value-pairs-using-spirit-qi/ http://boost-spirit.com/home/2010/02/24/parsing-skippers-and-skipping-parsers/
Boost spirit parsing string with leading and trailing whitespace
I am looking for a solution to my problem, which doesn't seem to be entirely covered by those articles. I would also like to better understand how this is achieved. As a small bonus question, I keep seeing the '%=' operator, is this useful in my case? MyRule %= MyRule ... is used for recursive parsing?
The code below parses my strings properly except that it doesn't remove the spaces between the last non-space character and the separator. :( The skipper used is qi::blank_type (space without EOL).
Thanks!
template <typename Iterator, typename Skipper>
struct KeyValueParser : qi::grammar<Iterator, std::map<std::string, std::string>(), Skipper> {
KeyValueParser() : KeyValueParser::base_type(ItemRule) {
ItemRule = PairRule >> *(qi::lit(END_OF_CMD) >> PairRule);
PairRule = KeyRule >> PAIR_SEP >> ValueRule;
KeyRule = +(qi::char_ - qi::lit(PAIR_SEP));
ValueRule = +(qi::char_ - qi::lit(END_OF_CMD));
}
qi::rule<Iterator, std::map<std::string, std::string>(), Skipper> ItemRule;
qi::rule<Iterator, std::pair<std::string, std::string>(), Skipper> PairRule;
qi::rule<Iterator, std::string()> KeyRule;
qi::rule<Iterator, std::string()> ValueRule;
};