2001级编译原理试题(B)
2003.12
一、简答题(60分)
1. 编译程序在逻辑上由哪几部分组成?
六个阶段: 词法分析,语法分析,语义分析,中间代码生成,中间代码优化和目标代码生成。
2. 编译程序和解释程序有哪些区别?
解释程序是源程序的一个执行系统,而编译程序是源程序的一个转换系统;解释器直接由源程序得到运行结果,而编译器是生成等价于源程序的某种目标机程序。
3. 给出能被3整除的二进制数表示形式的正则定义。
S(0A | 1 B
A(0A | 1 B | 0
B(0C | 1 A | 1
C(0B | 1 C
4. 给出识别正则表达式((a|bc)*d)+的NFA 。
5. 已知文法G[S]: S → S;G│G
G → G(T)│ H
H → a │ (S)
T → T+S │ S
找出句型:a(T+S);H;(S)的短语、简单短语和句柄。
短语: a, T+S, a(T+S) , H , a(T+S);H , (S)
简单短语:a , T+S , H , (S) 句柄是 a .
6. 已知文法G[S]为:
S→AB | bC A→b | λ
B→aD | λ C→AD | b
D→aS | c
对其每一个非终级符求First集和Follow集。
First (S) = { b , a , λ }
First (A) = { b , λ }
First (B) = { a , λ }
First (C) = { b , a , c }
First (D) = { a , c }
Follow (S) = { # }
Follow (A) = { a , c , #}
Follow (B) = { # }
Follow (C) = { # }
Follow (D) = { # }
7.什么是过程的活动记录?过程活动记录存储哪些信息?
过程的活动记录也就是过程的一个现场记录。每当调用一个过程时,因为当前过程被中断,需要保存现场,以便返回时执行被中断了的过程,为此要保存一些信息,这些信息就是放在过程的活动记录内。
过程活动记录存储的信息:
过程控制信息:包括返回地址、先行活动记录的动态链指针、层数和长度等。
机器控制信息:包括寄存器状态等过程中断时的机器状态。
全局变量信息:包括有关访问非局部变量的信息。
局部变量值: 包括形参变量、局部变量、和临时变量的值。
8.设对偶表(L,N)分别表示程序在当前位置的层数和偏移量,确定下面程序段中括号部分的内容。假设系统规定整型(int)变量占2个单元,实型(real)变量占4个单元。
(L, N) Type at = array of [1..10] of int;
(() var x :real;
(() function f ( ( ?,M) var a: at,
(() b: at,
(() var x: real ) : int
(() ( L , N) (() ( L , N + 4)
(() ( L+1 , M +1) (() ( L+1 , M +21)
9.设有语言L(G)={WaWR|W∈{a,c}*,WR为W之逆},试构造产生此语言的上下文无关文法G。
G: S( a S a | c S c | a
10.对下面文法
S ( ( L) L ( L ( S
S ( a L ( S
给出一个翻译方案,它输出每个a的嵌套深度。如句子(a, (a, a) ),输出是1 2 2。
S(< init > ( <inc> L ) < dec >
S( a < out >
L( L , S
L( S
< init>: k : = 0;
<inc> : k : = k + 1;
<dec>: k : = k -1;
<out>: print(k) ;
11.什么是Display表?它的作用是什么?
Display表用来表示变量访问环境,对于每一个AR,求出其变量访问环境,并把它以地址表的形式(Display表)保存在AR中,这样通过查询Display表就可以找到变量。
12.如下是当前执行某个过程时的活动记录,设变量x的层数和偏移量分别为L和Off,说明如何访问变量x。
sp
... ...
... ....
Add(x)=[sp+D+L]+Off
13.当实参为变量,形参分别为变参和值参时,传参的区别。
形参为变参时,AR中保存实参变量的地址,改变形参即改变实参变量;
形参为值参时,AR中保存形参变量,其初始值为实参的值,此后形参与实参没有联系。
14.寄存器的使用准则有哪些?
寄存器先行准则、寄存器活跃准则、寄存器多在准则。
15. 设有下面基本块,试写出各临时变量的活动区间。
( + , X, 1, T1 ) [1]
( - , A, T1, T2) [2]
( * , Y, T2, T3) [3]
( - , T3, T1, T4) [4]
(( , T3, Y ) [5]
( * ,T3, T4, T5) [6]
(( , T5, Z ) [7]
各临时变量的活动区间:T1: [1]~[4], T2: [2]~[3],T3:[3]~[6],
T4: [4]~[6], T5: [6]~[7]
二、(10分)设有文法G[A]: A ( iB*e
B ( SB|(
S ( [eC]|.i
C ( eC|(
判定该文法是否为LL(1)文法?若是则给出它的LL(1)分析表,否则说明理由。
先计算各个产生式的Predict集:
Predict (A-> iB*e)={ i };
Predict (B-> SB) ={ [ , .}
Predict (B->( ) ={ * }
Predict (S->[eC]) ={ [ }
Predict (S->. i) ={ . }
Predict (C-> eC) ={ e }
Predict (C->( ) ={ ] }
因为Predict集没有冲突,所以是LL(1)文法。
LL(1)分析表如下:
i
*
e
[
]
.
A
-> iB*e
-> (
B
->S B
->S B
S
->[e C]
->. i
C
->eC
-> (
三、(15分)设有文法G[S]: S ( LaR|R
L ( bR|c
R ( L
判断该文法是否为LR(1)文法。若是则给出它的LR(1)状态机以及LR分析表。
LR(1)状态机如下:
因为状态机中没有冲突,所以是LR(1)文法。
LR(1)分析表如下:
(1) S( LaR
(2) S( R
(3) L( bR
(4) L( c
(5) R( L
a
b
c
#
S
L
R
1
S6
S4
2
5
3
2
Acc
3
R2
4
R4
R4
5
S7
R5
6
S6
S4
8
9
7
S12
S13
11
10
8
R5
R5
9
R3
R3
10
R1
11
R5
12
S12
S13
11
14
13
R4
14
R3
四、(15分)给出如下程序段的中间代码,并将其优化为最简代码形式。(中间代码的操作符可用自身代替)。其中A:Array of [1..10] of Array [1..10] of integer。整型变量占1个存储单元。
a:=1;
while a<=10 do
begin if a<>b then
A[a,b]:=A[a,b]+2;
a:=a+1;
end
中间代码:
( : = ,1 , a )
(LABLE, L1 )
(LE , a , 10 ,t1 )
(JUMP0, L2)
(EQ, a , b , t2 )
(JUMP1 , L3)
(- , a , 1, t3)
(* , t3 ,10 ,t4 )
(- ,b , 1 ,t5)
(+ , t4 ,t5 ,t6)
(*, t6 , 1 ,t7 )
([], A ,t7 ,t8)
(+ , t8 , 2 ,t9)
(- , a , 1 ,t10)
(* , t10 , 10 ,t11)
(- , b ,1 ,t12)
(+, t11,t12, t13)
(* , t13,1 , t14)
([], A , t14, t15)
(:= ,t9 , t15)
(+, a , 1 , t16 )
(:= , t16 , a)
(LABLE,L3)
(JUMP , L1)
(LABLE, L2)
优化后的最间代码形式:
( : = ,1 , a )
(LABLE, L1 )
(LE , a , 10 ,t1 )
(JUMP0, L2)
(EQ, a , b , t2 )
(JUMP1 , L3)
(- , a , 1, t3)
(* , t3 ,10 ,t4 )
(- ,b , 1 ,t5)
(+ , t4 ,t5 ,t6)
(*, t6 , 1 ,t7 )
([], A ,t7 ,t8)
(+ , t8 , 2 ,t9)
(:= ,t9 , t8)
(+, a , 1 , t10 )
(:= , t10, a)
(17) (LABLE,L3)
(18) (JUMP , L1)
(LABLE, L2)