【问题标题】:Does a Symbol Table store AST (Declaration)Nodes or are the "Symbols" different objects/classes?符号表是否存储 AST(声明)节点或者“符号”是不同的对象/类?
【发布时间】:2018-06-03 14:22:02
【问题描述】:

关于 AST / 符号表关系,我有一些我不明白的地方。

我目前有一个用 C# 实现的 AST,它具有用于变量声明的节点(这些包含有关名称、类型、源位置、可能的常量值作为表达式节点等的信息)。

现在我想填写一个符号表(在我的 AST 上使用访问者模式),但我的问题是:“符号”是新类,例如 VariableSymbol,还是符号表直接存储来自 AST 的 VariableDeclarationNode?

如果符号是新类,那么谁来存储常量变量、VariableDeclarationNode 或 VariableSymbol 或其他地方的计算表达式值?

(我看过一些解释器示例,它们将所有变量值(包括常量)存储在一个附加的哈希表中,但我正在使用源到源编译器而不是解释器,所以我不确定你将在这种情况下评估常量。抱歉,我知道这些问题有点多)

【问题讨论】:

  • 如果您正在使用源到源编译器,为什么还要存储常量表达式的计算表达式值?它是关于翻译成目标语言的语法,而不是解释或维护任何运行时状态。一旦您拥有变量的声明/初始化节点,您能否举例说明您的代码应该做什么/应该做什么?存储对在您用作目标代码发射基础的对象中声明符号的节点的引用本身并没有对错,这取决于您所考虑的架构。
  • 我当前的架构是生成 AST 的扫描仪和解析器,我的目标是将 AST 转换为 C 代码,但前提是代码是“有效的”,例如不是多个具有相同名称的变量.我看到了一些博客/教程,他们描述了我可以从 AST 中构建一个范围/符号表来进行语义检查。我发现的示例都有访问者模式来访问所有变量声明并将它们添加到范围/符号表中,但一些示例存储 AST 节点(本示例中为 VariableDeclarationNode),其他示例创建一个新类,例如 VariableSymbol跨度>
  • 这就是为什么我不确定哪个解决方案更好,如果我应该直接将 AST 节点添加到范围/表中,或者我是否应该为符号创建新类。您对常量表达式是正确的,遗憾的是我需要出于某种“愚蠢”/遗留原因评估它们,不允许有多个具有相同名称的变量,但有一个特殊规则,如果两个变量都是常量并且具有相同的值,那么应该没有错误消息(但只使用一个变量),这就是为什么我必须为这种特殊的遗留案例评估和存储常量变量的值
  • 我想补充一点,这目前是用于源到源编译器,但 AST 将来可能会用于其他用途,因为我们可能稍后会添加解释器,这就是我想要制作的原因确保我使用了一个好的架构,因为这是我第一次用 AST / 编译器做任何事情
  • 我明白了。仍然可能a)意见问题或b)由您的帖子中不够清楚的设计考虑驱动:如果AST节点中的信息对任务足够,那么您只需存储参考就可以了在范围树/表中。如果你从语法树解释而不是仅仅发出代码,那么你需要复杂的数据结构,其中对原始 AST 节点的引用是次要问题(c'ued)

标签: c# compilation abstract-syntax-tree symbol-table compiler-construction


【解决方案1】:

是“符号”新类,例如 VariableSymbol,还是符号表直接存储来自 AST 的 VariableDeclarationNode?​​p>

如果 AST 节点中的信息足以完成任务,那么只需将引用存储在范围树/表中即可。如果您从语法树解释而不是仅仅发出代码,那么您需要复杂的数据结构,其中对原始 AST 节点的引用是次要问题。我们已经看到并完成了这两项工作。在词法分析和解析之外的阶段不保留对“原始”AST 节点的引用是一种更简洁的方法。

[将评估的常量值(对于特殊情况)存储在符号类中会很脏吗?或者我应该为这些创建一个附加表吗?

这也确实取决于...如果您将常量值设想为声明的固有属性,请将其存储在符号描述符类中:

class Symbol : ISymbol {
    ASTNode DeclaringNode;
    SymbolType RuntimeType;
    bool InitializeAsConstant;
    RuntimeValue ConstantValue;

    ...
}

如果您保留包含的右值,那么您可以在目标语言中逐字复制声明,然后将它们视为变量直到过程结束:

/* fantasy source language */
Constant $$IAMCONSTANT :=> /03\ MUL /02\ KTHXBYE

/* target language */
const int IAMCONSTANT = 3 * 2;

/* as opposed to compilation stage 1 precomputed */
const int IAMCONSTANT = 6;

对于源到源的情况,第一个更容易,因为您可能会在编译器中不计算表达式值的情况下逃脱。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-02
    • 1970-01-01
    • 2021-01-20
    • 2014-03-27
    相关资源
    最近更新 更多