You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Boost Spirit X3规则级自定义错误实现问题排查

Boost.Spirit X3 自定义期望点错误信息实现问题

阅读完规则级自定义错误相关的官方issue后,我尝试参考对应方案,结合社区中解决expectation_failure的which()方法返回值异常的适配思路做整合实现,但最终代码无法正常运行,调试结果和预期存在偏差。

即便显式使用x3::expect[],expectation_failure的what()成员也只会返回通用内置类型名称,使用mandatory封装时,预期输出的double、int甚至char x这类自定义名称无法正常返回,实际运行输出样例如下:

'a .e-z' error handler id 'rule_a': expect boost::spirit::x3::expectation_failure

我原本的设计思路是将辅助工具with_error_handler(也称为as)绑定到mandatory上下文/结构体,对应实现代码如下:

template <typename RuleID, typename AttributeT>
struct mandatory_type {
    template <typename Expr>
    auto with_error_handler(Expr&& expr, char const* name = typeid(decltype(expr)).name()) const {
        using tag = my_error_handler<RuleID>;
        return x3::rule<tag, AttributeT>{ name } = x3::as_parser(std::forward<Expr>(expr));
    }
    template <typename Expr>
    auto operator()(Expr&& expr, char const* name = typeid(decltype(expr)).name()) const {
        return x3::expect[ with_error_handler<RuleID, AttributeT>(expr, name) ];
    }
};

上述代码无法通过编译,以下是完整复现代码,可从中明确实现意图:

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

namespace x3 = boost::spirit::x3;

template <typename RuleID>
struct my_error_handler
{
    template <typename Iterator, typename Exception, typename Context>
    static x3::error_handler_result on_error(Iterator&, Iterator const&, Exception const& e, Context const&)
    {
        char const* id_name = typeid(RuleID).name();
        std::cerr << "error handler id '" << boost::core::demangle(id_name) << "': "
                  << "expect " << e.what() << "\n";
        return x3::error_handler_result::accept;
    }
};

template <typename RuleID, typename AttributeT>
struct mandatory_type {
    template <typename Expr>
    auto with_error_handler(Expr&& expr, char const* name = typeid(decltype(expr)).name()) const {
        using tag = my_error_handler<RuleID>;
        return x3::rule<tag, AttributeT>{ name } = x3::as_parser(std::forward<Expr>(expr));
    }
    template <typename Expr>
    auto operator()(Expr&& expr, char const* name = typeid(decltype(expr)).name()) const {
        return x3::expect[ with_error_handler<RuleID, AttributeT>(expr, name) ];
    }
};
template <typename RuleID, typename T> static const mandatory_type<RuleID, T> mandatory = {};

struct rule_a : my_error_handler<rule_a> {};
struct rule_b : my_error_handler<rule_b> {};
struct rule_grammar : my_error_handler<rule_grammar> {};

auto const a = x3::rule<rule_a>{ "double" } = x3::expect[x3::double_];
auto const b = x3::rule<rule_b>{ "int" } = x3::expect[x3::int_];
auto  const grammar = x3::rule<rule_grammar>{ "grammar" } =
      'a' >> a 
    | 'b' >> b 
    | x3::expect['x'] 
    //| mandatory<rule_grammar, char>('x', "char x")
    ;

int main() {
    for (std::string_view test: { "a 1.23", "b 123", "a .e-z", "b .0", "x", "d" }) {
        std::cerr << "'" << test << "' ";
        if (!phrase_parse(begin(test), end(test), grammar, x3::space)) {
            std::cerr << "parse error\n";
        }
        else {
            std::cout << "ok\n";
        }
    }
}

内容的提问来源于stack exchange,提问作者Olx

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 04:31:13