1、Tianges reference1第一章 什么是编译器? 编译程序的结构分为几个阶段,各阶段的任务是什么? 遍、编译前端及编译后端的含义? 编译程序的生成方式有哪些?第二章 1. 写一文法,使其语言是偶正整数的集合。 要求:(1)允许 0 打头 (2) 不允许 0 打头解:(1)允许 0 开头的偶正整数集合的文法ENT|DTNT|DND|1|3|5|7|9D0|2|4|6|8(2)不允许 0 开头的偶正整数集合的文法ENT|DTFT|GND|1|3|5|7|9D2|4|6|8FN|0GD|02.证明下述文法 G表达式 是二义的。表达式=a|(表达式)|表达式 运算符 表达式运算符=+|-|*
2、|/解:可为句子 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 SAA
3、AaAb| Tianges reference2(2) 1n0m1m0n| n,m=0S1S0|AA0A1|第三章1、构造一个 DFA,它接收=a, b上所有满足下述条件的字符串:字符串中的每个 a 都有至少一个 b 直接跟在其右边。解:已知=a, b,根据题意得出相应的的正规式为: (b*abb*)*根据正规式画出相应的 DFA M,如下图所示用子集法将其确定化XY(b*abb*)*XYb*abb*1XYb12 3456bba I Ia IbX,1,2,3,Y 4 2,34 5,6,1,2,3,Y2,3 4 2,35,6,1,2,3,Y4 6,1,2,3,Y6,1,2,3,Y 4 6,1,2
4、,3,Y由 DFA 得状态图 用最小化方法化简得: 0,1,2,3,4,按顺序重新命名 DFA MI Ia Ib0 1 21 32 1 23 1 44 1 4Tianges reference3102 43a aa abbbbb 0 312aa abbb第四章练习 1:文法 GV:VN|NE EV|V+E Ni是否为 LL(1)文法,如不是,如何将其改造成 LL(1)文法。解:LL(1)文法的基本条件是不含左递归和回溯(公共左因子) ,而 GV中含有回溯,所以先消除回溯得到文法 GV:GV: VNV V|E EVE E|+ENi由 LL(1)文法的充要条件可证 GV是 LL(1)文法练习 2:
5、有文法 Gs:SBA ABS|d BaA|bS|c(1)证明文法 G 是 LL(1)文法。(2)构造 LL(1)分析表。(3)写出句子 adccd 的分析过程解:(1)一个 LL(1)文法的充要条件是:对每一个非终结符 A 的任何两个不同产生式A|,有下面的条件成立: FIRST()FIRST()=; 若 *, 则有 FIRST()FOLLOW(A)=对于文法 Gs: SBA ABS|d BaA|bS|c其 FIRST 集如下:FIRST(B)=a, b, c; FIRST(A)=a, b, c, d; FIRST(S)=a, b, c。其 FOLLOW 集如下:首先, FOLLOW(S)=#
6、;对 SBA 有: FIRST(A)加入 FOLLOW(B), 即 FOLLOW(B)=a, b, c, d ;对 ABS 有:FIRST(S)加入 FOLLOW(B), 即 FOLLOW(B)=a, b, c, d ;对 BaA 有:FOLLOW(B)加入 FOLLOW(A), 即 FOLLOW(A)=a, b, c, d ;对 BbS 有:FOLLOW(B)加入 FOLLOW(S), 即 FOLLOW(S)=#, a, b, c, d ;由 ABS|d 得:FIRST(BS) FIRST(d) = a, b, c d = ;由 BaA|bS|c 得: FIRST(aA) FIRST(bS)
7、 FIRST(c) =a b c= 。由于文法 Gs不存在形如 的产生式,故无需求解形如 FIRST()FOLLOW(A)的值。Tianges reference4也即,文法 GS是一个 LL(1)文法。(2) 由 Gs:SBA ABS|d BaA|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)预测分析表如下:a b c d #S SBA SBA SBA A A
8、BS ABS ABS Ad B BaA BbS Bc S SBA SBA SBA A ABS ABS ABS Ad B BaA BbS Bc (3)在分析表的控制下,句子 adccd 的分析过程如下:第五章1 已知文法 GS为:Sa|(T) TT,S|S (1) 计算 GS的 FIRSTVT 和 LASTVT。(2) 构造 GS的算符优先关系表并说明 GS是否为算符优先文法。(3) 给出输入串 (a,(a,a)#的算符优先分析过程。解:文法:Sa|(T) TT,S|S 展开为: Sa S S(T) TT,S TS(1) FIRSTVT - LASTVT 表 非终结符 FIRSTVT 集 LAS
9、TVT 集 栈 当 前 输 入 符 号 输 入 串 说 明#S a dccd# S BA#AB a dccd# B aA#AAa a dccd#AA d ccd# A d#Ad d ccd#A c cd# A BS#SB c cd# B c#Sc c cd#S c d# S BA#AB c d# B c#Ac c d#A d # A d#d d # # 分 析 成 功Tianges reference5S a ( a ) T a ( , a ) , (2)算符优先关系表如下: 表中无多重入口所以是算符优先(OPG)文法。 a ( ) , #a(),# (3) 输入串(a,(a,a))# 的算符
10、优先分析过程为:栈 当前字符 剩余输入串 动作 #(#(a#(N#(N,#(N,(#(N,(a#(N,(N#(N,(N,#(N,(N,a#(N,(N,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)#)#)#)#)#Move inMove inReduce: SaMove inMove inMove inReduce: SaMove inMove inReduce: SaReduce: TT,SMove inReduce: S(T)Reduce: TT,SMove inReduce:
11、S(T) 第六章例 1:有文法: S(L)|a LL,S|S给此文法配上语义动作子程序(或者说为此文法写一个语法制导定义),它输出配对括号的个数。如对于句子(a,(a,a),输出是 2。解:加入新开始符号 S和产生式 SS,设 num 为综合属性,代表值属性,则语法制导定义如下:产生式 语义规则SS print(S.num)S(L) S.num:=L.num+1Sa S.num:=0Tianges reference6LL1,S L.num:=L1.num+S.numLS L.num:=S.num例 2:构造属性文法,能对下面的文法,只利用综合属性获得类型信息。D L,id | L L T i
12、d T int | real解:属性文法(语法制导)定义:产生式 语义规则D L,id D.type:=L.typeaddtype(id.entry,L.type)D L D.type:=L.typeL T id L.type:=T.typeaddtype(id.entry,T.type)T int T.type:=integerT real T.type:=real第七章例 1:给出下面表达式的逆波兰表示(后缀式):(1) a*(-b+c)(2) if(x+y)*z=0 then s:=(a+b)*c else s:=a*b*c解:(1) ab-c+*(2) xy+z*0=sab+c*:=s
13、ab*c*:=¥(注:¥表示 if-then-else 运算)例 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)
14、(2) (+, c, d, t2)(3) (*, t1, t2, t3) (4) (-, t3, /, t4)(5) (+, a, b, t5) (6) (-, t4, t5, t6) 例 3:请将下列语句while (AD) then X:=Y+Z翻译成四元式解:假定翻译的四元式序列从(100)开始:(100) if AD goto(104)Tianges reference7(103) goto (100)(104) T=Y+Z(105) X=T(106) goto (100)(107)例 4:写出 for 语句的翻译方案解:产生式 动作S for E do S1 S.begin := n
15、ewlabelS.first := newtempS.last := newtempS.curr:= newtempS.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
16、:=initial to final E.init := initial.placeE.final := final.place第八章例 1:C 语言中规定变量标识符的定义可分为 extern, extern static, auto, local static 和 register 五种存储类:(1) 对五种存储类所定义的每种变量,分别说明其作用域。(2) 试给出适合上述存储类变量的内存分配方式。(3) 符号表中登记的存储类属性,在编译过程中支持什么样的语义检查。解:(1) extern 定义的变量,其作用域是整个 C 语言程序。extern static 定义的变量,其作用域是该定义所在的
17、 C 程序文件。auto 定义的变量,其作用域是该定义所在的例程。local static 定义的变量,其作用域是该定义所在的例程。且在退出该例程时,该变量的值仍保留。register 定义的变量,其作用域与 auto 定义的变量一样。这种变量的值,在寄存器有条件时,可存放在寄存器中,以提高运行效率。(2) 对 extern 变量,设置一个全局的静态公共区进行分配。对 extern static 变量,为每个 C 程序文件,分别设置一个局部静态公共区进行分配。对 auto 和 register 变量,设定它们在该例程的动态区中的相对区头的位移量。而例程动态区在运行时再做动态分配。对 local
18、 static 变量,为每个具有这类定义的例程,分别设置一个内部静态区进行分配。Tianges reference8(3) 实施标识符变量重复定义合法性检查,及引用变量的作用域范围的合法性检查。第九章例 1:下面的程序执行时,输出的 a 分别是什么?若参数的传递办法分别为(1)传名;(2)传地址;(3)得结果;4)传值。 program main (input,output);procedure p(x,y,z); beginy=y+1; z=z+x;end; begina=2; b=3; p(a+b,a,a); print a end. 解:(1) 参数的传递办法为“传名”时,a 为 9。(
19、2) 参数的传递办法为“传地址” ,a 为 8。(3) 参数的传递办法为“得结果” ,a 为 7。(4) 参数的传递办法为“传值” ,a 为 2。 例 2:过程参数的传递方式有几种?简述“传地址”和“传值”的实现原理。解:参数的传递方式有下述几种:传值,传地址,传名,得结果“传值”方式,这是最简单的参数传递方法。即将实参计算出它的值,然后把它传给被调过程。具体来讲是这样的:1.形式参数当作过程的局部变量处理,即在被调过程的活动记录中开辟了形参的存储空间,这些存储位置即是我们所说的实参或形式单元。2.调用过程计算实参的值,并将它们的右值(r-value)放在为形式单元开辟的空间中。3.被调用过程
20、执行时,就像使用局部变量一样使用这些形式单元。“传地址”方式,也称作传地址,或引用调用。调用过程传给被调过程的是指针,指向实参存储位置的指针。1.如实参是一个名字或是具有左值的表达式,则左值本身传递过去。2.如实参是一个表达式,比方 a+b 或 2,而没有左值,则表达式先求值,并存入某一位置,然后该位置的地址传递过去。3.被调过程中对形式参数的任何引用和赋值都通过传递到被调过程的指针被处理成间接访问。例 3:下面是一个 Pascal 程序program PP(input,output)var K:integer;function F(N:integer):integerbeginif N) a
21、nd sym ( , 是算符文法,并且是算符优先文法6G(3)优先函数a ( ) ,f 4 4 2 4 4g 5 5 5 2 3aff(f)f,Tianges reference20gag()g,(4)栈 输入字符串 动作# (a,(a,a))# 预备#( a, (a,a)# 进#(a , (a,a)# 进#(s , (a,a)# 归#(t , (a,a)# 归#(t, (a,a))# 进#(t,( a,a) )# 进#(t,(a ,a) )# 进#(t,(s ,a) )# 归#(t,(t ,a) )# 归#(t,(t, a) )# 进#(t,(t,a ) )# 进#(t,(t,s ) )#
22、归#(t,(t ) )# 归#(t,(t) )# 进#(t,s )# 归#(t )# 归#(t ) # 进# s # 归P1641 答:表达式(4*7+1)*2 的附注语法树如下图:digit.lexval=2F.val=2E.val=58 ndigit.lexval=4digit.lexval=7digit.lexval=1F.val=4F.val=7F.val=1T.val=4 *T.val=28E.val=28 +T.val=1E.val=1E.val=29( )F.val=29T.val=29T.val=58*LTianges reference21P1642答:(1)(2)P1651
23、1答:(1)Did L D.type:= L.type;addtype(id.type,L.type)L, id L 1 L.type:= L1.type;addtype(id.type,L 1.type)L : T L.type:= T.typeTinteger T.type := integerT real T.type := realP2171a*(-b+c) abc+*a+b*(c+d/e) abcde/+*+-a+b*(-c+d) abcd+*+A (C or not D) A not C D not or not or(A and B) or (not C or D) A B an
24、d C not D or or (A or B) and (C or not D and E) A B or C D not E and or and if (x+y)*z =0 then (a+b)c else abcxy+z*0= ab+cabc ¥或 xy+z*0= P1 jez ab+c P2 jump abc P1 P2P2173-(a+b)*(c+d)-(a+b+c)的三元式序列:(1) +, a, b(2) , (1), -(3) +, c, d(4) *, (2), (3)(5) +, a, b(6) +, (5), c(7) -, (4), (6)a b+a b+Tiange
25、s reference22间接三元式序列:三元式表:(1) +, a, b(2) , (1), -(3) +, c, d(4) *, (2), (3)(5) +, (1), c(6) -, (4), (5)间接码表:(1)(2)(3)(4)(1)(5)(6)四元式序列:(1) +, a, b, 1T(2) , , -, 2(3) +, c, d, 3(4) *, , , 24(5) +, a, b, 5(6) +, , c, T6(7) -, , , 47P2187100.(j100 goto L2-halt B4-L2: F:=F-1goto L1 B5B1B2B5B4B3read CA:=0B:=1L1: A:=A+Bif BC goto L2B:=B+1goto L1L2: write AhaltTianges reference24-基本块为 B1、B 2、B 3、B 4、B 5程序流图如右: P307-4B1 B2B3B2 构成一个循环。进行循环优化后,得到:B1 B2B2B3I:=1read J,KL: C:=A*Bwrite CA:=A+KB:=B+Jif AR goto LhaltA:=K*IB:=J*IR:=K*100I:=1read J,KL: A:=K*IB:=J*IC:=A*Bwrite CI:=I+1if I100 goto Lhalt