boost::spirit::qi соответствует [] проблемам

У меня проблема с разбором моего проекта. По крайней мере, я нашел минимальный пример кода, на котором появляется проблема. Итак, сейчас пытается разобрать строку

"логическая функция1; константная логическая функция2;"

Вот минимальный пример кода:

namespace qi = boost::spirit::qi;
using qi::lexeme;
using qi::string;
typedef boost::spirit::ascii::space_type TSkipper;

struct MyField
{
    bool isConst;
    std::string mtype;
    std::string name;
};

BOOST_FUSION_ADAPT_STRUCT
    (
    MyField,
    (bool, isConst)
    (std::string, mtype)
    (std::string, name)
    )

void SpiritTestSimple()
{
    qi::rule<std::string::const_iterator, std::string(), TSkipper> valid_symbols;
    qi::rule<std::string::const_iterator, MyField(), TSkipper> field;

    valid_symbols %= lexeme[*qi::char_("a-zA-Z")];

    field %= qi::matches[string("const")] >> valid_symbols >> valid_symbols;

    std::string data = "aaa aaaa; const bbb bbbb;";

    //-----------------------------------------------------------------
    std::string::const_iterator first = data.begin(), last = data.end();
    std::list<MyField> parsed_vals;
    bool is_parsed;
    try
    {
        is_parsed = qi::phrase_parse(   first, last,  
                                        +(field > ';'), 
                                        boost::spirit::ascii::space, parsed_vals);
    }
    catch(const qi::expectation_failure<std::string::const_iterator>& e)
    {
        std::string frag(e.first, e.last);
        std::cout << e.what() << "'" << frag << "'" << std::endl;
    }

    BOOST_ASSERT(is_parsed && "the example not parsed");
}

Я написал

+(field > ';')

потому что в моем проекте этот блок может отсутствовать. И каждое объявление функции должно заканчиваться знаком ';'. Когда запускается приведенный выше пример кода, я вижу, что возникло исключение, и в консоли появилась запись:

boost::spirit::qi::expectation_failure''

Как я правильно понимаю - после последней точки с запятой синтаксический анализатор пытается проанализировать следующее правило поля, и он проанализировал "совпадения" (потому что он возвращает значение в любом случае), но следующий синтаксический анализ valid_symbols не удается, потому что после последней точки с запятой нет данных . Так что синтаксический анализ не работает.

Как избежать сбоя синтаксического анализа в моем случае?


person AeroSun    schedule 31.08.2014    source источник


Ответы (1)


Самая большая проблема с

valid_symbols = qi::lexeme[*qi::char_("a-zA-Z")];

Проблема здесь в том, что он может соответствовать пустой строке. Таким образом, вся продукция для «поля» может быть пустой строкой. Если вы измените его на (используя qi::alpha в качестве сокращения):

valid_symbols = qi::lexeme[+qi::alpha];

Вы обнаружите, что он правильно анализирует ввод.

Дополнительные примечания:

  • когда вы говорите "Я написал +(field > ';'), потому что в моем проекте этот блок может отсутствовать", это кажется мне противоречивым. Если бы вы хотели сделать весь блок необязательным, вы бы написали

    *(field > ';')
    

    или если вы захотите повторить ;; я ожидаю

    *(-field > ';')
    

    (или, возможно, +(-field > ';')).

  • вы захотите научиться использовать BOOST_SPIRIT_DEBUG для самостоятельного выявления проблем

См. полный рабочий пример для демонстрации использования встроенных возможностей отладки Spirit: Live On Coliru< /а>

#define BOOST_SPIRIT_DEBUG
#include <boost/fusion/adapted/struct.hpp>
#include <boost/spirit/include/qi.hpp>

namespace qi = boost::spirit::qi;
typedef boost::spirit::ascii::space_type TSkipper;

struct MyField
{
    bool isConst;
    std::string mtype;
    std::string name;
};

BOOST_FUSION_ADAPT_STRUCT
    (
     MyField,
     (bool, isConst)
     (std::string, mtype)
     (std::string, name)
    )

template <typename It, typename TSkipper = boost::spirit::ascii::space_type>
struct MyGrammar : qi::grammar<It, std::list<MyField>(), TSkipper>
{
    MyGrammar() : MyGrammar::base_type(start) {
        valid_symbols = qi::lexeme[+qi::alpha];
        field         = qi::matches[qi::string("const")] >> valid_symbols >> valid_symbols;
        start         = +(field > ";");

        BOOST_SPIRIT_DEBUG_NODES((valid_symbols)(field)(start))
    }
  private:
    qi::rule<std::string::const_iterator, std::string(),        TSkipper> valid_symbols;
    qi::rule<std::string::const_iterator, MyField(),            TSkipper> field;
    qi::rule<std::string::const_iterator, std::list<MyField>(), TSkipper> start;
};

int main()
{
    std::string const data = "aaa aaaa; const bbb bbbb;";

    //-----------------------------------------------------------------
    std::string::const_iterator first = data.begin(), last = data.end();
    std::list<MyField> parsed_vals;

    bool is_parsed = false;

    try
    {
        MyGrammar<std::string::const_iterator> grammar;

        is_parsed = qi::phrase_parse(   first, last,  
                                        grammar, 
                                        boost::spirit::ascii::space, 
                                        parsed_vals);
    }
    catch(const qi::expectation_failure<std::string::const_iterator>& e)
    {
        std::string frag(e.first, e.last);
        std::cout << "Expectation failure: " << e.what() << " at '" << frag << "'" << std::endl;
    }

    BOOST_ASSERT(is_parsed && "the example not parsed");
}

Что печатает:

<start>
<try>aaa aaaa; const bbb </try>
<field>
    <try>aaa aaaa; const bbb </try>
    <valid_symbols>
    <try>aaa aaaa; const bbb </try>
    <success> aaaa; const bbb bbb</success>
    <attributes>[[a, a, a]]</attributes>
    </valid_symbols>
    <valid_symbols>
    <try> aaaa; const bbb bbb</try>
    <success>; const bbb bbbb;</success>
    <attributes>[[a, a, a, a]]</attributes>
    </valid_symbols>
    <success>; const bbb bbbb;</success>
    <attributes>[[0, [a, a, a], [a, a, a, a]]]</attributes>
</field>
<field>
    <try> const bbb bbbb;</try>
    <valid_symbols>
    <try> bbb bbbb;</try>
    <success> bbbb;</success>
    <attributes>[[b, b, b]]</attributes>
    </valid_symbols>
    <valid_symbols>
    <try> bbbb;</try>
    <success>;</success>
    <attributes>[[b, b, b, b]]</attributes>
    </valid_symbols>
    <success>;</success>
    <attributes>[[1, [b, b, b], [b, b, b, b]]]</attributes>
</field>
<field>
    <try></try>
    <valid_symbols>
    <try></try>
    <fail/>
    </valid_symbols>
    <fail/>
</field>
<success></success>
<attributes>[[[0, [a, a, a], [a, a, a, a]], [1, [b, b, b], [b, b, b, b]]]]</attributes>
</start>
person sehe    schedule 31.08.2014
comment
PS. Вы можете написать qi::matches["const"] прямо там - person sehe; 01.09.2014