第六章(1)语义分析(Semantic Analysis)
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
–是描述一个合法定义的程序结构的规则。
语义:
–说明一个合法定义的程序的含义的规则。
5
z+1 x>y Z=
z-1 x≤y
PASCAL语言的条件语句: if x>y then z := z+1 else z := z -1
C语言的条件语句: if (x>y) { z = z+1; } else { z=z-1; }
34
子界类型:
Size Kind HostType Low Up SubSize SubTy
例:T=1..10;
Size Kind HostType Low Up
1 subTy IntPtr 1
10
TypeIR’ (Size:1, Kind:subTy HostType:intPtr, low:1, up:10)
{ float a; // 函数内部定义的局部整型变量a,
//屏闭了外部定义的整型变量a
int b;
… … a … // 引用的是函数内部定义的局部实数类型变量a … }
26
2、分程序结构 :C语言中分程序语句的语法是:
{ 声明 语句 } 分程序的一个特点是它的嵌套结构。 分程序结构的声明作用域由下面的最近嵌套规则给出:
6
int i; switch (i){ case 0:printf(“%s\n”,“auto”) ;break; case 1:printf(“%s\n”,“static”);break; case 2:printf(“%s\n”,“extern”);break; case 1:printf(“%s\n”,“register”);break; }
符号表的作用:
– 存储标识符的属性;
– 便于检查语义错误;
– 代码阶段作为地址分配的依据。
12
语义分析的主要任务(续1)
在整个程序范围内检查语义错误
– 声明和使用相关的错误 – 类型相关的语义错误
13
常见的语义错误
声明和使用相关的语义错误
常见的语义错误: – 每个使用性标识符是否都有声明?在同层内有无标识符被声
标识符的属性(续2)
存取方式 因为变量标识符代表的是一个内存单元或一段 连续的内存单元,根据这些内存单元中存放信息的类别 又可以把变量分为间接存取变量和直接存取变量。
如果变量标识符p所代表的内存单元中存放的是另一 个变量q对应的内存地址,则称变量p为间接存取变量; 如果变量标识符p所代表的内存单元中存放的是一个 值,则称变量p为直接存取变量。
– 编译时(compile-time)可以检查的语义 – 例如:标识符未声明
动态语义
– 目标程序运行时(run-time)才能检查的 语义
– 例如:除零溢出错误
10
如何描述程序设计语言的语义?
程序设计语言的形式语义 – 属性文法 (用于描述静态语义) – 操作语义(Operational Semantics) – 指称语义(Denotational Semantics) – 代数语义(Algebra Semantics) – 公理语义(Axiomatic Semantics)
– 函数说明中的函数类型和返回值的类型是否一致? – V[E]中的V是不是变量,而且是不是数组类型? – V.id中的V是不是变量,而且是不是结构体类型? id是不是该
记录类型中的成员? – V↑(*V)中的V是不是指针或文件变量? – y+f(....)中的f是不是函数名?形参个数和实参个数是否一致? – p(....)语句中的p是不是过程名?形参个数和实参个数是否一
24
通常一个变量的作用域就是该变量可以出现的 场合,也就是说在某个变量作用域范围内该变 量是可以引用的,这就是变量可视性的作用域 规则。
有两种情况也将影响变量的可视性。
25
1、函数的形式参数和函数外部定义的变量重名:
函数的形式参数在函数内可见 。
int a; // 外部定义的整型变量a int func( )
7
1. int x=10; 2. Main( )
符合变量声明的语法、语义
3. { printf( “%d”,x+x );
4. x( );
符合函数调用的语法、不符合语义
5. f = x; 6. }
符合赋值语句的语法、不符合语义
7. float f( ) 8. {int x=20,y;
符合函数声明的语法、语义 符合变量声明的语法、语义
第6章 语义分析(Semantic Analysis) 和符号表
Semantic:of or relating to meaning, especially meaning in language.
1
语义分析在编译程序中的逻辑位置
表处理
中
源
词
语
语
间
程
法
法
义
代
序
分
分
分
码
析
析
析
生
成
中
目
间
标
目
代
代
标
码
码
14
常见的语义错误(续1)
类型相关的语义错误
– 各种条件表达式的类型是不是boolean型? – 运算符的分量的类型是否相容? – 赋值语句的左右部的类型是否相容? – 形参和实参的类型是否相容? – 下标表达式的类型是否为所允许的类型? – 变体记录中表示情形的常量是否为合法类型?
常见的语义错误(续2)
(1)分程序B中声明的作用域包括B。 (2)如果名字x没有在B中声明,那么B中x的出现 是在外围分程序B 的x声明的作用域中,且满足:
(a)B 有x的声明; (b)B 比其它任何含x声明的分程序更接近被 嵌套的B。
27
…
{int a; // 第一层头,定义的局部整型变量a
…
{char a; // 第二层头,定义的局部字符型变量a
1.将根据语言的定义,按照该标识符在程序 中的作用域和可视性规则进行相应的处理。
2.在一些允许操作重载(Operator Overload)的语言中,函数名、过程名是可以重名 的,对于这类标识符要通过它们的参数个数和类型、 函数返回值类型来区别,以达到它们在符号表中的 唯一性。
20
标识符的属性 (续1)
程
优
生
序
化
成
错误处理
2
6.1 语义分析概述 6.2 符号表的数据结构 6.3 符号表的管理 6.4 程序设计语言符号表的实例
3
主要内容:
语义分析的功能及重要性; 标识符的内部表示; 类型的内部表示; 符号表的组织。
6.1 语义分析概述
6.1 语义分析概述
语法和语义的区别
语法:
35
数组类型(方案1):
Size Kind Low Up ElemType SubSize ArrayTy
其中各个域的含义如下:
Size表示数组类型所占空间的大小,是数组所有成分数 据占用空间的和,需要通过计算得到,Size = (UpLow+1)*sizeof(ElemType), 其中sizeof是一个辅助函数 ,用于计算每种类型的size; Kind = arrayTy, 表示是数组类型; Low表示数组下标的下界,在C语言中Low = 0; Up表示数组下标的上界; ElemType 表示数组成分类型的内部表示指针。
9. float x; 10. printf( “%d”,x ); 11. }
符合变量声明的语法、不符合语义
8
语义分析的必要性
一个语法正确的程序不能保证它是有意义 的!
程序中容易出现各种语义错误:
– 标识符未声明 – 操作数的类型与操作符的类型不匹配 – ……
9
程序设计语言语义的分类
静态语义
明多次? – 标号是否有声明?有无重复声明和重复定位错误?有无非法
转入错误? 如何检查? – 每当遇到新声明的标识符,查符号表:
如果当前有效的所有标识符中有相同名字的,则是重复声 明错误;
否则生成它的属性信息,保存到符号表中; – 每当遇到标识符的使用,查符号表
如果没有找到,说明该标识符没有声明; 否则, 得到该标识符的属性,进行进一步分析;
为[ord(C1)...ord(C2)]
31
类型的内部表示
类型表达式:
如: at = ARRAY[1..10] OF ARRAY[1..100] OF integer; rt = RECORD x : real; a : at;
CASE u : boolean OF false:( k : integer ); true :( y: real; b :boolean ) END
类型的内部表示:表示类型表达式所包含的各种 信息的数据结构。
32
类型的种类属性: 标准、子界、枚举、数组、记录、
集合、文件、指针类型等等。 TypeKind = ( intTy,boolTy,charTy,realTy,
enumTy,subTy,arrayTy, structTy,setTy,fileTy,pointerTy)
22
ห้องสมุดไป่ตู้
标识符的属性(续3)
存储类别 存储类别是指数据的存储方式,存储方式可分为两大类:静 态和动态。 静态存储方式是指在程序运行前即为数据分配好存储空间( 在静态区),在程序运行期间,数据的存储空间仍保持不变; 动态存储方式则是在程序运行期间根据函数调用(函数被激 活)和分程序语句的开始执行(分程序语句被激活)的需要进行 动态存储分配。 标识符的存储类别属性是编译过程语义处理、检查和存储分 配的重要依据。编译程序一般根据变量的存储类别以及它们出 现的位置和次序来确定每一个变量应分配的存储区及在该区中 的具体位置。
23
作用域和可视性
标识符在程序中起作用的范围,称为它的作用
域。
一般地,定义该标识符的位置及存储类关键字 决定了它的作用域。如:C语言中, 动态存储: 自动变量(本函数内有效) 寄存器变量(本函数内有效) 形式参数(本函数内有效) 静态存储: 静态局部变量(函数内有效) 静态外部变量(本文件内有效) 外部变量(其他文件可引用)
符号表 判定
18
6.2 符号表的数据结构
标识符的属性
名字 类型 存取方式 存储类别 作用域和可视性
19
标识符的属性
名字 在程序语言中,标识符可以作为变量的名字、 函数的名字或过程的名字,是变量、函数或过程的 唯一标志,因此在符号表中标识符的名字一般不允 许重名。
若程序中出现重名标识符:
类型 除过程标识符之外,其他标识符都具有类型属 性,函数的数据类型指的是函数返回值的数据类 型。 基本类型有整型、实型、字符型以及布尔型等。 在基本类型的基础上,还可以定义数组、结构 体、联合、枚举、子界、集合、指针等结构类型。 标识符的类型是在程序中该标识符的定义部分 得到的。 变量标识符的类型属性决定了变量所占存储空 间的大小以及能够施于变量上的操作等。 21
类型size属性:表示此种类型数据应该分配的内存空间的大小。 其它属性依类型的不同而不同。
33
内部表示:
标准类型:
Size
Kind
intPtr IntSize intTy
boolPtr BoolSize boolTy
charPtr CharSize charTy
realPtr RealSize realTy
非结构类型值的内部表示: 实型: 指针: 有序类型:整数形式
30
有序类型的常量表示:
整型常量: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 子界常量:设有子界类型C1..C2,则值空间
致? – 子界类型中的下界和上界类型是否相容?下界是否小于等
于上界?
16
语义分析的实现
方式一:不作为独立的一遍 ① 语义错误检查:可以安排在中间代码生
成时进行 。 ② 一般的语义检查:与语法分析相结合
17
方式二、独立一遍的语义分析的功能图示
语法分析树 TokenList 语义定义
语义分析
自然语言描述规定
…
{ // 第三层头
…
{float a; // 第四层头,定义的局部实型变量a
…
} // 第四层尾
…a… // 引用第二层定义的局部字符型变量a
} // 第三层尾
…
} // 第二层尾
....
} // 第一层尾
28
三种内部表示
标识符的内部表示 类型的内部表示 值的内部表示
值的内部表示
形式语义描述技术没有形式语法描述技术成熟 硕士研究生的课程-《形式语义学》
11
语义分析的主要任务
根据声明部分建立符号表
符号表(symbol table):是一种供编译器用于保 存有关源程序构造的各种信息的数据结构。符号表 的每个条目中包含与一个标识符相关的信息,这些 信息全面地反映该名字的属性及它们在编译过程中 的特征。
语义:
–说明一个合法定义的程序的含义的规则。
5
z+1 x>y Z=
z-1 x≤y
PASCAL语言的条件语句: if x>y then z := z+1 else z := z -1
C语言的条件语句: if (x>y) { z = z+1; } else { z=z-1; }
34
子界类型:
Size Kind HostType Low Up SubSize SubTy
例:T=1..10;
Size Kind HostType Low Up
1 subTy IntPtr 1
10
TypeIR’ (Size:1, Kind:subTy HostType:intPtr, low:1, up:10)
{ float a; // 函数内部定义的局部整型变量a,
//屏闭了外部定义的整型变量a
int b;
… … a … // 引用的是函数内部定义的局部实数类型变量a … }
26
2、分程序结构 :C语言中分程序语句的语法是:
{ 声明 语句 } 分程序的一个特点是它的嵌套结构。 分程序结构的声明作用域由下面的最近嵌套规则给出:
6
int i; switch (i){ case 0:printf(“%s\n”,“auto”) ;break; case 1:printf(“%s\n”,“static”);break; case 2:printf(“%s\n”,“extern”);break; case 1:printf(“%s\n”,“register”);break; }
符号表的作用:
– 存储标识符的属性;
– 便于检查语义错误;
– 代码阶段作为地址分配的依据。
12
语义分析的主要任务(续1)
在整个程序范围内检查语义错误
– 声明和使用相关的错误 – 类型相关的语义错误
13
常见的语义错误
声明和使用相关的语义错误
常见的语义错误: – 每个使用性标识符是否都有声明?在同层内有无标识符被声
标识符的属性(续2)
存取方式 因为变量标识符代表的是一个内存单元或一段 连续的内存单元,根据这些内存单元中存放信息的类别 又可以把变量分为间接存取变量和直接存取变量。
如果变量标识符p所代表的内存单元中存放的是另一 个变量q对应的内存地址,则称变量p为间接存取变量; 如果变量标识符p所代表的内存单元中存放的是一个 值,则称变量p为直接存取变量。
– 编译时(compile-time)可以检查的语义 – 例如:标识符未声明
动态语义
– 目标程序运行时(run-time)才能检查的 语义
– 例如:除零溢出错误
10
如何描述程序设计语言的语义?
程序设计语言的形式语义 – 属性文法 (用于描述静态语义) – 操作语义(Operational Semantics) – 指称语义(Denotational Semantics) – 代数语义(Algebra Semantics) – 公理语义(Axiomatic Semantics)
– 函数说明中的函数类型和返回值的类型是否一致? – V[E]中的V是不是变量,而且是不是数组类型? – V.id中的V是不是变量,而且是不是结构体类型? id是不是该
记录类型中的成员? – V↑(*V)中的V是不是指针或文件变量? – y+f(....)中的f是不是函数名?形参个数和实参个数是否一致? – p(....)语句中的p是不是过程名?形参个数和实参个数是否一
24
通常一个变量的作用域就是该变量可以出现的 场合,也就是说在某个变量作用域范围内该变 量是可以引用的,这就是变量可视性的作用域 规则。
有两种情况也将影响变量的可视性。
25
1、函数的形式参数和函数外部定义的变量重名:
函数的形式参数在函数内可见 。
int a; // 外部定义的整型变量a int func( )
7
1. int x=10; 2. Main( )
符合变量声明的语法、语义
3. { printf( “%d”,x+x );
4. x( );
符合函数调用的语法、不符合语义
5. f = x; 6. }
符合赋值语句的语法、不符合语义
7. float f( ) 8. {int x=20,y;
符合函数声明的语法、语义 符合变量声明的语法、语义
第6章 语义分析(Semantic Analysis) 和符号表
Semantic:of or relating to meaning, especially meaning in language.
1
语义分析在编译程序中的逻辑位置
表处理
中
源
词
语
语
间
程
法
法
义
代
序
分
分
分
码
析
析
析
生
成
中
目
间
标
目
代
代
标
码
码
14
常见的语义错误(续1)
类型相关的语义错误
– 各种条件表达式的类型是不是boolean型? – 运算符的分量的类型是否相容? – 赋值语句的左右部的类型是否相容? – 形参和实参的类型是否相容? – 下标表达式的类型是否为所允许的类型? – 变体记录中表示情形的常量是否为合法类型?
常见的语义错误(续2)
(1)分程序B中声明的作用域包括B。 (2)如果名字x没有在B中声明,那么B中x的出现 是在外围分程序B 的x声明的作用域中,且满足:
(a)B 有x的声明; (b)B 比其它任何含x声明的分程序更接近被 嵌套的B。
27
…
{int a; // 第一层头,定义的局部整型变量a
…
{char a; // 第二层头,定义的局部字符型变量a
1.将根据语言的定义,按照该标识符在程序 中的作用域和可视性规则进行相应的处理。
2.在一些允许操作重载(Operator Overload)的语言中,函数名、过程名是可以重名 的,对于这类标识符要通过它们的参数个数和类型、 函数返回值类型来区别,以达到它们在符号表中的 唯一性。
20
标识符的属性 (续1)
程
优
生
序
化
成
错误处理
2
6.1 语义分析概述 6.2 符号表的数据结构 6.3 符号表的管理 6.4 程序设计语言符号表的实例
3
主要内容:
语义分析的功能及重要性; 标识符的内部表示; 类型的内部表示; 符号表的组织。
6.1 语义分析概述
6.1 语义分析概述
语法和语义的区别
语法:
35
数组类型(方案1):
Size Kind Low Up ElemType SubSize ArrayTy
其中各个域的含义如下:
Size表示数组类型所占空间的大小,是数组所有成分数 据占用空间的和,需要通过计算得到,Size = (UpLow+1)*sizeof(ElemType), 其中sizeof是一个辅助函数 ,用于计算每种类型的size; Kind = arrayTy, 表示是数组类型; Low表示数组下标的下界,在C语言中Low = 0; Up表示数组下标的上界; ElemType 表示数组成分类型的内部表示指针。
9. float x; 10. printf( “%d”,x ); 11. }
符合变量声明的语法、不符合语义
8
语义分析的必要性
一个语法正确的程序不能保证它是有意义 的!
程序中容易出现各种语义错误:
– 标识符未声明 – 操作数的类型与操作符的类型不匹配 – ……
9
程序设计语言语义的分类
静态语义
明多次? – 标号是否有声明?有无重复声明和重复定位错误?有无非法
转入错误? 如何检查? – 每当遇到新声明的标识符,查符号表:
如果当前有效的所有标识符中有相同名字的,则是重复声 明错误;
否则生成它的属性信息,保存到符号表中; – 每当遇到标识符的使用,查符号表
如果没有找到,说明该标识符没有声明; 否则, 得到该标识符的属性,进行进一步分析;
为[ord(C1)...ord(C2)]
31
类型的内部表示
类型表达式:
如: at = ARRAY[1..10] OF ARRAY[1..100] OF integer; rt = RECORD x : real; a : at;
CASE u : boolean OF false:( k : integer ); true :( y: real; b :boolean ) END
类型的内部表示:表示类型表达式所包含的各种 信息的数据结构。
32
类型的种类属性: 标准、子界、枚举、数组、记录、
集合、文件、指针类型等等。 TypeKind = ( intTy,boolTy,charTy,realTy,
enumTy,subTy,arrayTy, structTy,setTy,fileTy,pointerTy)
22
ห้องสมุดไป่ตู้
标识符的属性(续3)
存储类别 存储类别是指数据的存储方式,存储方式可分为两大类:静 态和动态。 静态存储方式是指在程序运行前即为数据分配好存储空间( 在静态区),在程序运行期间,数据的存储空间仍保持不变; 动态存储方式则是在程序运行期间根据函数调用(函数被激 活)和分程序语句的开始执行(分程序语句被激活)的需要进行 动态存储分配。 标识符的存储类别属性是编译过程语义处理、检查和存储分 配的重要依据。编译程序一般根据变量的存储类别以及它们出 现的位置和次序来确定每一个变量应分配的存储区及在该区中 的具体位置。
23
作用域和可视性
标识符在程序中起作用的范围,称为它的作用
域。
一般地,定义该标识符的位置及存储类关键字 决定了它的作用域。如:C语言中, 动态存储: 自动变量(本函数内有效) 寄存器变量(本函数内有效) 形式参数(本函数内有效) 静态存储: 静态局部变量(函数内有效) 静态外部变量(本文件内有效) 外部变量(其他文件可引用)
符号表 判定
18
6.2 符号表的数据结构
标识符的属性
名字 类型 存取方式 存储类别 作用域和可视性
19
标识符的属性
名字 在程序语言中,标识符可以作为变量的名字、 函数的名字或过程的名字,是变量、函数或过程的 唯一标志,因此在符号表中标识符的名字一般不允 许重名。
若程序中出现重名标识符:
类型 除过程标识符之外,其他标识符都具有类型属 性,函数的数据类型指的是函数返回值的数据类 型。 基本类型有整型、实型、字符型以及布尔型等。 在基本类型的基础上,还可以定义数组、结构 体、联合、枚举、子界、集合、指针等结构类型。 标识符的类型是在程序中该标识符的定义部分 得到的。 变量标识符的类型属性决定了变量所占存储空 间的大小以及能够施于变量上的操作等。 21
类型size属性:表示此种类型数据应该分配的内存空间的大小。 其它属性依类型的不同而不同。
33
内部表示:
标准类型:
Size
Kind
intPtr IntSize intTy
boolPtr BoolSize boolTy
charPtr CharSize charTy
realPtr RealSize realTy
非结构类型值的内部表示: 实型: 指针: 有序类型:整数形式
30
有序类型的常量表示:
整型常量: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 子界常量:设有子界类型C1..C2,则值空间
致? – 子界类型中的下界和上界类型是否相容?下界是否小于等
于上界?
16
语义分析的实现
方式一:不作为独立的一遍 ① 语义错误检查:可以安排在中间代码生
成时进行 。 ② 一般的语义检查:与语法分析相结合
17
方式二、独立一遍的语义分析的功能图示
语法分析树 TokenList 语义定义
语义分析
自然语言描述规定
…
{ // 第三层头
…
{float a; // 第四层头,定义的局部实型变量a
…
} // 第四层尾
…a… // 引用第二层定义的局部字符型变量a
} // 第三层尾
…
} // 第二层尾
....
} // 第一层尾
28
三种内部表示
标识符的内部表示 类型的内部表示 值的内部表示
值的内部表示
形式语义描述技术没有形式语法描述技术成熟 硕士研究生的课程-《形式语义学》
11
语义分析的主要任务
根据声明部分建立符号表
符号表(symbol table):是一种供编译器用于保 存有关源程序构造的各种信息的数据结构。符号表 的每个条目中包含与一个标识符相关的信息,这些 信息全面地反映该名字的属性及它们在编译过程中 的特征。