(!x3::lexeme[keyword >> !(x3::alnum | '_')] >> symbol) > ('(-6ren">
gpt4 book ai didi

c++ - 避免在期望解析器失败时抛出 expectation_failure

转载 作者:太空狗 更新时间:2023-10-29 20:57:09 25 4
gpt4 key购买 nike

当期望解析器失败时,如何避免抛出异常?

我有一条规则 "function" > (!x3::lexeme[keyword >> !(x3::alnum | '_')] >> symbol) > ('(' > -lvalue_list > ')') > statements > "end"解析如下代码:

function a() return one end

keyword s 是(zeroonefunctionreturnend 等)。

如果我向解析器提供 function one() return zero end代码,然后在函数中 expect_directive::parse从这里抛出的异常:

if (!r)
{
boost::throw_exception(
expectation_failure<Iterator>(
first, what(this->subject)));
}

发生这种情况时,我得到程序意外完成。中止(核心转储)(取决于使用的终端)。

调试代码时,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)); line 是信号发射前执行的最后一行。为什么没有用于异常处理程序搜索的堆栈展开?为什么立即中止(看起来像 boost::throw_exceptionnoexcept 说明符)?

我已拥抱成try { ... } catch (x3::expectation_failure< input_iterator_type > const & ef) { ... } x3::phrase_parse函数调用。 x3::expectation_failure< input_iterator_type >正是 boost::throw_exception 抛出的期望.一切都无所谓。

有没有办法完全避免x3::expectation_failure Boost.Spirit X3 中的异常,但仍然中断整体代码解析并生成 x3::phrase_parse返回 false关于期望失败?

接下来是我的怀疑:

由于常规返回值parse()所有解析器的成员函数(作为 X3 中的概念)是 bool ,我怀疑只有两种方法可以报告失败:exception xor return code(只能是truefalsetrue已经被Parse successful结果报告占用)。它是 C++ 中递归降序解析器实现的固有特性。但是如果我们改变 parse 的结果类型来自 bool对于更广泛的东西,我们可以在解析期间以更灵活的方式区分报告硬错误或软错误(或其他东西)——通过不同的返回码值。

最佳答案

在使用期望解析器时,你无法避免抛出期望失败。这是此运算符的目的。

使用 operator>> 表示“可回溯期望”(即备选方案)。

当您确实使用期望点 (operator>) 时,也只需处理异常¹。

Note This looks like a typo

('(' > -lvalue_list > '>')

should probably be

('(' > -lvalue_list > ')')

此外 return one end 不匹配 "begin">> statements >> "end" 无论 statements 被定义为...

修复问题:

Live With Rule Debugging (仅限 C++14)

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

namespace SO {
namespace x3 = boost::spirit::x3;

x3::symbols<char> const keyword = []{
x3::symbols<char> kw;
kw += "for","begin","end","function","while","break","switch";
return kw;
}();

x3::rule<struct symbol_tag> const symbol ("symbol");
x3::rule<struct identifier_tag> const identifier ("identifier");
x3::rule<struct lvalue_list_tag> const lvalue_list("lvalue_list");
x3::rule<struct statements_tag> const statements ("statements");
x3::rule<struct rule_tag> const rule ("rule");

auto symbol_def = x3::lexeme[x3::alnum >> *(x3::alnum | '_')];
auto identifier_def = (!(x3::lexeme[keyword >> !(x3::alnum | '_')]) >> symbol);
auto lvalue_list_def = identifier % ',';
auto statements_def = *identifier;
auto rule_def = "function"
>> identifier
>> ('(' > -lvalue_list > ')')
>> ("begin" > statements > "end")
;

BOOST_SPIRIT_DEFINE(symbol, identifier, lvalue_list, statements, rule)
}

int main() {
std::string const sample = "function a() begin return one end";
auto f = sample.begin(), l = sample.end();

bool ok = phrase_parse(f, l, SO::rule, SO::x3::space);
if (ok)
std::cout << "Parse success\n";
else
std::cout << "Parse failed\n";

if (f!=l)
std::cout << "Remaining unparsed: '" << std::string(f,l) << "'\n";
}

打印:

<rule>
<try>function a() begin r</try>
<identifier>
<try> a() begin return on</try>
<symbol>
<try> a() begin return on</try>
<success>() begin return one </success>
</symbol>
<success>() begin return one </success>
</identifier>
<lvalue_list>
<try>) begin return one e</try>
<identifier>
<try>) begin return one e</try>
<symbol>
<try>) begin return one e</try>
<fail/>
</symbol>
<fail/>
</identifier>
<fail/>
</lvalue_list>
<statements>
<try> return one end</try>
<identifier>
<try> return one end</try>
<symbol>
<try> return one end</try>
<success> one end</success>
</symbol>
<success> one end</success>
</identifier>
<identifier>
<try> one end</try>
<symbol>
<try> one end</try>
<success> end</success>
</symbol>
<success> end</success>
</identifier>
<identifier>
<try> end</try>
<fail/>
</identifier>
<success> end</success>
</statements>
<success></success>
</rule>
Parse success

没有调试

它变得简单多了:

Live On Coliru (g++/clang++)

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

int main() {
namespace x3 = boost::spirit::x3;

x3::symbols<char> keyword;
keyword += "for","begin","end","function","while","break","switch";

static auto symbol = x3::lexeme[x3::alnum >> *(x3::alnum | '_')];
static auto identifier = (!(x3::lexeme[keyword >> !(x3::alnum | '_')]) >> symbol);
static auto lvalue_list = identifier % ',';
static auto statements = *identifier;
static auto rule = "function"
>> identifier
>> ('(' > -lvalue_list > ')')
>> ("begin" > statements > "end")
;

std::string const sample = "function a() begin return one end";
auto f = sample.begin(), l = sample.end();

bool ok = phrase_parse(f, l, rule, x3::space);
if (ok)
std::cout << "Parse success\n";
else
std::cout << "Parse failed\n";

if (f!=l)
std::cout << "Remaining unparsed: '" << std::string(f,l) << "'\n";
}

只是打印

Parse success

¹ 只是为了向您展示可以很好地处理期望失败:Expectation Failure Handling

关于c++ - 避免在期望解析器失败时抛出 expectation_failure,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31553900/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com