📜  编译器中的符号表

📅  最后修改于: 2021-09-27 14:31:04             🧑  作者: Mango

先决条件 –编译器的阶段

符号表是编译器创建和维护的重要数据结构,用于跟踪变量的语义,即它存储有关范围的信息和有关名称的绑定信息,有关各种实体的实例的信息,例如变量和函数名称、类、对象, 等等。

  • 它建立在词法和语法分析阶段。
  • 该信息由编译器的分析阶段收集,并被编译器的综合阶段用于生成代码。
  • 编译器使用它来实现编译时效率。
  • 它被编译器的各个阶段使用如下:-
    1. 词法分析:在表中创建新的表条目,例如关于令牌的条目。
    2. 语法分析:在表格中添加有关属性类型、范围、维度、参考线、用途等的信息。
    3. 语义分析:使用表中的可用信息来检查语义,即验证表达式和赋值在语义上是否正确(类型检查)并相应地更新它。
    4. 中间代码生成:参考符号表以了解分配了多少和什么类型的运行时,表有助于添加临时变量信息。
    5. 代码优化:使用符号表中存在的信息进行机器相关优化。
    6. 目标代码生成:使用表中存在的标识符的地址信息生成代码。

符号表条目——符号表中的每个条目都与支持不同阶段编译器的属性相关联。
存储在符号表中的项目:

  • 变量名和常量
  • 过程和函数名称
  • 字面量常量和字符串
  • 编译器生成的临时文件
  • 源语言中的标签

编译器使用的符号表中的信息:

  • 数据类型和名称
  • 申报程序
  • 存储偏移
  • 如果是结构或记录,则指向结构表的指针。
  • 对于参数,无论是按值传递还是按引用传递
  • 传递给函数的参数的数量和类型
  • 基地址

符号表的操作——定义在符号表上的基本操作包括:

符号表的实现——
以下是用于实现符号表的常用数据结构:-

  1. 列表 –
    • 在此方法中,数组用于存储名称和相关信息。
    • 在所有存储记录的末尾维护一个“可用”指针,并在新名称到达时按顺序添加
    • 为了搜索一个名字,我们从列表的开头开始直到可用的指针,如果没有找到,我们会得到一个错误“使用未声明的名字”
    • 插入新名称时,我们必须确保它不存在,否则会出现错误,即“多个定义的名称”
    • 插入速度快 O(1),但大表的查找速度很慢——平均 O(n)
    • 优点是占用最少的空间。
  2. 链表——
    • 此实现使用链表。每个记录中都会添加一个链接字段。
    • 名称的搜索是按照链接字段的链接所指向的顺序进行的。
    • 保持一个指针“First”指向符号表的第一条记录。
    • 插入速度快 O(1),但大表的查找速度很慢——平均 O(n)
  3. 哈希表 –
    • 在散列方案中,维护了两个表——一个散列表和一个符号表,是实现符号表最常用的方法。
    • 哈希表是一个索引范围为:0 到 tablesize – 1 的数组。这些条目是指向符号表名称的指针。
    • 为了搜索名称,我们使用哈希函数,该函数将生成 0 到 tablesize – 1 之间的任何整数。
    • 插入和查找可以非常快——O(1)。
    • 优点是可以快速搜索,缺点是散列实现起来很复杂。
  4. 二叉搜索树 –
    • 另一种实现符号表的方法是使用二叉搜索树,即我们添加两个链接字段,即左子和右子。
    • 所有名称都作为根节点的子节点创建,始终遵循二叉搜索树的属性。
    • 插入和查找平均为 O(log 2 n)。