先决条件 –编译器的阶段
符号表是编译器创建和维护的重要数据结构,用于跟踪变量的语义,即它存储有关范围的信息和有关名称的绑定信息,有关各种实体的实例的信息,例如变量和函数名称、类、对象, 等等。
- 它建立在词法和语法分析阶段。
- 该信息由编译器的分析阶段收集,并被编译器的综合阶段用于生成代码。
- 编译器使用它来实现编译时效率。
- 它被编译器的各个阶段使用如下:-
- 词法分析:在表中创建新的表条目,例如关于令牌的条目。
- 语法分析:在表格中添加有关属性类型、范围、维度、参考线、用途等的信息。
- 语义分析:使用表中的可用信息来检查语义,即验证表达式和赋值在语义上是否正确(类型检查)并相应地更新它。
- 中间代码生成:参考符号表以了解分配了多少和什么类型的运行时,表有助于添加临时变量信息。
- 代码优化:使用符号表中存在的信息进行机器相关优化。
- 目标代码生成:使用表中存在的标识符的地址信息生成代码。
符号表条目——符号表中的每个条目都与支持不同阶段编译器的属性相关联。
存储在符号表中的项目:
- 变量名和常量
- 过程和函数名称
- 字面量常量和字符串
- 编译器生成的临时文件
- 源语言中的标签
编译器使用的符号表中的信息:
- 数据类型和名称
- 申报程序
- 存储偏移
- 如果是结构或记录,则指向结构表的指针。
- 对于参数,无论是按值传递还是按引用传递
- 传递给函数的参数的数量和类型
- 基地址
符号表的操作——定义在符号表上的基本操作包括:
符号表的实现——
以下是用于实现符号表的常用数据结构:-
- 列表 –
- 在此方法中,数组用于存储名称和相关信息。
- 在所有存储记录的末尾维护一个“可用”指针,并在新名称到达时按顺序添加
- 为了搜索一个名字,我们从列表的开头开始直到可用的指针,如果没有找到,我们会得到一个错误“使用未声明的名字”
- 插入新名称时,我们必须确保它不存在,否则会出现错误,即“多个定义的名称”
- 插入速度快 O(1),但大表的查找速度很慢——平均 O(n)
- 优点是占用最少的空间。
- 链表——
- 此实现使用链表。每个记录中都会添加一个链接字段。
- 名称的搜索是按照链接字段的链接所指向的顺序进行的。
- 保持一个指针“First”指向符号表的第一条记录。
- 插入速度快 O(1),但大表的查找速度很慢——平均 O(n)
- 哈希表 –
- 在散列方案中,维护了两个表——一个散列表和一个符号表,是实现符号表最常用的方法。
- 哈希表是一个索引范围为:0 到 tablesize – 1 的数组。这些条目是指向符号表名称的指针。
- 为了搜索名称,我们使用哈希函数,该函数将生成 0 到 tablesize – 1 之间的任何整数。
- 插入和查找可以非常快——O(1)。
- 优点是可以快速搜索,缺点是散列实现起来很复杂。
- 二叉搜索树 –
- 另一种实现符号表的方法是使用二叉搜索树,即我们添加两个链接字段,即左子和右子。
- 所有名称都作为根节点的子节点创建,始终遵循二叉搜索树的属性。
- 插入和查找平均为 O(log 2 n)。