gpt4 book ai didi

compiler-construction - 如何在编译器中管理符号表

转载 作者:行者123 更新时间:2023-12-01 11:40:58 25 4
gpt4 key购买 nike

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

例如说我有两种方法

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。没有其他符号表可以引用

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

谢谢

最佳答案

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

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

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

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

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

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

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

关于compiler-construction - 如何在编译器中管理符号表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20934662/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com