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
相关产品推荐
相关产品推荐

