- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
(!x3::lexeme[keyword >> !(x3::alnum | '_')] >> symbol) > ('(-6ren">
当期望解析器失败时,如何避免抛出异常?
我有一条规则 "function" > (!x3::lexeme[keyword >> !(x3::alnum | '_')] >> symbol) > ('(' > -lvalue_list > ')') > statements > "end"
解析如下代码:
function a() return one end
keyword
s 是(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)));
}
发生这种情况时,我得到程序意外完成。或中止(核心转储)(取决于使用的终端)。
调试代码时,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_exception
有 noexcept
说明符)?
我已拥抱成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(只能是true
或false
,true
已经被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/
我之前让 dll 注入(inject)器变得简单,但我有 Windows 7,我用 C# 和 C++ 做了它,它工作得很好!但是现在当我在 Windows 8 中尝试相同的代码时,它似乎没有以正确的方
我正在尝试制作一个名为 core-splitter 的元素,该元素在 1.0 中已弃用,因为它在我们的项目中起着关键作用。 如果您不知道 core-splitter 的作用,我可以提供一个简短的描述。
我有几个不同的蜘蛛,想一次运行所有它们。基于 this和 this ,我可以在同一个进程中运行多个蜘蛛。但是,我不知道如何设计一个信号系统来在所有蜘蛛都完成后停止 react 器。 我试过了: cra
有没有办法在达到特定条件时停止扭曲 react 器。例如,如果一个变量被设置为某个值,那么 react 器应该停止吗? 最佳答案 理想情况下,您不会将变量设置为一个值并停止 react 器,而是调用
https://code.angularjs.org/1.0.0rc9/angular-1.0.0rc9.js 上面的链接定义了外部js文件,我不知道Angular-1.0.0rc9.js的注入(in
我正在尝试运行一个函数并将服务注入(inject)其中。我认为这可以使用 $injector 轻松完成.所以我尝试了以下(简化示例): angular.injector().invoke( [ "$q
在 google Guice 中,我可以使用函数 createInjector 创建基于多个模块的注入(inject)器。 因为我使用 GWT.create 在 GoogleGin 中实例化注入(in
我在 ASP.NET Core 1.1 解决方案中使用配置绑定(bind)。基本上,我在“ConfigureServices Startup”部分中有一些用于绑定(bind)的简单代码,如下所示: s
我在 Spring MVC 中设置 initBinder 时遇到一些问题。我有一个 ModelAttribute,它有一个有时会显示的字段。 public class Model { privat
我正在尝试通过jquery post发布knockoutjs View 模型 var $form = $('#barcodeTemplate form'); var data = ko.toJS(vm
如何为包含多态对象集合的复杂模型编写自定义模型绑定(bind)程序? 我有下一个模型结构: public class CustomAttributeValueViewModel { publi
您好,我正在尝试实现我在 this article 中找到的扩展方法对于简单的注入(inject)器,因为它不支持开箱即用的特定构造函数的注册。 根据这篇文章,我需要用一个假的委托(delegate)
你好,我想自动注册我的依赖项。 我现在拥有的是: public interface IRepository where T : class public interface IFolderReposi
我正在使用 Jasmine 测试一些 Angular.js 代码。为此,我需要一个 Angular 注入(inject)器: var injector = angular.injector(['ng'
我正在使用 Matlab 代码生成器。不可能包含代码风格指南。这就是为什么我正在寻找一个工具来“ reshape ”、重命名和重新格式化生成的代码,根据我的: 功能横幅约定 文件横幅约定 命名约定 等
这个问题在这里已经有了答案: Where and why do I have to put the "template" and "typename" keywords? (8 个答案) 关闭 8
我开发了一种工具,可以更改某些程序的外观。为此,我需要在某些进程中注入(inject)一个 dll。 现在我基本上使用这个 approach .问题通常是人们无法注入(inject) dll,因为他们
我想使用 swing、spring 和 hibernate 编写一个 java 应用程序。 我想使用数据绑定(bind)器用 bean 的值填充 gui,并且我还希望它反射(reflect) gui
我有这段代码,当两个蜘蛛完成后,程序仍在运行。 #!C:\Python27\python.exe from twisted.internet import reactor from scrapy.cr
要点是 Spring Batch (v2) 测试框架具有带有 @Autowired 注释的 JobLauncherTestUtils.setJob。我们的测试套件有多个 Job 类提供者。因为这个类不
我是一名优秀的程序员,十分优秀!