第5章 语义分析(Semantic Analysis)

Slides:



Advertisements
Similar presentations
电子成绩单项目实现.
Advertisements

教 师:曾晓东 电 话: E_mail: 计算机软件技术基础 教 师:曾晓东 电 话: E_mail:
四資二甲 第三週作業 物件導向程式設計.
计算机应用基础 Excel部分.
第三章 鏈結串列 Linked List.
编译原理上机实习
计算机硕士专业基础—C语言 赵海英
数据结构——树和二叉树 1/96.
第二章 线性表 1 线性表的逻辑结构及其基本操作 2 线性表的顺序存储结构 3 线性表的链式存储结构 4 静态链表 5 应用实例.
数据结构与算法 数据结构与算法实验
C++程序设计 王希 图书馆三楼办公室.
複習 struct score_Type{ int chinese,english; }; struct my_Type{
C程序设计 第9章 自定义数据类型 主讲教师: 鲁 萍 西安建筑科技大学 理学院.
程式設計 博碩文化出版發行.
struct 可以在同一個名稱下擁有多種資料型態。使用struct能讓資料的存取和處理更為靈活。
C 程式設計— 結構 台大資訊工程學系 資訊系統訓練班.
内容提要 对象的生命周期 构造函数 析构函数 拷贝构造函数. 常宝宝 北京大学计算机科学与技术系
.NET 程式設計入門(使用 C#) 講師:鄧智鴻.
第二章 C# 基础知识.
複習 char name1[20]; //長度為20的字串 char name2[20]; //讀取字串 gets(name1);
啟示錄.
Derived Class 前言 衍生類別的定義 單一繼承 public, protected, 和 privated 基底類別
第十一章 面向对象设计 第十二章 面向对象实现
补充内容 结构体 概述 定义结构体类型和定义结构体变量 结构体变量的引用 结构体变量的初始化 指针与结构体 用typedef定义类型的别名.
第3章 變數、資料型別與運算子.
结构体和共用体 2 梁春燕 华电信息管理教研室.
第五章 数组和 广义表 数组 稀疏矩阵 广义表.
6 下标变量的中间代码生成 下标:数组;变量: 下标变量:即数组分量: 简单变量:id,其地址可查到;
第9章 自訂資料型態 – 結構 9-1 結構資料型態 9-2 結構陣列 9-3 指標與結構 9-4 動態記憶體配置 9-5 聯合資料型態
授课老师:龚涛 信息科学与技术学院 2018年3月 教材: 《Visual C++程序员成长攻略》 《C++ Builder程序员成长攻略》
第三章 C++中的C 面向对象程序设计(C++).
第12章 從C到C++語言 12-1 C++語言的基礎 12-2 C++語言的輸出與輸入 12-3 C++語言的動態記憶體配置
2 C++ 的基本語法和使用環境 親自撰寫和執行程式是學好程式語言的不二法門。本章藉由兩個簡單的程式,介紹C++ 程式的基本結構和開發環境,讓初學者能逐漸建立使用C++ 的信心。
C 程式設計— 結構 台大資訊工程學系 資訊系統訓練班.
第十三章 其他的C語言課題.
第3章 變數、常數與資料型態 3-1 C語言的識別字 3-2 變數的宣告與初值 3-3 指定敘述 3-4 C語言的資料型態
第3章 變數、資料型別與運算子 3-1 變數與資料型別的基礎 3-2 變數的命名與宣告 3-3 資料型別 3-4 運算式與運算子
第3章 堆栈和队列 堆栈 堆栈应用 队列 队列应用 优先级队列 主要知识点.
fp=fopen("CD2.dat","wb"); fwrite(&min,8,1,fp); fclose(fp);
THE C PROGRAMMING LANGUAGE
第13章 结构体的应用 13.1 了解由用户构造的数据类型 13.2 结构体类型说明及结构体变量 13.3 结构体数组
明解C++教學手冊 柴田望洋 博士 著 書號:PG20269
C++语言程序设计 C++语言程序设计 第七章 类与对象 第十一组 C++语言程序设计.
$10 可空类型.
C#程序设计基础 第二章 数据类型.
第三章 数据类型、运算符与表达式.
语义分析概述 符号表 第六章 语义分析.
第1章 概述 本章要点: C语言程序结构和特点 C语言程序的基本符号与关键字 C语言程序的编辑及运行 学习方法建议:
第三章 链表 单链表 循环链表 多项式及其相加 双向链表 稀疏矩阵.
第九章 目标代码生成.
编译原理实践 11.语义分析与代码生成.
常宝宝 北京大学计算机科学与技术系 数据结构(三) 常宝宝 北京大学计算机科学与技术系
C语言程序设计.
第十章 用户自定义数据类型 目录 学生信息管理系统的开发 结构体数据类型的概述 结构体变量的使用 结构体数组
OOP6 結構Struct 黃兆武.
第十章 结构体与链表 西安工程大学.
第1讲 C语言基础 要求: (1) C程序的组成 (2) C语言的标识符是如何定义的。 (3) C语言有哪些基本数据类型?各种基本数
Java變數 2014/6/24.
C++复习2----类与对象.
第三章 数据抽象.
<编程达人入门课程> 本节内容 为什么要使用变量? 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ:
第二章 基本数据类型 ——数据的表示.
第二讲 基本数据类 型及数组等 此为封面页,需列出课程编码、课程名称和课程开发室名称。
#include <iostream.h>
第二章 Java基本语法 讲师:复凡.
本章主題 C++的程式結構 資料型態與宣告 算術運算 簡易的輸入輸出指令 程式編譯(Compile)的過程與原理.
《数据结构与算法设计》第一部分 面向对象的C++程序设计基础.
第二章 数据类型、运算符和表达式 §2.1 数据与数据类型 §2.2 常量、变量和标准函数 §2.3 基本运算符及其表达式 目 录 上一章
第2章 Java语言基础.
第六章 复合数据类型 指针的声明与使用 数组的声明与使用 指针与数组的相互引用 字符串及相关库函数 new与delete
Presentation transcript:

第5章 语义分析(Semantic Analysis) 和符号表 语义分析概述 符号表的数据结构 符号表的管理 程序设计语言符号表的实例

语义分析在编译程序中的逻辑位置 表 处 理 源 程 序 词 法 分 析 语 法 分 析 语 义 分 析 中 间 代 码 生 成 中 间 代 优 化 目 标 代 码 生 成 目 标 程 序 错 误 处 理

1 语义分析概述 1.1 语法和语义的区别 语法是描述一个合法定义的程序结构的规则。 语法分析是编译过程的一个逻辑阶段。语法分析的任务是在词法分析的基础上将单词序列组合成各类语法短语。源程序的结构由上下文无关文法描述。 语义是说明一个合法定义的程序的含义的规则。 语义分析是编译过程的一个逻辑阶段。语义分析的任务是对结构上正确的源程序符号进行上下文有关性质的审查, 进行类型审查。

1.2 语义分析的必要性 一个语法正确的程序不能保证它是有意义的. 程序中容易出现各种语义错误: 标识符未声明 操作数的类型与操作符的类型不匹配 ……

符合变量声明的语法、语义 int x=10; Main( ) { printf( “%d”,x+x ); x( ); } f = x; } float f( ) {int x=20,y; float x; printf( “%d”,x ); 符合变量声明的语法、语义 符合函数调用的语法、不符合语义 符合赋值语句的语法、不符合语义 符合函数声明的语法、语义 符合变量声明的语法、语义 符合变量声明的语法、不符合语义

1.3 程序设计语言语义的分类 静态语义 动态语义 在编译阶段(compile-time)可以检查的语义 例如:标识符未声明 目标程序运行时(run-time)才能检查的语义 例如:除零、溢出错误

1.4 语义分析的主要任务 在变量、常量、类型、函数等标识符的定义和使用间建立联系 - 建立符号表保存标识符相关信息   - 建立符号表保存标识符相关信息 在整个程序范围内检查静态语义错误 声明和使用相关的错误 类型相关的语义错误 执行真正的翻译:生成更简单的中间表示形式或生成目标代码。

1.5 语义错误检查 类型检查 一般性的语义检查 1、各种条件表达式的类型是不是boolean型? 2、运算符的分量的类型是否相容? 3、赋值语句的左右部的类型是否相容? 4、形参和实参的类型是否相容? 5、下标表达式的类型是否为所允许的类型? 6、函数说明中的函数类型和返回值的类型是否一致? 一般性的语义检查 1、每个使用性标识符是否都有声明?在同层内有无标识符被声明多次? 2、标识符是否正确使用? V[E]中的V是不是变量,而且是数组类型? V.id中的V是不是变量,而且是记录类型? id是不是该记录类型中的域名? y+f(…)中的f是不是函数名?形参个数和实参个数是否一致? p(…)语句中的p是不是过程名?形参个数和实参个数是否一致? V↑中的V是不是指针或文件变量? 子界类型中的下界和上界类型是否相容?下界是否小于等于上界?

1.6 语义分析的实现 语义检查要与语法分析相结合 语法分析树 语义分析 符号表 TokenList 语义定义 判定

C 语言语义分析过程 void main( ) { int x; float y=10; x=y+5*y; } 符号表 符号名 种类 类型 存储位置 …… main funKind void x varKind int Off y float Off+sizeof(int) … …….

2 符号表的数据结构 符号表(symbol table):是一种供编译器用于保存有关源程序的各种信息的数据结构。符号表的每个条目中包含与一个标识符相关的信息,这些信息全面地反映该名字的属性及它们在编译过程中的特征。 符号表的作用: 收集存储标识符的属性; 上下文语义的合法性检查的依据; 代码生成阶段作为地址分配的依据。

2.1 标识符的语义检查 标识符的声明性出现:int x; 标识符的使用性出现: x=10; 通过遍历语法树检查:创建标识符a所对应的符号表,将a在符号表中的地址指针存入树中标识符节点; 通过扫描TokenList:创建标识符a所对应的符号表,将原token <标识符,a>转化为 <标识符,符号表a项指针> 标识符的使用性出现: x=10; 通过遍历语法树检查:到符号表中查找a,找到则将a在符号表中的地址指针存入树中标识符节点; 通过扫描TokenList:到符号表中查找a,找到则将token <标识符,a>转化为<标识符,符号表a项指针>

2.2 符号的内部表示 1. 值的内部表示 2. 类型的内部表示 3. 标识符的内部表示

1.值的内部表示 基本类型:整型,实型 有序类型:布尔,字符,枚举,数组下标 布尔常量:ord(false)=0, ord(true)= 1 字符常量:ord(C) = ASCⅡ(C) 枚举常量:设有枚举类型(D,A,B),则有ord(D)=0,ord(A)=1,ord(B)=2

2.类型的内部表示 类型语义信息的作用 类型的语义检查 分配空间的大小 标识符的语义信息我们都表示出来了,也就是种类信息、类型信息、其他信息,种类信息按照前面的介绍来看我们已经可以把它充分的表现出来了但是对于我们来说,类型却没有准确的语义表示。下面我们就来看一下类型的语义信息如何表示出来。 可能大一的时候大家就觉得为什么我们要给出变量的声明,又要给出他的类型,这种声明到底有啥意义,现在学编译,我们就可以知道这些声明是为了我们编译的工作提供一些信息。类型信息有什么作用呢?他的作用主要有两类: 1、做类型的检查,前面我们也说了很多的问题,xxx等等~ 原因是不同类型的数在计算机中的表示形式是不同的 2、我们要根据类型的大小为每一个变量分配存储空间的,一个简单变量和一个数组他们占用的存储空间的大小是不同的,我们根据什么给他们分配存储空间呢?~就是根据类型的大小,在真正执行的时候为他们进行存储空间的分配。这就是类型的作用。

2.类型的内部表示 … Kind Size 类型的种类Kind属性: 标准、子界、枚举、数组、记录、 集合、文件、指针类型等等。 Kind = ( intTy,boolTy,charTy,realTy, enumTy,subTy,arrayTy, structTy,setTy,fileTy,pointerTy) 类型存储占用空间大小size属性:为方便起见,规定RealSize取2外,IntSize、BoolSize、CharSize取1。 其它属性依类型的不同而不同。

(1)标准类型: Size Kind IntSize intTy BoolSize boolTy CharSize charTy RealSize realTy intPtr boolPtr charPtr realPtr Size Kind 1 intTy boolTy charTy 2 realTy intPtr boolPtr charPtr realPtr

(2)数组类型 其中各个域的含义如下: --Size Size = (Up-Low+1)*sizeof(ElemType) ElemType TypePtr ArraySize Size Kind ArrayTy Low Up 其中各个域的含义如下: --Size Size = (Up-Low+1)*sizeof(ElemType) -- Kind = arrayTy, 表示是数组类型; -- Low表示数组下标的下界,在C语言中Low = 0; -- Up表示数组下标的上界; -- ElemType 表示数组成分类型的内部表示指针。

例:C语言的数组 typedef int A[10]; typedef char B [5] [10]; A和B的内部表示分别为: ElemType IntPtr Size Kind ArrayTy Low Up 9 10 ElemType Size Kind ArrayTy Low Up 4 50 ElemType CharPtr Size Kind 10 ArrayTy Low Up 9

(3)结构体与共用体类型 其中各个域的含义如下: Size:结构体是所有域占用空间的和,共用体类型则是所有域中占用空间的最大者的值。 FieldList Kind Size 其中各个域的含义如下: Size:结构体是所有域占用空间的和,共用体类型则是所有域中占用空间的最大者的值。 Kind = structTy表示是结构体或共用体类型 FieldList 是域名表的表头指针。

TypePtr是域名标识符类型的内部表示指针; 域名Field标识符的内部表示如下: Name Typeptr Off link 其中各个域的含义如下: Name表示标识符的名字; TypePtr是域名标识符类型的内部表示指针; Off表示域名标识符相对于结构体或共用体类型分配的内存块起始地址的偏移量,对于联合类型而言,所有的域名标识符的起始偏移都是相同的,所以可以省略; link:下一个域名标识符的内部表示的指针。

typedef struct DateType {int year, month, day;} datetype; 例: typedef struct DateType {int year, month, day;} datetype; Size Kind FieldList structTy 3 Name Type Off intPtr year 1 intPtr month 域名表其它表示 2 intPtr day intPtr year 1 month 2 day null

structTy intPtr j 1 IntPtr ArrayTy 9 例: typedef struct { int j; int r[10]; } A; Size Kind FieldList structTy 11 Name Type Off intPtr j 1 r ElemType IntPtr Size Kind ArrayTy Low Up 9 10

typedef union {char ch; int i; float f;} datatype; structTy 2 charPtr ch intPtr i realPtr f

(4)枚举类型 其中各个域的含义如下: size表示枚举类型所占空间的大小; Kind = enumTy; FieldList Kind Size ElemList Kind Size 其中各个域的含义如下: size表示枚举类型所占空间的大小; Kind = enumTy; ElemList是指向枚举常量表表头的指针. 枚举常量表内部表示: Value Name Name表示枚举常量的名字; Value表示枚举常量所代表的整数值。

例:c语言的枚举类型 enum color {red, yellow, blue} enumTy 1 red 例:c语言的枚举类型 enum color {red=10, yellow=red+2, blue} 1 yellow 2 blue enumTy 1 10 red 12 yellow 13 blue

(5)指针类型 c语言中指针类型其定义形式为:T * T称为此指针类型的基类型。 指针类型的内部表示: 其中各个域的含义如下: Type Kind Size 其中各个域的含义如下: size表示指针类型所占空间的大小; Kind = pointTy表示是指针类型; Type是指向指针类型的基类型的内部表示的指针。

typedef int* T1; typedef float* T2; intPtr pointTy 1 realPtr pointTy 1 例:c语言的针举类型 typedef int* T1; typedef float* T2; intPtr pointTy 1 realPtr pointTy 1

类型内部表示 … Kind Size (1)标准类型: int,real,bool,char Kind Size TypePtr ArraySize ArrayTy Low Up ElemType (2)数组类型 (3)结构体与共用体类型 FieldList structTy Size off typePtr Name link (4)枚举类型 Value Name enumList enumTy Size (5)指针类型 TypePtr pointTy Size

3. 标识符的内部表示 其它属性依种类的不同而不同。 标识符名字Name 种类Kind 常量名、类型名、变量名、函数名、过程名。 Kind = ( consKind, typeKind, varKind, procKind, funcKind) 所属类型Typeptr:指向该标识符所属类型内部表示指针。 其它属性依种类的不同而不同。 Name Kind Typeptr …

(1)常量标识符的内部表示 其中各个域的含义如下: Name是常量的名字; Kind = constKind,表明该标识符是常量标识符; Value TypePtr Kind Name 其中各个域的含义如下: Name是常量的名字; Kind = constKind,表明该标识符是常量标识符; Type = TypePtr, 其中TypePtr是指向具体常量的类型的内部表示的指针; Value = ValPtr,其中ValPtr是指向具体常量值的内部表示的指针。

常量标识符pai 和count的内部表示为: #define pai 3.14 const int count=100 常量标识符pai 和count的内部表示为: ↑<3.14> realPtr constKind pai ↑<100> intPtr constKind count

(2)变量标识符的内部表示 其中各个域的含义如下: Name是变量的名字; Kind = varKind,表明该标识符是变量标识符; Off Level Access TypePtr Kind Value Name 其中各个域的含义如下: Name是变量的名字; Kind = varKind,表明该标识符是变量标识符; Type = TypePtr, 其中TypePtr是指向具体变量的类型的内部表示的指针;

Access = dir表示变量是直接变量,Access = indir表示变量是间接变量; Off Level Access TypePtr Kind Value Name 其中各个域的含义如下: Access = dir表示变量是直接变量,Access = indir表示变量是间接变量; Level表示该变量声明所在主程序/函数/过程的层数; Off表示该变量相对它所在主程序/函数/过程的内存块起始地址的偏移量; Value = ValPtr, 如果变量定义时说明了初值,则为初值的内部表示的指针,否则为空。

变量标识符x、y和z的内部表示为(当前层为L,当前偏移量为off ): 例: C语言的变量声明: int x=10; float y; float* z; 变量标识符x、y和z的内部表示为(当前层为L,当前偏移量为off ): off L dir intPtr varKind ↑<10> x Off+1 L dir realPtr varKind null y Off+3 L indir varKind null z realPtr pointTy 1

(3) 类型标识符的内部表示 其中各个域的含义如下: Name是类型标识符的名字; TypePtr Kind Name 其中各个域的含义如下: Name是类型标识符的名字; Kind = typeKind, 表示标识符是类型标识符; Type = TypePtr, 指向类型标识符指代的类型的内部表示。

类型标识符t1和t2的内部表示为: 例: C语言的类型定义: typedef int t1; typedef int t2 [10]; Size Kind 1 intTy intPtr typeKind t1 typeKind t2 ElemType intPtr Size Kind 10 ArrayTy Low Up 9

(4) 过程/函数标识符的内部表示 函数定义一般需包含两部分的内容, --函数头:定义函数的名字和形式参数的名字、类型和个数,以及函数返回值的类型; --函数体:定义函数的语句序列,即函数的功能部分的具体体现。 int f ( int x, float* y) ......"头" { ...... f的函数体部分 }

有函数体部分的过/函称为实在过/函,而出现在其他过/函定义的参数部分的过/函称为形式过/函,因为它们只是起着说明参数的性质的作用,并没有实际的函数体部分,只有形实参结合时,才能获得真正的函数体。 C语言的函数定义: int f ( int x, float* y, int inc(int *a)) ......"头" { ...... f的函数体部分 }

过程/函数标识符的内部表示 其中各个域的含义如下: Name是过/函标识符的名字; Forward Size Code Class Param Level Kind TypePtr off 其中各个域的含义如下: Name是过/函标识符的名字; TypePtr表示函数返回值类型的内部表示(过程情形是NULL) Kind = routKind; Level表示过/函的层数; Off只对形式过/函有效,表示形式过/函在所属过/函内存块中的偏移。形式过/函在内存中占2个字节空间,用于存入口地址;

过程/函数标识符的内部表示(续3) 其中各个域的含义如下: Name Forward Size Code Class Param Level Kind TypePtr off 其中各个域的含义如下: Param表示过/函的参数表指针,参数表的结构同符号表的结构相同,参数信息可以填入符号表,也可以填入单独的参数表当中; Class= actual表示实在过/函,Class = formal表示形式过/函; Code只对实在过/函有效,表示过/函定义对应生成的目标代码的起始地址,当目标代码生成时回填得到,形式过/函的code为NULL;

过程/函数标识符的内部表示(续4) 其中各个域的含义如下: Name Forward Size Code Class Parm Level Kind TypePtr off 其中各个域的含义如下: Size只对实在过/函有效,表示过/函所占内存区的大小,也要当目标代码生成以后回填得到; Forward 属性只对实在过/函有效,Forward= true表示过/函是超前声明, Forward = false表示过/函不是超前声明。

dir intPtr varKind x indir varKind y dir intPtr varKind a 例:C语言的函数定义: int f(int x,float* y, int inc(int a)) ......"头" { ......f的函数体部分 } Name TypePtr Kind Level off Parm Class Code Size Forward f false XXX actual L routKind intPtr off0 L+1 dir intPtr varKind x off0+1 L+1 indir varKind y realPtr pointTy 1 inc formal L+1 routKind intPtr off0 +2 dir intPtr varKind a

标示符内部表示 (1)常量标识符的内部表示 (2)变量标识符的内部表示: (3)类型标识符的内部表示 (4)过程/函数标识符的内部表示 Name Kind Typeptr … (1)常量标识符的内部表示 Value Typeptr constKind Name (2)变量标识符的内部表示: Off Level Access TypePtr varKind Value Name (3)类型标识符的内部表示 TypePtr typeKind Name (4)过程/函数标识符的内部表示 Name Forward Size Code Class Param Level TypePtr routKind off