4

我想知道是否只有一个符号表存储有关源文件的所有信息,或者有多个相互堆叠的符号表,并且仅在当前范围与表相关时才获取。

例如说我有两种方法

int foo(int a){
    int b;

    bar(b);
    ...
}

double bar (int a){
   int b;
   ...
}

这里两个中的a和b的作用域不同,所以如果符号表是堆叠的,则在执行foo时会先获取与foo关联的符号表。但是在执行 bar 时,bar 的符号表会堆叠在 foo 上,因此当前符号表包含 bar 的 a 和 b 的信息。

如果符号表是集中式的,则 foo 的 info 和 bar 的 info 都驻留在一个符号表中,但可能有条目指定 foo 中的 a,b 属于 foo 的范围,而 bar 中的 a,b 属于 bar。没有其他符号表可供参考

以上是我对符号表的假设。请告诉我哪一个是真实案例,并填写可能更多的细节。

谢谢

4

1 回答 1

5

您需要将标识符映射到类型/含义,每个范围实例在源代码中找到,由语言定义。有些人会将这样一个单一的映射称为“符号表”,但我认为这是对该术语的滥用;对于此类单独的范围图,我更喜欢术语“符号空间”。对我来说,范围映射就是符号表。

符号空间/表的概念与编译器创建此类符号空间/表的方式和时间无关。

对于经典的类似 Pascal 的语言,范围恰好以与程序嵌套语法相匹配的方式嵌套(“词法范围”)。对于此类语言,可以以类似堆栈的方式创建符号空间,从上到下(从最低行号到最大行号)处理程序。当遇到每个新的范围边界时,一个新的符号空间被压入堆栈。标识符查找通过搜索当前符号空间(堆栈顶部的符号空间)来进行,如果未找到标识符,则在堆栈的下方搜索符号空间。当一个范围退出时,该符号空间可以被删除(例如,弹出)。此方案仅在编译器单程处理程序时才有效。有时您希望保留所有符号空间以允许在多遍中对程序进行复杂处理;在这种情况下,

许多语言的范围规则根本不适合符号堆栈空间。一个明显的例子是命名空间,它实际上只是可以从程序的广泛分离部分访问的符号空间。

我使用工具基础架构构建了大量需要符号表的语言处理工具(有关该工具的详细信息,请参阅 bio)。大多数情况下,我不使用堆栈样式的符号空间,并且工具基础结构可以直接创建(并在必要时删除)符号空间,并提供一个符号空间和另一个符号空间之间的链接。其中一个链接是一个特殊的词法范围链接,使基础设施能够记录一个符号空间在词法上嵌入另一个符号空间。然后,标准查找方案搜索“当前”范围,如果没有找到匹配的符号,则按照词法范围链接继续搜索。

该方案实际上更聪明一点。每个符号空间都有一个关联的父符号空间链接序列;当在当前范围内找不到符号时,标准词法搜索会(递归地)访问父代。只有一个父链接,这与词法范围相同。使用多个父链接,它可以很好地处理多重继承。命名空间是通过使用“知名”顶级符号空间处理的,其中包含顶级命名空间的符号等。您可以在这个 SO 答案中看到 C++ 的样子:https ://stackoverflow.com/一个/32012786/120163

在访问词法范围链接之前调用自定义操作(“程序附件”);这允许操作决定首先访问任意其他符号空间。特别是,这使得 Java 的符号空间搜索可以从文件系统中获取源/类文件,提取它们的符号,然后根据需要继续搜索。

于 2014-01-05T15:11:16.103 回答