1

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

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

4

2 回答 2

5

你必须决定你的编译器要保留多少上下文来支持优化和代码生成。

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

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

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

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

于 2016-02-07T04:14:58.610 回答
2

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

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

于 2016-02-07T00:10:49.530 回答