1.1 作用域检查

1.1.1 作用域规则

PASCAL-S采用最内嵌套的静态作用域规则,即:由一个定义引进的标识符在这个定义所在的作用域里可见,而且在其内部嵌套的每个作用域里也可见,除非它被嵌套于内部的对同名标识符的另一个定义所掩盖。由于PASCAL-S不支持程序的嵌套定义,且变量和常量的定义只能在程序一开始的位置,在复合语句块之前,所以其作用域层次最多只有两层。

1.1.2 重定义检查

在一个标识符被定义时,需要进行重定义检查,包括:主程序头中的主程序名、主程序参数;子程序头中的子程序名、子程序参数;主程序中的变量和常量定义;子程序中的变量和常量定义。
重定义检查中,我们规定了三种无视任何作用域不能与其同名的标识符,即库程序名、主程序名、主程序参数名,也就是说,即使是在子程序中定义的参数、变量等标识符也不能和这三种标识符同名。
下面先介绍几种重定义检查的特殊情况,最后再对重定义的检查范围进行分析。

1.1.2.1 库程序名、主程序名、主程序参数名的重定义检测

地位最高的是库程序名,主程序名和主程序参数名都不能和库程序名同名。
其次是主程序名,所有的主程序参数名除了不能和库程序同名,也不能和主程序名同名。
最后是主程序参数名,除了要求不能和库程序名、主程序名同名,还要求主程序参数名之间不能重名。
其它所有的符号都不能和这三者同名,所以专门设计了一个函数,用于在进行其它重定义检测前,先检测与这三者的同名情况。该函数的介绍在1.7.1.2中。

1.1.2.2 子程序名

首先需要检查是否和库程序名、主程序名、主程序参数名同名。
过程/函数除了拥有自己的子符号表,其本身的头信息都保存在主符号表中,因此在碰到子程序定义时,需检测子程序名是否和主符号表中的已有标识符重命名。

1.1.2.3 子程序内部定义符号

首先需要检查是否和库程序名、主程序名、主程序参数名同名。
子程序内部定义的符号不能和子程序名同名,包括参数、变量、常量定义,这也就解释了为什么需要将子程序名保存在子符号表的第0个位置。

1.1.2.4 检查范围

3.1中已经说明了PASCAL-S所采用的作用域规则,因此,在检测当前定义标识符是否存在重定义的问题时,除了需要检测其是否与库程序名、主程序名、主程序参数名同名,只需要检测其是否与当前符号表内已有的符号重定义即可,无需再返回到外层符号表进行检查。

1.1.3 未定义检查

在一个标识符被引用而非定义时,需要对其进行未定义检查,这是进行进一步的类型检查的前提。
未定义检查不像重定义检查有那么多的特殊情况,只需要从当前符号表检查是否已定义,如果当前符号表无定义,且当前符号表是子符号表,还需返回到外层主符号表进行检查。
另外,需要特别注意循环变量的未定义检查和常量定义右值标识符的未定义检查