Ed Barbu
Ed Barbu

Reputation: 1649

Boost.Spirit parser does not match

I am having difficulty understanding why the following parser fails to parse test. After the call to qi::phrase_parse, result is true, it2 points at the end of the string, but mynr is still 0:

std::string test = "#define   SOMEMACRO 8.0";
  auto it2 = test.begin();
  auto endIt2 = test.end();
  double mynr = 0;
  bool result = 
    qi::phrase_parse(
      it2, 
      endIt2, 
      ("#define" >> (*qi::alnum) >> qi::double_[ref(mynr) = qi::_1]), 
      qi::space);

I am suspecting it has something to do with qi::alnum and space skipping.

I tried reducing my case to individual components. I verified these three parsers separately and found that:

Separately, each parser works fine, however put together in the form above works oddly. Further small tests seemed to indicate to me (*qi::alnum) when used like I am using it seems to consume more than just SOMEMACRO, but the rest of the string also.

Upvotes: 2

Views: 398

Answers (1)

Bill Lynch
Bill Lynch

Reputation: 82006

Your updates actually made me realize what was going on. And you're correct, *alnum is eating more than you want.

("#define" >> lexeme[*qi::alnum] >> (qi::double_)[boost::phoenix::ref(mynr) = boost::spirit::_1])

This works.

*alnum is eating alphanumeric characters, and skipping spaces between them. So it actually ate SOMEMACRO 8. Then, when I suggested that it worked when eating 8.0 at the end, that was because the double parser consumed .0.

The new parser at the top requires that the *alnum have no spaces in the middle of it.

Here's the new things to note about the grammar:

  1. I've included the semantic action to store the value of the double. It stores it in a double called mynr.
  2. I've wrapped *alnum in a lexeme. This causes the parser to not skip any characters while inside.
  3. With this correct grammar, it's able to parse "#define SOMEMACRO 8.0" and "#define SOMEMACRO 8"

Upvotes: 2

Related Questions