编译原理清华大学第8章语法制导翻译和中间代码生成讲述.ppt
文本预览下载声明
* * * * * * * * * * * * * * * * * 8.7 简单说明语句的翻译 程序设计语言中的说明语句旨在定义各种形式的有名实体,如常量、变量、数组、记录(结构)、过程、子程序等等,说明语句的种类也多,对象说明、变量说明、类型说明、过程说明等等。 程序设计语言中最简单的说明句的语法描述为: D→integer〈namelist〉|real〈namelist〉 〈namelise〉→〈namelist〉,id|id 用上述文法来制导翻译(自下而上)存在着这样一个问题,我们只能在把所有的名字都归约成namelist后才能把它们的性质登记进符号表。这意味着namelist必须用一个队列(或栈)来保存所有这些名字。 文法改写: D→D1,id |integer id |realid 翻译方案: (1) D→integerid {enter(id,int); D.ATT∶=int} (2) D→realid {enter(id,real); D.ATT∶=real} (3) D→D1,id {enter(id,D1.ATT); D.ATT∶=D1.ATT} 8.8 含数组元素的赋值语句的翻译 数组的一般定义 a [l1:u1,l2:u2,…,lk:uk,…,ln:un] (1≤k≤n) 其中a是数组名,lk称为数组下界,uk称为数组上界,变量k是数组的维数。 一维数组a [l1:u1]: a [i] =起始地址 + 元素在数组中的线性序号 – 1 =b1 + ( i - l1) b1是数组a的起始地址。 考虑存储宽度ω, 则: a [i] =起始地址 + 元素在数组中的线性序号 – 1 =b1 + ( i - l1) * ω 整理后有: a [i] =(b1 - l1) * ω + i * ω 令C=(b1 - l1) * ω, 则有: a [i] =C+ i * ω 二维数组a [l1:u1,l2:u2]: 必须事先约定存储顺序。常见的有按行存放和按列存放两种。如有一个2行3列的二维数组a [1:2,1:3],则有: 按行存放顺序为:a[1,1],a[1,2],a[1,3],a[2,1],a[2,2],a[2,3] 按列存放顺序为:a[1,1],a[2,1],a[1,2],a[2,2],a[1,3],a[2,3] 存放顺序不一样则数组元素存储地址的计算就不一样,下面我们仅讨论按行存放方式的数组元素存储地址的计算。 例:A是10×20的二维数组。 按行存放: A[1 , 1] A[1 , 2] 第一行 . A[1, 20] A[2, 1] 第二行 A[10, 20] 第十行 . . . . . . . . . . . 按列存放: A[1 , 1] A[2 , 1] 第一列 . A[20, 1] A[1, 2] 第二列 A[1, 20] 第十列 . . . . . . . . . . . 例如:对于二维数组a [1:2,1:3], a [ i,j ] =起始地址 + 元素在数组中的线性序号 – 1 =b + ( i - 1) * 3+ ( j - 1) 一般地二维数组a [l1:u1,l2:u2],数组元素a [ i,j ] 的存储地址计算为: a [ i1,i2 ] =起始地址 + 元素在数组中的线性序号–1 =b +[(行数-1) * 每行个数+ 列数] - 1) =b + [((i1 - l1+1)- 1) * (u2- l1+1) + (i2 - l2+ 1) ]- 1) =b + [(i1 - l1) * n2 + (i2 - l2+ 1) ]- 1) =b-( l1* n2+ l2)+ [(i1* n2)+ i2] =C+ [(i1* n2)+ i2] 其中:n2=(u2- l1+1) 考虑存储宽度则有: a [ i1,i2 ] =C+
显示全部