gpt4 book ai didi

c++ - 在运行时组合规则并返回规则

转载 作者:搜寻专家 更新时间:2023-10-31 02:06:48 25 4
gpt4 key购买 nike

我正在尝试编写一些基于 Spirit-X3 的复杂解析器,所以我需要了解一些事情:

♦ 如何在运行时组合规则。 (用 Nabialek 的把戏)

♦ 是否可以返回这样的规则:

x3::rule<char> SomeFunction(std::string &str)
{
x3::rule<char> foo;
auto bar = baz;
BOOST_SPIRIT_DEFINE(foo, bar);
return foo;
}

PS:SomeFunction 没有固定的返回,所以我不能只使用 x3::sequence

最佳答案

是的,x3 使编写规则变得容易得多。

主要是因为解析器表达式在分配给变量时不倾向于保留对临时变量的引用,就像在齐国时代那样。

局限性:在 X3 中使用外部链接声明解析器要复杂得多,需要与您展示的宏一起跳舞 BOOST_SPIRIT_{DECLARE,DEFINE} .

你的样本

那不会飞,因为宏是要在命名空间范围内使用的。好消息是您可能不需要它,因为没有必要将规则与定义分开声明,除非您正在处理递归要求的规则。

题外话x3::rule<char>很可能是一个错误。 char是该声明中的标记类型,这不是一个好的标记类型。如果您想要一个属性 类型,则需要将其作为第二个模板参数。

auto SomeFunction(std::string &str)
{
return x3::rule<struct _tag, std::string> {"dynamic"}
= '[' >> x3::lit(str) >> ']';
}

其实我经常在报关点做小工厂:

template <typename Attr>
auto compose = [](auto p1, auto p2) {
return rule<struct _, Attr> {"compose"}
= nocase [
lexeme [ "property:" << as_parser(p1) ]
>> '='
lexeme [ "value:" << as_parser(p2) ]
];
};

这有点做作,但应该会给您一些想法。像compose<int>("number", x3::int_)一样使用它或 compose<std::string>("name", +x3::graph)

一些鼓舞人心的例子

  • Understanding the List Operator (%) in Boost.Spirit显示临时 as<>[]设施:

    namespace {
    template <typename T>
    struct as_type {
    template <typename Expr>
    auto operator[](Expr&& expr) const {
    return x3::rule<struct _, T>{"as"} = x3::as_parser(std::forward<Expr>(expr));
    }
    };

    template <typename T> static const as_type<T> as = {};
    }
  • Avoid throwing expectation_failure when expectation parser fails它动态地组成一个符号查找:

    x3::symbols<char> const keyword = []{
    x3::symbols<char> kw;
    kw += "for","begin","end","function","while","break","switch";
    return kw;
    }();
  • Dynamically switching symbol tables in x3这是一个非常完整的示例,包含许多解析器工厂:

    // (case insensitive) keyword handling
    static auto kw = [](auto p) { return x3::lexeme[p >> !(x3::graph - x3::char_("/=,()"))]; };
    static auto ikw = [](auto p) { return x3::no_case [kw(p)]; };
    static auto qualifier = [](auto p) { return x3::lexeme['/' >> ikw(p)]; };

    甚至展示了如何覆盖 as_spirit_parser对于您自己的类型:

    // Options and CiOptions
    namespace util {
    template <typename Tag>
    auto as_spirit_parser(Options<Tag> const& o, bool to_lower = false) {
    x3::symbols<typename Options<Tag>::type> p;
    int n = 0;
    for (std::string el : o._options) {
    if (to_lower) boost::to_lower(el);
    p.add(el, n++);
    }
    return kw(p);
    }

    template <typename Tag>
    auto as_spirit_parser(IcOptions<Tag> const& o) {
    return x3::no_case [ as_spirit_parser(o, true) ];
    }
    }

    使用自动生成的语义操作编写成员智能传播助手的非常优雅的方式:

        auto set = [](auto member, auto p) {
    auto propagate = [member](auto& ctx) {
    traits::move_to(_attr(ctx), _val(ctx).*(member));
    };
    return as_parser(p)[propagate];
    };

    using T = ast::ShowSymbolsCommand;;
    return qualifier("all") >> set(&T::all, attr(true))
    | qualifier("full") >> set(&T::full, attr(true))
    | qualifier("out") >> set(&T::out, '=' >> Filespec)
    | qualifier("type") >> set(&T::types, '=' >> SymbolTypes)
    | set(&T::wildcard, Wildcard);

我强烈建议您每次使用这些示例来了解 X3 组合的强大程度。只有当你/真的/需要它时,我才会考虑重新创建类似 qi::lazy 的东西在 X3


¹ 或者实际上任何基于 Proto 的东西,比如 Phoenix 也是

关于c++ - 在运行时组合规则并返回规则,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49722452/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com