5.9说明语句的翻译 ● 说明语句的作用是指明被说明的量的一些 具体属性,如类型、种属、存储分配特点及 其它属性等等。 。¥ 编译程序对说明语句进行处理的主要任务 是把有关属性填入符号表相应登记项中。 说明语句主要有变量定义(也称美型说明)语 句、数组说明语句及类型定义语句等
5.9 说明语句的翻译 • 说明语句的作用是指明被说明的量的一些 具体属性,如类型、种属、存储分配特点及 其它属性等等。 • 编译程序对说明语句进行处理的主要任务 是把有关属性填入符号表相应登记项中。 • 说明语句主要有变量定义(也称类型说明)语 句、数组说明语句及类型定义语句等
5.9.1美型说明语句的翻译 美型说明语句的常见形式为 其中,类型名可以是程序设计语言提供的简单数据类型 名(如integer、.real、boolean等)或是程序员自 己定义的数据类型(如结构、联合类型等)的名字。 变量名表是以逗号隔开的变量或数组名。为了叙述方便, 我们假定简单类型名只有int、real、boolean三种 (其它简单类型的处理与其类似),而自定义数据类型名 的处理将在5.9.2节中讨论。 我们假定数组名具有形式name[l:u1,l22,…3 nun],其中,,山(=1,2,.,n)为整型常数,且满足I <Uj
5.9.1 类型说明语句的翻译 类型说明语句的常见形式为 其中,类型名可以是程序设计语言提供的简单数据类型 名(如integer、real、boolean等)或是程序员自 己定义的数据类型(如结构、联合类型等)的名字。 变量名表是以逗号隔开的变量或数组名。为了叙述方便, 我们假定简单类型名只有int、real、boolean三种 (其它简单类型的处理与其类似),而自定义数据类型名 的处理将在5.9.2节中讨论。 我们假定数组名具有形式 name[l1 ..u1 , l2 ..u2 , … , ln ..un] ,其中, l i ,ui (i=1,2,…,n)为整型常数,且满足l i < ui
类型说明的属性翻译 文法 ·为了区分一般变量与指针,我们在符号表 中引入一个标志域IsPointer,当其为真 (=1)时表示该变量为指针,否则(=0〉 为一般变量。另外,我们假定指针变量的 定义形式与C语言相同
类型说明的属性翻译 文法 • 为了区分一般变量与指针,我们在符号表 中引入一个标志域IsPointer,当其为真 (=1)时表示该变量为指针,否则(=0) 为一般变量。另外,我们假定指针变量的 定义形式与C语言相同
Varable-iden {$$=Entry($1):/*变量在符号表中序号*/ VarList[$$].CAT=SimVar:/*种属为简单变量*/ VarList[$$].IsPointer:=0:/*指针标志*/ VarList[$$].ADDR=NULL;/*尚未分配内存空间,下同 */} |*?iden/*指针*/ {$$=Entry($1)/*变量在符号表中序号*/ VarList[$$].CAT=SimVar;/*种属为简单变量*/ VarList[$$].IsPointer=1;/*指针标志*/ VarList[$$].ADDR=NULL; } ArrayVar$=$1;}
Varable → iden {$$=Entry($1);/*变量在符号表中序号*/ VarList[$$].CAT=SimVar;/*种属为简单变量*/ VarList[$$].IsPointer=0;/*指针标志*/ VarList[$$].ADDR=NULL;/*尚未分配内存空间,下同 */} | ‘*’ iden /*指针*/ {$$=Entry($1);/*变量在符号表中序号*/ VarList[$$].CAT=SimVar;/*种属为简单变量*/ VarList[$$].IsPointer=1;/*指针标志*/ VarList[$$].ADDR=NULL; } | ArrayVar{$$=$1;}
ArrayMSG-iden number..number $$=Entry($1):VarList[$$].CAT=Arrayi/*种属为数组*/ VarLIst[$$].IsPointer=0;VarList[$$].ADDR->DIM=1;/* 记录维数;下面为内情向量申请空间,并填入第一维下标信息,其中,前两 个单元(下标为[0]和[1])用来存放a、C之值(此时暂不填写),n值可 由DIM保存,因此不必另存。*/ VarList[$$].ADDR->Vector=malloc(5*sizeof(int)); VarList[$$].ADDR->Vector[2]=$3;/*第一维下界*/ VarList[$$].ADDR->Vector[3]=$5;/*第一维上界*/ VarList[$$].ADDR->Vector[4]=$5-$3+1/*第一维界差*/
ArrayMSG → iden [ number .. number { $$=Entry($1); VarList[$$].CAT=Array;/*种属为数组*/ VarLIst[$$].IsPointer=0; VarList[$$].ADDR->DIM=1; /* 记录维数;下面为内情向量申请空间,并填入第一维下标信息,其中,前两 个单元(下标为[0]和[1])用来存放a、C之值 (此时暂不填写),n值可 由DIM保存,因此不必另存。*/ VarList[$$].ADDR->Vector=malloc(5*sizeof(int)); VarList[$$].ADDR->Vector[2]=$3;/*第一维下界*/ VarList[$$].ADDR->Vector[3]=$5;/*第一维上界*/ VarList[$$].ADDR->Vector[4]=$5-$3+1/*第一维界差*/ }
|*iden[number.number/*指针数组*/ { $$=Enty($1): VarList[$$].CAT=Arrayi/*种属为数组*/ VarList[$$].IsPointer=1; VarList[$$].ADDR->DIM=1;/*记录维数.下面的填写工作与上一 产生式相同,注释略*/ VarList[$$].ADDR->Vector=malloc(5*sizeof(int)); VarList[$$].ADDR->Vector[2]=$4;/*第一维下界*/ VarList[$$].ADDR->Vector[3]=$6;/*第一维上界*/ VarList[$$].ADDR->Vector[4]=$6-$4+1/*第一维界差*/
| *iden [ number .. number /*指针数组*/ { $$=Entry($1); VarList[$$].CAT=Array;/*种属为数组*/ VarList[$$].IsPointer=1; VarList[$$].ADDR->DIM=1;/*记录维数. 下面的填写工作与上 一 产生式相同,注释略*/ VarList[$$].ADDR->Vector=malloc(5*sizeof(int)); VarList[$$].ADDR->Vector[2]=$4;/*第一维下界*/ VarList[$$].ADDR->Vector[3]=$6;/*第一维上界*/ VarList[$$].ADDR->Vector[4]=$6-$4+1/*第一维界差*/ }
ArrayMSG,number .number int dim=VarList[$$].ADDR->DIM+1;=1; VarList[$$].ADDR->DIM++;/*维数加1*/ /*下面增加向量空间,记录新一维的信息*/ VarList[].ADDR->Vector= realloc (VarList[$$].ADDR->Vector, (3*dim+2)*sizeof(int)); /*下面记录当前维的下、上界及界差*/ VarList[$$].ADDR->Vector[3*dim-1]=$3; VarList[].ADDR->Vector[3*dim]=$5; VarList[$$].ADDR->Vector[3*dim+1]=$5-$3+1;
| ArrayMSG , number .. number {int dim= VarList[$$].ADDR->DIM+1; $$=$1; VarList[$$].ADDR->DIM++;/*维数加1*/ /*下面增加向量空间,记录新一维的信息*/ VarList[$$].ADDR->Vector= realloc (VarList[$$].ADDR->Vector, (3* dim+2)*sizeof(int)); /*下面记录当前维的下、上界及界差*/ VarList[$$].ADDR->Vector[3*dim-1]=$3; VarList[$$].ADDR->Vector[3*dim]=$5; VarList[$$].ADDR->Vector[3*dim+1]=$5-$3+1; }
ArrayVar→ArrayMSG]K/*传递数组名在表中序号*/ $$=$1;Fi川ArrMSG_C($$);/*计算并填写数组内情向量的C值*/ } Type-int {$$Type=INT;} real$.Type=REAL;} boolean {$$.Type=BOOL;} SelfDef {$$.Type=$1.Type;} DefVarable-Type Varable FillVarType($2,$1.Type); $$.Type=$1.Type;} I DefVarable,Varable FillVarType($3,$1.Type); $$.Type=$1.Type;
ArrayVar → ArrayMSG ]{/*传递数组名在表中序号*/ $$=$1; FillArrMSG_C($$);/*计算并填写数组内情向量的C值*/ } Type → int {$$.Type=INT;} |real{$$.Type=REAL;} | boolean {$$.Type=BOOL;} | SelfDef {$$.Type=$1.Type;} DefVarable → Type Varable { FillVarType($2,$1.Type); $$.Type=$1.Type; } | DefVarable , Varable { FillVarType($3,$1.Type); $$.Type=$1.Type; }
在上面的属性翻释文法中,我们引入了两个辅助函数 void FillVarType(int NO,int TYPE) void FillArrMSG C(int NO) 第一个函数完成将类型信息TYPE填写到符号表中的第NO项 之类型(type)域的工作; 第二个函数计算并填写符号表中第NO登记项ADDR所指示的 内情向量中的C(CONSTPART)值。 非终结符SelfDef用于描述用户自定义熬据美型,其文法定义 将在5.9.2节中讨论,这里,我们只需知道它具有一个属性 Type(用大于零的整型数表示)
在上面的属性翻译文法中,我们引入了两个辅助函数 void FillVarType(int NO,int TYPE) 和 void FillArrMSG_C(int NO) 第一个函数完成将类型信息TYPE填写到符号表中的第NO项 之类型(type)域的工作; 第二个函数计算并填写符号表中第NO登记项ADDR所指示的 内情向量中的C(CONSTPART)值。 非终结符SelfDef用于描述用户自定义数据类型,其文法定义 将在5.9.2节中讨论,这里,我们只需知道它具有一个属性 Type(用大于零的整型数表示)
对于简单数据类型(如real、int等),我们规定用负整数表示; 为了便于阅读,这里使用了助记符(常量定义)。另外,还利用符 号表(VarList)的ADDR域作为指针,指向一个结构 struct int DIM;int *Vector;} 其中,DIM用于描述数组的维数,Vector是一3*DIM+2个 整型数组成的向量,用于存放除(维数)外的内情向量信息, 其中存放首地址a的单元暂为空。 由于各个数组的维数可以不同,这里采用了动态申请(不断增大) 空间的方法保存上述信息。 另外,为保持一致性,当说明简单变量时,将其ADDR域赋值为 NULL
对于简单数据类型(如real、int等),我们规定用负整数表示; 为了便于阅读,这里使用了助记符(常量定义)。另外,还利用符 号表(VarList)的ADDR域作为指针,指向一个结构 struct { int DIM; int *Vector; } 其中,DIM用于描述数组的维数,Vector是一3*DIM+2个 整型数组成的向量,用于存放除n(维数)外的内情向量信息, 其中存放首地址a的单元暂为空。 由于各个数组的维数可以不同,这里采用了动态申请(不断增大) 空间的方法保存上述信息。 另外,为保持一致性,当说明简单变量时,将其ADDR域赋值为 NULL