Как реализовать пользовательский объект синтаксического анализатора с Boost Spirit x3, чтобы он отлично работал со шкипером? - PullRequest
2 голосов
/ 28 января 2020

Я знаю, что могу реализовать собственный синтаксический анализатор, создав объект с соответствующим шаблоном функции-члена parse, но я не знаю, что мне нужно сделать, чтобы он использовал шкипер в контексте, который, кажется, нужно сделать. То есть ниже, я ожидал, что оба случая будут успешными, но второй не удастся:

namespace x3 = boost::spirit::x3;

namespace parser {

    struct foobar : x3::parser<foobar> {

        using attribute_type = std::string;

        template<typename Iterator, typename Context, typename RContext, typename Attribute>
        bool parse(Iterator& first, Iterator const& last, Context const& context,
            RContext const& rcontext, Attribute& attr) const
        {
            static const std::string foobar_str = "foobar";
            auto i = first;
            auto j = foobar_str.begin();
            while (i != last && j != foobar_str.end()) {
                if (*i++ != *j++)
                    return false;
            }
            first = i;
            attr = foobar_str;
            return true;
        };
    };

    const auto foo = foobar();
}

int main()
{
    std::string input = "foobarfoobarfoobar";
    std::vector<std::string> strings;

    auto foobars = parser::foo >> parser::foo >> parser::foo;

    bool success = x3::phrase_parse(input.begin(), input.end(), foobars, x3::space, strings);
    if (success)
        std::cout << "yes\n";  // yes for this one
    else
        std::cout << "no\n";

    input = "foobar    foobar    foobar";
    success = x3::phrase_parse(input.begin(), input.end(), foobars, x3::space, strings);
    if (success) 
        std::cout << "yes\n"; 
    else 
        std::cout << "no\n";  // no because of the spaces
}

1 Ответ

2 голосов
/ 28 января 2020

Вы можете просто применить шкипер, получив его из контекста. Вы сами решаете, когда его использовать (например, является ли пост-пропуск частью поведения), но я предполагаю, что предварительный пропуск подразумевается, когда в любом случае есть активный шкипер.

Если вы наследуете от x3 :: parser_base, вы можете просто вызвать

 skip_over(f, l, ctx);

для выполнения работы.

См. пример Правило синтаксического анализа X3 не компилируется

...