【问题标题】:Symbol tables and type checking [closed]符号表和类型检查 [关闭]
【发布时间】:2025-12-16 12:50:02
【问题描述】:

我有两个与符号表相关的正交问题:

  1. 我是否应该在解析代码时构建符号表并执行类型检查? Parsing first and then traversing the AST 构建符号表对我来说看起来更干净。但是,我喜欢拥有不可变 AST(类似于 Clang)的想法,并且我不能在两步过程中拥有它(因为我需要在类型检查阶段插入额外的类型转换节点)。

  2. 符号表应该负责做类型检查吗?我读了multiplearticles,其中符号表用于此目的。这是推荐的做法吗?我觉得这很尴尬。

注意:我使用的是自上而下的递归下降解析器。

【问题讨论】:

    标签: parsing compiler-construction typechecking symbol-table


    【解决方案1】:

    我相信这是你应该做的:

    第一个:您应该首先构建您的 AST,然后,正如您所说,遍历它以填充符号表并进行类型检查。不可变的 AST 看起来不错,但它不会像遍历 AST 那样干净。

    第二个:是的,符号表应该参与类型检查(不做类型检查)。需要存储变量之类的东西的类型。没有什么尴尬的:-)

    【讨论】:

    • 不可变的 AST 看起来不错,但它不会像遍历 AST 那样干净。你介意扩展一下吗?现在,我的几个 AST 节点已经有了类型信息(例如,变量声明有一个名称 + 一个类型)。这会在符号表中重复吗?其他 AST 节点(例如二进制表达式)是否也应该有一个类型,在类型检查期间将被填充? (-> 需要一个可变的 AST)
    • @Touloudou -- 啊,这就是你正在做的。在我编写的大多数编译器中,我没有立即获得类型信息(只要构造了 AST 节点)。相反,我让节点被构造(no 在构造函数中进行评估),然后,我在它上面运行类型检查器;最后,我调用了进行评估的方法。它的设计非常简洁。
    • @Touloudou -- 另外,是的 -- 二进制操作应该有一个类型(通过类型检查器运行时)。您将需要它,因为当将二进制操作分配给变量时,您可以轻松获取类型。
    • 我不确定我是否遵循。在构建 AST 时如何不解析类型?当你遇到变量声明时,如果不在 AST 节点中,你将类型信息保存在哪里?好的二进制操作,谢谢!
    • @Touloudou -- 这是你在构建 AST 之后解析类型的方式:你有一个类型检查访问者,它访问所有 AST 节点,将类型信息添加到符号表中,并检查所有其他类型。如果您愿意,您还可以使用它们各自的类型来注释 AST 节点。