第7章语义分析与中间代码生成内容摘要:
struct node *next。 } node。 xx yy nn ee xx tt 0 4 8 2020/11/17 45 记录的翻译 符号表及有关表格处理 为每个记录类型单独构造一张符号表 将域名 id的信息 (名字、类型、字节数 )填入到该记录的符号表中 所有域都处理完后, offset将保存记录中所有数据对象的宽度总和 record应用于指向该记录符号表的指针获得 2020/11/17 46 记录的翻译 T record D end T record L D end { := record(top(tblptr))。 := top(offset)。 pop(tblptr)。 pop(offset) } L {t := mktable(nil)。 push(t,tblprt)。 push(0,offset)} 2020/11/17 47 赋值语句的翻译 翻译的需求 充分了解各种语言现象的语义 包括:控制结构、数据结构、单词 充分了解它们的实现方法 目标语言的语义 了解中间代码的语义 了解运行环境 2020/11/17 48 辅助子程序与语义属性设置 辅助子程序 gencode(code), emit(code):产生一条中间代码 newtemp:产生新的临时变量 lookup:检查符号表中是否出现某名字 语义属性设置 中间代码序列: code 地址: addr 下一条四元式序号: nextquad 2020/11/17 49 简单赋值语句的翻译 S id := E {p := lookup()。 if p nil then gencode( p, ‘:=’, ) else error } E E1 + E2{ := newtemp。 emit(,‘:=’,‘+’,)} E E1 { := newtemp。 emit(,‘:=’,‘uminus’,)} E (E1) { := } E id {p := lookup()。 if p nil then := p else error } 2020/11/17 50 临时名字的重用 大量临时变量的使用对优化有利 大量临时变量会增加符号表管理的负担 也会增加运行时临时数据占的空间 E E1 + E2的动作产生的代码的一般形式为 计算 E1到 t1 计算 E2到 t2 t3 := t1 + t2 (( ))((( )( ))( )) 临时变量的生存期像配对括号那样嵌套或并列 2020/11/17 51 基于临时变量生存期特征的三地址代码 x := a b + c d e f 语 句 计数器 c的值 0 $0 := a b 1 $1 := c d 2 $0 := $0 + $1 1 $1 := e f 2 $0 := $0 $1 1 x := $0 0 引入一个计数器 c,它的初值为 0。 每当临时变量仅作为运算对象使用时, c减去 1;每当要求产生新的临时名字时,使用 $c并把 c增加 1。 2020/11/17 52 数组元素的寻址 数组元素引用的翻译 完成上下界检查 生成完成相对地址计算的代码 目标 x := y[i] 和 y[i] := x y为数组地址的固定部分 ——相当于第 1个元素的地址, i是相对地址,不是数组下标 数组说明的翻译 •符号表及有关表格 (内情向量 )的处理 •维数、下标上界、下标下界、类型等 •首地址、需用空间计算 •按行存放、按列存放 ——影响具体元素地址的计算 2020/11/17 53 数组元素地址计算 ——行优先 一维数组 A[low1:up1] (nk=upklowk+1) addr(A[i])=base+(ilow1)*w =(baselow1*w)+i*w=c+i*w 二维数组 A[low1:up1 ,low2:up2]; A[i1,i2] addr(A[i1,i2])=base+((i1 low1)*n2+(i2low2))*w = base+(i1 low1)*n2*w+(i2low2)*w = base low1* n2*wlow2*w +i1 * n2*w+ i2*w = base(low1* n2 low2)*w +(i1 * n2 + i2)*w =c+(i1*n2+ i2)*w A[1, 1], A[1, 2], A[1, 3] A[2, 1], A[2, 2], A[2, 3] 2020/11/17 54 数组元素地址计算的翻译方案设计 下标变量访问的产生式 L id[Elist] | id Elist Elist, E | E 为了使数组各维的长度 n在我们将下标表达式合 并到 Elist时是可用的 , 需将产生式改写为: L Elist ] | id Elist Elist, E | id[E 2020/11/17 55 数组元素地址计算的翻译方案设计 L Elist ] | id Elist Elist, E | id[E 目的 使我们在整个下标表达式列表 Elist的翻译过程中随时都能知道符号表中相应于数组名 id的表项,从而能够了解登记在符号表中的有关数组 id的全部信息。 于是我们就可以为非终结符 Elist引进一个综合属性,用来记录指向符号表中相应数组名字表项的指针。 2020/11/17 56 数组元素地址计算的翻译方案设计 属性 ,用来记录指向符号表中相应数组名字表项的指针。 ,用来记录 Elist中下标表达式的个数,即数组的维数。 ,用来临时存放 Elist的下标表达式计算出来的值。 函数 limit(array, j),返回 nj 2020/11/17 57 带有数组引用的赋值语句的翻译 S Left := E E E + E E (E) E Left Left Elist] Left id Elist Elist,E Elist id[E 2020/11/17 58 赋值语句的翻译模式 Leftid { :=。 :=null} Elistid[E {:=。 := 1。 := } ElistElist1,E {t:=newtemp。 m:=+1。 gencode(t,‘:=’,‘’, limit(,m))。 gencode(t,‘:=’,t,‘+’,)。 :=。 := t。 := m} Left Elist] { := newtemp。 := newtemp。 gencode(,‘:=’,base(),‘’,invariant())。 gencode(,‘:=’,‘’,w)} i1*n2 (i1*n2)+i2 ((i1*n2)+i2)*w base(low1* n2 low2)*w 2020/11/17 59 赋值语句的翻译模式 E Left {if = null then / Left是简单变量 / := else begin := newtemp。 gencode(,‘:=’,‘[’,‘]’)end} E E1 + E2 { := newtemp。 gencode(,‘:=’,‘+’,)} E (E1) { := } S Left := E {if =null then /Left是简单变量 / gencode(, ‘:= ’, ) else gencode(,‘[’,‘]’,‘:=’,)} ((i1*n2)+i2)*w+(base(low1* n2 low2)*w) ((i1*n2)+i2)*w+(base(low1* n2 low2)*w) 2020/11/17 60 例:设 A是一个 10 20的整型数组 ——w=4 S := := x := null x := t4 := t2 := t3 := t1 := 2 := A , := y := 1 := A := z := z := null := y := y := null A [ z ] y x := A[ y, z ]的注释分析树 2020/11/17 61 例 S := := x := null x := t4 := t2 := t3 := t1 := 2 := A , := y := 1 := A := z := z := null := y := y := null A [ z ] y x := A[ y, z ]的注释分析树 t1 := y 20 t1 := t1 + z 2020/11/17 62 例 S := := x := null x := t4 := t2 := t3 := t1 := 2 := A , := y := 1 := A := z := z := null := y := y := null A [ z ] y x := A[ y, z ]的注释分析树 t1 := y 20 t1 := t1 + z t2 :=baseA 84 t3 := 4 t1 2020/11/17 63 例 S := := x := null x := t4 := t2 := t3 := t1 := 2 := A , := y := 1 := A := z := z := null := y := y := null A [ z ] y x := A[ y, z ]的注释分析树 t1 := y 20 t1 := t1 + z t4 := t2 [t3 ] t2 :=baseA 84 t3 := 4 t1 2020/11/17 64 例 S := := x := null x := t4 := t2 := t3 := t1 := 2 := A , := y := 1 := A := z := z := null := y := y := null A [ z ] y x := A[ y, z ]的注释分析树 t1 := y 20 t1 := t1 + z t4 := t2 [t3 ] x := t4 t2 :=baseA 84 t3 := 4 t1 2020/11/17 65 类型检查 类型检查具有发现程序错误的能力 , 为了进行类型检查 , 编译程序需要为源程序的每个语法成分赋予一个类型表达式 , 名字的类型表达式保存在符号表中 , 其他语法成分 (如表达式 E或语句 S)的类型表达式则作为文法符号的属性保存在语义栈中。 类型检查的任务就是确定这些类型表达式是否符合一定的规则 , 这些规则的集合通常称为源程序的类型系统 2020/11/17 66 类型检查的规则 类型综合 从子表达式的类型确定表达式的类型 要求名字在引用之前必须先进行声明 if f的类型为 s→t and x的类型为 s then 表达式 f(x)的类型为 t 类型推断 根据语言结构的使用方式来确定其类型 经常被用于从函数体推断函数类型 if f(x)是一个表达式 then 对某两个类型变量 α和 β,f具有类型 →β and。第7章语义分析与中间代码生成
相关推荐
mp。 x1, amp。 x2) 函数的参数有两类:输入参数和输出参数。 一般,输入参数用值传递,输出参数用指针传递。 在参数表中,输入参数放在前面,输出参数放在后面。 《 程序设计 》 程序设计 49 原型的改进 并不是每个一元二次方程都有两个不同根,有的可能有两个等根,有的可能没有根。 函数的调用者如何知道 x1和 x2中包含的是否是有效的解。 解决方案:让函数返回一个整型数。
()wake _ up _ pr oces s ()wake _ up ()_ up ()TASK _ZOMBLE sy s _ exi t () do _ exi t () WAIT ING STA TU Swake _ up _ i nt er ru pt i bl e ()do _ si gnal () SIG _ KILL || S I G _ C ON T wa k e _ up _
动脉瘤,大小约 10 10cm,与周围组织粘连紧密 切开瘤体,可见瘤壁增生水肿,附有大量脓性渗出物,瘤腔内形成分叶间隔,其内可见大量血栓及覆膜支架一枚 支架内可见附壁血栓,导致支架闭塞 组织和渗出物细菌培养 +药敏 手 术 资 料 —— 术中所见 2020/11/17 曲乐丰 15 手 术 资 料 —— 术中所见 假性动脉瘤巨大、粘连 2020/11/17 曲乐丰 16 手 术 资
可知:kZ的特征根为mikii,2,1, ( 5 ) 并且kZ与kW之间它们的特征向量与 XX 的特征向量相同,与k无关。 ( 6 ) 记: )()(ˆ)(ˆ)(ˆ kHkkEkM S E )(ˆ)(ˆ)( kkEkH