编译原理题库.docx
《编译原理题库.docx》由会员分享,可在线阅读,更多相关《编译原理题库.docx(33页珍藏版)》请在冰豆网上搜索。
编译原理题库
编译原理题库
§什么就是编译器?
§编译程序得结构分为几个阶段,各阶段得任务就是什么?
§遍、编译前端及编译后端得含义?
§编译程序得生成方式有哪些?
第二章§1、写一文法,使其语言就是偶正整数得集合。
§要求:
(1)允许0打头
(2)不允许0打头解:
(1)允许0开头得偶正整数集合得文法
E→NT|D
T→NT|D
N→D|1|3|5|7|9
D→0|2|4|6|8
(2)不允许0开头得偶正整数集合得文法
E→NT|D
T→FT|G
N→D|1|3|5|7|9
D→2|4|6|8
F→N|0
G→D|02、证明下述文法G[〈表达式〉]就是二义得。
〈表达式〉∷=a|(〈表达式〉)|〈表达式〉〈运算符〉〈表达式〉〈运算符〉∷=+||*|/解:
可为句子a+a*a构造两个不同得最右推导:
最右推导1
〈表达式〉Þ〈表达式〉〈运算符〉〈表达式〉Þ〈表达式〉〈运算符〉aÞ〈表达式〉*aÞ〈表达式〉〈运算符〉〈表达式〉*aÞ〈表达式〉〈运算符〉a
*aÞ〈表达式〉+a*aÞ
a+a*a最右推导2
〈表达式〉Þ〈表达式〉〈运算符〉〈表达式〉Þ〈表达式〉〈运算符〉〈表达式〉〈运算符〉〈表达式〉Þ〈表达式〉〈运算符〉〈表达式〉〈运算符〉aÞ〈表达式〉〈运算符〉〈表达式〉*aÞ〈表达式〉〈运算符〉a
*aÞ〈表达式〉+a*aÞ
a+a*a3、给出生成下述语言得上下文无关文法:
(1){anbnambm|n,m=0}
(2){1n0m1m0n|n,m=0}解:
(1){anbnambm|n,m=0}
S→AAA→aAb|ε
(2){1n0m1m0n|n,m=0}S→1S0|AA→0A1|ε第三章1、构造一个DFA,它接收∑={a,b}上所有满足下述条件得字符串:
字符串中得每个a都有至少一个b直接跟在其右边。
解:
已知∑={a,b},根据题意得出相应得得正规式为:
(b*abb*)*根据正规式画出相应得DFAM,如下图所示用子集法将其确定化
IIaIb{X,1,2,3,Y}{4}{2,3}{4}—{5,6,1,2,3,Y}{2,3}{4}{2,3}{5,6,1,2,3,Y}{4}{6,1,2,3,Y}{6,1,2,3,Y}{4}{6,1,2,3,Y}由DFA得状态图
用最小化方法化简得:
{0},{1},{2},{3,4},按顺序重新命名DFAM’
第四章练习1:
文法G[V]:
V→N|N[E]
E→V|V+E
N→i
就是否为LL
(1)文法,如不就是,如何将其改造成LL
(1)文法。
解:
LL
(1)文法得基本条件就是不含左递归与回溯(公共左因子),而G[V]中含有回溯,所以先消除回溯得到文法G’[V]:
IIaIb0121—3212314414XY(b*abb*)*XYb*abb*1eeeeXYb123456bbaeeeeeeeeeeee10243aaaabbbbb0312aaabbb
G’[V]:
V→NV’
V’→ε|[E]
E→VE’
E’→ε|+E
N→i由LL
(1)文法得充要条件可证G’[V]就是LL
(1)文法练习2:
有文法G[s]:
S→BA
A→BS|d
B→aA|bS|c
(1)证明文法G就是LL
(1)文法。
(2)构造LL
(1)分析表。
(3)写出句子adccd得分析过程解:
(1)一个LL
(1)文法得充要条件就是:
对每一个非终结符A得任何两个不同产生式A→α|β,有下面得条件成立:
①FIRST(α)∩FIRST(β)=Φ;
②若β*Þε,则有FIRST(α)∩FOLLOW(A)=Φ对于文法G[s]:
S→BA
A→BS|d
B→aA|bS|c其FIRST集如下:
FIRST(B)={a,b,c};
FIRST(A)={a,b,c,d};
FIRST(S)={a,b,c}。
其FOLLOW集如下:
首先,FOLLOW(S)={#};对S→BA有:
FIRST(A)\{ε}加入FOLLOW(B),即FOLLOW(B)={a,b,c,d};对A→BS有:
FIRST(S)\{ε}加入FOLLOW(B),即FOLLOW(B)={a,b,c,d};对B→aA有:
FOLLOW(B)加入FOLLOW(A),即FOLLOW(A)={a,b,c,d};对B→bS有:
FOLLOW(B)加入FOLLOW(S),即FOLLOW(S)={#,a,b,c,d};由A→BS|d得:
FIRST(BS)∩FIRST(d)={a,b,c}∩{d}=Φ;由B→aA|bS|c得:
FIRST(aA)∩FIRST(bS)∩FIRST(c)={a}∩{b}∩{c}=Φ。
由于文法G[s]不存在形如β→ε得产生式,故无需求解形如FIRST(α)∩FOLLOW(A)得值。
也即,文法G[S]就是一个LL
(1)文法。
(2)由G[s]:
S→BA
A→BS|d
B→aA|bS|c得FIRST(B)={a,b,c};
FOLLOW(B)={a,b,c,d};
FIRST(A)={a,b,c,d};
FOLLOW(A)={a,b,c,d};FIRST(S)={a,b,c}。
FOLLOW(S)={#,a,b,c,d}可构造LL
(1)预测分析表如下:
abcd#SS→BAS→BAS→BA
AA→BSA→BSA→BSA→d
BB→aAB→bSB→c
SS→BAS→BAS→BA
AA→BSA→BSA→BSA→d
BB→aAB→bSB→c
(3)在分析表得控制下,句子adccd得分析过程如下:
第五章1已知文法G[S]为:
S→a|∧|(T)
T→T,S|S
(1)计算G[S]得*****与LASTVT。
(2)构造G[S]得算符优先关系表并说明G[S]就是否为算符优先文法。
(3)给出输入串(a,(a,a))#得算符优先分析过程。
解:
文法:
S→a|∧|(T)
T→T,S|S
展开为:
S→aS→∧S→(T)
T→T,S
T→S
(1)*****
LASTVT表
非终结符
*****集
LASTVT集
S{a∧(}{a∧)}T{a∧(,}
{a∧),}
(2)算符优先关系表如下:
表中无多重入口所以就是算符优先(OPG)文法。
a∧
(),#a∧(),#
≮≮
≮
≮≮
≮
≮≮
≮≯≯≒≯≯≯≯≮≯≯≯≯≯≒(3)输入串(a,(a,a))#得算符优先分析过程为:
栈
当前字符
剩余输入串动作
##(#(a#(N#(N,#(N,(#(N,(a#(N,(N#(N,(N,#(N,(N,a#(N,(N,N#(N,(N#(N,(N)#(N,N#(N(a,,(a,,a))))))a,(a,a))#,(a,a))#(a,a))#(a,a))#a,a))#,a))#a))#a))#))#)#)#)####MoveinMoveinReduce:
S→aMoveinMoveinMoveinReduce:
S→aMoveinMoveinReduce:
S→aReduce:
T→T,SMoveinReduce:
S→(T)Reduce:
T→T,SMovein栈当前输入符号输入串说明#Saadccd#S→BA#ABaadccd#B→aA#AAaaadccd##AAddccd#A→d#Adddccd##Acccd#A→BS#SBcccd#B→c#Sccccd##Sccd#S→BA#ABccd#B→c#Acccd##Add##A→d#ddd######分析成功
#(N)#N##
Reduce:
S→(T)
第六章例1:
有文法:
S→(L)|a
L→L,S|S
给此文法配上语义动作子程序(或者说为此文法写一个语法制导定义),它输出配对括号得个数。
如对于句子(a,(a,a)),输出就是2。
解:
加入新开始符号S“与产生式S“→S,设num为综合属性,代表值属性,则语法制导定义如下:
产生式
语义规则
S"→S
print(S、num)
S→(L)
S、num:
=L、num+1
S→a
S、num:
=0
L→L1,S
L、num:
=L1、num+S、num
L→S
L、num:
=S、num例2:
构造属性文法,能对下面得文法,只利用综合属性获得类型信息。
D→L,id|L
L→Tid
T→int|real解:
属性文法(语法制导)定义:
产生式
语义规则
D→L,id
D、type:
=L、type
addtype(id、entry,L、type)
D→L
D、type:
=L、type
L→Tid
L、type:
=T、type
addtype(id、entry,T、type)
T→int
T、type:
=integer
T→real
T、type:
=real第七章例1:
给出下面表达式得逆波兰表示(后缀式):
(1)
a*(b+c)
(2)
if(x+y)*z=0
thens:
=(a+b)*celses:
=a*b*c解:
(1)abc+*
(2)xy+z*0=sab+c*:
=sab*c*:
=¥(注:
¥表示ifthenelse运算)例2:
请将表达式(a+b)*(c+d)(a+b)分别表示成三元式、间接三元式与四元式序列。
解:
三元式
间接三元式
(1)(+
a,
b)
间接三元式序列
间接码表
(2)(+
c,
d)
(1)(+
a,
b)
(1)
(3)(*
(1),
(2))
(2)(+
c,
d)
(2)
(4)(
(3),
/)
(3)(*
(1),
(2))
(3)
(5)(+
a,
b)
(4)(
(3),
/)
(4)
(6)(
(4),(5))
(5)(
(4),
(1))
(1)
(5)
四元式
(1)(+,
a,
b,t1)
(2)(+,c,
d,t2)
(3)(*,t1,t2,t3)
(4)(,t3,
/,t4)
(5)(+,a,
b,t5)
(6)(,t4,t5,t6)
例3:
请将下列语句
while(AB)doif(CD)thenX:
=Y+Z
翻译成四元式解:
假定翻译得四元式序列从(100)开始:
(100)ifABgoto(102)(101)goto(107)(102)ifCDgoto(104)(103)goto(100)(104)T∶=Y+Z(105)X∶=T(106)goto(100)(107)例4:
写出for语句得翻译方案解:
产生式
动作S→forEdoS1
S、begin:
=newlabel
S、first:
=newtemp
S、last:
=newtemp
S、curr:
=newtemp
S、code:
=gen(S、first“:
=”E、init)
||gen(S、last“:
=”E、final)
||gen(“if”S、first“”S、last“goto”S、next)
||gen(S、curr“:
=”S、first)
||gen(S、begin“:
”)
||gen(“if”S、curr“”S、Last“goto”S、next)
||S1、code
||gen(S、curr:
=succ(S、curr))
||gen(“goto”S、begin)E→v:
=initialtofinal
E、init:
=initial、place
E、final:
=final、place第八章例1:
C语言中规定变量标识符得定义可分为extern,externstatic,auto,localstatic与register五种存储类:
(1)对五种存储类所定义得每种变量,分别说明其作用域。
(2)试给出适合上述存储类变量得内存分配方式。
(3)符号表中登记得存储类属性,在编译过程中支持什么样得语义检查。
解:
(1)extern定义得变量,其作用域就是整个C语言程序。
externstatic定义得变量,其作用域就是该定义所在得C程序文件。
auto定义得变量,其作用域就是该定义所在得例程。
localstatic定义得变量,其作用域就是该定义所在得例程。
且在退出该例程时,该变量得值仍保留。
register定义得变量,其作用域与auto定义得变量一样。
这种变量得值,在寄存器有条件时,可存放在寄存器中,以提高运行效率。
(2)对extern变量,设置一个全局得静态公共区进行分配。
对externstatic变量,为每个C程序文件,分别设置一个局部静态公共区进行分配。
对auto与register变量,设定它们在该例程得动态区中得相对区头得位移量。
而例程动态区在运行时再做动态分配。
对localstatic变量,为每个具有这类定义得例程,分别设置一个内部静态区进行分配。
(3)实施标识符变量重复定义合法性检查,及引用变量得作用域范围得合法性检查。
第九章例1:
下面得程序执行时,输出得a分别就是什么?
若参数得传递办法分别为
(1)传名;
(2)传地址;(3)得结果;4)传值。
programmain(input,output);
procedurep(x,y,z);
begin
y∶=y+1;
z∶=z+x;
end;
begin
a∶=2;
b∶=3;
p(a+b,a,a);
printa
end、
解:
(1)参数得传递办法为“传名”时,a为9。
(2)参数得传递办法为“传地址”,a为8。
(3)参数得传递办法为“得结果”,a为7。
(4)参数得传递办法为“传值”,a为2。
例2:
过程参数得传递方式有几种?
简述“传地址”与“传值”得实现原理。
解:
参数得传递方式有下述几种:
传值,传地址,传名,得结果“传值”方式,这就是最简单得参数传递方法。
即将实参计算出它得值,然后把它传给被调过程。
具体来讲就是这样得:
1、形式参数当作过程得局部变量处理,即在被调过程得活动记录中开辟了形参得存储空间,这些存储位置即就是我们所说得实参或形式单元。
2、调用过程计算实参得值,并将它们得右值(rvalue)放在为形式单元开辟得空间中。
3、被调用过程执行时,就像使用局部变量一样使用这些形式单元。
“传地址”方式,也称作传地址,或引用调用。
调用过程传给被调过程得就是指针,指向实参存储位置得指针。
1、如实参就是一个名字或就是具有左值得表达式,则左值本身传递过去。
2、如实参就是一个表达式,比方a+b或2,而没有左值,则表达式先求值,并存入某一位置,
然后该位置得地址传递过去。
3、被调过程中对形式参数得任何引用与赋值都通过传递到被调过程得指针被处理成间接访问。
例3:
下面就是一个Pascal程序
programPP(input,output)
varK:
integer;
functionF(N:
integer):
integer
begin
ifN=0thenF:
=1
elseF:
=N*F(N1);
end;
begin
K:
=F(10);
、、、
end;当第二次(递归地)进入F后,*****得内容就是什么?
当时整个运行栈得内容就是什么?
解:
第十章例1:
何谓代码优化?
进行优化所需要得基础就是什么?
解:
对代码进行等价变换,使得变换后得代码运行结果与变换前代码运行结果相同,而运行速度加快或占用存储空间减少,或两者都有。
优化所需要得基础就是在中间代码生成之后或目标代码生成之后。
例2:
编译过程中可进行得优化如何分类?
最常用得代码优化技术有哪些?
解:
依据优化所涉及得程序范围,可以分为:
局部优化、循环优化与全局优化。
最常用得代码优化技术有1、删除多余运算2、代码外提3、强度削弱4、变换循环控制条件5、合并已知量与复写传播6、删除无用赋值例3:
试对以下基本块B2:
B:
=3
D:
=A+CE:
=A*C
F:
=D+EG:
=B*F
H:
=A+CI:
=A*C
J:
=H+IK:
=B*5
L:
=K+J
M:
=L应用DAG对它们进行优化,并就以下两种情况分别写出优化后得四元式序列:
(1)假设只有G、L、M在基本块后面还要被引用。
(2)假设只有L在基本块后面还要被引用。
解:
基本块对应得DAG如下:
B:
=3
D:
=A+CE:
=A*C
F:
=D+EG:
=B*F
H:
=A+CI:
=A*C
J:
=H+IK:
=B*5
L:
=K+JM:
=L例1一个编译程序得代码生成要着重考虑哪些问题?
解:
代码生成器得设计要着重考虑目标代码得质量问题,而衡量目标代码得质量主要从占用空间与执行效率两个方面综合考虑。
课后习题答案:
PP3666
(1)就是0~9组成得数字串
(2)最左推导:
NNDNDDNDDDDDDDDDDDDDNNDDDDNNDNDDDDDDDDÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞ0010120127334556568最右推导:
NNDNNDNNDNDNNDNDNNDNNDNDÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞ77272712712701274434886868568P368
文法:
最左推导:
EETTTFTiTiTFiFFiiFiiiETTFFFiFiEiETiTTiFTiiTiiFiiiÞ+Þ+Þ+Þ+Þ+Þ+Þ+Þ+ÞÞÞÞÞÞ+Þ+Þ+Þ+Þ+Þ+********()*()*()*()*()*()*()最右推导:
EETETFETiEFiEiiTiiFiiiiiETFTFFFEFETFEFFEiFTiFFiFiiiiiÞ+Þ+Þ+Þ+Þ+Þ+Þ+Þ+ÞÞÞÞÞ+Þ+Þ+Þ+Þ+Þ+Þ+**********()*()*()*()*()*()*()*()语法树:
/********************************
EEFTE+TFFT+iiiEEFTE-TFFT-iiiEEFT+TFFTiii*i+i+ii-i-ii+i*iP3699
句子iiiei有两个语法树:
P64–77
(1)
0
1
1
0
1
1确定化:
01{X}φ{1,2,3}φφφ{1,2,3}{2,3}{2,3,4}{2,3}{2,3}{2,3,4}{2,3,4}{2,3,5}{2,3,4}{2,3,5}{2,3}{2,3,4,Y}{2,3,4,Y}{2,3,5}{2,3,4}
0
1
0
0
0
1
1
0
0
1
0
1
1
1最小化:
0
1
0
0
1
0X1234Y5XY6012354012
0
1
0
1
1
1P64–12
(a)
a
a,b
a确定化:
ab{0}{0,1}{1}{0,1}{0,1}{1}{1}{0}φφφφ给状态编号:
ab012112203333
a
a
a
b
b
b
b
a最小化:
a
a
b
b
a
b(b)
b
b
a
a
b543012301201023
a
a
b
b
a
a
a已经确定化了,进行最小化最小化:
{{,},{,,,}}
012345011012423451305234523452410243535353524012435011012424{,}{}{,}{,}{,,,}{,,,}{,,,}{,,,}{,}{,}{,}{,}{,}{,}{,}{,}{{,},{,},{,}}{,}{}{,}{,}{,}abababababa=============={,}{,}{,}{,}{,}{,}{,}10243535353524
bab
b
b
a
a
b
aP81–11
(1)按照T,S得顺序消除左递归
递归子程序:
proc