[Spirit Development][Qi] Bug parsing arrays with the OR operator.

Robert Nelson <[email protected]> Tue, 4 Jan 2011 13:21:15 -0700
Newsgroups gmane.comp.parsers.spirit.devel
Message-ID <[email protected]>
I posted this bug a while back, but it seems that it was fixed, and
has now come up again.

When parsing branches of a variant, if the first branch fails, then
_val should be reset to what it was before the branch was taken.

Consider the following example:

input "hello"
rule %= ((string("hello") >> eps[_pass = false]) | eps) >> string("hello")

When the first branch ((string("hello") >> eps[_pass = false]) | eps)
is parsed, the first part of the first branch will pass, appending
"hello" onto val.  The second part of the branch will then fail, and
we will go the the second alternative of the variant which passes.
_val should currently equal "", but it instead contains "hello" and
the iterator is set a the beginning of the input stream again.  We
then parse the last part of the rule, which just matches the input
string, and adds "hello" to _val.

In trunk this results in the output "hellohello" instead of the
correct output "hello".

Thanks
--Robert Nelson

------------------------------------------------------------------------------
Learn how Oracle Real Application Clusters (RAC) One Node allows customers
to consolidate database storage, standardize their database environment, and, 
should the need arise, upgrade to a full multi-node Oracle RAC database 
without downtime or disruption
http://p.sf.net/sfu/oracle-sfdevnl

_______________________________________________
Spirit-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/spirit-devel
main.cpp (text/x-c++src, 607 B)
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_fusion.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <string>

int main()
{
  using namespace boost::spirit::qi;
  using namespace boost::phoenix;
  std::string input = "hello";
  boost::spirit::qi::rule<std::string::iterator,std::string()> rule;
  rule %= ((string("hello") >> eps[_pass = false]) | eps) >> string("hello");
  std::string output;
  bool passed = parse(input.begin(),input.end(),rule > eoi,output);
  assert(passed);
  std::cout<<"output: '"<<output<<"'"<<std::endl; //should be "hello" 
}