【问题标题】:How does a compiler remember declared variable when used in expression?编译器在表达式中使用时如何记住声明的变量?
【发布时间】:2019-04-01 16:18:53
【问题描述】:

当变量在表达式中使用时,编译器如何跟踪变量的声明?

例如,如果我有以下代码:

int num = 1; //declaration
num = 2; //expression

我知道语法树会为声明生成一个分支,为表达式生成一个分支,但它如何在语义分析器中维护它们之间的连接?

【问题讨论】:

  • 学习这些东西的最好方法(IMO)是尝试制作你的自己的编译器(对于一些简单的语言)。这很有趣,而且你会学到很多东西(除了符号和变量如何在编译器的不同部分之间传递)。

标签: c compiler-construction abstract-syntax-tree semantics


【解决方案1】:

编译器的语义分析阶段包括处理一个符号表,顾名思义,它跟踪程序中使用的所有符号(名称)。例如,这也允许检测未声明的名称。

因此,当分析器“看到”一个声明时,它会创建一个新符号(如 Symbol(type=Int, offset=0))并将其插入到映射 name -> Symbol 中。例如,symbol_table["num"] = Symbol(type=Int, offset=0)

然后,在分析表达式或语句(在您的示例中为语句)时,编译器可以分析其成员的类型。为此,它会查找符号表中使用的名称:

assign_to_symbol = symbol_table["num"]
if assign_to_symbol.type == right_hand_side.type:
    DoStuff()
else:
    ThatIsAnError()

如果此范围内没有名称 "num",则查找失败,从而发出错误信号。

【讨论】:

  • 符号表会是哈希映射吗?或者它会是一个堆栈?它也会处理适当的范围吗?
  • 嗯,堆栈可以用字符串索引吗?它不能,但哈希映射可以。它是否跟踪范围取决于您的语言的实现和规范。给定适当的语义操作,您当然可以做到这一点。
  • 这只是符号可以包含的信息的一个示例。在这种情况下,它是从当前堆栈帧开始的偏移量。这使得为​​函数本地数据分配内存成为可能。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-08
  • 2013-05-24
  • 1970-01-01
  • 1970-01-01
  • 2022-08-21
  • 1970-01-01
相关资源
最近更新 更多