向图 6-19 的翻译方案中加入对应于下列产生式的规则:
产生式 语义规则 E -> E1 * E2 { E.addr = new Temp(); E.code = E1.code || E2.code || gen(E.addr '=' E1.addr '*' E2.addr); } | +E1 { E.addr = E1.addr; E.code = E1.code; }
使用图 6-20 的增量式翻译方案重复练习 6.4.1
产生式 语义规则 E -> E1 * E2 { E.addr = new Temp(); gen(E.addr '=' E1.addr '*' E2.addr; } | +E1 { E.addr = E1.addr; }
使用图 6-22 的翻译方案来翻译下列赋值语句:
x = a[i] + b[j]
语法分析树:
三地址代码
t_1 = i * awidth t_2 = a[t_1] t_3 = j * bwidth t_4 = b[t_3] t_5 = t_2 + t_4 x = t_5
x = a[i][j] + b[i][j]
语法分析树:
三地址代码:
t_1 = i * ai_width t_2 = j * aj_width t_3 = t_1 + t_2 t_4 = a[t_3] t_5 = i * bi_width t_6 = j * bj_width t_7 = t_5 + t_6 t_8 = b[t_7] t_9 = t_4 + t_8 x = t_9
! x = a[b[i][j]][c[k]]
修改图 6-22 的翻译方案,使之适合 Fortran 风格的数据引用,也就是说 n 维数组的引用为 id[E1, E2, …, En]
仅需修改 L 产生式(同图 6-22 一样,未考虑消除左递归)
L -> id[A] { L.addr = A.addr; global.array = top.get(id.lexeme); } A -> E { A.array = global.array; A.type = A.array.type.elem; A.addr = new Temp(); gen(A.addr '=' E.addr '*' A.type.width; } A -> A1,E { A.array = A1.array; A.type = A1.type.elem; t = new Temp(); A.addr = new Temp(); gen(t '=' E.addr '*' A.type.length); gen(A.addr '=' A1.addr '+' t); }
令 a 表示一个 i*j 的数组,单个元素宽度为 w
a.type = array(i, array(j, w)) a.type.length = i a.type.elem = array(j, w)
将公式 6.7 推广到多维数据上,并指出哪些值可以被存放到符号表中并用来计算偏移量。考虑下列情况:
令 n_i 为第 i 维数组的元素个数,计算公式:n_i = h_i - l_i + 1
3. A[i_1]]…[i_k] = base + ( (i_1 - l_1) * n_2 * … * n_k + … + (i_k-1 - l_k-1) * n_k + (i_k - l_k) ) * w 4. A[i_1]]…[i_k] = base + ( (i_1 - l_1) + (i_2 - l_2) * n_1 + … + (i_k - l_k) * n_k-1 * n_k-2 * … * n_1 ) * w
一个按行存放的整数数组 A[i, j] 的下标 i 的范围为 1~10,下标 j 的范围为 1~20。每个整数占 4 个字节。假设数组 A 从 0 字节开始存放,请给出下列元素的位置:
计算公式:((i-1) 20 + (j-1)) 4
假定 A 是按列存放的,重复练习 6.4.6
计算公式:((j-1) * 10 + (j-1)) * 4
一个按行存放的实数型数组 A[i, j, k] 的下标 i 的范围为 1~4,下标 j 的范围为 0~4,且下标 k 的范围为 5~10。每个实数占 8 个字节。假设数组 A 从 0 字节开始存放,计算下列元素的位置:
计算公式:((i-1) 5 6 + j 6 + (k-5)) 8
假定 A 是按列存放的,重复练习 6.4.8
计算公式:((i-1) + j 4 + (k-5) 5 4) 8
Copyright© 2013-2020
All Rights Reserved 京ICP备2023019179号-8