【问题标题】:Reusing symbol table from semantic analysis phase for code generation重用语义分析阶段的符号表进行代码生成
【发布时间】:2016-05-13 03:37:01
【问题描述】:

我目前正在为具有全局变量和嵌套子例程功能的语言构建编译器。以前,我只为只有局部变量而没有嵌套子例程的语言构建了一个编译器。

我在代码生成阶段如何重用在语义分析阶段填充的符号表有一个问题。我将符号表作为一个链表堆栈,其中每个链表代表在特定范围内声明的标识符。每次进入范围时,都会创建一个新列表并将其推送到堆栈并成为当前范围。同样,每次离开作用域时,堆栈顶部的列表都会弹出。最后,语义分析完成后,我实际上有一个空的符号表,就像它开始时一样。但是,代码生成器需要一个完全填充的符号表才能正确生成代码。如何在不重新执行语义分析期间完成的操作(即在符号表中输入标识符)的情况下做到这一点?

【问题讨论】:

  • 您是否考虑过将符号表构建为树而不是堆栈,所以最后会有一整棵范围树?
  • 你的意思是让它遵循 AST 层次结构吗?我认为最好让各自的范围数据成为 AST 节点的一部分,就像接受的答案一样,这就是为什么我在进入/退出范围时不需要遍历两次
  • 不,范围遵循自己的层次结构。您出于多种原因保留所有变量及其所属的范围,包括符号列表和调试器。 AST 仍应指向解析中使用的符号。
  • 您可以在符号表中添加另一个称为嵌套级别的字段,以实现嵌套过程。

标签: compiler-construction code-generation code-reuse semantic-analysis symbol-table


【解决方案1】:

您必须决定编译器将保留多少上下文以支持优化和代码生成。

您可以构建一个纯粹的即时代码生成器,如果它已经生成了将为该范围生成的所有代码(或 IR),它会在离开范围时丢弃符号表信息。如果您正在构建一个快速而肮脏的编译器,这可能会起作用,并且当您的计算机没有很多内存时它很有用。 (在现代 PC 上,您不能提出后一种说法)。

如果您在解析过程结束之前不进行任何代码分析/优化/IR 或代码生成,那么您将不得不更长时间地保留每个作用域的符号表信息。在这种情况下,您会发现您也必须坚持使用 AST,否则您将无法从中生成代码。 (在现代 PC 上,这不是问题)。

要构建具有简单架构的编译器,您可能希望隔离解析、语义分析和代码生成通道。在这种情况下,您的解析器运行并只是构建一个 AST;不要费心构建符号表。通过两次遍历树,并建立对应于 AST 部分的符号表,并保持这种关系;现在你有了 AST 和相关的符号表。 Pass 3 现在可以遍历 AST 并使用符号信息生成 IR。 Pass 4 优化 IR;它可能仍然引用用类型信息和可能的存储位置分配修饰的符号表条目。之后,您可以进行优化和最终代码生成。

这一切的重点是,不要把符号表扔掉。保存它们并将它们与代码生成所需的代码结构相关联。你有很多内存可以保存它们。

【讨论】:

  • 这实际上与接受的答案相同,但需要在最后两段进一步挖掘。由于我只能接受一个答案,因此给予了投票。
  • 同意,但这也是推理+1的更详细/更好的答案
【解决方案2】:

这会有点抽象 - 正如你的问题 - 因为我对编译器的内部数据结构一无所知。

当您弹出您的范围时,而不是像我假设您现在所做的那样删除它,将指向范围数据的指针分配给您为该范围生成代码的数据成员,以便代码生成器可以开始吧。

【讨论】:

  • 我太傻了,我确实可以将指向范围数据的指针作为相应 AST 节点成员的一部分。以后可以将其与 AST 一起丢弃。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-30
  • 2013-09-23
  • 1970-01-01
  • 1970-01-01
  • 2011-06-15
  • 2019-03-20
相关资源
最近更新 更多