Разбор строки в кавычках работает только в некоторых случаях

Я столкнулся с чем-то странным при попытке разобрать простые строки в кавычках. Итак, я написал этот простой синтаксический анализатор, который успешно анализирует строки в кавычках, такие как "string" или "".

#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;
}

Все это отлично работает, но когда я расширяю правила синтаксического анализа, чтобы также анализировать вещи до строки в кавычках, они внезапно ломаются.

Так, например, это успешно анализируется:

std::string input = "normalString 10.0 1.5 1.0 1.0 1.0 1.0" С правилом разбора:

*char_ >> *double_

А теперь, если я комбинирую это правило с правилом строки в кавычках:

std::string input = "normalString 10.0 1.5 1.0 1.0 1.0 1.0 \"quotedString\""

С правилом разбора:

*char_ >> *double_ >> '\"' >> *~char_('\"') >> '\"'

Внезапно он больше не работает, и синтаксический анализ не выполняется. Понятия не имею почему. Кто-нибудь может это объяснить?

РЕДАКТИРОВАТЬ: на всякий случай я использую Boost 1.53


person Krienie    schedule 16.08.2013    source источник


Ответы (1)


Как cv_and_he заявил ранее - ваш *char_ ест все и по "обновленной" последовательности парсера вы можете догадаться почему он не работал :-)

#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;
}
person G. Civardi    schedule 16.08.2013
comment
Вот два случая, упомянутых в вопросе с использованием BOOST_SPIRIT_DEBUG Вы можете ясно видеть, что *char_ использует всю строку. В первом случае *double_ преуспевает с пустым атрибутом, поскольку он соответствует 0 двойникам. Во втором случае все работает так же, пока литерал '"' не дает сбой. - person llonesmiz; 17.08.2013
comment
Предполагая, что строка, которую вы хотите проанализировать, является стандартным идентификатором, я думаю, что самым простым способом решения этой проблемы будет: lexeme[alpha >> *alnum] >> *double_ >> '"' >> *~char_('"') >> '"';. Если вы используете правила, как в приведенном выше примере, вы даже можете опустить lexeme, если удалите шкипера из своего правила: rule<std::string::const_iterator,std::string()> string_rule = alpha >> *alnum;. - person llonesmiz; 17.08.2013
comment
@cv_and_he - что касается добавления дополнительного правила - полностью согласен. Я думаю, хорошо знать оба пути. - person G. Civardi; 17.08.2013
comment
Спасибо за ответ, теперь мне стало понятнее. Я думал, что, поскольку я определил синтаксический анализатор double_ после того, как дух *char_ автоматически проанализирует все числа с помощью синтаксического анализатора double_, но, видимо, я ошибся.. @cv_and_he Спасибо за пример отладки. Я даже не знал, что ты так умеешь :) - person Krienie; 17.08.2013
comment
Пожалуйста. Случайно столкнулся с подобным issue несколько дней назад :-) - person G. Civardi; 17.08.2013