views:

89

answers:

3

Hello :)

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 quotes ("" "")"

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.

+1  A: 

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.

Matthieu M.
That sort of makes sense except for the fact that `std::wstring` has no member assigning from a `wchar_t` ...
Billy ONeal
Right, so I am probably off.
Matthieu M.
+1  A: 

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.

Billy ONeal
+2  A: 

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'"'.

hkaiser