4
votes

I'm having some trouble integrating a class with iostream parsing support into a spirit parser. The example below (modified from the Spirit examples) demonstrates the problem. If I attempt to parse ONLY the custom class, it succeeds as shown by the first parse and call to assert. If I attempt to parse the custom class as well as (in this case) a comma and float, the parser fails.

Could anyone cast light on why this would be? If I use spirit parsers instead of the stream parser, I can make the second example work, but this defeats the purpose of using the stream_parser.

I've enabled rule debugging in my local example, and this shows that the custom parser consumes the entire contents of the string - however, the code shows that it shouldn't be doing this...

Any help appreciated!

Boost 1.44.0, gcc 4.1.1

#include <boost/spirit/include/qi.hpp>

struct complex
{
  complex (double a = 0.0, double b = 0.0) : a(a), b(b) {}
  double a,b;
};

std::istream& operator>> (std::istream& is, complex& z)
{
  char lbrace = '\0', comma = '\0', rbrace = '\0';
  is >> lbrace >> z.a >> comma >> z.b >> rbrace;
  if (lbrace != '{' || comma != ',' || rbrace != '}')
      is.setstate(std::ios_base::failbit);
  return is;
}

int main( int argc, char**argv)
{
  using namespace boost::spirit;
  complex parsedComplex;
  float   parsedFloat;
  bool result;

  std::string str = "{1.0,2.5}";
  std::string::iterator first = str.begin();
  result = qi::phrase_parse(first,str.end(),
    qi::stream_parser<char,complex>(), ascii::blank,parsedComplex);
  assert(result && first==str.end()); // OK

  str = "{1.0,2.5},123.456";
  first = str.begin();
  result = qi::phrase_parse(first,str.end(),
     qi::stream_parser<char,complex>() >> qi::lit(',') >> qi::float_,
     ascii::blank,parsedComplex,parsedFloat);
  assert(result && first==str.end());  // FAILS
}
1
Don't get impatient, I'm investigating...hkaiser

1 Answers

5
votes

This turned out to be a bug in the stream parser component. It didn't account for the fact that the underlying std stream was buffering the input. The problem is fixed in SVN and the fix will be part of Boost V1.47. I added a new test to Spirit's regression test suite based on your code - I hope you don't mind. Thanks for reporting!