Lel*_*mbo 1 compiler-construction code-reuse code-generation semantic-analysis symbol-table
我目前正在为具有全局变量和嵌套子例程功能的语言构建编译器。以前,我只为只有局部变量而没有嵌套子例程的语言构建了一个编译器。
我在代码生成阶段如何重用在语义分析阶段填充的符号表有问题。我将符号表作为一个链表堆栈,其中每个链表代表在特定范围内声明的标识符。每次它进入一个范围时,都会创建一个新列表并将其推送到堆栈中,它成为当前范围。同样,每次离开作用域时,栈顶的列表都会被弹出。最后,在语义分析完成后,我实际上有空符号表,就像它开始时一样。但是,代码生成器需要一个完全填充的符号表才能正确生成代码。如何在不重新做语义分析期间所做的事情(即向符号表输入标识符)的情况下做到这一点?
您必须决定您的编译器将保留多少上下文来支持优化和代码生成。
您可以构建一个纯粹的即时代码生成器,它会在离开作用域时丢弃符号表信息,如果它已经生成了它将为该作用域生成的所有代码(或 IR)。如果您正在构建一个快速而肮脏的编译器,这可以工作,并且当您的计算机没有很多内存时它很有用。(在现代 PC 上,您不能提出后一种论点)。
如果您在解析过程结束之前不进行任何代码分析/优化/IR 或代码生成,那么您将不得不更长时间地保留每个范围的符号表信息。在这种情况下,您会发现您也必须使用 AST,否则您将无法生成任何代码。(在现代 PC 上,这不是问题)。
要构建具有简单架构的编译器,您可能希望无论如何都要隔离解析、语义分析和代码生成过程。在这种情况下,您的解析器会运行并构建一个 AST;不要费心构建符号表。通过两次遍历树,并构建对应于 AST 部分的符号表,并保持这种关系;现在你有了 AST 和相关的符号表。Pass 3 现在可以遍历 AST 并使用符号信息生成 IR。Pass 4 优化了 IR;它仍然可以引用用类型信息和可能的存储位置分配修饰的符号表条目。之后,您可以进行优化和最终代码生成。
所有这一切的要点是,不要扔掉符号表。保存它们并将它们与代码生成所需的代码结构相关联。你有很多内存可以保存它们。