开发者

What is the problem with this simple boost::spirit::qi parser?

开发者 https://www.devze.com 2023-01-05 00:41 出处:网络
I\'ve got this simple parser intended to parse VB style double quoted strings. Thus, the parser should turn something like

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.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号