编译原理(第3版)习题精选与解析(第三章部分解析)

内容

3ư17给出接受文法S→(L)|aL→L,S|S的活前缀的一个DFA。答首先将文法进行如下拓广,其中S′是拓广文法的开始符号。S′→SS→(L)|aL→L,S|S接受该文法活前缀的一个DFA的状态转换图见图3ư5,开始状态是I0,所有的状态都是接受状态。图3ư5识别文法活前缀的DFA分析文法活前缀是LR分析的一个重要概念,接受文法活前缀的DFA是构造LR分析表过程中的重要一步。一些同学在构造LR分析表时会画这样的状态转换图,但是却未理解这是接受文法活前缀的DFA。构造SLR(1)分析表、规范LR(1)分析表和LALR(1)分析表时都需要先构造这样的DFA,由于用SLR(1)方法得到的DFA的状态数最少[实际上这个DFA就是用LR(0)方法构造的DFA],因此用SLR(1)方法。3ư18一个文法如下:S→(S)13
S→a请给出该文法中对活前缀(((有效的LR(1)项目。答该文法中对活前缀(((有效的LR(1)项目如下:S→(ưS),)S→ư(S),)S→ưa,)分析构造识别该文法活前缀的DFA时,实际上只要画出三个LR(1)项目集就可以看出结果了,这三个项目集见图3ư6。图3ư6识别文法活前缀的三个项目集3ư19接受文法S→Aa|bAc|dc|bdaA→d活前缀的DFA见图3ư7。请根据这个DFA来构造该文法的SLR(1)分析表,并说明该文法为什么不是SLR(1)文法。图3ư7识别文法活前缀的DFA答分析表见表3ư4,注意FOLLOW(A)={a,c}。因为有两处有移进-归约冲突,所以该文法不是SLR(1)文法。23
表3ư4为3ư19题的文法构造的分析表状态动作转移abcd$SA0s3s4121acc2s53s764r5s8,r55r16s97s10,r58r39r210r43ư20证明文法S→AaAb|BbBaA→εB→ε是LL(1)文法,但不是SLR(1)文法。答先证明它是LL(1)文法。因为仅非终结符S有两个不同的选择,因此只需考察它的两个右部。由于FIRST(AaAb)={a}FIRST(BbBa)={b}它们的交集为空,所以该文法是LL(1)文法。这里不是通过构造SLR(1)分析表,而是通过简单的分析来判断该文法不是SLR(1)。根据该文法,不管对什么句子,在面临第一个符号时进行空归约。由于FOLLOW(A)和FOLLOW(B)都等于{a,b},那么就不能确定是把ε归约成A还是归约成B,因此出现归约-归约冲突,所以该文法不是SLR(1)的。分析其实,该语言只有两个句子ab和ba,这个冲突是很容易解决的。但是由于用SLR方法构造分析表时,不是根据向前搜索符,而是根据所有可能的后继符号来填归约项目,这种粗糙性决定了会出现这样的归约-归约冲突。不要从这个例子得出LL(1)方法比SLR(1)方法强的错误结论。例如,习题3ư16中的表达式文法是SLR(1)的,但它不是LL(1)的,因为它有左递归。33
3ư21证明文法S→Aa|bAc|dc|bdaA→d是LALR(1)文法,但不是SLR(1)文法。答通过构造分析表来回答这个问题并不困难(见3ư23题),但是在文法很简单时,也应该能直观地分析出来。先说明该文法不是SLR(1)文法。从产生式很容易看出FOLLOW(A)={a,c}。若句子是dc,在d进分析栈后,面临的是c,这时出现移进-归约冲突,因为项目[S→dưc]要求移进,而由于c在FOLLOW(A)中,项目[A→dư]要求归约(这两个项目出现在同一项目集中)。上面的移进-归约冲突在规范LR(1)情况下不存在,因为只有在面临a时才进行d到A的归约。上面的文法还有另一个移进-归约冲突,在bd进栈后,面临a的情况,其冲突的原因和上面的类似。该冲突在规范LR(1)情况下也不存在。这样,该文法是LR(1)文法。显然,该文法的规范LR(1)项目集的集合中没有同心项目集,因此该文法也是LALR(1)文法。3ư22证明文法S→Aa|bAc|Bc|bBaA→dB→d是LR(1)文法,但不是LALR(1)文法。答该文法产生的语言仅含四个句子:da,bdc,dc和bda。不难看出,在规范LR(1)的情况下,d在什么情况下归约成A、什么情况下归约成B是能区分清楚的,所以它是LR(1)文法。在该文法的规范LR(1)项目集的集合中,对活前缀d有效的项目集是{[A→dư,a],[B→dư,c]}对活前缀bd有效的项目集是{[A→dư,c],[B→dư,a]}这两个集合都不含冲突,并且它们同心。合并同心集后变成{[A→dư,a/c],[B→dư,a/c]}出现归约-归约冲突,所以该文法不是LALR(1)文法。3ư23说明下面的文法不是SLR(1)文法,并重写一个等价的SLR(1)文法。S→Aa|bAc|dc|bdaA→d43
答分析表的部分状态见图3ư8,虽然只给出部分状态,但可能有的冲突都表现出来了。因为a是A的后继符号之一,因此在上面最右边一个项目集中有移进-归约冲突。类似地,下面中间那个状态也有移进-归约冲突。等价的SLR(1)文法是:S→da|bdc|dc|bda图3ư8分析表的有关状态3ư24下面的文法不是LR(1)的,对它略做修改,使之成为一个等价的SLR(1)文法。program→begindeclist;statementenddeclist→d;declist|dstatement→s;statement|s答修改后的文法如下:program→begindecliststatementenddeclist→d;declist|d;statement→s;statement|s分析该文法产生的句子的形式是:begind;d;…;d;s;s;…;send即主要是由分号分隔的若干个声明构成的声明表和由分号分隔的若干个语句构成的语句表,两表之间用分号分隔。由于分号既作为声明的分隔符,又作为声明表和语句表的分隔符,这就出现一个问题。该文法的第一步归约是将最后一个d归约成declist。当分析器将d压入分析栈,面临“;”时,它不能判断该d是否为最后一个d,因此有移进-归约冲突。如果把d后面的分号压入栈后再决定动作,移进-归约冲突就会消失。按这样的想法来修改文法,修改后的文法把声明d后的分号看成是d的结束符,因此把原来分隔声明表和语句表的分号看成是最后一个声明d的结束符。这时就不会有移进-归约冲突了

pdf

https://bill.lanzoui.com/iZOScx16aza

猜你喜欢

转载自blog.csdn.net/horizon08/article/details/121619403