What is the problem with this simple boost::spirit::qi parser?
I've got this simple parser intended to parse VB style double quoted strings. Thus, the parser should turn something like
"This is a quoted string containing quo开发者_JAVA技巧tes ("" "")"
into an output of
This is a quoted string containing quotes (" ")
Here is the grammar I came up with for this:
namespace qi = boost::spirit::qi;
namespace wide = qi::standard_wide;
class ConfigurationParser : public qi::grammar<std::wstring::iterator, std::wstring()>
{
qi::rule<std::wstring::iterator, std::wstring()> quotedString;
qi::rule<std::wstring::iterator> doubleQuote;
public:
ConfigurationParser() : ConfigurationParser::base_type(quotedString, "vFind Command Line")
{
doubleQuote = (wide::char_(L'"') >> wide::char_(L'"'));
quotedString = L'"' >> +(doubleQuote[qi::_val = L'"'] | (wide::char_ - L'"'))>> L'"';
}
};
However, the attribute I'm getting is a single quote mark ("), rather than the full parsed message.
You can do it without any semantic actions:
class ConfigurationParser
: public qi::grammar<std::wstring::iterator, std::wstring()>
{
qi::rule<std::wstring::iterator, std::wstring()> quotedString;
qi::rule<std::wstring::iterator, wchar_t()> doubleQuote;
public:
ConfigurationParser()
: ConfigurationParser::base_type(quotedString, "vFind Command Line")
{
doubleQuote = wide::char_(L'"') >> omit[wide::char_(L'"')];
quotedString = L'"' >> +(doubleQuote | (wide::char_ - L'"')) >> L'"';
}
};
The omit[]
directive still executes the embedded parser but doesn't expose any attribute, making the doubleQuote rule return a single L'"'
.
I think you don't save the result properly:
doubleQuote[qi::_val = L'"']
Here, because of the '=' sign, you override what was already in. Try with '+=' instead.
doubleQuote[qi::_val += L'"']
Also, I don't know if saving is automatic, you may have to add the same '+=' after the other parser in the alternative:
(wide::char_ - L'"')[qi::_val += boost::spirit::arg_names::_1]
But I am not that good with Qi so perhaps it IS automated, which would make sense.
Well, I'm not entirely sure why, but I was able to fix it by moving that assignment action into the sub rule:
doubleQuote %= (wide::char_(L'"') >> L'"')[qi::_val = L'"'];
doubleQuote.name("double quote");
quotedString = L'"' >> +(doubleQuote | (wide::char_ - L'"')) >> L'"';
quotedString.name("quoted string");
Note the use of operator %=
for doubleQuote and the fact that the semantic action is now located there.
精彩评论