Dan*_*iel 3 compiler-construction symbol-table
我想知道是否只有一个符号表存储有关源文件的所有信息,还是有多个符号表相互堆叠,并且仅在当前作用域与该表相关时才获取。
例如说我有两种方法
int foo(int a){
int b;
bar(b);
...
}
double bar (int a){
int b;
...
}
Run Code Online (Sandbox Code Playgroud)
这里两个中的a和b的作用域不同,因此,如果符号表堆叠在一起,则在执行foo时会首先获取与foo相关的符号表。但是,在执行bar时,bar的符号表堆叠在foo的上面,因此当前符号表包含bar的a和b的信息。
如果符号表是集中式的,则foo的信息和bar的信息都驻留在一个符号表中,但是可能有一些条目指定foo中的a,b属于foo的范围,而bar中的a,b属于bar。没有其他符号表可参考
以上是我对符号表的假设。请告诉我哪一个是真实的案例,并在其中填入更多详细信息。
谢谢
根据语言定义,您需要在源代码中找到的每个作用域实例的标识符映射到类型/含义。有些人将单个这样的单个映射称为“符号表”,但是我认为这是对术语的滥用。对于这样的单个作用域图,我更喜欢术语“符号空间”。对我来说,一组范围映射的是符号表。
符号空间/表的概念与编译器创建此类符号空间/表的方式和时间无关。
对于类似Pascal的经典语言,范围发生嵌套的方式与程序嵌套语法(“词法作用域”)相匹配。对于此类语言,可以以类似堆栈的方式创建符号空间,从上到下(最低行号到最大行号)处理程序。遇到每个新的作用域边界时,都会将新的符号空间压入堆栈。通过搜索当前符号空间(堆栈顶部的那个)来进行标识符查找,如果找不到标识符,则在堆栈的更下方搜索符号空间。当退出作用域时,可以删除(例如弹出)该符号空间。仅当编译器单次处理程序时,此方案才有效。有时您想保留所有符号空间,以允许多次处理程序。在这种情况下,
许多语言的作用域规则根本不适合符号堆栈空间。一个明显的例子是名称空间,它实际上只是符号空间,可从程序的广泛分离的部分进行访问。
我使用工具基础结构构建了许多需要符号表的语言处理工具(有关该工具的详细信息,请参见bio)。通常,我不使用符号样式的堆栈样式,该工具基础结构使创建(并在必要时删除)符号空间变得很简单,并提供了一个符号空间与另一个符号空间之间的链接。这些链接之一是特殊的词法范围链接,使基础结构能够记录一个符号空间在词法上嵌入另一个符号空间。然后,标准的搜索方案搜索“当前”范围,如果找不到匹配的符号,则遵循词法范围链接以继续搜索。
该方案实际上更聪明。每个符号空间都有一个关联的父符号空间链接序列;当在当前作用域中未找到符号时,标准词汇搜索(递归)访问父级。仅具有一个父链接,这与词法作用域相同。通过多个父链接,它可以很好地处理多个继承。命名空间是通过使用“知名”顶级符号空间来处理的,其中包含顶级命名空间的符号等。您可以在以下SO答案中看到C ++的外观:https : //stackoverflow.com/ a / 32012786/120163
在访问词汇表作用域链接之前,将调用自定义操作(“过程附件”)。这使操作可以决定首先访问任意其他符号空间。特别是,这使得Java的符号空间搜索有可能从文件系统中获取源/类文件,提取其符号,然后根据需要继续搜索。