如何将当前执行状态压入堆栈以便稍后继续执行?

2024-02-17

想象一个简单的语法:

(a|ab)c

其内容为(a 或 ab),后跟 c。解析树看起来像这样:

   and
   / \
  or  c
 /  \
a   ab

现在给它这个输入:

abc

我们首先沿着树的左侧向下遍历,并匹配“a”,然后返回上一层。由于“a”匹配,“or”也为真,因此继续处理“c”。 “c”不匹配,我们走到了路的尽头。

但它本可以采取另一条道路:如果我们向下遍历到“ab”,我们就会找到匹配项。

所以我想要对“或”节点做的基本上是这样的:

  1. 评估左分支
  2. 如果左分支不匹配,请尝试右分支
  3. 如果左侧匹配确实匹配,则将当前状态推入堆栈,以便我们可以在必要时从这一点继续

然后,每当解析器遇到死胡同时,我想从堆栈中弹出一个项目并从那里再次继续。

这是我无法弄清楚的部分......我如何基本上保存当前的调用堆栈?我可以将“ab”节点保存在堆栈中,以便我知道接下来必须执行该节点,但它仍然需要知道之后需要回退到“or”。


I think Chris https://stackoverflow.com/a/9747020/65387正在做某事。我们必须找到一种方法来平移树,这样就不需要像那样跳过树枝。例如,这个等效的解析树就不存在这个问题:

     or
    /  \
 and   and
 / \    / \
a   c  ab  c

这次我们向下解析左边,点击“a”,它通过了,所以我们尝试它旁边的“c”节点,失败了,“and”失败了,“or”必须尝试右边的分支,...“ab " 通过,另一个 "c" 通过,然后整个表达式通过。


按照你提出问题的方式,你已经得到了答案。

您需要保存state。棘手的部分是识别状态。保存它很容易。

您的问题是解析器在开始解析某些语法规则时“有一个状态”。 (如果您使用 LALR 解析器,这会变得更加混乱,它将许多规则的解析合并到一个状态中)。该状态包括:

  • 的状态input(例如,输入流在哪里?)。
  • 解析堆栈的状态(到目前为止看到的左侧上下文是什么?)
  • 解析器应该在哪里继续成功,在哪里继续失败

当您正在解析并面临您所描述的选择时,您需要“保存状态”,对第一项进行试验解析。如果成功,您可以丢弃保存的状态并继续。如果失败,恢复状态,并尝试第二个(和第n个替代方案)。 (无脑更容易,无论你是否面临替代方案,只是保存状态,但这取决于你)。

怎样才能拯救国家呢?将其推入堆栈。 (您通常有一个解析堆栈,这是一个非常方便的地方!如果您不喜欢这样,请添加另一个堆栈,但您会发现它和解析堆栈通常同步移动;我只是让解析堆栈包含一条记录我需要的所有东西,包括输入空间。您会发现“调用堆栈”对于状态的某些部分很方便;见下文)。

首先要做的就是保存input地点;这可能是文件源位置,并且出于优化原因可能是缓冲区索引。这只是一个标量,因此很容易保存。正在恢复输入流可能更难;无法保证解析器输入扫描器位于其所在位置附近。因此,您需要重新定位文件,重新读取任何缓冲区,并重新定位任何输入缓冲区指针。一些简单的检查可以使这在统计上变得便宜:存储任何缓冲区的第一个字符的文件位置;然后确定是否必须重新读取缓冲区只需将保存的文件位置与缓冲区起始文件位置进行比较即可。其余的应该是显而易见的。

如果您重新排列语法以最大限度地减少缓冲区,您将回溯更少的缓冲区(例如,您的解析器运行得更快)。在您的特定语法中,您有“(a | ab ) c”,可以手动将其重写为“a b?c”。后者至少不会回溯 a 代表的任何内容。

奇怪的部分是保存解析堆栈。好吧,你不必这样做,因为你的试验解析只会扩展你拥有的解析堆栈,并将其恢复到你拥有的解析状态,无论你的子解析成功还是失败。

“解析器在哪里失败”和“在哪里成功”只是另外两个标量。您可以将它们表示为解析代码块的索引和程序计数器(例如,延续)或调用堆栈上的返回地址(参见?另一个并行堆栈!),然后进行成功/失败的条件测试。

如果您想了解后者的详细信息,请查看我的所以回答手工编码的递归下降解析器。 https://stackoverflow.com/a/2336769/120163

如果您开始构建树,或者做其他事情作为解析的副作用,您将必须弄清楚如何捕获/保存副作用实体的状态,并恢复它。但无论它是什么,你最终都会将它压入堆栈。

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

如何将当前执行状态压入堆栈以便稍后继续执行? 的相关文章

随机推荐

  • 如何从一个docker容器到另一个docker容器执行命令

    我正在创建一个应用程序 允许用户上传视频文件 然后对这些文件进行一些处理 我有两个容器 Nginx为网站提供服务的容器 用户可以在其中上传视频文件 视频处理容器具有FFmpeg并安装了一些其他处理工具 我想要实现什么 我需要容器 1 才能在
  • 返回设备 3.1 中的设备确认令牌

    现在 Devise 已从数据库中删除了 confirmation token 我如何在 rspec 中返回 devise 确认令牌 我试图通过使用确认令牌手动访问 user confirmation 路径来测试可确认模块 我怎样才能实现这个
  • asp.net 中缓存密钥长度

    我正在研究 MVC3 源代码 并发现了以下内容 在 OutputCacheAttribute cs 中 该内容在生成用于输出缓存的密钥时被调用 The key is typically too long to be useful so we
  • 什么是 Oracle ADF?

    什么是 Oracle ADF 我在网上找到了如下定义 ADF 集成了多种子框架来提供关键功能 对象关系映射和其他形式的服务访问 数据 绑定和用户界面 以及用于固定的功能胶 这一切都在一起 ADF 代表 应用程序开发框架 它是由 Oracle
  • UITextField secureTextEntry 项目符号具有自定义字体吗?

    我正在使用自定义字体UITextField 其中有secureTextEntry打开 当我在单元格中输入时 我会看到项目符号采用我选择的字体 但是当字段失去焦点时 这些项目符号将恢复为系统标准字体 如果我再次点击该字段 它们就会变回我的字体
  • 从普通图像创建鱼眼效果的算法

    我正在尝试创建一个 OpenGL 片段着色器 将普通图像转换为包含鱼眼效果的图像 这就是我所说的鱼眼效果 http www marcofolio net photoshop create a fish eye lens effect in
  • 如何检查鼠标是否位于 jQuery 中的元素上?

    有没有一种快速简单的方法可以在 jQuery 中实现我所缺少的功能 我不想使用鼠标悬停事件 因为我已经将其用于其他用途 我只需要知道鼠标在给定时刻是否位于某个元素上 我想做这样的事情 如果有一个 IsMouseOver 函数 functio
  • 正向工程师在 MySQL Workbench 中不执行任何操作

    我的经验很少MySQL Workbench并需要一些帮助来解决问题 我从以下位置加载了新的 EER 图 MWBGUI 中的文件并试图将其转换为SQL with Forward engineer 最初 我连接到localhost当我按下For
  • Reactjs 和 Rxjs 有什么区别?

    基本上我开始学习 Rxjs 我对 React 和 Rxjs 有点困惑 我以为 Reactjs 和 Rxjs 是一样的 问题 如果 Reactjs 和 Rxjs 是相同的 那么为什么我们使用 Reactjs 而不是 Rxjs 反之亦然 如果
  • 如何将多个查询参数映射到 Jersey GET 请求上的 bean 字段?

    一个服务类有一个 GET接受多个参数的操作 这些参数作为查询参数传递给 GET服务电话 GET Path find Produces MediaType APPLICATION XML public FindResponse find Qu
  • MySQL 查询 - 仅使用条目的最新版本的内连接

    我有一张表 名为jobs与各种信息 每个作业都有一个作业编号 唯一的 ID 然后还有另一个表 名为purchaseOrders具有 jobID 的 FK 和 poID 的 PK 编辑采购订单条目时 旧信息将被保存 这意味着 我创建了一个新的
  • 无法使用 ionic cli 1.3.2 添加人行横道

    我从 git 克隆了一个现有的 ionic 项目 我有ionic 1 3 2 and cordova 4 2 0 克隆后 我cd编辑到目录中并执行了ionic browser add crosswalk 表示人行横道添加成功 然后当我尝试做
  • 从background-image属性中获取URL

    我怎样才能从background image属性中获取URL 现在我这样做 window getComputedStyle element getPropertyValue background image replace url repl
  • 在 Visual Studio 中打开文件的特定行号

    我有一个实用程序 grep 它给我一个文件名列表和行号 在确定 devenv 是打开文件的正确程序后 我想确保它在指定的行号处打开 在 emacs 中 这将是 emacs 140 filename c 我在 Visual Studio de
  • R 中带有背景颜色的文本标签

    我想知道是否有一种简单的方法可以使用基本图形系统将具有对比背景的文本标签添加到 R 图中 直到现在我一直使用rect 一起发挥作用graphics strheight and graphics strwidth 单独创建背景框 然后在其上放
  • 问题 C1083:无法打开包含文件:“chrono”:没有弹出这样的文件或目录

    我正在尝试编写一个程序 使 6 个数字随机出现 这是我的 pro 文件 QT core gui greaterThan QT MAJOR VERSION 4 QT widgets TARGET Lotto TEMPLATE app CONF
  • 使用 CodedUI 测试测试 WPF 应用程序,编码的 ui 测试项目是否应该共享解决方案?

    首先一些背景知识 我们正在 NET 4 5 中开发一个大型桌面 WPF 应用程序 目标是 64 位 Windows 7 和 8 我们使用 Visual Studio 2012 2 很快将成为 3 然后可能是 2013 年 和 TFS 201
  • BufferedReader.ready() 方法是否确保 readLine() 方法不返回 NULL?

    我有这样的代码来读取文本文件BufferedReader BufferedReader reader null try reader new BufferedReader new FileReader file1 txt while rea
  • BizTalk - 0 参数 Web 消息未在请求中发送

    我正在连接到 SOAP 1 1 Web 服务 不接受任何参数并返回一个简单的字符串响应 我已经使用旧的 NET 2 0 为复杂类型生成了 xsd 文件添加网页参考它还在 Reference odx 中生成了端口和多部分消息类型 在我的编排中
  • 如何将当前执行状态压入堆栈以便稍后继续执行?

    想象一个简单的语法 a ab c 其内容为 a 或 ab 后跟 c 解析树看起来像这样 and or c a ab 现在给它这个输入 abc 我们首先沿着树的左侧向下遍历 并匹配 a 然后返回上一层 由于 a 匹配 or 也为真 因此继续处