Spirit: невозможно использовать x3::skip(skipper)[какое-то рекурсивное правило] в определении правила

Допустим, мы хотим разобрать такой рекурсивный блок. Когда к блоку добавляется префикс «skip_comments_tag», мы рекурсивно пропускаем все комментарии (/*...*/) в этом блоке.

{
    {}
    {
        skip_comments_tag{
            {} /*comments*/ 
            { /*comments*/ } 
        }
    }
}

Легко придумать рекурсивный синтаксический анализатор, как в Coliru.

namespace Parser {
    auto const ruleComment = x3::lit("/*") >> *(x3::char_ - "*/") >> "*/" | x3::space;

    x3::rule<struct SBlockId> const ruleBlock;
    auto const ruleBlock_def = x3::lit('{') >> *(ruleBlock | "skip_comments_tag" >> x3::skip(ruleComment)[ruleBlock]) >> '}';

    BOOST_SPIRIT_DEFINE(ruleBlock)
}

Но он не компилируется (при вызове функции parse), поскольку генерирует бесконечный контекст (по x3::make_context в x3::skip_directive). x3::no_case и x3::with также имеют эту проблему, потому что все они используют x3::make_context в реализации.

Вопросы:

  1. Всегда ли есть лучший способ написать парсеры для такого рода вопросов, чтобы избежать такой ошибки компиляции, и как?
  2. Или реализация x3::make_context считается ошибочной для таких вопросов?

person Han    schedule 24.07.2017    source источник


Ответы (1)


Честно говоря, я действительно думаю, что это ограничение объекта make_context, и да, раньше оно меня кусало.

Возможно, вы сможете обойти это, используя разделение TU (макросы BOOST_SPIRIT_DECLARE, BOOST_SPIRIT_DEFINE и BOOST_SPIRIT_INSTANTIATE).

Честно говоря, я бы сообщил об этом в список рассылки: [spirit-general]

См. также http://boost.2283326.n4.nabble.com/Horrible-compiletimes-and-memory-usage-while-compiling-a-parser-with-X3-td4689104i20.html (FWIW I чувствую, что проблема "разделения последовательности" не имеет отношения)

person sehe    schedule 24.07.2017