В чем проблема с этим простым парсером boost::spirit::qi?

У меня есть этот простой синтаксический анализатор, предназначенный для анализа строк с двойными кавычками в стиле VB. Таким образом, парсер должен получить что-то вроде

"This is a quoted string containing quotes ("" "")"

в вывод

This is a quoted string containing quotes (" ")

Вот грамматика, которую я придумал для этого:

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'"';
    }
};

Однако атрибут, который я получаю, представляет собой одинарную кавычку ("), а не полное проанализированное сообщение.


person Billy ONeal    schedule 30.06.2010    source источник


Ответы (3)


Вы можете сделать это без каких-либо смысловых действий:

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'"'; 
    } 
}; 

Директива omit[] по-прежнему выполняет встроенный синтаксический анализатор, но не предоставляет никаких атрибутов, поэтому правило doubleQuote возвращает один L'"'.

person hkaiser    schedule 30.06.2010

Я думаю, что вы не сохраняете результат должным образом:

doubleQuote[qi::_val = L'"']

Здесь из-за знака «=» вы переопределяете то, что уже было. Попробуйте вместо этого использовать «+=».

doubleQuote[qi::_val += L'"']

Кроме того, я не знаю, происходит ли сохранение автоматически, возможно, вам придется добавить тот же «+=» после другого парсера в качестве альтернативы:

(wide::char_ - L'"')[qi::_val += boost::spirit::arg_names::_1]

Но я не очень хорошо разбираюсь в Ци, так что, возможно, она автоматизирована, что имеет смысл.

person Matthieu M.    schedule 30.06.2010
comment
В этом есть смысл, за исключением того факта, что std::wstring не имеет члена, назначенного из wchar_t ... - person Billy ONeal; 30.06.2010

Ну, я не совсем уверен, почему, но я смог исправить это, переместив это действие присваивания в подправило:

doubleQuote %= (wide::char_(L'"') >> L'"')[qi::_val = L'"'];
doubleQuote.name("double quote");

quotedString = L'"' >> +(doubleQuote | (wide::char_ - L'"')) >> L'"';
quotedString.name("quoted string");

Обратите внимание на использование operator %= для doubleQuote и тот факт, что семантическое действие теперь находится там.

person Billy ONeal    schedule 30.06.2010