编译原理学习笔记 6.4 分程序结构语言的符号表组织
前言
参考课上PPT内容。 该学习笔记目前仅打算个人使用。
后续会进一步整理,包括添加笔记内容,标明参考资料。
更新中。。。
一、分程序的结构语言
模块内可嵌入子模块。
二、标识符的作用域和基本处理方法
作用域
标识符局部于所定义的模块(最小模块)
-
模块中所定义标识符的作用域是定义该标识符的子程序。
- A为内分程序局部变量:
- A为内分程序局部变量:
-
A为内分程序全局变量:
-
都是局部变量:
-
全局变量与局部变量重名:
-
过程或函数说明中定义的标识符(包括形参)其作用域为本过程体。
-
循环语句中定义的标识符,其作用域为该循环语句。
- 不能从循环体外转到循环体内。循环语句应看作一层。
基本处理方法
建查符号表均要遵循标识符作用域规定进行。
- 建表:不能重复,不能遗漏。
- 查表:按标识符作用域查找。
处理方法:
假设标识符是先声明后引用(标号例外,要特殊处理)。
-
在程序声明部分读到标识符时(声明性出现) 建表:
查本层符号表,有无同名
- 有:重复声明,报错
- 无:填入符号表
-
在语句中读到标识符(引用性出现),查表:
查本层符号表,有无同名
- 有:即已声明。则取该名字信息(局部量)。
- 无,是否是最外层?
- 是:未声明标识符。报错
- 否:转到直接外层
-
标准标识符的处理
主要是语言定义的一些标准过程和函数的名字。它们是标识符的子集。
- 如 sin con abs….(注意它们不是语言的保留字)
特点:
- 用户不必声明就可全程使用。
- 设计编译程序时,标准名字及其数目已知。
处理方法:
- 单独建表:使用不便,费时。
- 预先将标准标识符填入名字表中。因为它们是全程量,所以应填入最外层。
分程序符号表的组织方式:
-
分层组织符号表的登记项
各分程序符号表登记项按照语法识别顺序连续排列在一起,不为其内层分程序的符号表登记项所割裂。
-
用“分程序表”索引各分程序符号表的信息
分程序表中的各登记项是自左至右扫描源程序的过程中,按分程序出现的顺序依次填入的,且对每一个分程序填写一个登记项。
分程序表登记项序号隐含地表征各分程序的编号。
分程序表结构:
- OUTERN:指明该分程序的直接外层分程序的编号
- ECOUNT:记录该分程序符号表登记项的个数
- POINTER:指向该分程序符号表的起始位置
例:设有如下分程序
PROCEDURE …
VAR A, B, C, D: REAL;
PROCEDURE …
LABEL L1;
VAR E, F: REAL;
BEGIN
…
END;
PROCEDURE …
LABEL L2, L3;
VAR G, H: REAL;
FUNCTION …
VAR A: INTERGER;
BEGIN
…
END;
BEGIN
…
END;
BEGIN
…
END;
嵌套结构:
分程序表和符号表:
分程序索引表形成顺序:
- 按每个模块头的出现顺序
分程序符号表形成顺序:
- 按每个模块(语法分析时的语法单位)识别顺序
分程序符号表构造方法:
本例中,分程序符号表的形成顺序为2、4、3、1,这个次序是闭分程序的次序(分程序中END出现的次序)。
为使各分程序的符号表连续地邻接在一起,并在扫描具有嵌套分程序结构的源程序时,总是按先进后出的顺序来扫描其中各个分程序,可设一个临时工作栈。
每当进入一层分程序时,就在栈顶预造该分程序的符号表,而当遇到该层分程序的结束符(END)时,此时该分程序的全部登记项已位于栈顶,再将该分程序的全部登记项移至正式符号表中。
例: Pascal程序的分程序结构示例如下
program main (…);
var
x, y : real; i, k: integer;
name: array [1…16] of char;
:
procedure m1 (ind: integer);
var x : integer
procedure p2 (j : real);
:
procedure p3;
var
f : array [1…5] of intrger
test1: boolean;
begin
:
end; {p3}
begin
:
end;{p2}
procedure q2;
var r1,r2 : real;
begin
:
p2(r1+r2);
:
end; {q2}
begin
:
p2(x/y);
:
end;{m1}
begin
:
m1(i+k);
:
end {main}
栈式符号表结构:
编译P3说明部分后的符号栈状态:
编译q2说明部分后:
当过程和函数体编译完成后,应将与之相应的参数名和局部变量名以及后者的特性信息从符号表中删去。
上一篇: 用Construct 2制作飞机小游戏