单击此处编辑母版标题样式,*,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,语义分析和符号表,主要内容:,语义分析概述(必要性、功能、描述方法),符号表,类型表达式,声明和程序体的语义分析,语义分析的必要性,语法和语义的区别;,语法:,关于什么样的字符串才是该语言,在组成结构上合法的程序的法则。,语义:,关于结构上合法的程序的意义的,法则。,语义分析的分类,语义种类,静态语义:,在编译阶段(从程序文本上)可,以检查的语义。,动态语义:,通过程序的执行才能检查的语,义。,语义错误,各种条件表达式的类型是不是,boolean,型,?,运算符的分量的类型是否相容,?,赋值语句的左右部的类型是否相容,?,形参和实参的类型是否相容,?,下标表达式的类型是否为所允许的类型,?,变体记录中表示情形的常量是否为合法类型,?,函数说明中的函数类型和返回值的类型是否一致,?,VE,中的,V,是不是变量,而且是数组类型?,V.id,中的,V,是不是变量,而且是记录类型,?id,是不是该记录类型中的域名,?,V,中的,V,是不是指针或文件变量?,y+f,(.),中的,f,是不是函数名,?,形参个数和实参个数是否一致,?,p(.),语句中的,p,是不是过程名,?,形参个数和实参个数是否一致,?,每个使用性标识符是否都有声明,?,在同层内有无标识符被声明多次,?,标号是否有声明,?,有无重复声明和重复定位错误,?,有无非法转入错误?,子界类型中的下界和上界类型是否相容,?,下界是否小于等于上界?,语义分析的内容:,类型分析;,标识符相关信息;,语义分析的功能:,检查语义错误,构造标识符属性表(符号表),语义分析的实现:,与语法分析相结合,语义分析的功能图示,语义分析,语法分析树,TokenList,语义定义,自然语言描述规定,符号表,判定,标识符的内部表示,类型的内部表示,值的内部表示,三种内部表示,Code,标识符的内部表示,标识符种类:,常量名、类型名、变量名、函数名、过程名、域名。,TYPE,idkind,=(,consKind,typeKind,varKind,fieldKind,procKind,funcKind,),内部表示(,AttributeIR,):,常量:,类型:,变量:,域名*:,过函:,Value,Kind,TypePtr,Forward,Kind,TypePtr,Off,Level,Access,Kind,TypePtr,HostType,Off,Kind,TypePtr,Size,Forward,Class,Parm,Level,Kind,TypePtr,Off,例有声明如下:,CONST,pai,=3.14;,TYPE vector=ARRAY1.10 OF integer;,VAR x,y:real;,r,s:vector;,设当前层数和可用,offset,值分别为,L,和0,构造标识符,pai,vector,x,y,r,和,s,的属性表示。,类型的内部表示,类型的种类:,标准、子界、枚举、数组、记录、,集合、文件、指针类型等等。,TypeKind,=(,intTy,boolTy,charTy,realTy,enumTy,subTy,arrayTy,recordTy,setTy,fileTy,pointerTy,),内部表示:(,TypeIR,),标准类型:,sub:,enum,:,array:,Up,Low,HostType,Kind,Size,Leng,Elems,Kind,Size,ElemType,IndexType,Kind,Size,Kind,Size,record:,FixBody:,VariBody:,set:,file:,pointer:,VariBody,FixBody,Kind,Size,Next,Off,FixUnitType,id,VariUnits,CaseUnit,Next,VariBody,FixBody,Off,CaseType,id,BaseType,Kind,Size,CompType,Kind,Size,TypeName,Kind,Size,例有如下的类型定义:,at=ARRAY 1.10 OF,ARRAY1.100 OF integer;,rt,=RECORD x:real;a:at;,CASE u:,boolean,OF,false:(k,:integer);,true:(y,:real;b:,boolean,),END,构造类型的内部表示。,值的内部表示,非结构类型值的内部表示:,实型:,指针:,有序类型:整数形式,有序类型的常量表示:,整型常量:,ord(N,)=N,布尔常量:,ord(false,)=0,ord(true,)=1,字符常量:,ord(C,)=ASC(C),枚举常量:,设有枚举类型(,D,A,B),则有,ord(D,)=0,ord(A)=1,ord(B)=2,子界常量:,设有子界类型,C,1,.C,2,则值空间,为,ord(C,1,).ord(C,2,),符号表,标识符的作用:,声明部分:定义了各种对象及对应的属性和,使用规则。,程序体:对所定义的对象进行各种操作。,$,id,idname,Idname,AttributeIR,必要性,Token:,新表符号表(种类、类型等信息):,有关符号表的操作:,添加、作用域删除、查询,处理符号表的模块:,定义符号表数据结构,定义符号表上的操作,符号表,符号表的作用:,为语义检查和代码生成提供,标识符的语义信息。,标识符的处理思想:,遇到定义性标识符时,在符号表中填写,被定义标识符的符号项;,当遇到使用性标识符时,用该标识符查,符号表求得其属性。,标识符的特点,标识符的作用域:,标识符有效的最大程序段,嵌套作用域规则:,当存在标识符的嵌套声明时,最近定义的属性为标识符的当前属性,局部化单位:,允许有声明的程序段,P:,Var x,y,z,Var x,m,n,x:=1;,m:=x+1;,y:=x+1;,x:=0;,Q:,局部化区入口,Proc p(,Func f(,形式过,/,函,p(f(,Record begin,符号表的种类:,全局符号表、局部符号表,原则:,进入一个局部化区时,记录本层符号表的位置,遇到定义性标识符时,构造其语义信息,查本层符号表,若存在,则有重复声明错误,否则将语义信息填入表中,遇到一个使用性标识符时,查表(从里层到外层),查不到则有未定义标识符错误,否则构造新的,TOKEN,退出一个局部化区时,作废本层符号表,标识符处理的原则,符号表的实现,用局部符号表实现,proc p:x,y,z,proc p1:x,y1,z1,proc p2:y,y,z,x,y1,z1,y,proc p3:z,a,x,y,a,x,z,符号表的实现,用全局符号表实现,proc p0:x,y,proc p1:x,z,y,proc p2:x1,y1,y,x,z,语义分析例子,program p(),type at=array1.100 of array1.10 of inteter,var x:real;a:at;i:integer;,proc p1(var a1:at,;,a2:at),var x:integer;a:real;,proc p2(n:integer),var m:1.50;x:real;,m,n,x(,使用性出现,),end,a1,a2,x,a,i,(使用性出现),end,x,a,i,(使用性出现),end,标号的语义分析,标号出现的位置:,标号声明:,label,1,2,n,;,标号定位,(,语句前):,i,:Statement;,标号使用(,Goto,后):,goto,i,;,标号部分的语义错误:,标号重复声明;,标号重复定位;,标号有定位而无声明;,标号有使用而无定位;,Goto,语句有非法转入.,标号部分语义分析原理,设置五种表:,LDEC,,,LDEF,,,LUSE,,,SL,,,PL,LDEC,表,:,(,Flag,Label,,,),;,LDEF、LUSE,表:,(,Label),;,SL,表:,(kind,,,LDEFaddr,,,LUSEaddr,),;,PL,表:,(,LDECaddr,,,LDEFaddr,),;,标号的语义分析原理,1,),进入一个,过,/,函,时,将本层,LDEC,和,LDEF,的地址填入,PL,表;,2,),遇到一个标号声明“,label,1,2,n,”,时,建立本层,LDEC,表(检查重复声明错误),其中的,Flag,标志均设置为,0;,3,),遇到定位性标号“,:Statement,”时:,检查在,LDEC,表中有无,,若无则表示无标号声明错误;,若有,则检查其,Flag,位,若是,1,,则有重复定位错误;,若,Flag=0,,令其,Flag,位为,1,,并将,填入,LDEF,表中。,查看,LUSE,表,若其中有,则将其删除掉。,4,),进入一个,结构语句,时,将本语句的,LDEF,和,LUSE,表位置填入,SL,表;,5,),遇到一个“,goto ”,时:,查看,LDEF,表,看其中是否有,;,若无,将填入,LUSE,表;,6,),退出一个,结构化语句,时:,清查本层,LUSE,表(若有定位则删除该项):用本层的,LUSE,中标号查本层定位表,若查到,则把该项从,LUSE,中删除;,作废本层的,LDEF,。,7,),退出一个,过,/,函,时:,清查本层,LUSE,表;,作废本层的,LDEC,和,LDEF,。,8,),程序结束,时,清查,LUSE,表,若非空,则说明有标号为定位的错误。,