对于那些不遵循 POJ(JVM 上的 Pascal)的人来说,它是一个将 子集 从 Pascal 转换为 JASM 的编译器( Java Assembly),以便我们可以使用 JVM 作为执行环境。
在上一篇文章中,我们解决了一些重要的错误,特别是在程序集的生成中。在这篇文章中,我们将讨论如何正确生成嵌套句子的程序集。
当我们为 JVM 进行编译时,有必要详细说明这个令人难以置信的虚拟机的各个点的功能。因此,我多次详细介绍 JVM 的内部功能及其一些指令(操作码)。
正确处理嵌套句子的必要功能之一是解析器中可能具有多个上下文。这是因为,如果 解析器 仅假定一个上下文,则会生成 标签 并跳转的嵌套控制语句(如 if、for、while 和 repeat) 将错误地生成跳转寻址。
处理上下文有两种方法,分别是:
通常我会使用递归解析器方法。然而,为了使用 ANTLR 实现递归解析器,由于 POJ 中语法的结构方式,需要将代码直接注入到语法中,但不推荐这种方法。因此,我们选择了堆叠上下文的方法。
由于已经有一个堆栈实现来监视解析器在 JVM 中堆栈/取消堆栈的类型,为了不必为特定类型创建另一个堆栈,我们决定创建一个stack 此 PR 中的通用。除了稍后能够利用此实现之外,我仍然可以重构旧代码并删除现有的特定 stack.
在此提交中,解析器已更改为正确堆栈/取消堆栈函数上下文。基本上,在函数的 解析器 的开头,上下文是堆叠的,而在最后,上下文是未堆叠的。
if、for、while 和 repeat 等控制语句可以正常工作。然而,如果有嵌套句子,POJ 不会存储上下文,最终会错误地生成 labels 并跳转。这里和这里讨论了程序集的生成如何适用于这些控制语句。
对于下面的示例,其中包含嵌套在另一个 if 中的示例,POJ 错误地生成了 标签 和必要的跳转:
program NestedIfs; begin if (1 > 2) then if (2 > 3 ) then writeln('1 > 2 and 2 > 3') else writeln('1 > 2 and 2 <= 3') else writeln('1 <= 2'); end.
这个错误是已知的,我选择在解析器支持上下文时解决它。
在此提交中,创建了 LabelsContext 结构,其中包含以下 标签:
为了验证程序集的正确生成,创建了测试来验证嵌套if's、嵌套repeat's、嵌套while以及for's 嵌套。此处创建测试是为了验证在递归函数的情况下程序集的生成。此外,有必要更新所有现有测试的预期程序集。最后,在此 PR 中,解析器 已更新为使用新的上下文结构。
以下是这些更改的完整 PR。这里我们有 commit ,其中包含 if 句子正确运行的更改,这里 commit 指的是 repeat,这里commit 指的是 while,这里 commit 指的是 for。
在下一篇文章中我们将讨论数据输入。现在不久我们就完成了这个项目的目标之一:从标准输入中读取一个数字并计算其阶乘。
包含项目完整代码和文档的存储库位于此处。
以上是嵌套句子的详细内容。更多信息请关注PHP中文网其他相关文章!