资源描述
第第9章章 符号表符号表9.1符号表的作用和位置9.2符号的主要属性及作用9.3符号表的组织9.4 符号表的管理符号表的作用和位置符号表的作用和位置:搜集符号属性搜集符号属性 上下文语义的合法性检查的根据上下文语义的合法性检查的根据 作为目的代码生成阶段地址分配的作为目的代码生成阶段地址分配的根据根据 9.19.1符号表的作用和位置符号表的作用和位置 搜集符号属性 编译程序扫描阐明部分搜集有关标识符的属性,并在符号表中建立符号的相应属性信息。例如,编译程序分析到下述两个阐明语句int A;float B5;那么在符号表中搜集到关于符号A的属性是一个整型变量,关于符号B的属性是具有5个浮点型元素的一维数组。上下文语义的合法性检查的根据:在语义分析中,符号表所登记的内容将用于语义检查如检查一个名字的运用和原先的阐明能否一致和产生中间代码。经过符号表中属性记录可进展相应上下文的语义检查。例如,在一个C言语程序中出现int i 35;/定义整型数组ifloat i42;/定义实型数组i,重定义冲突int i 35;/定义整型数组i,重定义冲突 编译过程首先在符号表中记录了标识符i的属性是35个整型元素的数组,而后在分析第二、第三这两个定义阐明时编译系统可经过符号表检查出标识符i的二次重定义冲突错误。本例还可以看到不论在后二句中i的其它属性与前一句能否完全一样,只需标识符名重定义,就将产生重定义冲突的语义错误。在目的代码生成阶段,当对符号名进展地址分配时,在目的代码生成阶段,当对符号名进展地址分配时,符号表是地址分配的根据。符号表是地址分配的根据。作为目的代码生成阶段地址分配的根据一张符号表的的组成:包括两项,即名字栏和信息栏。信息栏包含许多子栏和标志位,用来记录相应名字和种种不同属性,名字栏也称主栏。主栏的内容称为关键字key word。名字栏(NAME)信息栏(INFORMATION)在整个编译期间,对于符号表的操作大致可归纳为五类:对给定名字,查询名字能否已在表中;往表中填入一个新的名字;对给定名字,访问它的某些信息;对给定名字,填写或更新它的某些信息;删除一个或一组无用的项。上述五个方面只是一些根本的共同操作。符号表的主要属性符号表的主要属性(信息信息几种通常都是需求的。几种通常都是需求的。1 名字名字2 类型类型 3 存储类别存储类别 4 作用域及可视性作用域及可视性 5 存储分配信息存储分配信息 6 其它属性其它属性 数组内情向量数组内情向量 记录构外型的成员信息记录构外型的成员信息 函数及过程的形参函数及过程的形参 9.2符号的主要属性及作用符号的主要属性及作用 符号名 符号表中设置一个符号名域,存放该标识符,该域通常就是符号表的关键字域。符号的类型 标识符中除过程标识符之外,函数和变量标识符都具有数据类型data type属性。对于函数的数据类型指的是该函数值的数据类型。根本数据类型有整型、实型、字符型、逻辑型布尔型及位组型等,符号的类型属性是在该符号的定义时得到。变量符号的类型属性决议了该变量的数据在存储空间的存储格式,还决议了在该变量上可以施加的运算操作。符号的存储类别 大多数言语对变量的存储类别定义采用二种方式。一种是用关键字指定:例如在C言语中用Static定义是属于文件的静态存储变量或属于函数内部的静态存储变量,用regist定义运用存放器存储的变量。另一种方式是根据变量阐明在程序中的位置来决议:例如在C言语中,在函数体外缺省存储类关键字所定义的变量是外部变量,即程序的公共存储变量,而在函数体内缺省存储类关键字所定义的变量是内部变量,即属于该函数所独有的私有存储变量 符号的作用域及可视性 一个符号变量在程序中起作用的范围,称谓它的作用域。普通来说,定义该符号的位置及存储类关键字决议了该符号的作用域。C言语中一个外部变量的作用域是整个程序,因此一个外部变量符号的定义在整个程序中只能出现一次。普通来说一个变量的作用域就是该变量可以出现的场所,这就是变量可视性的作用域规那么。但是变量可视性不仅仅取决于它的作用域,还有两种情况影响到一个变量的可视性。函数的方式参数:影响变量可视性的举例函数的方式参数:影响变量可视性的举例int a;/外部定义的整型变量外部定义的整型变量aint func(a,b)float a;/函数内部定义的部分整型变量函数内部定义的部分整型变量a,屏闭了外部定义的整型变量屏闭了外部定义的整型变量aint b;a/援用的是函数内部定义援用的是函数内部定义(此处是形参此处是形参)的部分整型变量的部分整型变量a 函数的方式参数可以和该函数外层定义的变量包括外部变量重名,这时两个函数的方式参数可以和该函数外层定义的变量包括外部变量重名,这时两个重名的变量其类型定义可以是完全不同的。重名的变量其类型定义可以是完全不同的。分程序或复合语句构造:分程序或复合语句构造:影响变量可视性的举例影响变量可视性的举例int aint a;/第一层头第一层头,定义的部分整型变量定义的部分整型变量a achar achar a;/第二层头第二层头,定义的部分字符型变量定义的部分字符型变量a a/第三层头第三层头float afloat a;/第四层头第四层头,定义的部分实型变量定义的部分实型变量a a/第四层尾第四层尾a/a/援用第二层定义的部分字符型变量援用第二层定义的部分字符型变量a a/第三层尾第三层尾/第二层尾第二层尾/第一层尾第一层尾 图中第三层所援用的图中第三层所援用的a a,既不是第四层的,既不是第四层的float afloat a;也不是第一层;也不是第一层int aint a;而;而是第二层是第二层char achar a;也就可以说从第三层向外,看到的第一个定义;也就可以说从第三层向外,看到的第一个定义a a的变量定义即的变量定义即char achar a。为确立符号的作用域和可视性。符号表属性中除了需求符号的存储类别之外还需为确立符号的作用域和可视性。符号表属性中除了需求符号的存储类别之外还需求表示该符号在程序构造上被定义的层次。符号表中设置一个表达符号所在层次求表示该符号在程序构造上被定义的层次。符号表中设置一个表达符号所在层次的属性域,存放该符号的定义层次。普通来说,假设把外部变量视为的属性域,存放该符号的定义层次。普通来说,假设把外部变量视为0 0层的话,层的话,那么函数内部作为第那么函数内部作为第1 1层,依次向内嵌套定义的分程序分别为层,依次向内嵌套定义的分程序分别为2 2,3 3,层。层。符号变量的存储分配信息 通常一个编译程序有两类存储区,即静态存储区和动态存储区;静态存储区 该存储区单元经定义分配后成为静态单元,即在整个言语程序运转过程中是不可改动的。作静态分配的符号变量是具有整个程序运转过程的生命周期。因此编译程序可以设置一个固定的空间作为静态存储区。但由于不同的静态变量具有不同的可视性,编译程序也可以设置几个不同的固定空间作为静态区。根据变量存储类别及作用域规那么,这类静态存储区通常又可分为公共静态区和假设干个部分静态区。一个言语程序中的公共变量或称外部变量是被指定分配到该公共静态存储区中。例Pascal或C言语中的外部量就属于这类共静态存储区的分配。在公共静态区中的变量具有的生命周期是该程序运转的全过程,且其作用域亦是整个言语程序留意:当它被同名部分量屏蔽时,该变量成为不可视的。动态存储区 根据变量的部分定义和分程序构造,编译程序设置动态存储区来顺应这些部分变量的生存和消亡。部分动态变量的生存期是定义该变量的部分范围,即在该定义范围之外此变量曾经没存在的必要。及时撤销时这些单元的分配可以回收,从而提高程序运转时的空间效率。符号的其它属性符号的其它属性 数组内情向量数组内情向量 内情向量包括数组类型,维数,各维的上、下界及数组首地址,这内情向量包括数组类型,维数,各维的上、下界及数组首地址,这些属性信息是确定存储分配时数组所占空间的大小和数组元素位置些属性信息是确定存储分配时数组所占空间的大小和数组元素位置的根据。的根据。记录构外型的成员信息记录构外型的成员信息 一个记录构外型的变量,在存储分配时所占空间大小要由它的全体一个记录构外型的变量,在存储分配时所占空间大小要由它的全体组成成员来确定,另外对于记录构外型变量还需求有它所属成员陈组成成员来确定,另外对于记录构外型变量还需求有它所属成员陈列次序的属性信息。列次序的属性信息。函数及过程的形参函数及过程的形参 每个函数或过程的形参个数、形参的陈列次序及每个形参的类型,每个函数或过程的形参个数、形参的陈列次序及每个形参的类型,都表达了调用该函数或过程时的属性,它们都应该反映在符号表的都表达了调用该函数或过程时的属性,它们都应该反映在符号表的函数或过程标识符的项中。函数或过程标识符的项中。9.3 9.3 符号表的组织符号表的组织总体组织和表项属性信息组织总体组织和表项属性信息组织 P197P197198198页的图页的图第一种:第一种:把属性种类完全一样的那些符号组织在把属性种类完全一样的那些符号组织在一同,构造出表项是分别为等长的多个符号表一同,构造出表项是分别为等长的多个符号表 第二种:第二种:把一切言语中的符号都组织在一张符号把一切言语中的符号都组织在一张符号表中。组成一张包括了一切属性的庞大的符号表表中。组成一张包括了一切属性的庞大的符号表 第三种折衷方式是根据符号属性类似程度分类组织第三种折衷方式是根据符号属性类似程度分类组织成假设干张表,每张表中记录的符号都有比较多成假设干张表,每张表中记录的符号都有比较多的一样属性。的一样属性。9.3.1 9.3.1 符号表的总体组织符号表的总体组织编译程序按名字的不同种属分别运用许多符号表,如常数表、变量名表、过程名表等等。9.3.2 符号表项的陈列符号表项的陈列符号表作为一个多元组,表中元组的陈列组符号表作为一个多元组,表中元组的陈列组织是构造符号表的重要成分。在编译程序织是构造符号表的重要成分。在编译程序的整个任务过程中,符号表被频繁地用来的整个任务过程中,符号表被频繁地用来建立表项,找查表项,填充和援用表项的建立表项,找查表项,填充和援用表项的属性。因此表项的陈列组织对该系统运转属性。因此表项的陈列组织对该系统运转的效率起着非常重要的作用。在编译程序的效率起着非常重要的作用。在编译程序中,符号表项的组织传统上采用三种构造中,符号表项的组织传统上采用三种构造方法。即线性法,二分法及散列法。方法。即线性法,二分法及散列法。线性组织 这种方法规定符号表中表项按它的符号被扫描到的先后顺序登录。例如有一程序中出现符号的情况如下:a/第一次出现a的地方b/第一次出现b的地方a/第二次出现a的地方d/第一次出现d的地方c/第一次出现c的地方b/第二次出现b的地方那么符号表中表项陈列将如下图:其中h表示该符号表之表头,是表的开场位置,p表示该符号表的表项是符号表当前的终了位置。排序组织及二分法 言语中的每一个符号,排序组织的符号表,就是在符号表中的表项按其符号的字符代码串可以看成一个整数值的值的大小从大到小或从小到大陈列的。对上述例子中的符号出现情况按排序组织得到的符号表将如下图:编译扫描的次序是a,b,d,c。由于c代码小于d代码,因此c应在d表项之前。关于排序表的表项建立及符号查找,通常采用二分法。散列组织 一个符号在散列表中的位置,是由对该符号即字符代码串进展某种函数操作通常称为杂凑函数所得到的函数值来确定的。所得到的函数值与该表项在表中位置的对应关系,是经过对函数值的求整以及相对于表长的求余得到的。符号表的散列组织相对来说具有较高的运转效率,因此绝大多数编译程序中的符号表采用散列组织。但是经过杂凑运算后,就有能够得到一样的杂凑值,这种不同符号散列到同一表项位置的景象,我们称它为散列冲突。大多数编译程序中,处理冲突采用的多次散列方法如下。从冲突点位置向下寻觅空表项,找到的第一个空表项即为发生冲突的符号所散列的位置。如假设不断到表底,没有找到空表项,那么循环从表头开场寻觅空表项,如假设不断到冲突点仍设有空表项,那么阐明该言语程序中的符号太多,符号表已不能包容全部符号登入,这时编译程序将发出符号表溢出的系统出错音讯。9.3.3 关键字域的组织关键字域的组织符号表的关键字域段就是符号称号符号表的关键字域段就是符号称号 等长关键字域段符号表等长关键字域段符号表 不等长关键字段符号表不等长关键字段符号表-采用关键字池的采用关键字池的索引构造。索引构造。为使得符号表中存放标识符的关键字段等长,可设置关键字段为标识符的最大长度。譬如上述C言语的关键字段长度可以是32个,图示如下。等长关键字域段符号表等长关键字域段符号表由于程序中的标识符长短不一,有时能够差别很大,用等长构造会产生溢出或冗余。不等长关键字段符号表不等长关键字段符号表-采用关键字池的采用关键字池的索引构造。索引构造。例如我们有一组标识符anexemplerof key-wrdsfield关键字段的组织构造如图。在此构造中,关键字池可以是一个字符数组,也可以是一个字符串空间。假设关键字池是字符数组时,符号表中关键字段可以是一个整型数值段,整型值表示该关键字在池中位置的下标。假设关键字是一个字符串,那么符号表中关键字段可以是一个指向字符的指针,指针指向该关键字在池中的位置。P是指向池的空区。9.3.4 9.3.4 其它域的组织其它域的组织符号表属性域的组织,根据属性性质大致分成两类:符号表属性域的组织,根据属性性质大致分成两类:1 1、等长属性值域组织、等长属性值域组织 可以取相应的数据类型表达属性可以取相应的数据类型表达属性值。值。defined1表示已定义defined0表示尚未定义或definedtrue表示已定义definedfalse表示尚未定义1表示该符号布尔性质的属性域,可用1个bit位来表示;也 可用1个布尔量来表示。如2表示符号的数据类型可以用假设干个bit位来表示;也可用1个整型量来表示C言语为例data-type 3个bit位Char000Short001int010long011unsigned100float101double110data-type整型值char0short1int2long3unsiqned4float5double6或有一些是表示符号之间关系的属性,可用指针或指针链来构造这些属性域。有一些是表示符号之间关系的属性,可用指针或指针链来构造这些属性域。如函数符号与它的形参符号之间就需求建立关系,可以在符号表中设置一个如函数符号与它的形参符号之间就需求建立关系,可以在符号表中设置一个“函数函数-形参指针域。形参指针域。对函数符号:在该属性域中存放指向该函数第一个形参的符号所在符号表中对函数符号:在该属性域中存放指向该函数第一个形参的符号所在符号表中位置的指针。位置的指针。而对方式参数符号:在该属性域中存放指向它的下一个方式参数符号所在符而对方式参数符号:在该属性域中存放指向它的下一个方式参数符号所在符号表中的位置的指针。号表中的位置的指针。假设一个函数是无参的,那么该参数符号项中假设一个函数是无参的,那么该参数符号项中“函数函数形参指针域值为形参指针域值为“空。空。假设某个方式参数是它所属函数的最后一个方式参数,那么该形参符号项中假设某个方式参数是它所属函数的最后一个方式参数,那么该形参符号项中“函数函数形参指针域值亦为形参指针域值亦为“空。空。举例如下:有函数举例如下:有函数func1(para1,para2,para3)func1(para1,para2,para3)func2()func2()C C言语的构造量中构造标志与成员之间也有上述函数与形参之间的类似言语的构造量中构造标志与成员之间也有上述函数与形参之间的类似关系,也可以在符号表中设立一个关系,也可以在符号表中设立一个“构造构造-成员指针域。成员指针域。对于构造标志符号:在该属性域中存放指向该构造第一个成员的符号在对于构造标志符号:在该属性域中存放指向该构造第一个成员的符号在符号表中的位置的指针,符号表中的位置的指针,而对于成员符号:在该属性域中存放指向它的下一个成员的符号在符号而对于成员符号:在该属性域中存放指向它的下一个成员的符号在符号表中位置的指针。表中位置的指针。假设某个成员是一个构造量的最后一个成员:那么该成员符号项中假设某个成员是一个构造量的最后一个成员:那么该成员符号项中 构构呵斥员呵斥员 属性域值为空。属性域值为空。struct tag1 memb1;/第一层构造定义,tag1的第一个成员 memb2;/tag1的第二个成员 struct tag2 memb3;/第二层构造定义,/tag2的第一个成员 memb4;/tag2的第二个成员 memb5;/tag2的第n个成员 memb6;/tag1的第三个成员 memb7;stv;/tag1的第m个成员 2、不等长属性值域的组织 符号的某些属性值是不等长的,例如数组内情向量属性值是典型的不等长属性值。对于不等长属性值的属性域,普通不把一切属性值都存放在符号表项的某个域内,而另设相关空间存放属性值。一个数组的内情向量属性可分成两种值,数组维数的个数及每维的元素个数。设有以下两个数组array1(subscrip1,subscrip2)array2(subscrip3,subscrip4,subscrip5,subscrip6)数组符号在符号表项中可以设立一个指向内情向量空间的指针,而在内情向量空间记录关于该数组的维数个数和每一维的元素个数,下页图表示了array1及array2两个数组在符号表中内情向量的组织。内情向量空间最后一行0值用来表示下标到此为止,9.3.59.3.5下推链域的组织下推链域的组织为了实现这种同名标识符的语义功能,符号表中需设立一为了实现这种同名标识符的语义功能,符号表中需设立一个下推链域组织。个下推链域组织。例:有一个C程序:int i;.(1).func()(2)float i;.(3).(4)int i5;5 .(6)int i;(7)i(8).i(9)下推链域要求下推链域要求:在进入内层在进入内层构造并发生重名标识符定构造并发生重名标识符定义时,需把当前符号中外义时,需把当前符号中外层的该符号下推到下推链层的该符号下推到下推链中,而在符号表被下推的中,而在符号表被下推的表项处,建立内层的同名表项处,建立内层的同名标识符表项。标识符表项。9.4 9.4 符号表的管理符号表的管理在编译程序任务过程中,符号表所起的作用在编译程序任务过程中,符号表所起的作用反映了符号表的行为特征,符号表的行为通常主反映了符号表的行为特征,符号表的行为通常主要是符号表的初始化、符号的登录、符号的查找要是符号表的初始化、符号的登录、符号的查找和有关分程序构造的符号表层次管理。对符号表和有关分程序构造的符号表层次管理。对符号表的这些管理除初始化之外,都是动态进展的。的这些管理除初始化之外,都是动态进展的。1 1、符号表的初始化、符号表的初始化表符号的初始化,就是在对言语程序开场编译的表符号的初始化,就是在对言语程序开场编译的时辰,定义建立符号表的初始形状。符号表的不同组时辰,定义建立符号表的初始形状。符号表的不同组织方法,要求不同的初始化方法。通常有以下两种情织方法,要求不同的初始化方法。通常有以下两种情况:况:符号表的表长是渐增变化的情况 线性组织和二分法组织的符号表,其表的长度反映已登录表项个数,在编译开场时通常为0,而随着符号的逐渐登录,表长增长。按这类方法组织的符号表,其初始化方法只需将表尾推向表头即可。渐增符号表初态 符号表的表长是确定的情况 例:散列组织的符号表,其表长通常是确定的,这时的表长并不反映已登录的表项个数,能否已有表项登录是取决于该符号表中能否存在已有表项值的表项。因此对这类符号表的初始化方法,需求将表中全部表项值去除。定长符号表初态 2 2 符号的登录符号的登录当编译程序从言语程序中获得一个标识符符号并确定当编译程序从言语程序中获得一个标识符符号并确定该符号在符号表中尚不存在时,就要将此符号登录到符号该符号在符号表中尚不存在时,就要将此符号登录到符号表中。表中。登录符号到符号表中,首先要确定登录的位置。但对于线性方法组织的符号表,首先要在符号表中创建一个新的表项,通常该表的尾指针指向的表项是作为新创建的表项,而尾指针向下一个备用表项。对于线性组织的符号表,该新创建的表项就是登录符号的表项。线性符号表登录前后 对于二分法组织的符号表,在创建了新的表项后,根据登录符号在符号表中按词典排序所确定的位置,把该位置以后的一切原表项下移一个表项的位置,然后在选定位置登录新符号。排序符号表登录前后对于散列表,新符号的登录是经过杂凑算法决议登录表项的位置。3 3、符号的查找、符号的查找每当编译程序从言语源程序获得一个符号,首先要确定该每当编译程序从言语源程序获得一个符号,首先要确定该符号的类别。根据类别分别在相应的符号表中进展查找。符号的类别。根据类别分别在相应的符号表中进展查找。通常先在保管字表和运算符表中查找该符号能否保管字或运算符。假设通常先在保管字表和运算符表中查找该符号能否保管字或运算符。假设是,那么相应地把该符号转换为保管字或运算符的内部代码。假设不是,是,那么相应地把该符号转换为保管字或运算符的内部代码。假设不是,那么再在标识符表中进展查找。假设在标识符表中查到同名符号,那么那么再在标识符表中进展查找。假设在标识符表中查到同名符号,那么表示该符号已在符号表中登录,假设查不到,那么表示该符号是一个新表示该符号已在符号表中登录,假设查不到,那么表示该符号是一个新的需求登录的符号。的需求登录的符号。查找符号表的目的查找符号表的目的:是建立或确认该符号的语义属性。是建立或确认该符号的语义属性。(1)(1)对查到的符号来说,可获得该符号已登录的语义属性,从而对查到的符号来说,可获得该符号已登录的语义属性,从而进展语义上下文的检查,进展语义上下文的检查,(2)(2)在有些情况下登录该符号的新的属性内容在有些情况下登录该符号的新的属性内容(3)(3)对没查到的符号,那么进展符号及其属性的登录。对没查到的符号,那么进展符号及其属性的登录。符号表中分程序构造层次的管理符号表中分程序构造层次的管理对于具有分程序型构造的言语程序,不同层次分程序中定义的标识符号具有不同的作用域和不同的可视性规那么。通常对于具有分程序构造的言语可用两种方式组织它们的符号表:一是对每个分程序建立一个独立的分表构造的符号表;一是把各分程序符号组织在一张单表构造的符号表中。下面给出了一个分程序构造的例子。源程序的方式/第一层分程序int a;float b,d;/第二层分程序int c;float a;/第三层分程序int d;float c;/第四层分程序float d;a=b+c+d;(1)(1)分表构造分表构造分表构造的组织管理,其根本思想是,每当编译程序扫描到一分表构造的组织管理,其根本思想是,每当编译程序扫描到一个分程序构造开场时,为该分程序建立一张符号表,在该分程序中个分程序构造开场时,为该分程序建立一张符号表,在该分程序中定义的标识符,都被登录在该符号表中。而当编译程序扫描到一个定义的标识符,都被登录在该符号表中。而当编译程序扫描到一个分程序的终了时,编译程序释放为该分程序所建立的符号表。这种分程序的终了时,编译程序释放为该分程序所建立的符号表。这种符号表的分表构造与源程序的分程序层次构造是完全一致的,这种符号表的分表构造与源程序的分程序层次构造是完全一致的,这种层次构造是编译过程中动态建立和动态消亡的。层次构造是编译过程中动态建立和动态消亡的。分程序构造的分表组织 根据分程序作用域和可视规那么。符号的查找是首先在该分程序符号表中进展;假设没有查到,再根据分程序的层次构造,逐层向外地依次查找各层符号表。不断到查到为止。第四层分程序的表达式a=b+c+d中a是第二层定义的float a,b是第一层定义的float b,c是第三层定义的float c,d是第四层定义的float d。(2)(2)单表构造单表构造单表构造的组织管理其根本思想是,一切分程序中定单表构造的组织管理其根本思想是,一切分程序中定义的标识符都集中在单张符号表中。为了实现分程序构造义的标识符都集中在单张符号表中。为了实现分程序构造中标识符的作用域和可视性规那么的要求。在这种单表组中标识符的作用域和可视性规那么的要求。在这种单表组织的符号表中,由于分层的分程序构造,因此需求强调三织的符号表中,由于分层的分程序构造,因此需求强调三个主要的特定要求。个主要的特定要求。首先,为了标志一个符号所属的分程序层次,在符号表中可设立一个属首先,为了标志一个符号所属的分程序层次,在符号表中可设立一个属性域用来登录符号所在分程序的层次。性域用来登录符号所在分程序的层次。其次,进入分程序时,层次要添加一层其次,进入分程序时,层次要添加一层.在退出一个分程序时,层次降低在退出一个分程序时,层次降低一层,且需求把符号表中,一切在退出的分程序中登录的符号项去除。一层,且需求把符号表中,一切在退出的分程序中登录的符号项去除。最后,对于具有分程序构造的源程序,在不同的分程序中最后,对于具有分程序构造的源程序,在不同的分程序中(指嵌套的分程指嵌套的分程序中序中)允许定义重名的标识符,在单表构造下,重名标识符可用下推链来允许定义重名的标识符,在单表构造下,重名标识符可用下推链来组织组织进入分程序第一层时的符号表层次属性表达 进入分程序第二层时的符号表层次属性表达 进入分程序第三层时的符号表层次属性表达 进入分程序第四层时的符号表层次属性表达 阐明部分的分析与处置阐明部分的分析与处置n对每个过程阐明的对象变量,常量和过程造名字表对每个过程阐明的对象变量,常量和过程造名字表n填写标识符的所在层次、属性和分配的相对位置。标识符的填写标识符的所在层次、属性和分配的相对位置。标识符的属性不同时,所需填入的信息也不同。登录信息由属性不同时,所需填入的信息也不同。登录信息由ENTERENTER过过程完成。程完成。阐明部分的分析与处置程序阐明部分的分析与处置程序n阐明类型的定义:n object=(constant,variable,procedur)n 定义纯量/枚举类型P413n名字表的定义 P414)n table:array0.txmax of recordn name:alfa;n case kind:object ofn constant:(val:integer);n variable:procedur:(level,adr,size:integer);N NA AM ME E:A A N NA AM ME E:B B N NA AM ME E:C C N NA AM ME E:D D N NA AM ME E:E E N NA AM ME E:P P K KI IN ND D:C CO ON NS ST TA AN NT T K KI IN ND D:C CO ON NS ST TA AN NT T K KI IN ND D:V VA AR RI IA AB BL LE E K KI IN ND D:V VA AR RI IA AB BL LE E K KI IN ND D:V VA AR RI IA AB BL LE E K KI IN ND D:P PR RO OC CE ED DU UR R V VA AL L:3 35 5 V VA AL L:4 49 9 L LE EV VE EL L:L LE EV V L LE EV VE EL L:L LE EV V L LE EV VE EL L:L LE EV V L LE EV VE EL L:L LE EV V A AD DR R:D DX X A AD DR R:D DX X+1 1 A AD DR R:D DX X+2 2 A AD DR R:过过程程的的入入口口(待待填填)S SI IZ ZE E:4 4 N NA AM ME E:G G K KI IN ND D:V VA AR RI IA AB BL LE E L LE EV VE EL L:L LE EV V+1 1 A AD DR R:D DX X 例程序阐明部分为:例程序阐明部分为:CONST A=35CONST A=35,B=49B=49;VAR CVAR C,D D,E E;PROCEDURE PPROCEDURE P;VAR G VAR G;名字名字 类型类型 层次层次/值值 地址地址 存储空间存储空间Const常量无层次对应名字表对应名字表主函数中调用block函数。Block函数定义见P417Block的过程体见P424例如:对变量定义的语法处置语法::=var,;程序:(P424)if sym=varsym thenbegingetsym;repeatvardeclaration;(*变量阐明处置*)while sym=comma dobegingetsym;vardeclarationend;if sym=semicolon thengetsymelse error(5)until symident;end;变量阐明处置程序:(P 418)Procedure vardeclaration;beginif sym=ident thenbeginenter(variable);(*调用过程enter造名字表*getsymendelse error(4)end(*vardeclaration*);过程ENTER的实现程序:(P417)tx:table表的指针procedure enter(k:object);begin(*enter object into table*)tx:=tx+1;with tabletx do(*开域语句*beginname:=id;(*表示tabletx.name:=id;名字记录在table表中*kind:=k;(*表示tabletx.kind:=k;类型记录在table表中*)case k ofconstant:beginif numamax thenbeginerror(31);num:=0;end;val:=num;(*tabletx.val:=num;常量的值记录在table表中*)end;variable:beginlevel:=lev;*表示tabletx.level:=lev变量定义的所在层次记录 在table表中*adr:=dx;*表示tabletx.adr:=dx给变量分配的位置记录在table表中*dx:=dx+1;*给变量分配位置的指示器加1,指向下一个变量的位置*end;procedur:level:=lev;(*表示tabletx.level:=lev;过程定义的所在层次记录在table表中*end(*case*);endend(*enter*);PL/0编译程序编译程序nTable表的下标指针tx补充阐明:主程序主程序BLOCK第第1次调用次调用blockBLOCK0,0,0 0 .BLOCK BLOCKLEV+1,TX,(递归进入分程序递归进入分程序)LEVtxLEVtx66 91 tx是是BLOCK的的实践值参实践值参
展开阅读全文