【发布时间】:2023-03-22 22:36:01
【问题描述】:
当期望解析器失败时如何避免抛出异常?
我有一条规则 "function" > (!x3::lexeme[keyword >> !(x3::alnum | '_')] >> symbol) > ('(' > -lvalue_list > ')') > statements > "end" 来解析代码,例如:
function a() return one end
keywords 是(zero、one、function、return、end 等)。
如果我为解析器提供function one() return zero end 代码,那么在函数expect_directive::parse 中抛出异常:
if (!r)
{
boost::throw_exception(
expectation_failure<Iterator>(
first, what(this->subject)));
}
当它发生时,我得到 程序意外完成。 或 Aborted (core dumped)(取决于使用的终端)。
在调试代码时,gdb 会在 boost::throw_exception 函数中的右大括号 '}' 自动中断,并带有消息:
The inferior stopped because it received a signal from the Operating System.
Signal name :
SIGABRT
Signal meaning :
Aborted
当逐步执行上述功能时,可以看到,throw enable_current_exception(enable_error_info(e)); 行是信号发出之前执行的最后一行。为什么异常处理程序搜索没有堆栈展开?为什么 abort 立即提出(看起来像 boost::throw_exception 有 noexcept 说明符)?
我已经接受了 try { ... } catch (x3::expectation_failure< input_iterator_type > const & ef) { ... } x3::phrase_parse 函数调用。 x3::expectation_failure< input_iterator_type > 正是从 boost::throw_exception 引发的期望。一切都无所谓。
有没有办法完全避免 Boost.Spirit X3 中的 x3::expectation_failure 异常,但仍会中断整体代码解析并使 x3::phrase_parse 在预期失败时返回 false? p>
接下来是我的怀疑:
由于所有解析器的成员函数parse()的常规返回值(作为X3中的概念)是bool,我怀疑只有两种方法可以报告失败:异常xor return代码(只能是true 或false,并且true 已被占用解析成功 结果报告)。它是 C++ 中递归降序解析器实现所固有的。但是,如果我们将 parse 的结果类型从 bool 更改为更广泛的类型,我们可以在解析期间以更灵活的方式区分报告硬错误或软错误(或其他错误)——通过返回代码的不同值。
【问题讨论】:
-
哇。你终于让我尝试 X3。非常喜欢
-
我知道将两个问题合二为一是错误的。对于问题的第二部分,我找到了答案:我使用 libunwind,正如它在最新的Eli Bendersky's article 中所描述的那样,并链接到它。系统范围内安装的 libunwind 和 gdb 之间似乎存在干扰,后者在内部使用 libunwind(可能版本不同)。
-
好的 - 很有趣。现在把它放在我的脑海里以备将来参考
-
@sehe 不值得。我无法在另一台机器上重现该行为。
-
好的,感谢您的推动。事情发生了。
标签: c++ boost-spirit boost-spirit-x3