编译原理教程课后习题答案——第五章
编译原理-第1-5章习题课答案解析
不同的语法树,或者两种以上不同的最 左/右推导,则称这个文法是二义的。
首先:找到此文法对应的一个句子 iiiei 其次:构造与之对应的两棵语法树
S
S
i SeS
iS
iS
i
i S eS
i
ii
结论:因为该文法存在句子iiiei对应两棵 不同的语法树,因而该文法是二义的。
思路:先写出满足条件的正规式,由正规式构造 NFA,再把NFA确定化和最小化。
满足条件的正规式:(0|10)*
(0|10)*
x
y
1
0
1
0
0
1
2
0
x 1
y
编译原理
确定化: 给状态编号:
0
1
2
0
x 1
{X,1,Y} {1,Y} {2}
0
{1,Y} {1,Y} {1,Y}
0
0
1
1
1
2
1
chapter1~5习题
(1){0,1}上的含有子串010的所有串。 正规式:(0 | 1)* 010 (0 | 1)*
(2) {0,1}上不含子串010的所有串。 正规式:1*(0|11*1)* 1*( 0 | 11)*1* 1*0*1* (0 | 11)*(0 | 1) DFA做法同第7题。
编译原理
chapter1~5习题
编译原理
chapter1~5习题
8、给出下面正规表达式 (5)沒有重複出現的數字的數字符號串的全體
令ri=i| ,i=0,1,2...9 R0|R1|R2|...|R9記為∑Ri i (0,1,2...,9) P(0,1,2...,9)表示0,1,2...,9的全排列
编译原理-第5章-习题与答案2上课讲义
编译原理-第5章-习题与答案2第五章习题5-1 设有文法G[S]:S→A/ A→aA∣AS∣/(1) 找出部分符号序偶间的简单优先关系。
(2) 验证G[S]不是简单优先文法。
5-2 对于算符文法G[S]:S→E E→E-T∣T T→T*F∣F F→-P∣P P→(E)∣i(1) 找出部分终结符号序偶间的算符优先关系。
(2) 验证G[S]不是算符优先文法。
5-3 设有文法G′[E]:E→E1 E1→E1+T1|T1 T1→T T→T*F|F F→(E)|i其相应的简单优先矩阵如题图5-3所示,试给出对符号串(i+i)进行简单优先分析的过程。
题图5-3 文法G′[E]的简单优先矩阵5-4 设有文法G[E]:E→E+T|TT→T*F|FF→(E)|i其相应的算符优先矩阵如题图5-4所示。
试给出对符号串(i+i)进行算符优先分析的过程。
题图5-4 文法G[E]的算符优先矩阵5-5 对于下列的文法,试分别构造识别其全部可归前缀的DFA和LR(0)分析表,并判断哪些是LR(0)文法。
(1) S→aSb∣aSc∣ab(2) S→aSSb∣aSSS∣c(3) S→A A→Ab∣a5-6 下列文法是否是SLR(1)文法?若是,构造相应的SLR(1)分析表,若不是,则阐明其理由。
(1) S→Sab∣bR R→S∣a(2) S→aSAB∣BA A→aA∣B B→b(3) S→aA∣bB A→cAd∣ε B→cBdd∣ε5-7 对如下的文法分别构造LR(0)及SLR(1)分析表,并比较两者的异同。
S→cAd∣b A→ASc∣a5-8 对于文法G[S]:S→A A→BA∣ε B→aB∣b(1) 构造LR(1)分析表;(2) 给出用LR(1)分析表对输入符号串abab的分析过程。
5-9 对于如下的文法,构造LR(1)项目集族,并判断它们是否为LR(1)文法。
(1) S→A A→AB∣ε B→aB∣b(2) S→aSa∣a第5章习题答案25-1 解:(1) 由文法的产生式和如答案图5-1(a)所示的句型A//a/的语法树,可得G中的部分优先关系如答案图5-1(b)所示。
《编译原理》课后习题答案
第7 题证明下述文法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 * a第8 题文法G[S]为:S→Ac|aB A→ab B→bc该文法是否为二义的?为什么?答案:对于串abc(1)S=>Ac=>abc (2)S=>aB=>abc即存在两不同的最右推导。
所以,该文法是二义的。
或者:对输入字符串abc,能构造两棵不同的语法树,所以它是二义的。
第9 题考虑下面上下文无关文法:S→SS*|SS+|a(1)表明通过此文法如何生成串aa+a*,并为该串构造语法树。
(2)G[S]的语言是什么?答案:(1)此文法生成串aa+a*的最右推导如下S=>SS*=>SS*=>Sa*=>SS+a*=>Sa+a*=>aa+a*(2)该文法生成的语言是:*和+的后缀表达式,即逆波兰式。
第10 题文法S→S(S)S|ε(1) 生成的语言是什么?(2) 该文法是二义的吗?说明理由。
答案:(1)嵌套的括号(2)是二义的,因为对于()()可以构造两棵不同的语法树。
第11 题令文法G[E]为:E→T|E+T|E-T T→F|T*F|T/F F→(E)|i证明E+T*F 是它的一个句型,指出这个句型的所有短语、直接短语和句柄。
编译原理第三版课后习题答案
编译原理第三版课后习题答案编译原理是计算机科学中的一门重要课程,它研究的是如何将高级程序语言转换为机器语言的过程。
而《编译原理》第三版是目前被广泛采用的教材之一。
在学习过程中,课后习题是巩固知识、提高能力的重要环节。
本文将为读者提供《编译原理》第三版课后习题的答案,希望能够帮助读者更好地理解和掌握这门课程。
第一章:引论习题1.1:编译器和解释器有什么区别?答案:编译器将整个源程序转换为目标代码,然后一次性执行目标代码;而解释器则逐行解释源程序,并即时执行。
习题1.2:编译器的主要任务是什么?答案:编译器的主要任务是将高级程序语言转换为目标代码,包括词法分析、语法分析、语义分析、中间代码生成、代码优化和目标代码生成等过程。
第二章:词法分析习题2.1:什么是词法分析?答案:词法分析是将源程序中的字符序列划分为有意义的词素(token)序列的过程。
习题2.2:请给出识别下列词素的正则表达式:(1)整数:[0-9]+(2)浮点数:[0-9]+\.[0-9]+(3)标识符:[a-zA-Z_][a-zA-Z_0-9]*第三章:语法分析习题3.1:什么是语法分析?答案:语法分析是将词法分析得到的词素序列转换为语法树的过程。
习题3.2:请给出下列文法的FIRST集和FOLLOW集:S -> aAbA -> cA | ε答案:FIRST(S) = {a}FIRST(A) = {c, ε}FOLLOW(S) = {$}FOLLOW(A) = {b}第四章:语义分析习题4.1:什么是语义分析?答案:语义分析是对源程序进行静态和动态语义检查的过程。
习题4.2:请给出下列文法的语义动作:S -> if E then S1 else S2答案:1. 计算E的值2. 如果E的值为真,则执行S1;否则执行S2。
第五章:中间代码生成习题5.1:什么是中间代码?答案:中间代码是一种介于源代码和目标代码之间的表示形式,它将源代码转换为一种更容易进行优化和转换的形式。
《编译原理》课后习题答案第5章
《编译原理》课后习题答案第5章《编译原理》课后习题答案第5章.pdf《编译原理》课后习题答案第5章.pdf第5章自顶向下语法分析方法第1题对文法G[S] S→a|∧|(T) T→T,S|S(1) 给出(a,(a,a))和(((a,a),∧,(a)),a)的最左推导。
(2) 对文法G,进行改写,然后对每个非终结符写出不带回溯的递归子程序。
(3) 经改写后的文法是否是LL(1)的?给出它的预测分析表。
(4) 给出输入串(a,a)#的分析过程,并说明该串是否为G的句子。
答案:(1) 对(a,(a,a)的最左推导为:S(T) (T,S) (S,S) (a,S) (a,(T)) (a,(T,S)) (a,(S,S)) (a,(a,S)) (a,(a,a))对(((a,a),∧,(a)),a) 的最左推导为:S(T) (T,S) (S,S) ((T),S) ((T,S),S) ((T,S,S),S) ((S,S,S),S) (((T),S,S),S) (((T,S),S,S),S) (((S,S),S,S),S) (((a,S),S,S),S) (((a,a),S,S),S) (((a,a),∧,S),S) (((a,a),∧,(T)),S)(((a,a),∧,(S)),S)《编译原理》课后习题答案第5章.pdf《编译原理》课后习题答案第5章.pdf(((a,a),∧,(a)),S) (((a,a),∧,(a)),a)(2) 改写文法为:0) S→a 1) S→∧ 2) S→( T ) 3) T→S N 4) N→, S N 5) N→ε非终结符FIRST集FOLLOW集S {a,∧,(} {#,,,)} T {a,∧,(} {)} N {,,ε} {)}对左部为N的产生式可知:FIRST (→, S N)={,} FIRST (→ε)={ε} FOLLOW (N)={)}由于SELECT(N →, S N)∩SELECT(N →ε) ={,}∩ { )}= 所以文法是LL(1)的。
编译原理 第5章习题解答
第五章习题解答5.1 设一NDPDA识别由下述CFG定义的语言,试给出这个NDPDA的完整形式描述。
S→SASCS→εA→AaA→bC→DcDD→d5.2 消除下列文法的左递归:① G[A]:A→BX∣CZ∣WB→Ab∣BcC→Ax∣By∣Cp② G[E]:E→ET+∣ET–∣TT→TF*∣TF/FF→(E)∣i③ G[X]:X→Ya∣Zb∣cY→ Zd∣Xe∣fZ→X e∣Yf∣a④ G[A]:A→Ba|Aa|cB→Bb|Ab|d5.3 设文法G[<语句>]:<语句>→<变量>: = <表达式>|if<表达式>then<语句>|if<表达式>then<语句>else<语句> <变量>→i<表达式>→<项>|<表达式>+<项><项>→<因子>|<项>*<因子><因子>→<变量>|′(′<表达式>′)′试构造该文法的递归下降子程序。
5.4 设文法G[E]:E→ TE'E'→ + E∣εT→ FT'T'→ T∣εF→ PF'F'→ *F∣εP→ (E)∣ a∣^①构造该文法的递归下降分析程序;②求该文法的每一个非终结符的FIRST集合和FOLLOW集合;③构造该文法的LL(1)分析表,并判断此文法是否为LL(1)文法。
5.5 设文法G[S]:S→ SbA∣aAB→ SbA→ Bc①将此文法改写为LL(1)文法;②求文法的每一个非终结符的FIRST集合和FOLLOW集合;③构造相应的LL(1)分析表。
5.6 设文法G[S]:S→ aABbcd∣εA→ ASd∣εB→ SAh∣eC∣εC→ Sf∣Cg∣εD→ aBD∣ε①求每一个非终结符的FOLLOW集合;②对每一个非终结符的产生式选择,构造FIRST集合;③该文法是LL(1)文法。
【编译原理】1-5章课后习题答案精心整理版,可直接缩印
第一章1.2 计算机执行用高级语言编写的程序有哪些途径?它们之间的主要区别是什么? 【解答】计算机执行用高级语言编写的程序主要有两种途径:解释和编译。
这两种途径的主要区别在于:解释方式下不生成目标代码程序,而编译方式下生成目标代码程序。
从执行速度上看,编译型的高级语言比解释型的高级语言要快,但解释方式下的人机界面比编译型好,便于程序调试。
(在解释方式下,翻译程序事先并不采用将高级语言程序全部翻译成机器代码程序,然后执行这个机器代码程序的方法,而是每读入一条源程序的语句,就将其解释(翻译)成对应其功能的机器代码语句串并执行,而所翻译的机器代码语句串在该语句执行后并不保留,最后再读入下一条源程序语句,并解释执行。
这种方法是按源程序中语句的动态执行顺序逐句解释(翻译)执行的,如果一语句处于一循环体中,则每次循环执行到该语句时,都要将其翻译成机器代码后再执行。
在编译方式下,高级语言程序的执行是分两步进行的:第一步首先将高级语言程序全部翻译成机器代码程序,第二步才是执行这个机器代码程序。
因此,编译对源程序的处理是先翻译,后执行。
)1.3 请画出编译程序的总框图。
如果你是一个编译程序的总设计师,设计编译程序时应当考虑哪些问题? 【解答】编译程序总框图如图1-1所示。
作为一个编译程序的总设计师,首先要深刻理解被编译的源语言其语法及语义;其次,要充分掌握目标指令的功能及特点,如果目标语言是机器指令,还要搞清楚机器的硬件结构以及操作系统的功能;第三,对编译的方法及使用的软件工具也必须准确化。
总之,总设计师在设计编译程序时必须估量系统功能要求、硬件设备及软件工具等诸因素对编译程序构造的影响等。
第二章2.1 正规式M1和M2等价是指:M1和M2所识别的语言集相等。
2.2 什么是扫描器?扫描器的功能是什么?【解答】扫描器就是词法分析器,它接受输入的源程序,对源程序进行词法分析并识别出一个个单词符号,其输出结果是单词符号,供语法分析器使用。
编译原理(第二版)清华大学---答案详解
第1章引论第1题解释下列术语:(1)编译程序(2)源程序(3)目标程序(4)编译程序的前端(5)后端(6)遍答案:(1) 编译程序:如果源语言为高级语言,目标语言为某台计算机上的汇编语言或机器语言,则此翻译程序称为编译程序。
(2) 源程序:源语言编写的程序称为源程序。
(3) 目标程序:目标语言书写的程序称为目标程序。
(4) 编译程序的前端:它由这样一些阶段组成:这些阶段的工作主要依赖于源语言而与目标机无关。
通常前端包括词法分析、语法分析、语义分析和中间代码生成这些阶段,某些优化工作也可在前端做,也包括与前端每个阶段相关的出错处理工作和符号表管理等工作。
(5) 后端:指那些依赖于目标机而一般不依赖源语言,只与中间代码有关的那些阶段,即目标代码生成,以及相关出错处理和符号表操作。
(6) 遍:是对源程序或其等价的中间语言程序从头到尾扫视并完成规定任务的过程。
第2题一个典型的编译程序通常由哪些部分组成?各部分的主要功能是什么?并画出编译程序的总体结构图。
答案:一个典型的编译程序通常包含8个组成部分,它们是词法分析程序、语法分析程序、语义分析程序、中间代码生成程序、中间代码优化程序、目标代码生成程序、表格管理程序和错误处理程序。
其各部分的主要功能简述如下。
词法分析程序:输人源程序,拼单词、检查单词和分析单词,输出单词的机内表达形式。
语法分析程序:检查源程序中存在的形式语法错误,输出错误处理信息。
语义分析程序:进行语义检查和分析语义信息,并把分析的结果保存到各类语义信息表中。
中间代码生成程序:按照语义规则,将语法分析程序分析出的语法单位转换成一定形式的中间语言代码,如三元式或四元式。
中间代码优化程序:为了产生高质量的目标代码,对中间代码进行等价变换处理。
目标代码生成程序:将优化后的中间代码程序转换成目标代码程序。
表格管理程序:负责建立、填写和查找等一系列表格工作。
表格的作用是记录源程序的各类信息和编译各阶段的进展情况,编译的每个阶段所需信息多数都从表格中读取,产生的中间结果都记录在相应的表格中。
5编译原理,陈意云 ,课后答案5
2019/2/12
luanj@
8
7.4 (续)
• D -> ID_LIST:T ID_LIST -> ID_LIST,ID_LIST|id • D -> { Init(idtable) } ID_LIST:T { for each name in idtable do enter(name, T.type, offset); offset := offset + T.width; end; } ID_LIST -> { Init(idtable1); Init(idtable2) } ID_LIST1,ID_LIST2 { merge(idtable1, idtable2, idtable) } ID_LIST -> id { add(idtable, ); }
编译原理习题课(5)
栾 俊 luanj@ 2019/2/12
7.1
• 把算术表达式 –(a+b)*(c+d)+(a+b-c) 翻译成: (a) 语法树 (b) 有向无环图 (c) 后缀表示 (d) 三地址代码
2019/2/12
luanj@
{ enter(, T.type, offset); offset += T.width; } { T.type = integer; T.width = 4; } { T.type = real; T.width = 8; } { T.type = array(num.val, T1.type); T.width = num.val * T1.width; } { T.type = pointer(T1.type); T.width = 4; }
2019/2/12 luanj@ 11
程序设计语言_编译原理(第三版-习题库-答案)第五章 语法制导翻译及中间代码生成
第五章语法制导翻译及中间代码生成5.1说明属性文法与属性翻译文法有何异同?5.2考虑下面的属性文法:Z →sXattribution:Z.a=X.c;X.b=X.a;Z.p=X.b;Z →t Xattribution:X.b=X.d;Z.a=X.b;X →uattribution:X.d=1;X.c=X.d;X →Vattribuion:X.c=2;X.d=X.c;(1) 上述文法中的属性哪些是继承的?哪些是综合的?(2) 上述文法中的属性依赖是否出现了循环?5.3为什么说S属性文法一定是L属性文法?反之结论亦正确吗?5.4将下列中缀式改写为逆波兰式。
(1) -A*(B+C)↑(D-E)(2) ((a*d+c)/d+e)*f+g(3) a+x≤4∨(C∧d*3)(4) a∨b∧c+d*e↑f(5) s=0; i=1;while (i<=100) {s+=i*i; i++;}5.5将下列后缀式改写为中缀式。
(1) abc*+(2) abc-*cd+e/-(3) abc+≤a0>∧ab+0≠a0∧∨(4) ab<p1 BZ xab-c↑= p2 BR gh=↑↑p1p25.6设已给文法G[E]:E →E+T | -T | TT →T*F | FF →P ↑F | PP →(E) | i试设计一个递归下降分析器,要求此分析器在语法分析过程中,将所分析的符号串翻译成后缀式。
5.7设已给布尔表达式文法G[Z]:Z →EE →T{∨T}T →F{∧F}F → F | (E) | b试设计一个递归下降分析器,它把由G[Z]所描述的布尔表达式翻译为四元式序列。
5.8(1) 利用54节所给的属性翻译文法将赋值语句:X=A*(B+C)+D翻译成四元式序列,给出语法制导的翻译过程。
(2) 利用55节所给的属性翻译文法将布尔表达式:A∧(B∨(C∨D F))翻译成四元式序列,给出语法制导的翻译过程。
(3) 利用56节所给的属性翻译文法将语句:while A<C∧B>0 doif A=1 then C∶=C+1else while A<=D do A∶=A+2翻译成四元式序列,给出语法制导的翻译过程。
编译原理-第五章习题答案
上一页
下一页
11
例:5.3 文法:SaAcBe A bAb B d 句子:abbcde
步骤 (1) (2) (3) (4) (5) (6)
栈
# #a #ab #aA #aAb #aA #aAc #aAcd #aAcB #aAcBe #S
输入 abbcde# bbcde# bcde# bcde# cde# cde#
上一页
下一页
20
5)构造算符优先文法G的优先表的算法
思路:对文法中的每一个产生式的候选式检查,判断句型中相邻符号之间 的关系 来构造优先表; 具体算法: FOR 每条产生式P→X1X2…Xn FOR i=1 TO n-1 IF Xi,Xi+1∈VT,THEN Xi=Xi+1; IF i ≤n-2且Xi,Xi+2∈VT,Xi+1∈VN THEN Xi=Xi+2; IF Xi∈VT,Xi+1∈VN THEN FOR FIRSTVT(Xi+1)中的每个a Xi <. a; NEXT IF Xi∈VN,Xi+1∈VT THEN FOR LASTVT(Xi)中的每个a DO a .> Xi+1; NEXT NEXT NEXT
上一页
下一页
8
例:5.1 P85 文法: E→T|E+T T→F|T*F F→i|(E) 句型:i1*i2+i3其中:短语有i1、i2、i3、i1*i2、 i1*i2+i3 直接短语:i1、i2、i3;句柄:i1 例:5.2 P85 文法如上 E 句型:E+T*F+i 短语:E+T*F+i,E+T*F,T*F,i 直接短语:T*F和i E + 句柄:T*F
编译原理教程课后习题答案——第五章
第五章代码优化5.1 完成以下选择题:(1) 优化可生成的目标代码。
a. 运行时间较短b. 占用存储空间较小c. 运行时间短但占用内存空间大d. 运行时间短且占用存储空间小(2) 下列优化方法不是针对循环优化进行的。
a. 强度削弱b. 删除归纳变量c. 删除多余运算d. 代码外提(3) 基本块内的优化为。
a. 代码外提,删除归纳变量b. 删除多余运算,删除无用赋值c. 强度削弱,代码外提d. 循环展开,循环合并(4) 在程序流图中,我们称具有下述性质的结点序列为一个循环。
a. 它们是非连通的且只有一个入口结点b. 它们是强连通的但有多个入口结点c. 它们是非连通的但有多个入口结点d. 它们是强连通的且只有一个入口结点(5) 关于必经结点的二元关系,下列叙述中不正确的是。
a. 满足自反性b. 满足传递性c. 满足反对称性d. 满足对称性【解答】(1) d (2) c (3) b (4) d (5) d5.2 何谓局部优化、循环优化和全局优化?优化工作在编译的哪个阶段进行?【解答】优化根据涉及的程序范围可分为三种。
(1) 局部优化是指局限于基本块范围内的一种优化。
一个基本块是指程序中一组顺序执行的语句序列(或四元式序列),其中只有一个入口(第一个语句)和一个出口(最后一个语句)。
对于一个给定的程序,我们可以把它划分为一系列的基本块,然后在各个基本块范围内分别进行优化。
通常应用DAG方法进行局部优化。
(2) 循环优化是指对循环中的代码进行优化。
例如,如果在循环语句中某些运算结果不随循环的重复执行而改变,那么该运算可以提到循环外,其运算结果仍保持不变,但程序运行的效率却提高了。
循环优化包括代码外提、强度削弱、删除归纳变量、循环合并和循环展开。
5.3 将下面程序划分为基本块并作出其程序流图。
read(A,B)F=1C=A*AD=B*Bif C<D goto L1E=A*AF=F+1E=E+Fwrite(E)haltL1: E=B*BF=F+2E=E+Fwrite(E)if E >100 goto L2haltL2: F=F-1goto L1【解答】先求出四元式程序中各基本块的入口语句,即程序的第一个语句,或者能由条件语句或无条件转移语句转移到的语句,或者条件转移语句的后继语句。
《编译原理》习题参考答案(六)
《编译原理》习题参考答案(六)第五章5.4 为下列类型写类型表达式:(a) 指向实数的指针数组,数组的下标从1到100。
(b) 两位数组(即数组的数组),他的行下标从1到10,列下标从1到20。
(c) 函数,他的定义域是从整数到整数的指针的函数,它的值域是从一个整数和一个字符组成的纪录。
Solution:(a) array ( 1 . . 100 , pointer ( real ) )(b) array ( 1 . . 10 , array ( 1 . . 20 , type ) )(c) ( integer →pointer(integer) )→record((i : integer) * ( c : char )) 假定作为值域的记录类型的两个域分别叫i和c。
5.6 下列文法定以字面常量表的表。
符号的解释和图5.2文法的那些相同,增加了类型list,它表示类型T的元素表。
→ D ; EP→ D ; D | id : TD→ list of T | char | integerTE→ ( L ) | literal | num | id→ E , L | EL写一个类似5.3节中的翻译方案,以确定表达式( E )和表( L )的类型。
P→ D ; ED→ D ; DD→ id : T { addtype ( id.entry , T.type ) }T→ char { T.type := char }T→ integer { T.type := integer }T→ list of T1 { T.type := list ( T1.type ) }E→ literal { E.type := char }E→ num { E.type := integer }E→ id { E.type := lookup ( id.entry ) }E→ ( L ) { E.type := list ( L.type ) }L→E{L.type:=E.type}L→ E , L1 { L.type := if L1.type = E.type then E.typeelse type_error }5.16 对下面的每对表达式,找出最一般的合一代换:(a) α1 → ( α2 →α1 )(b) array ( β1 ) → ( pointer( β1 ) →β2 )(c) γ1 →γ2(d) δ1 →(δ1 →δ2 )Solution:S(α1) = array ( β1 ) S(α2) = pointer ( β1 ) S(β2) = array ( β1 ) (a)(c):S(γ1) = α1 S(γ2) = α2 → α1 (a)(d):S(α1) = S(α2) = S(δ1) = S(δ2) = α (b)(c):S(γ1) = array ( β1 ) S(γ2) = pointer ( β1 ) → β2 (b)(d): 无 (c)(d):S(γ1) = δ1 S(γ2) = δ1 → δ25.17 仿效例5.5,推到下面map 的多态类型: map: ∀ α . ∀ β . ( ( α → β ) * list ( α ) ) → list ( β ) map 的ML 定义是 fun map ( f , l ) = if null ( l ) then nilelse cons ( f ( hd ( l ) ) , map ( f , tl ( l ) ) );在这个函数体中,内部定义的标识符的类型是: null : ∀α . list (α ) → boolean ; nil : ∀α . list (α ) ;cons : ∀α . ( α * list (α ) ) → list (α ) ;hd:∀α . list (α ) →α;∀α . list (α ) → list (α ) ;tl:Solution:行定型断言代换规则(1) f : α( Exp Id )(2) l : β( Exp Id )(3) map : γ( Exp Id )(4) map ( f , l ) : δγ = ( α * β ) →δ(Exp Funcall)(5) null : list (α0) → boolean ( Exp Id ) 和( Type Fresh )(6) null ( l ) : boolean β = list (α0) (Exp Funcall)(7) nil : list (α1) ( Exp Id ) 和( Type Fresh )(8) l : list (α0) 由(2)可得(9) hd : list (α2) →α2( Exp Id ) 和( Type Fresh )(10) hd ( l ) : α0α2 = α0(Exp Funcall)(11) f ( hd ( l ) ) : α3α = α0→α3( Exp Id )(12) f : α0→α3由(1)可得(13) tl : list (α4)→ list (α4) ( Exp Id ) 和( Type Fresh )(14) tl ( l ) : list (α0) α4 = α0(Exp Funcall)(15) map : ((α0→α3)*list(α0))→δ由(3)可得(16) map ( f , tl ( l ) ) : δ(Exp Funcall)(17) cons : α5 * list(α5) → list(α5) ( Exp Id ) 和( Type Fresh ) (18) cons (…) : list (α3) α5 = α3 , δ=list(α3) (Exp Funcall)(19) if : boolean *α6 * α6→α6( Exp Id ) 和( Type Fresh )(20) if (…) : list (α1) α6 = α1 , α3 = α1(Exp Funcall)(21) match : α7 *α7 →α7( Exp Id ) 和( Type Fresh ) (22) match (…) : list (α1) α7 = list (α1) (Exp Funcall)至此有map : ( (α0→α1)*list(α0) )→list(α1)所以map : ∀α . ∀β . ( ( α→β ) * list ( α ) ) → list ( β )5.18 假定类型名link和cell如5.5节那样定义,下面的表达式中,那些结构等价?那些名字等价?(a) link(b) pointer ( cell )(c) pointer ( link )(d) pointer ( record ( ( info : integer ) * ( next : pointer ( cell ) ) ) ) Solution:(a)、(b)、(d)结构等价,无名字等价。
编译原理答案第五章
练习5.1解答:输入(4*7+1)*2n,带注释的分析树如下:练习5.2解答: (1)根据表5.3中的语法制导定义建立表达式((a)+(b))的分析树和语法树(2)根据图5.17的翻译模式构造((a)+(b))的分析树和语法树练习5.3解答:设置下面的函数和属性:expr1||expr2:把表达式expr2拼写在表达式expr1后面。
deletep(expr):去掉表达式expr左端的‘(’和右端的‘)’。
E.expr,T.expr,F.expr:属性变量,分别表示E,T,F的表达式。
E.add,T.add,F.add,属性变量,若为true,则表示其表达式中外层有‘+’号,否则无‘+’号。
E.pmark,T.pmark,F.pmark,属性变量,若为true,表示E,T,F的表达式中左端为‘(’,右端是‘)’。
语法制导定义如下:产生式语义规则E -> E1 +T if(T.pmark==true)THEN E.expr=E1.expr||'+'||deletep(T.expr) ELSE E.expr:=E1.expr||'+'||T.expr;E.add:=true;E.pmark:=false;E -> T if(T.pmark==true)THEN E.expr:=deletep(T.expr)ELSE E.expr:=T.expr;E.add:=T.add;E.pmark:=false;T -> T1*F T.expr:=T1.expr||'*'||F.expr; T.add:=false;T.pmark:=false;T -> F T.expr:=F.expr; T.add:=F.add;T.pmark:=F.pmark;F -> (E) if(E.add==false)THEN BEGINF.expr:=E.expr;F.add:=false;F.pmark:=false;ENDELSE BEGINF.expr:='('||E.expr||')';F.add:=true;F.pmark:=true;END;F -> id F.expr:=id.lexval;F.add:=false;F.pmark:=false;练习5.4解答: (1)语法制导定义如下:产生式语义规则E -> E1+T if(E1.type==int) AND (T.type==int) THEN E.type:=intELSE E.type:=real;E -> T E.type:=T.type;T -> num T.type:=int;T -> num.num T.type:=real;(2)设E.pf和T.pf分别是E和T的前缀形式,||是两个字符串的连接,语法制导定义如下:产生式语义规则E -> E1+T if(E1.type==int) AND (T.type==int)THEN E.type:=intELSE BEGINE.type:=real;if(E1.type==int) AND (T.type==real)THEN E1.pf:='inttoreal'||E1.pfELSE if(E1.type==real)AND(T.type==int)THEN T.pf:='inttoreal'||T.pfEND;E.pf:='+'||E1.pf||T.pf;E -> T E.type:=T.type; E.pf:=T.pf;T -> num T.type:=int; T.pf:=int.lexval;T ->num.numT.type:=real; T.pf:=real.lexval;练习5.5解答: (1)用综合属性决定s.val的语法制导定义:产生式语义规则S -> L S.val:=L.val;S ->L1.L2S.val:=L1.val+L2.val*L2.p;L -> B L.val:=B.val; L.p:=2-1;L -> L1B L.val:=L1.val*2+B.val; L.p:=L.p*2-1;B -> 0 B.val:=0;B -> 1 B.val:=1;注:L.p表示恢复L.val的因子。
编译原理-第1~5章习题课答案
选择题2答案
编译原理的主要目的是将高级语言编写的 程序转换成低级语言编写的程序,以提高 程序的运行效率和可移植性。
编译过程主要包括词法分析、语法分析、 语义分析、中间代码生成、代码优化和目 标代码生成等阶段。
选择题3答案
选择题4答案
词法分析是将源程序分解成一个个的单词 或符号,供语法分析器识别和匹配。
编译原理-第1~5章习题课答案
目录
CONTENTS
• 第一章习题答案 • 第二章习题答案 • 第三章习题答案 • 第四章习题答案 • 第五章习题答案
01 第一章习题答案
CHAPTER
填空题答案
填空题1答案
编译原理是将高级语言编写的程 序转换成低级语言编写的程序的
过程。
填空题2答案
编译过程主要包括词法分析、语法 分析、语义分析、中间代码生成、 代码优化和目标代码生成等阶段。
• 简答题3答案:编译器的输入是源程序,输出是目标程序。源程序是用高级语言编写的程序,目标程序是用低级语言编 写的程序。
02 第二章习题答案
CHAPTER
填空题答案
填空题1答案
编译原理是将高级语言编写的程序转 换成低级语言编写的程序的过程。
02
填空题2答案
编译过程主要包括词法分析、语法分 析、语义分析、中间代码生成、代码 优化和目标代码生成等阶段。
是编译过程的基础。
简答题3答案
编译原理中的语义分析阶段主要 包括类型检查、语义检查和符号 表管理等任务,以确保源程序的
语义正确性。
04 第四章习题答案
CHAPTER
填空题答案
填空题1答案
01
编译原理是将高级语言编写的程序转换成低级语言编写的程序
(完整版)编译原理第五章作业参考答案
SELECT(F PF/ )=FIRST(P)={(,a,b,^};
SELECT(F/ *F /)={*}; SELECT(F/ ε )=FOLLOW(F/)={(,a,b,^,+,),#};
SELECT(P (E))={(}
SELECT(P a)={a}
SELECT(P b)={b}
SELECT(P ^)={^} 可见,相同左部产生式的
if(CH== ’ aR’E)AD(CH);// 产生式 S a else if(CH== ’ ^ ’ ) READ(C产H)生;//式 S ^ else if(CH== ’产( ’生)式// S (T) {
READ(CH); P_T(); IF (CH= =’ ) ’TH)EN READ(CH) else ERROR } else ERR; } void P_T()// 非终结符 S 的子程序 { if(IsIn(CH,FIRST_SU)) //FIRST_SU 为 T SU 的右部的 FIRST 集合 { P_S(); P_U(); } } void P_U()// 非终结符 U 的子程序 { if(CH== ’ , ’产生)//式 U , SU
3.已知文法 G[S] :
S MH|a
H LSo| ε K dML|ε
L eHf
M K|bLM 判断 G是否是 LL( 1)文法,如果是,构造 LL( 1)分析表。 解: 首先求各非终结符的 FIRST 集合:
FIRST 集合有:
FIRST(E)=FIRST(T)=FIRST(F)=FIRST(P)={(,a,b,^}; FIRST(E / )={+, ε }
FIRST(T)=FIRST(F)=FIRST(P)={(,a,b,^}; FIRST(T / )=FIRST(T) ∪ { ε }={(,a,b,^, ε };
编译原理教程第五版课后答案
编译原理教程第五版课后答案第一章:引言问题1答:编译器是一种将高级编程语言源代码转换为目标机器代码的软件工具。
它由多个阶段组成,包括词法分析、语法分析、语义分析、中间代码生成、代码优化和代码生成等。
问题2答:编译器的主要任务包括以下几个方面: - 词法分析:将源代码划分为词法单元,如标识符、关键字、操作符等。
- 语法分析:根据语法规则,将词法单元组成语法树。
- 语义分析:对语法树进行语义检查,如类型匹配、变量声明等。
- 中间代码生成:将语法树转换为中间代码表示形式。
- 代码优化:对中间代码进行优化,以提高程序的效率。
- 代码生成:将优化后的中间代码转换为目标机器代码。
第二章:词法分析问题1答:词法单元是编译器在词法分析阶段识别的最小的语法单位,它由一个或多个字符组成。
常见的词法单元包括关键字、标识符、常量和运算符等。
问题2答:识别词法单元的方法包括以下几种: - 正则表达式:通过正则表达式匹配字符串,识别出各类词法单元。
- 有限自动机:构建有限状态自动机,根据输入字符的不同状态转移,最终确定词法单元。
- 递归下降法:使用递归下降的方式,根据语法规则划分出词法单元。
第三章:语法分析问题1答:语法分析是编译器的一个重要阶段,它的主要任务是根据给定的语法规则,将词法单元序列转换为语法树。
语法分析有两个主要的方法:自顶向下的分析和自底向上的分析。
问题2答:自顶向下的分析是从文法的起始符号开始,根据语法规则逐步向下展开,直到生成最终的语法树。
常见的自顶向下的分析方法包括LL(1)分析和递归下降分析。
问题3答:自底向上的分析是从输入串开始,逐步合并词法单元,最终生成语法树。
常见的自底向上的分析方法包括LR分析和LALR分析。
第四章:语义分析问题1答:语义分析的主要任务是对语法树进行语义检查和类型推断。
语义分析阶段会检查变量的声明和使用是否合法,以及类型是否匹配等。
问题2答:常见的语义错误包括变量未声明、类型不匹配、函数调用参数不匹配等。
(完整版)编译原理第五章作业参考答案
第五章自顶向下语法分析方法1.对文法G[S]S→a|∧|(T)T→T,S|S(1)给出(a,(a,a))和(((a,a),∧,(a)),a)的最左推导。
(2)对文法G,进行改写,然后对每个非终结符写出不带回溯的递归子程序。
(3)经改写后的文法是否是LL(1)的?给出它的预测分析表。
(4)给出输入串(a,a)#的分析过程,并说明该串是否为G的句子。
解:(1) (a,(a,a))的最左推导为S→(T)→(T,S)→(S,S)→(a,(T))→(a,(T,S))→(a,(S,a))→(a,(a,a))(((a,a),∧,(a)),a)的最左推导为S→(T)→(T,S)→(S,a)→((T),a)→((T,S),a)→((T,S,S),a)→((S,∧,(T)),a)→(((T),∧,(S)),a) →(((T,S),∧,(a)),a)→(((S,a),∧,(a)),a)→(((a,a),∧,(a)),a)(2)由于有T→T,S的产生式,所以消除该产生式的左递归,增中一个非终结符U有新的文法G/[S]:S→a|∧|(T)T→SUU→,SU|ε分析子程序的构造方法对满足条件的文法按如下方法构造相应的语法分析子程序。
(1) 对于每个非终结号U,编写一个相应的子程序P(U);(2) 对于规则U::=x1|x2|..|xn,有一个关于U的子程序P(U),P(U)按如下方法构造:IF CH IN FIRST(x1) THEN P(x1)ELSE IF CH IN FIRST(x2) THEN P(x2)ELSE ......IF CH IN FIRST(xn) THEN P(xn)ELSE ERROR其中,CH存放当前的输入符号,是一个全程变量;ERROR是一段处理出错信息的程序;P(xj)为相应的子程序。
(3) 对于符号串x=y1y2...yn;p(x)的含义为:BEGINP(y1);P(y2);...P(yn);END如果yi是非终结符,则P(yi)代表调用处理yi的子程序;如果yi是终结符,则P(yi)为形如下述语句的一段子程序IF CH=yi THEN READ(CH) ELSE ERROR即如果当前文法中的符号与输入符号匹配,则继续读入下一个待输入符号到CH中,否则表明出错。
编译原理课后习题答案-清华大学-第二版
《编译原理》课后习题答案第二章
第 2 章 PL/0 编译程序的实现
第1题
PL/0 语言允许过程嵌套定义和递归调用,试问它的编译程序如何解决运行时的存储管 理。
答案: PL/0 语言允许过程嵌套定义和递归调用,它的编译程序在运行时采用了栈式动态存储
管理。(数组 CODE 存放的只读目标程序,它在运行时不改变。)运行时的数据区 S 是由 解释程序定义的一维整型数组,解释执行时对数据空间 S 的管理遵循后进先出规则,当每 个过程(包括主程序)被调用时,才分配数据空间,退出过程时,则所分配的数据空间被释放。 应用动态链和静态链的方式分别解决递归调用和非局部变量的引用问题。
(2) 扩充 repeat 语句的语法图为:
EBNF 的语法描述为: 〈 重复语句〉::= repeat〈语句〉{;〈语句〉}until〈条件〉
《编译原理》课后习题答案第三章
第 3 章 文法和语言
第1题
文法 G=({A,B,S},{a,b,c},P,S)其中 P 为: S→Ac|aB A→ab B→bc 写出 L(G[S])的全部元素。
注意:如果问编译程序有哪些主要构成成分,只要回答六部分就可以。如果搞不清楚, 就回答八部分。 第3题
何谓翻译程序、编译程序和解释程序?它们三者之间有何种关系? 答案:
翻译程序是指将用某种语言编写的程序转换成另一种语言形式的程序的程序,如编译程 序和汇编程序等。
编译程序是把用高级语言编写的源程序转换(加工)成与之等价的另一种用低级语言编 写的目标程序的翻译程序。
地址,用以过程执行结束后返回调用过程时的下一条指令继续执行。 在每个过程被调用时在栈顶分配 3 个联系单元,用以存放 SL,DL, RA。
第5题
PL/0 编译程序所产生的目标代码是一种假想栈式计算机的汇编语言,请说明该汇编语 言中下列指令各自的功能和所完成的操作。 (1) INT 0 A (2) OPR 0 0 (3) CAL L A
清华大学编译原理第二版课后习答案
Lw.《编译原理》课后习题答案第一章第 1 章引论第 1 题解释下列术语:(1)编译程序(2)源程序(3)目标程序(4)编译程序的前端(5)后端(6)遍答案:(1)编译程序:如果源语言为高级语言,目标语言为某台计算机上的汇编语言或机器语言,则此翻译程序称为编译程序。
(2)源程序:源语言编写的程序称为源程序。
(3)目标程序:目标语言书写的程序称为目标程序。
(4)编译程序的前端:它由这样一些阶段组成:这些阶段的工作主要依赖于源语言而与目标机无关。
通常前端包括词法分析、语法分析、语义分析和中间代码生成这些阶段,某些优化工作也可在前端做,也包括与前端每个阶段相关的出错处理工作和符号表管理等工作。
(5)后端:指那些依赖于目标机而一般不依赖源语言,只与中间代码有关的那些阶段,即目标代码生成,以及相关出错处理和符号表操作。
(6)遍:是对源程序或其等价的中间语言程序从头到尾扫视并完成规定任务的过程。
第 2 题一个典型的编译程序通常由哪些部分组成?各部分的主要功能是什么?并画出编译程序的总体结构图。
答案:一个典型的编译程序通常包含 8 个组成部分,它们是词法分析程序、语法分析程序、语义分析程序、中间代码生成程序、中间代码优化程序、目标代码生成程序、表格管理程序和错误处理程序。
其各部分的主要功能简述如下。
词法分析程序:输人源程序,拼单词、检查单词和分析单词,输出单词的机内表达形式。
语法分析程序:检查源程序中存在的形式语法错误,输出错误处理信息。
语义分析程序:进行语义检查和分析语义信息,并把分析的结果保存到各类语义信息表中。
中间代码生成程序:按照语义规则,将语法分析程序分析出的语法单位转换成一定形式的中间语言代码,如三元式或四元式。
中间代码优化程序:为了产生高质量的目标代码,对中间代码进行等价变换处理。
盛威网()专业的计算机学习网站1《编译原理》课后习题答案第一章目标代码生成程序:将优化后的中间代码程序转换成目标代码程序。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
第五章代码优化5.1 完成以下选择题:(1) 优化可生成的目标代码。
a. 运行时间较短b. 占用存储空间较小c. 运行时间短但占用内存空间大d. 运行时间短且占用存储空间小(2) 下列优化方法不是针对循环优化进行的。
a. 强度削弱b. 删除归纳变量c. 删除多余运算d. 代码外提(3) 基本块内的优化为。
a. 代码外提,删除归纳变量b. 删除多余运算,删除无用赋值c. 强度削弱,代码外提d. 循环展开,循环合并(4) 在程序流图中,我们称具有下述性质的结点序列为一个循环。
a. 它们是非连通的且只有一个入口结点b. 它们是强连通的但有多个入口结点c. 它们是非连通的但有多个入口结点d. 它们是强连通的且只有一个入口结点(5) 关于必经结点的二元关系,下列叙述中不正确的是。
a. 满足自反性b. 满足传递性c. 满足反对称性d. 满足对称性【解答】(1) d (2) c (3) b (4) d (5) d5.2 何谓局部优化、循环优化和全局优化?优化工作在编译的哪个阶段进行?【解答】优化根据涉及的程序范围可分为三种。
(1) 局部优化是指局限于基本块范围内的一种优化。
一个基本块是指程序中一组顺序执行的语句序列(或四元式序列),其中只有一个入口(第一个语句)和一个出口(最后一个语句)。
对于一个给定的程序,我们可以把它划分为一系列的基本块,然后在各个基本块范围内分别进行优化。
通常应用DAG方法进行局部优化。
(2) 循环优化是指对循环中的代码进行优化。
例如,如果在循环语句中某些运算结果不随循环的重复执行而改变,那么该运算可以提到循环外,其运算结果仍保持不变,但程序运行的效率却提高了。
循环优化包括代码外提、强度削弱、删除归纳变量、循环合并和循环展开。
5.3 将下面程序划分为基本块并作出其程序流图。
read(A,B)F=1C=A*AD=B*Bif C<D goto L1E=A*AF=F+1E=E+Fwrite(E)haltL1: E=B*BF=F+2E=E+Fwrite(E)if E >100 goto L2haltL2: F=F-1goto L1【解答】先求出四元式程序中各基本块的入口语句,即程序的第一个语句,或者能由条件语句或无条件转移语句转移到的语句,或者条件转移语句的后继语句。
然后对求出的每一入口语句构造其所属的基本块,它是由该入口语句至下一入口语句(不包括该入口语句)或转移语句(包括该转移语句)或停语句(包括该停语句)之间的语句序列组成的。
凡未被纳入某一基本块的语句都从程序中删除。
要注意基本块的核心只有一个入口和一个出口,入口就是其中第一个语句,出口就是其中最后一个语句。
如果发现某基本块有两个以上的入口或两个以上的出口,则划分基本块有误。
程序流图画法是当下述条件(1)和(2)有一个成立时,从结点i有一有向边引到结点j:(1) 基本块j在程序中的位置紧跟在基本块i之后,并且基本块i的出口语句不是无条件转移语句goto(s)或停语句。
(2) 基本块i的出口语句是goto(s)或if…goto(s),并且(s)是基本块j的入口语句。
应用上述方法求出本题所给程序的基本块及程序流图见图5-1,图中的有向边、实线是按流图画法(1)画出的,虚线是按流图画法(2)画出的。
图5-1 程序流图5.4 基本块的DAG 如图5-2所示。
若: (1) b 在该基本块出口处不活跃; (2) b 在该基本块出口处活跃; 请分别给出下列代码经过优化之后的代码:(1) a=b+c (2) b=a-d(3) c=b+c (4) d=a-d图5-2 习题5.4的DAG 图【解答】 (1) 当b 在出口处不活跃时,生成优化后的代码为a=b0+c0d=a-d0c=d+c0(2) 当b 在出口活跃时,生成优化后的代码为a=b0+c0b=a-d0d=bc=d+c05.5 对于基本块P :S0=2S1=3/S0S2=T-CS3=T+CR=S0/S3H=RS4=3/S1S5=T+CS6=S4/S5H=S6*S2(1) 应用DAG 对该基本块进行优化;(2) 假定只有R 、H 在基本块出口是活跃的,试写出优化后的四元式序列。
【解答】 (1) 根据DAG 图得到优化后的四元式序列为S0=2S4=2S1=1.5S2=T-CS3=T+CS5=S3R=2/S3S6=RH=S6*S2(2) 若只有R 、H 在基本块出口是活跃的,优化后的四元式序列为S2=T-C00S3=T+CR=2/S3H=R*S25.6 试画出如下中间代码序列的程序流图,并求出:(1) 各结点的必经结点集合D(n);(2) 流图中的回边与循环。
J=0L1:I=0if I< 8 goto L3L2:A=B+CB=D*CL3:if B =0 goto L4write Bgoto L5L4:I= I+1if I<8 goto L2L5:J= J+1if J<=3 goto L1halt【解答】(1) 各结点的必经结点集分别为D(n0)={n0}D(n1)={n0,n1}D(n2)={n0,n1,n2}D(n3)={n0,n1,n3}D(n4)={n0,n1,n3,n4}D(n5)={n0,n1,n3,n5}D(n6)={n0,n1,n3,n6}D(n7)={n0,n1,n3,n6,n7}程序流图如图5-3所示。
5-3 习题5.6的程序流图由于有n5→n2和n6→n1,而n2不是n5的必经结点,n1是n6的必经结点,所以n6→n1为回边;即该回边表示的循环为{ n1,n2,n3,n4,n5,n6},入口结点为n1,出口结点为n6。
5.7 证明:如果已知有向边n →d 是一回边,则由结点d 、结点n 以及有通路到达n 而该通路不经过d 的所有结点组成一个循环。
【解答】 根据题意画出示意图,如图5-4所示。
图5-4 具有回边n →d 的流图证明过程如下:(1) 令结点d 、结点n 以及有通路到达n 而该通路不经过d 的所有结点构成集合L(即图5-4中的全部结点),则L 必定是强连通的。
为了证明这一点,令M=L-{d,n}。
由L 的组成成分可知M 中每一结点ni 都可以不经过d 而到达n 。
又因d DOM n(已知n →d 为回边,由回边定义知必有d DOM n),所以必有d DOM ni ,如图5-4所示。
如不然,则从首结点就可以不经过d 而到达ni ,从而也可以不经过d 到达n ,这与d DOM n 矛盾。
因d DOM ni 所以d 必有通路到达M 中任一结点ni ,而M 中任一结点又可以通过n 到达d(n →d 为回边),从而M 中任意两个结点之间必有一通路,L 中任意两个结点之间亦必有一通路。
此外,由M 中结点性质可知:d 到M 中任一结点ni 的通路上所有结点都应属于M ,ni 到n 的通路上所有结点也都属于M 。
因此,L 中任意两结点间通路上所有结点都属于L ,也即,L 是强连通的。
(2) 因为对所有ni ∈L ,都有d DOM ni ,所以d 必为L 的一个入口结点。
我们说d 也一定是L 的唯一入口结点。
如不然,必有另一入口结点d1∈L 且d1≠d 。
d1不可能是首结点,否则d DOM n 不成立(因为有d DOM d1,如果d1是首结点,则d 就是首结点d1的必经结点,则只能是d=d1,与d ≠d1矛盾)。
现设d1不是首结点,且设d1在L 之外的前驱是d2,那么,d2和n 之间必有一条通路d2→d1→…→n ,且该通路不经过d ,从而d2应属于M ,这与d2∈L 矛盾。
所以不可能存在上述结点d1,也即d 是循环的唯一入口结点。
至此,我们已经满足了循环的定义:循环是程序流图中具有唯一入口结点的强连通子图,也即,L 是包含回边n →d 的循环,d 是循环的唯一入口结点。
5.8 对下面四元式代码序列:A=0I=1L1: B=J+1C=B+IA=C+Aif I=100 goto L2I=I+1goto L1L2: write A1kn i jhalt(1) 画出其控制流程图;(2) 求出循环并进行循环的代码外提和强度削弱优化。
【解答】 (1) 在构造程序的基本块的基础上画出该程序的流图,如图5-5所示。
我们知道,强度削弱不仅可对乘法运算进行,也可对加法运算进行。
由于本题中的四元式程序不存在乘法运算,所以只能进行加法运算的强度削弱。
从图5-5中可以看到,B2中的C=B+I ,变量B 因代码外提其定值点已在循环之外,故相当于常数。
而另一加数I 值由B3中的I=I+1决定,即每循环一次I 值增1;也即每循环一次,B2中的C=B+I 其C 值增量与B3中的I 相同,即常数1。
因此,我们可以对C 进行强度削弱,即将B2中的四元式C=B+I 外提到前置结点B2′中,同时在B3中I=I+1之后给C 增加一个常量1。
进行强度削弱后的结果如图5-7所示。
图5-7 习题5.8中强度削弱后的程序流图B 4B 45.9 某程序流图如图5-8所示。
(1) 给出该流图中的循环;(2) 指出循环不变运算;(3) 指出哪些循环不变运算可以外提。
图5-8 习题5.9的程序流图【解答】(1) 流图中的循环为{B2,B3,B4}。
(2) B3中的i=2是循环不变运算。
(3) 循环不变运算外提的条件是:①该不变运算所在的结点是循环所有出口结点的必经结点;②当把循环不变运算A=B op C(B或op C可以没有)外提时,要求循环中其他地方不再有A的定值点;③当把循环不变运算A=B op C外提时,要求循环中A的所有引用点都是而且仅仅是这个定值所能到达的。
由于i=2所在的结点不是循环所有出口结点的必经结点,故不能外提。
5.10化。
5.10的程序流图【解答】由图5-9可知,B5→B4与B6→B2为流图的有向边,从而有D(B5)={B1,B2,B3,B4,B5}D(B6)={B1,B2,B3,B4,B6}故有B4 DOM B5和B2 DOM B6,因此B5→B4和B6→B2为回边(其余都不是回边),即分别组成了循环{B4,B5}、{B2,B3,B4,B5,B6}。
对循环{B4,B5}、{B2,B3,B4,B5,B6}进行代码外提、强度削弱和删除归纳变量等优化后,其优化后的程序流图如图5-10所示。
图5-10 习题5.10中优化后的程序流图。