《编译原理(第2版)7-1语义出理概述.ppt》由会员分享,可在线阅读,更多相关《编译原理(第2版)7-1语义出理概述.ppt(21页珍藏版)》请在金锄头文库上搜索。
1、第七章语法制导翻译和中间代码生成7.1语义处理概述7.2属性文法和语法制导翻译7.3 中间代码生成(一些语句的翻译)7.4符号表源语言程序源语言程序中间代码中间代码汇编代码汇编代码词法分析词法分析语义分析语义分析语法分析语法分析中间代码生成中间代码生成代码生成代码生成在编译中的逻辑阶段在编译中的逻辑阶段前前端端处处理理后后端端处处理理语语义义处处理理7.1 语义处理(语义分析和中间代码生成)源语言程序源语言程序汇编代码汇编代码词法分析词法分析语义分析语义分析语法分析语法分析代码生成代码生成前前端端处处理理后后端端处处理理 语语义义处处理理语义处理语义处理语义处理的任务:静态语义检查静态语义:语
2、法规则的良形式条件静态语义检查:审查静态语义动态语义处理动态语义:程序单元执行的操作动态语义处理:生成(中间/目标)代码语义处理语义处理的实现:属性文法:描述语义规则。语法制导翻译:在语法分析的同时,执行语义规则描述的动作:检查静态语义生成中间代码/目标代码语义处理语义处理的环境:符号表为语义分析提供类型、作用域等信息。为代码生成提供类型、作用域、存储类别、存储(相对)位置等信息。语义处理if sym = callsym thenbegingetsym;if sym ident then error(14)elsebegin i := position(id);if i = 0 then er
3、ror(11)elsewith tablei doif kind = procedurthen gen(cal, lev-level, adr)else error(15);getsymend end PL/0编译程序的语义处理(一)编译程序的语义处理(一)call语句的处理语句的处理语义处理 error 11:标识符未说明; error 12:赋值语句中,赋值号左部的标识符属性应为 变量; error 15:call后标识符的属性应为过程; error 21:表达式内标识符属性不能为过程; error 32:read语句括号中的标识符不是变量。 PL/0编译程序的语义处理(二)语义错误列表P
4、L/0编译器的符号表const a=10;const a=10;varvar b,cb,c; ;procedure p;procedure p; beginbegin c:= c:=b+ab+a; ; end; end;beginbegin read(bread(b);); while while b#0b#0 do do begin begin call p; call p; write(2*c); write(2*c); read(bread(b);); end endendend. .namekindvalleveladdresssize a constant10 b variable
5、0 3c variable 0 4p procedure 03 编译程序分析到第编译程序分析到第8 8行时符号表的内容行时符号表的内容 const a=10;const a=10;varvar b,c; b,c;procedure p;procedure p; beginbegin c:=b+a; c:=b+a; end; end;beginbegin read(b); read(b); while while b#0b#0 do do begin begin call p; call p; write(2*c); write(2*c); read(b); read(b); end enden
6、d.end.( 0) ( 0) jmpjmp 0 8 0 8 转向转向主程序入口主程序入口( 1) ( 1) jmpjmp 0 2 0 2 转向转向过程过程p p入口入口( 2)( 2) intint 0 3 0 3 过程过程p p入口入口, ,为过程为过程p p开辟空间开辟空间( 3) ( 3) lodlod 1 1 3 3 取变量取变量b b的值到栈顶的值到栈顶( 4) lit 0 10 ( 4) lit 0 10 取常数取常数1010到栈顶到栈顶( 5) ( 5) opropr 0 2 0 2 次栈顶与栈顶相加次栈顶与栈顶相加( 6) ( 6) stosto 1 1 4 4 栈顶值送变量
7、栈顶值送变量c c中中( 7) ( 7) opropr 0 0 0 0 退栈并返回调用点退栈并返回调用点(16)(16)( 8)( 8) intint 0 5 0 5 主程序入口开辟主程序入口开辟5 5个栈空间个栈空间( 9) ( 9) opropr 0 16 0 16 从命令行读入值置于栈顶从命令行读入值置于栈顶(10) (10) stosto 0 3 0 3 将栈顶值存入变量将栈顶值存入变量b b中中(11) (11) lodlod 0 3 0 3 将变量将变量b b的值取至栈顶的值取至栈顶(12) lit 0 0 (12) lit 0 0 将常数值将常数值0 0进栈进栈(13) (13)
8、 opropr 0 9 0 9 次栈顶与栈顶是否不等次栈顶与栈顶是否不等(14) (14) jpcjpc 0 24 0 24 等时转等时转(24)(24)(条件不满足转条件不满足转)(15) (15) cal 0 2cal 0 2 调用过程调用过程p p(16) lit 0 2 (16) lit 0 2 常数值常数值2 2进栈进栈(17) (17) lodlod 0 0 4 4 将变量将变量c c的值取至栈顶的值取至栈顶(18) (18) opropr 0 4 0 4 次栈顶与栈顶相乘次栈顶与栈顶相乘(2(2*c)*c)(19) (19) opropr 0 14 0 14 栈顶值输出至屏幕栈顶
9、值输出至屏幕(20) (20) opropr 0 15 0 15 换行换行(21) (21) opropr 0 16 0 16 从命令行读取值到栈顶从命令行读取值到栈顶(22) (22) stosto 0 0 3 3 栈顶值送变量栈顶值送变量b b中中(23) (23) jmpjmp 0 11 0 11 无条件转到循环入口无条件转到循环入口(11)(11)(24) (24) opropr 0 0 0 0 结束退栈结束退栈归纳:语义分析(静态语义处理)(1)类型检查。验证程序中执行的每个操作是否遵守语言的类型系统的过程.,编译程序必须报告不符合类型系统的信息。(2)控制流检查。控制流语句必须使控
10、制转移到合法的地方。例如,在C语言中break语句使控制跳离包括该语句的最小while、for或switch语句。如果不存在包括它的这样的语句,则就报错。(3)一致性检查。在很多场合要求对象只能被定义一次。例如Pascal语言规定同一标识符在一个分程序中只能被说明一次,同一case语句的标号不能相同,枚举类型的元素不能重复出现等等。(4)相关名字检查。有时,同一名字必须出现两次或多次。例如,Ada 语言程序中,循环或程序块可以有一个名字,出现在这些结构的开头和结尾,编译程序必须检查这两个地方用的名字是相同的。 (5)名字的作用域分析类型检查程序的设计1.辨认语言中可用的类型2.辨认具有类型的语
11、言结构3.辨认语言的语义规则基础 类型的基本概念类型的基本概念数据类型的三要素: 用于区别这种数据类型的数据对象的属性 这种类型数据对象可以具有的值 可以施用在这种类型的数据对象上的操作数据类型分为:基本(初等)数据类型:数值数据,逻辑数据,字符数据,指针类型等。 复合数据类型:数组、结构、表、栈、树等。抽象数据类型:Ada的包(Package),C+的类(Class)等。类型的基本概念类型的等价关系和相容关系:等价关系如果在任何场合下,类型A和类型B的表达式都可以互相替代,则称类型A与类型B等价。相容关系如果在类型A的表达式出现的任何场合下,都可以用类型B的表达式替换,则称类型B相容于类型A
12、。类型的基本概念声明和定义,使用:声明:程序通过声明语句把标识符的名称、类型和作用域等信息传递给编译器。声明语句本身传递名字和类型信息,声明语句的位置传递作用域信息。定义:变量、类的声明就是定义。函数可以先声明一个原型,在定义中再给出实现的代码。类型的基本概念强类型语言和弱类型语言:强类型语言标识符必须先声明后才能使用。标识符的类型信息在编译时是已知的。例如:PASCAL, C弱类型语言标识符不声明就可以直接引用。标识符的类型信息在编译时不能确定,在运行时推测得到。例如:Lisp,ML运算符(函数)的重载 多态函数重载运算符(overloading operator)是指该符号有多个含义,但根
13、据上下文可以确定唯一的运算。如是重载符号,在AB中,当A和B为整数、实数、复数或者矩阵时,运算符执行不同类型的运算.当出现重载运算符时,要确定它所表示的唯一的意义,即进行运算符识别并检查运算符的操作数。多态函数(过程)-函数(过程)允许参数的类型变化.多态函数(过程)的特点是,每次被调用时,传递过来的参数可以具有不同类型。作用域分析分程序结构的作用域规则作用域分析的实现作用域作用域类型:Global scope在任何函数和类定义之外的区域。所声明的标识符具有全局作用域。Class scope特指类定义的作用域。所声明的类类型具有全局作用域。所声明的类成员具有类作用域。Function scop
14、e特指函数形参表中参数的作用域。所声明的函数具有全局作用域,或类作用域,或其它局部作用域。所声明的形参具有函数作用域。Local scope由定界符 /begin end分隔,定义在过程(函数)体或其它局部作用域(分程序)内。 所声明的标识符具有局部作用域。分程序结构语言的作用域规则当前开放的作用域中的标识符才能够被访问;在同一作用域中,不允许声明同名的标识符;在不同的作用域中,内层声明的标识符将遮蔽外层声明的同名标识符,使其变为不可见的。 int a; chara;floata; a 引用引用char a; 函数形参表中的变量在函数体中是可见的; int a;floatfunc(float
15、a,float b) aa引用引用float a;float a;分程序结构语言作用域举例(1) main()(2) int a;(3) (4) (5) bool a;(6) (7) (8) double a;(9) (10) (11) (12) a (13) (14) (15) (16) scope 3 scope 2 scope 1 scope 1: (1) - (16) scope 2: (4) - (14) 嵌套于嵌套于scope 1中中 scope 3: (7) - (10) 嵌套于嵌套于scope 2中中 scope 4: (11)- (12)嵌套于嵌套于scope 2中中 a(int) 在在scope 1中可见;中可见; a(bool) 在在scope 2, 4中可见;中可见; a(double)在在scope 3中可见中可见程序运行到第程序运行到第12行时:行时: scope 4是当前作用域;是当前作用域; scope 1, 2, 4是开放的作用域;是开放的作用域; scope 3是关闭的作用域。是关闭的作用域。 scope 4