您如何使用 boost spirit x3 实现自定义解析器对象,使其与船长配合得很好?

How do you implement a custom parser object with boost spirit x3 such that it plays nice with a skipper?

我知道我可以通过使用适当的 "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
}

您可以通过从上下文中获取它来简单地应用船长。由您决定何时使用它(例如,post-skip 是否是行为的一部分),但我想当有一个活跃的船长时,预跳过是隐含的。

如果您继承自 x3::parser_base,您只需调用

 skip_over(f, l, ctx);

完成工作。

查看示例