C++ 在运行时合并规则并返回规则

C++ 在运行时合并规则并返回规则,c++,c++14,boost-spirit,boost-spirit-x3,C++,C++14,Boost Spirit,Boost Spirit X3,我试图在Spirit-X3的基础上编写一些复杂的解析器,所以我需要知道一些事情: ♦ 如何在运行时组合规则。(用纳比亚莱克的把戏) ♦ 返回如下规则是否可以: x3::rule<char> SomeFunction(std::string &str) { x3::rule<char> foo; auto bar = baz; BOOST_SPIRIT_DEFINE(foo, bar); return foo; } x3::rule

我试图在Spirit-X3的基础上编写一些复杂的解析器,所以我需要知道一些事情:

♦ 如何在运行时组合规则。(用纳比亚莱克的把戏)

♦ 返回如下规则是否可以:

x3::rule<char> SomeFunction(std::string &str)
{
    x3::rule<char> foo;
    auto bar = baz;
    BOOST_SPIRIT_DEFINE(foo, bar);
    return foo;
}
x3::rule SomeFunction(std::string&str)
{
x3::规则foo;
自动条=baz;
提升精神定义(foo,bar);
返回foo;
}

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

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

这主要是因为解析器表达式在分配给变量时没有保留对临时变量的引用的倾向,就像它们在Qiü年代那样

限制:使用外部链接声明解析器要多得多。。。在X3中非常复杂,需要与显示的宏一起跳舞
BOOST\u SPIRIT{DECLARE,DEFINE}

你的样品 这将无法运行,因为宏将在名称空间范围内使用。好消息是您可能不需要它,因为不需要将规则与定义分开声明,除非您处理的是递归必需的规则

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

auto SomeFunction(std::string &str)
{
    return x3::rule<struct _tag, std::string> {"dynamic"}
        = '[' >> x3::lit(str) >> ']';
}
甚至还演示了如何为您自己的类型重写作为解析器的

// 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) ];
    }
}
我强烈建议您使用这些示例来了解X3组合的强大功能。只有当你真的需要它的时候,我才会考虑重新创建一些类似于<代码> Q::懒惰< /代码>在x3



或者事实上任何基于原型的东西,比如Phoenix也链接了“一些鼓舞人心的例子”,这些例子应该会让你对如何在x3中编写解析器有一个很好的了解。我记得在x3中编写自定义解析器也要简单得多。
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 = {};
}
x3::symbols<char> const keyword = []{
    x3::symbols<char> kw;
    kw += "for","begin","end","function","while","break","switch";
    return kw;
}();
// (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)]; };
// 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);