当期望解析器失败时避免抛出期望失败

2023-12-19

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

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

function a() return one end

keywords is (zero, one, function, return, end etc).

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

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

当它发生时,我得到了计划意外地结束了。 or 中止(核心转储)(取决于所使用的终端)。

调试代码时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 have 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) is bool,我怀疑只有两种方法来报告失败:异常异或返回码(只能是true or false, and true已经占用了解析成功结果报告)。它是递归降序解析器实现所固有的C++。但是如果我们改变结果类型parse from bool对于更广泛的东西,我们可以在解析期间以更灵活的方式通过不同的返回码值来区分报告硬错误或软错误(或其他错误)。


使用期望解析器时,您无法避免抛出期望失败。这就是这个操作符的目的。

Use operator>>对于“可回溯的期望”(即替代方案)。

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

Note这看起来像是一个错字

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

可能应该是

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

Also return one end不匹配"begin" >> statements >> "end"不管什么statements被定义为...

修理东西:

进行规则调试 http://coliru.stacked-crooked.com/a/5ab7de188dc272bd(仅限 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";
}

Prints:

<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 http://coliru.stacked-crooked.com/a/c07c14085ebc6d90 (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

¹ 只是为了向您展示can很好地处理期望失败:期望失败处理 http://coliru.stacked-crooked.com/a/c6461f997d4b1c8b

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

当期望解析器失败时避免抛出期望失败 的相关文章

  • C++:头文件中全局函数的多重定义错误

    该函数是全局的 在头文件中定义 暂时地我想把它留在那里 头文件还构成一个具有内联函数的特定类 其中一个函数调用this全局函数 源文件不包含任何有问题的全局函数 有关错误原因的任何提示吗 如果有人感兴趣的话我可以发布代码 mainwindo
  • 在两个 .cpp 文件之间定义全局变量 [重复]

    这个问题在这里已经有答案了 如何在 A cpp 和 B cpp 之间共享 全球化 bool 变量 其中它们都不包含其他 h 文件 他们有其他联合头文件 但彼此没有 我可以在这些共享标头中定义全局变量吗 Thanks 我可以在这些共享标头中定
  • 在 MVC 类上创建主键字段

    我是 MVC 和 C 新手 我只是偶然发现它并发现它很有趣 我遇到了一个不允许我继续的问题 这是我的代码 using System using System Collections Generic using System Linq usi
  • 为什么 LinkedList 通常比 List 慢?

    我开始在我的一些 C 算法中使用一些 LinkedList 而不是列表 希望能够加快速度 然而 我注意到他们只是感觉更慢 像任何优秀的开发人员一样 我认为我应该尽职调查并验证我的感受 所以我决定对一些简单的循环进行基准测试 我认为用一些随机
  • 浏览器收集哪些值作为回发数据?

    当页面被发送回服务器时 浏览器收集每个控件的当前值并将其粘贴到一个字符串中 然后 该回发数据通过 HTTP POST 发送回服务器 Q1 除了控件的 Text 属性和 SelectedIndexchanged 因此除了用户输入数据 之外 控
  • TestMethod:异步任务 TestSth() 不适用于 .NET 4.0

    我正在尝试使用 NET 4 0 BCL Async 和 MsTest 运行异步测试方法 看来这个设置不能处理 测试方法 异步Task测试Sth 由于测试用例资源管理器中缺少条目 将签名更改为异步后void 我可以运行测试用例 但结果错误 根
  • 如何在 C++ 的子目录中创建文件?

    这是我的代码 如何在子目录联系人中创建文件 每次创建该文件时 它都会出现在与我的程序相同的目录中 int main ofstream myfile contacts myfile open a myfile close 在构造函数中指定完整
  • 实体框架7审计日志

    我正在将一个旧项目移植到 ASP NET 5 和 Entity Framework 7 我使用数据库优先方法 DNX 脚手架 来创建模型 旧项目基于Entity Framework 4 审计跟踪是通过重写实现的SaveChanges的方法D
  • Windows 程序如何临时更改其时区?

    我写了一个函数来返回time t与给定日期的午夜相对应的值 当给定日期没有午夜时 它返回最早可用的时间 例如 当埃及进入夏令时时 这种情况就可能发生 今年 时间更改于 4 月 29 日晚上午夜生效 因此时钟直接从 23 59 转到 01 0
  • 使用 Microsoft Graph 创建用户

    如何使用 Microsoft graph 创建用户 因为我在保存过程中遇到了权限失败的问题 我确实有几个问题 在图中调用创建用户 API 将在哪里创建用户 是在 Azure AD 还是其他地方 我尝试通过传递 json 和必需的标头来调用创
  • IClaimsTransformation 未触发

    我尝试过实施一个IClaimsTransformation我在 ASP NET CORE 3 1 Web 应用程序中找到的类 public class ClaimsTransformer IClaimsTransformation publ
  • 使用对象列表构建树

    我有一个带有属性 id 和parent id 的对象列表 我想建造一棵树来连接那些孩子和父母 1 个父对象可以有多个子对象 并且有一个对象将成为所有对象的祖先 实现该功能最快的算法是什么 我使用 C 作为编程语言 但其他语言也可以 像这样的
  • IBM Watson 对话服务错误:无法从“方法组”转换为“conversation.onMessage”

    我正在尝试运行 IBM Watson会话服务团结和下面是代码片段 https github com watson developer cloud unity sdk conversation private Conversation m C
  • 打破条件变量死锁

    我遇到这样的情况 线程 1 正在等待条件变量 A 该变量应该由线程 2 唤醒 现在线程 2 正在等待条件变量 B 该变量应该由线程 1 唤醒 在我使用的场景中条件变量 我无法避免这样的死锁情况 我检测到循环 死锁 并终止死锁参与者的线程之一
  • 为什么我的 ITexthandler 不工作?我正在尝试将 XML 解析为 ITextSharp 文档

    我正在使用 Visual Developer 2010 MVC 3 c 我正在尝试将 XML 解析为 iTextSharp 文档 如下所示 ITextHandler textHandler new ITextHandler doc text
  • .NET 的 HttpWebResponse 是否会自动解压缩 GZiped 和 Deflated 响应?

    我正在尝试执行一个接受压缩响应的请求 var request HttpWebRequest HttpWebRequest Create requestUri request Headers Add HttpRequestHeader Acc
  • 如果数组为空,LINQ 返回 null

    public class Stuff public int x other stuff 我有一个IEnumerable
  • 使 C# 编译器相信执行将在成员返回后停止

    我认为目前这是不可能的 或者这是否是一个好主意 但这是我刚才正在考虑的事情 我使用 MSTest 对我的 C 项目进行单元测试 在我的一项测试中 我执行以下操作 MyClass instance try instance getValue
  • 为什么从绑定返回的对象会忽略额外的参数?

    假设我有一个带有两个参数的函数 void f int x int y 我想绑定其中之一 我可以用std bind如下 auto partiallyBoundF std bind f 10 1 partiallyBoundF仅需要一个参数 但
  • 统一;随机物体移动[关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我正在制作一款机器人战斗游戏 我希望敌人随机移动 然后有时会向敌人移动 我希望运动包含在其中的代码 else if avoid fal

随机推荐