编译TopDowntBottomUp习题解答.docx

上传人:b****4 文档编号:26783405 上传时间:2023-06-22 格式:DOCX 页数:16 大小:166.94KB
下载 相关 举报
编译TopDowntBottomUp习题解答.docx_第1页
第1页 / 共16页
编译TopDowntBottomUp习题解答.docx_第2页
第2页 / 共16页
编译TopDowntBottomUp习题解答.docx_第3页
第3页 / 共16页
编译TopDowntBottomUp习题解答.docx_第4页
第4页 / 共16页
编译TopDowntBottomUp习题解答.docx_第5页
第5页 / 共16页
点击查看更多>>
下载资源
资源描述

编译TopDowntBottomUp习题解答.docx

《编译TopDowntBottomUp习题解答.docx》由会员分享,可在线阅读,更多相关《编译TopDowntBottomUp习题解答.docx(16页珍藏版)》请在冰豆网上搜索。

编译TopDowntBottomUp习题解答.docx

编译TopDowntBottomUp习题解答

1、已知文法G(S):

SfaS|bS|a

(1)构造该文法的LR(O)项目集规范族

(2)构造识别该文法所产生的活前缀的DFA。

(3)构造其SLR分析表,并判断该文法是否是SLR

(1)文法。

解题思路

构造LR(O)项目集规范族,有两种方法:

一种是利用有限自动机来构造,另一种是利用函数CLOSURE和GO来构造。

本题采取第2种方法,通过计算函数CLOSURE和GO得到文法的LR(O)项目集规范族,而GO函数则把LR(0)项目集规范族连成一个识别该文法所产生的活前缀的DFA。

解答

(1)将文法G(S)拓广为G(S'):

(O)S'fS

(1)SfaS

(2)SfbS

(3)Sfa

构造该文法的LR(0)项目集规范族:

lo=CLOSURE({SS})={S厶S,S^aS,S^bS,S-a}

Ii=GO(Io,a)=CLOSURE({S-aS,S-a})={S-aS,S-a•,S—aS,

SfbS,Sf}a

I2=GO(Io,b)=CLOSURE({S-bS})={S-bS,S-aSS,-bS,S-}a

I3=GO(Io,S)=CLOSURE({S'-S})={S'}-S

GO(I1,a)=CLOSURE({S-aS,S-a})=I1

GO(I2,b)=CLOSURE({S-bS})=I2

I4=GO(I1,S)=CLOSURE({S-aS})={S-aS}

GO(I2,a)=CLOSURE({S-aS,S-a})=I1

GO(I2,b)=CLOSURE({S-bS})=I2

I5=GO(I2,S)=CLOSURE({S-bS})={S-bS}

所以,项目集Io,|1,|2,|3,|4和|5构成了该文法的LR(O)项目集规范族。

(2)我们用GO函数把LR(o)项目集规范族连成一个识别该文法所产生的活前缀的DFA如图4.1所示。

(3)构造其SLR分析表。

 

表4.1SLR分析表

ACTION

GOTO

状态

a

b

#

S

0

S1

S2

3

1

S1

S2

r3

4

2

S1

S2

5

3

acc

4

r1

5

r2

注意到状态Ii存在“移进-归纳”冲突,计算S的FOLLOW集合:

FOLLOW(S)={#}

可以采用SLR冲突消解法,得到表4.1所列的SLR分析表。

从分析表可以看出,表中没有冲突项,所以该文法是SLR

(1)文法。

2、证明AdBd是文法G(S)的活前缀。

说明活前缀在LR分析中的作用。

给出串dbdb#的LR分析过程。

G(S):

(1)S—AdB

(2)A—a(3)A

⑷B—b(5)B—BdbQB—£

解题思路

所谓活前缀是指规范句型的一个前缀,这种前缀不句柄之后的任何符号。

根据此定义,直接证明AdBd是文法G(S)的活前缀。

解答

存在下面的规范推导:

Sl》AdB・〉AdBdb

可见AdBdb是文法G的规范句型,AdBd是该规范句型的前缀。

另外,在该规范句型中Bdb是句柄,前缀是AdBd不含句柄Bdb之后的任何符号,所以AdBd是文法G(S)的活前缀。

在LR分析工作过程中的任何时候,栈里的方法符号(自栈底而上)X1X2…Xm应该构成活前缀,把输入串的剩余部分配上之后即应成为规范句型(如果整个输入串确实构成一个句

子)。

因此,只要输入串的已扫描部分保持可归约成一个活前缀,那就意味着所扫描过的部分没有错误。

构造文法G的LR分析表4.2所列。

表4.2LR分析表

ACTION

GOTO

a

d

b

#

S

A

B

0

s3

r3

1

2

1

acc

2

s4

3

r2

4

r6

s5

r6

6

5

r4

r4

6

s7

r1

7

s8

8

r5

r5

 

串dbdb#的LR分析过程如下:

步骤

状态

符号

输入串

0

0

#

dbdb#

1

02

#A

dbdb#

2

024

#Ad

bdb#

3

0245

#Adb

db#

4

0246

#AdB

db#

5

02467

#AdBd

b#

6

024678

#AdBdb

#

9

0246

#AdB

#

10

01

#S

#

acc

3、根据程序设计语言的

般要求,

为定义条件语句的二义文法

G(S)构造SLR

(1)分析表,

要求写出步骤和必要的说明。

G(S):

s—iSeS|iS|a

解答

将文法G(S)拓广为G(S'):

(0)S'—S

(1)S—iSeS

⑵S—iS

⑶S—a

构造此文法的LR(O)项目集规范族,识别该文法所产生的活前缀的DFA如图4.2所示。

图4”2识別活前缀的DFA

注意到状态丨4存在“移进—归约”冲突,计算FOLLOW集合:

FOLLOW(S)={e,#}

当LR分析器处于状态4时,如果下一输入符号是“#”,则按S—iS归约;如果下一输入符号是“e”,则既可以按S—iS归约,也可以执行移入。

根据程序设计语言的要求,条件语句的else子句应当和最近的没有else子句的if语句匹配,根据这一要求,我们规定:

当LR分析器处于状态4时,如果下一输入符号是“#”,则按S—iS归约;如果下一输入符号是“e”,则执行移入。

构造SLR

(1)分析表如表4.3所列。

表4.3SLR

(1)分析表

ACTION

GOTO

i

e

a

#

-S

0

s2

s3

1

1

acc

2

s2

s3

4

3

r3

r3

4

s5

r2

5

s2

s3

6

6

r1

r1

4、设下列文法生成变量的类型说明:

D—idL

L—,idL|:

T

T—integer|real

构造一个翻译模式,把每个标识符的类型存入符号表。

解题思路

这是一个对说明语句进行语义分析的题目,不需要产生代码,但要求把每个标识符的类型填入符号表中。

解答

对D,L,T设置综合属性type。

过程addtype(id,type)用来把标识符id及其类型type填入到符号表中。

翻译模式如下:

DfidL{addtype(id.entry,L.type)}

Lf,idL1{addtype(id.entry,L1.type);L.type:

=L1.type;}

Lf:

T{L.type:

=T.type}

Tfinteger{T.type:

=interger}

Tfreal{T.type:

=real}

5、文法G的产生式如下:

Sf(L)|a

LfL,S|S

(1)试写出一个语法制导定义,它输出配对括号个数;

(2)写一个翻译方案,打印每个a的嵌套深度。

如((a),a),打印2,1。

解题思路

本题包括两部分,第1部分要求写语法制导定义,第2部分要求写翻译方案。

语法制导定义(或属性文法)可以看作是关于语言翻译的高级规范说明,其中隐去实现细节,使用户从明确说明翻译顺序的工作中解脱出来。

翻译方案(也称翻译模式)给出了使用语义规则进行计算的次序,把某些实现细节表示出来。

读者从下面解答中可体会两者的区别。

解答

(1)为S、L引入属性h,代表配对括号个数。

语法制导定义如下:

产生式语义规则

Sf(L)S.h:

=L.h+1

SfaS.h:

=0

LfL1,SL.h:

=L1.h+S.h

LfSL.h:

=S.h

S'fSprint(S.h)

(2)为S、L引入d,代表a的嵌套深度。

翻译方案如下:

S'f{S.d:

=0;}S

Sf‘('{L.d:

=S.d+1;}

L

‘)'

Sfa{print(S.d);}

Lf{L1.d:

=L.d;}

L1

{S.d:

=L.d;}

S

Lf{S.d:

=L.d}

S

6、下列文法对整型常数和实型常数施用加法运算符“+”生成表达式;当两个整型数相加时,结果仍为整型数,否则,结果为实型数:

EfE+T|T

Tfnum.num|num

(1)试给出确定每个子表达式结果类型的属性文法。

(2)扩充

(1)的属性文法,使之把表达式翻译成后缀形式,同时也能确定结果的类型。

应该注意使用一元运算符inttoreal把整型数转换成实型数,以便使后缀形如加法运算符的两个操作数具有相同的类型。

解题思路

确定每个子表达式结果类型的属性文法是比较容易定义的。

关键是如何扩充此属性文法,使之把表达式翻译成后缀形式。

我们将不在name或num.num向T

归约的时候输出该运算对象,而是把运算对象的输出放在T或E+T向E归约的

时候。

这是因为考虑输出类型转换算符inttoreal的动作可能在E+T归约的时

候进行,如果这时两个运算对象都在前面name或num.num向T归约的时候已输出,需要为第1个运算对象输出类型转换算符时就已经为时太晚。

还要注意的是,在E+T向E归约时,该加法运算的第1个运算对象已经输出。

所以E-E+T的语义规则不需要有输出E运算对象的动作。

解答

(1)为文法符号E和T配以综合属性type,用来表示它们的类型。

类型值分别用int和real来表示。

确定每个子表达式结果类型的属性文法如下:

产生式

E-E1+T

E-T

语义规则

{T.type:

=ifE1.type=intandT.type=intthenintelsereal

{E.type:

=T.type}

T-num.numT.type:

=real

T-numT.type:

=int

(2)下面属性文法将表达式的后缀表示打印输出,其中lexeme属性表示单词的拼

写。

产生式语义规则

E-E1+TifE1.type=realandT.type=intthen

begin

E.type:

=real;print(T.lexeme);print(‘inttoreal');

end

elseifE1.type=intandT.type=realthenbegin

E.type:

=real;

print(‘inttoreal');

print(T.lexeme);

end

elsebegin

E.type:

=E1.type;print(T.lexeme);end

print(‘+');

E-TE.type:

=T.type;print(T.lexeme);

T-num.numT.type:

=real;T.lexeme:

=num1.lexeme||“.”||num2.lexeme

T-numT.type:

=int;T.lexeme:

=num.lexeme;

1:

构造如下给定的文法的预测分析表

SAB

A►Ba

B►Db|D

D——►d|&

解:

因为原文法存在左因子

先消除作因子:

将A的产生式代入S

S►BaB|B

提取左因子SBA'A——►aB

引入非终结符号B►DB'B'一|&

消除无用的产生式A——►Ba|&

得到文法:

S——►BA'

A►aB|&

B►DB'

B'►b|&

D►d|&

FIRST(D)={d,&}FIRST(B')={b,&}FIRST(B)={b,d,&}FIRST(A')={a,&}

FIRST(S)={a,b,d,&}FIRST(BA')={a,b,d,&}FIRST(aB)={a}FIRST(DB')={b,d,&}FOLLOW(S)={#}FOLLOW(A')={#}FOLLOW(B)={a,#}FOLLOW(B')={a,#}

FOLLOW(D)={a,b,#}

改写后文法的预测分析表:

a

b

d

#

S

S―►BA'

S―►BA'

S►BA'

S►BA'

A'

A-aB

A'►&

B

BkDB'

BDB

B~DB

BDB

B'

B►&

B'kb

B&

D

D►&

D►&

D―►d

D►&

因为预测分析表无冲突,所以改写后的文法是LL

(1)文法。

2:

判断下列文法可否改写为LL

(1)文法:

SA|B

AaA|a

B►bB|b

因为有左因子•所以原文法不是LL

(1)文法.

改写文法,提取左因子,提取文法:

SA|B

AkaA|&

AA|&

BkbB'

B'►B|£

求FIRSTT集和FOLLOW集

FIRST(B)={b}FIRST(B')={b,£}FIRST(B)={b,d,£}FIRST(A')={a,£}

FIRST(A)={a}FIRST(S)={a,b}FIRST(aB)={a}FIRST(DB')={b,d,£}FOLLOW(S)={#}FOLLOW(A')=FOLLOW(A)=FOLLOW(B)=FOLLOW(B')={#}因为:

FIRST(A)AFIRST(B)=Q

FIRST(A)AFIRST(A')=Q£FIRST(A)

FIRST(B)AFOLLOW(B')=Q£FIRST(B)

所以改写后的文法是LL

(1)文法。

3:

S—i|(E)

E——►E+S|E-S|S

解:

因为原文法有左递归和左因子•所以不是LL

(1)文法.

先消去E的产生式中的左递归:

ESE'

E'—E'|-SE'|£

得到文法:

Si|(E)

E——►SE'

E'—E'|-SE'|£

求FIRST()集和FOLLOW()集

FIRST(S)={i,(}

FIRST(E)=FIRST(SE')={i,(}

FIRST(E')={+,-,&}

FOLLOW(S)={+,-,),#}

FOLLOW(E)={)}

FOLLOW(E')={)}

FIRST(i)AFIRST((E))=①

FIRST(+SE)AFIRST(-SE)=①

£FIRST(+SE)£FIRST(-SE)

FOLLOW(E')FIRST(+SE),FIRST(-SE)

4:

求以下文法中各个非终结符号的

A►baB|&

BFbb|a

解:

FIRST(A)={b,&}

FIRST(B)={a,b}

FOLLOW(A)={b,#}

FOLLOW(B)={b,#}

改写文法消除左递归:

FIRST()集和FOLLOW()集

所以改写后的文法是LL

(1)文法.

M►MaH|H

Hb(M)|(M)|b

解引入M得到文法

M—HM

M—M|£

Hb(M)|(M)|b

此文法中不含左递归,但是关于H的产生式中含左因子,提取左因子得到文法

M—HMI,

M—M|£

HbH|(M)

H'►(M)|£

五:

构造如下给定文法的递归子程序:

S—a|f|(T)

TT,S|S

解:

引入「,消除左递归得到文法

S—►a||(T)

T►ST,

T'——T,|£

FIRST(S)={a,,(}

FIRST(T)=FIRST(S)FIRST(T,)={,£}FOLLOW(S)={,),#}FOLLOW(T)=FOLLOW(T,)={)}

因为FIRST(a),FIRST(f),FIRST((T))两两相交为①FIRST(,ST,)AFOLLOW(T,)=①£FIRST(,ST,)

所以改写后的文法是LL

(1)文法.

语法图:

 

T,

将T'代入T化简得到:

S的递归子程序:

ProcedureS

Begin

Iflookhead=''thenmatch(a'

Elseiflookhead='f'henmatach(T'

Elseiflookhead='('henBegin

Match('(');

Match(')'

end

end;

T递归子程序:

ProcedureT;

begin

S;

Whilelookhead='(do

Begin

Match(

S;Match()';

End

End;

主程序:

Begin

Lookhead==nexttoken;

S

End;

Match的子程序:

Procedurematch(t.token);

Begin

Iflookhead=tthen

Lookhead:

=nexttoken

Else

Error出错程序处理

End

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 自然科学 > 天文地理

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1