I've encountered something weird when trying to parse simple quoted strings.
So I've written this simple parser that successfully parses quoted strings like "string"
or ""
.
#include <iostream>
#include "boost/spirit/include/qi.hpp"
namespace qi = boost::spirit::qi;
namespace iso8859 = boost::spirit::iso8859_1;
int main( int argc, char* argv[] )
{
using namespace qi;
std::string input = "\"\"";
std::string::const_iterator front = input.cbegin();
std::string::const_iterator end = input.cend();
bool parseSuccess = phrase_parse( front, end,
'\"' >> *~char_('\"') >> '\"',
iso8859::space );
if ( front != end )
{
std::string trail( front, end );
std::cout << "String parsing trail: " << trail << std::endl;
}
if ( !parseSuccess )
std::cout << "Error parsing input string" << std::endl;
std::cout << "Press enter to exit" << std::endl;
std::cin.get();
return 0;
}
This all works perfectly fine, but when I extend the parsing rules to also parse things before the quoted string, it suddenly breaks..
So, of example, this parses successfully:
std::string input = "normalString 10.0 1.5 1.0 1.0 1.0 1.0"
With parsing rule:
*char_ >> *double_
And now if I combine this rule with the quoted string rule:
std::string input = "normalString 10.0 1.5 1.0 1.0 1.0 1.0 \"quotedString\""
With parsing rule:
*char_ >> *double_ >> '\"' >> *~char_('\"') >> '\"'
It suddenly doesn't work anymore and parsing fails. I have no idea why. Can anyone explain this?
EDIT: Just in case it matters, I'm using Boost 1.53
As cv_and_he stated earlier - your *char_
eats everything and from the "updated" parser sequence you can guess why it did not work :-)
#include <iostream>
#include "boost/spirit/include/qi.hpp"
namespace qi = boost::spirit::qi;
namespace iso8859 = boost::spirit::iso8859_1;
int main( int argc, char* argv[] )
{
using namespace qi;
std::vector< std::string > inputVec{
"normalString 10.0 1.5 1.0 1.0 1.0 1.0 \"quotedString\"",
"normalString \"quotedString\"",
"10.0 1.5 1.0 1.0 1.0 1.0 \"quotedString\"",
"10.0 1.5 1.0 1.0 1.0 1.0 \"\"",
"\"\""};
for( const auto &input : inputVec )
{
std::string::const_iterator front = input.cbegin();
std::string::const_iterator end = input.cend();
bool parseSuccess = phrase_parse( front, end,
no_skip [ *(char_ - space - double_ - '\"') ]
>> *double_ >> '\"' >> *~char_('\"') >> '\"',
iso8859::space );
if ( parseSuccess && front == end)
std::cout << "success:";
else
std::cout << "failure:";
std::cout << "`" << input << "`" << std::endl;
}
return 0;
}