Compiler construction 编写编译器:语义分析(类型检查)后符号表还会使用吗

Compiler construction 编写编译器:语义分析(类型检查)后符号表还会使用吗,compiler-construction,Compiler Construction,我正在阅读ML中的现代编译器实现,并尝试做编译器项目(tiger语言) 在第五章语义分析中,使用功能数据结构构建符号稳定。因此,insert table key value将返回一个新表,而不是修改现有表,并且在函数返回时保留旧表。因此,当完成类型检查时,符号表仍然为空 我的问题是,这是否意味着符号表纯粹用于类型检查?因为我已经读过这篇文章,它说符号表也将用于代码生成(我还没有走那么远) 如果在语义分析后使用符号表,我应该使用命令式数据结构吗 任何具体的例子都将不胜感激。:) 否。您可能希望它用

我正在阅读ML中的现代编译器实现,并尝试做编译器项目(tiger语言)

在第五章语义分析中,使用功能数据结构构建符号稳定。因此,
insert table key value
将返回一个新表,而不是修改现有表,并且在函数返回时保留旧表。因此,当完成类型检查时,符号表仍然为空

我的问题是,这是否意味着符号表纯粹用于类型检查?因为我已经读过这篇文章,它说符号表也将用于代码生成(我还没有走那么远)

如果在语义分析后使用符号表,我应该使用命令式数据结构吗


任何具体的例子都将不胜感激。:)

否。您可能希望它用于代码生成、错误/反馈报告和链接

类型检查只是验证程序是否明显疯狂。检查完成后,您现在可能希望生成中间代码。 Java表达式

  a+b
可以进行类型检查,但在生成代码时,a和b的类型很重要。根据a和b分别是数字还是字符串,甚至是不同的,您可以得到不同的代码

对于报告,可能是在代码生成和优化过程中,编译器对其无法生成特定预期结果的原因有意见。在这种情况下,它可能希望以用户的术语向用户传达意见;通常是指某个有助于观点的命名实体。要做到这一点,您需要保留中间表示形式与符号表中名称之间的联系

最后,您可能有一个单独编译的系统。如果是这种情况,则单独编译的元素之间的链接通常通过使用编译器从程序导出到链接器的名称来完成。如果foo是在另一个编译单元中定义的,则很难将调用链接到“foo”,除非编译器和链接器同意将链接命名为“foo”


所以不,你不应该扔掉符号表。

符号表当然会在代码生成过程中使用:
a*=5
应该生成浮点乘法的int吗?@MargaretBloom可以安全地说我应该为符号表使用命令式数据结构吗?Hashtable而不是bstI真的很困惑。当类型检查器从作用域返回时,该作用域不是从符号表中删除了吗?当类型检查完成后,符号表如何仍然保存有关内部作用域的信息?本书的语义分析练习是编写一个类型检查器
trans_prog:ast->unit
,这意味着函数不返回任何内容,本书在本章开头讨论了函数符号表,因为我使用了OCAMLI,所以我使用了OCAMLI。如果你坚持遵循一种非常老式的符号表构造,在这种构造中作用域是完全嵌套的,你会得到一个故事,讲述编译器如何在“进入”一个词汇范围的区域时将一个新的符号表推送到堆栈上,并在离开该区域时弹出(销毁)它。如果你同意我的观点,你不会想破坏它的。。。。。。如果您查看现代语言(特别是那些具有各种名称空间的语言),您会发现作用域到代码的映射不一定能够很好地嵌套语言的嵌套语法。现在需要有一个符号表,它的范围是在可视性中出现的,取决于源文本的哪部分被处理,以及各种有趣的语言规则(你应该看到C++),而且它们没有明显地(完全)词性范围。因此,无论如何,您都不想推送新/旧符号表。最好使用symobl映射将名称与特定上下文中的类型相关联,并且查找范围的规则仅取决于正在处理的程序部分。范围仍然是指“在某一点(nee周围区域)可见的符号”;它可能意味着以复杂顺序查询的符号映射集。