如何在 x3 中重写具有继承属性的 qi 解析器?

How to rewrite qi parsers with inherited attributes in x3?

如果在语义动作中使用继承的属性,我们可以使用x3::with指令。

如果我们想将属性用作解析器的一部分怎么办?例如,一个简单的解析器匹配 1 个或多个字母字符,但字符来自参数字符集。

qi::rule<std::string::const_iterator, qi::unused_type(char const*)> rule =
    +(qi::alpha - qi::char_(qi::_r1));

或者参数字符集可以用作惰性解析器。

qi::rule<std::string::const_iterator, qi::unused_type(char const*)> rule =
    +(qi::alpha - qi::lazy(qi::_r1));

x3::with 指令将此本地值放入上下文中。我不确定我们是否可以在语义操作之外使用此上下文并最终生成解析器。

干脆放弃一切都规则化的旧习惯。

#include <boost/spirit/home/x3.hpp>
#include <iostream>

namespace x3 = boost::spirit::x3;

template <typename... Args>
auto negate(Args&&... p) {
    return +(x3::char_ - x3::char_(std::forward<Args>(p)...));
};

int main() {
    std::string input("all the king's men and all the king's horses"), parsed;
    if (parse(input.begin(), input.end(), negate("horse"), parsed))
        std::cout << "'" << input << "' -> '" << parsed << "'\n";
}

Live On Coliru, 打印:

'all the king's men and all the king's horses' -> 'all t'

第二种口味:

#include <boost/spirit/home/x3.hpp>
#include <iostream>

namespace x3 = boost::spirit::x3;

template <typename Sub>
auto negate(Sub p) {
    return +(x3::char_ - x3::as_parser(p));
};

int main() {
    std::string input("all the king's men and all the king's horses"), parsed;
    if (parse(input.begin(), input.end(), negate("horse"), parsed))
        std::cout << "'" << input << "' -> '" << parsed << "'\n";
}

Live On Coliru, 打印:

'all the king's men and all the king's horses' -> 'all the king's men and all the king's '

更复杂的东西

您还可以在自定义解析器中聚合子解析器:

如果你需要通过传递的递归规则,我建议 x3::with<>(尽管我不确定上下文是否为 with<> 构建了可重入状态,你需要测试精确的语义,除非你能找到它的文档)