Search code examples
c++boostboost-spiritboost-spirit-qi

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:

  • "#define" indeed consumes "#define"
  • (*qi::alnum) is able to consume SOMEMACRO
  • qi::double_ is able to consume 8.0

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.


Solution

  • 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"