北京大学 编译原理 期中考试
2011年《编译技术》第三次小测验
(2011年6月1日)
姓名:_______________ 学号:________________
(本次小测验闭卷。时间:50分钟)
1.[45pt] 简答
a)[10pt] (类型表达式)假设类型名link和cell的定义如下(PASCAL):
TYPE link = ^cell;
cell = record
info: integer;
next: link
end;
FUNCTION foo (x:integer, y:cell) : link;
请写出foo的类型表达式。
foo的类型表达式:
integer × cell → POINTER (cell)
其中,cell的类型表达式: RECORD((info×integer)×(next×POINTER(cell))
a)[15pt] (语义检查)在C语言中,3++ 和(id+id)++这样的表达式
在编译时会报告如下的错误: invalid lvalue in increment。
现有如下简化的C语言表达式文法:
E → E +E | (E) | E++ | id | num
设计一个语法制导的翻译模式,使其能够检查 “++” 运算符的运算对象
是否合法。(如果不合法,输出上述的错误消息)。
E’→E { }
E → E1 + E2{ E.val := rvalue }
E → (E1) { E.val := E1.val }
if
(E1.val = rvalue) then
E → E1++ {
print(“invalid lvalue in increment”)
E.val := rvalue }
E → id { E.val := lvalue }
E → num { E.val := rvalue }
b)[12pt] (参数传递方式)给定Pascal的程序:
program main(input, output);
var a,b : integer;
procedure p(x,y,z: integer);
begin
y:= y+1; z:= z+x;
end;
begin
a:= 3; b:= 4;
p(a+b, a, a);
print a;
end.
假定采用如下的过程参数传递方式,上述程序的输出结果分别是什么?
(i) 传值调用:__________3_________________
(ii) 引用调用:__________11__________________
(iii) “复制-恢复”调用:________10_________________
(iv) 换名调用:_____________12___________________
c)[8pt] (运行时存储分配)一个PASCAL程序(采用栈式存储分配,用
存取链实现对非局部名字的访问)由主程序M和过程P、Q、R、S、T 构成,它们之间的全部包含关系是:M直接包含P和Q;P直接包含R 和S;Q直接包含T。这里用X→Y表示X调用Y。
当调用为M→P→P→R→Q→T→S时,画出此时栈中活动记录示意图。
活动记录只需给出控制链、存取链及相应的过程名字。
2.[30pt] (翻译模式)【注意:只允许使用继承和综合属性,不许使用全局变量】
设有文法:
S → (L) | a
L →L, S | S
a)设计一个适合自底向上分析的语法制导翻译模式,输出括号的对数。例
如,对于句子 (a, (a, a)),输出的结果是 2 (共包含两对括号)。【提示:添加S’ →S对文法进行拓广。】
S’ →S { print (S.count) }
S →(L) { S.count := L.count + 1}
S → a { S.count := 0 }
L →L1, S { L.count := L1.count + S.count }
L →S { L.count := S.count }
b)设计一个适合自顶向下分析的语法制导翻译模式,输出每个a的嵌套深
度。例如,对于句子 (a, (a,a)),输出的结果是 1 2 2。【提示:添加S’ →S
对文法进行拓广。】
S’ →{ S.depth := 0 } S
S →( { L.depth := S.depth +1 } L )
S → a { print(S.depth) }
L → { S.depth :=L.depth } S, { L1.depth := L.depth } L1
L →{ S.depth := L.depth } S
3.[25pt] 中间代码生成
设有说明(假设real占8个字节,integer占4个字节。):
var a: array[‐10..1, ‐1..10] of real;
rv: record i:integer
rec: record j:integer; k:integer end;
end;
x, y, z : integer;
给出下列语句的中间代码和相应的S.nextlist。
switch (x) {
case 10: if (y case 20: while(y default: x:=0 } (1)goto (24) (2)if y (3)goto ( ) (4)t1:= x+5 (5)t2:= ‐2*12 (6)t2:= t2+t1 (7)t3:= a+968 (8)t4:= 8*t2 (9)t5:= rv+8 (10)t6:= *t5 (11)t7:= t6+1 (12)t8:= inttoreal t7 (13)t3[t4]:=t8 (14)goto ( ) (15)if y (16)goto (20 ) (17)t9:= y+1 (18)y:= t9 (19)goto (15) (20)z:= 1 (21)goto ( ) (22)x:= 0 (23)goto ( ) (24)if (x=10) goto (2) (25)if (x=20) goto (15) (26)goto (22) S.nextlist = {3, 14, 21, 23}