660 likes | 934 Views
第7章 LR分析法. LR 分析法的归约过程是规范推导的逆过程,所以 LR 分析过程是一种规范归约过程。本章主要介绍 LR(K) 分析技术 L —— 从左到右扫描输入串 R —— 构造一个最右推导的逆过程 K —— 向右顺序查看输入串的 K 个( K≥0) 符号就可唯一地确定分析器的动作是移进还是归约和用哪个产生式归约. 7.1 LR 分析概述 一个 LR 分析器由3个部分组成: 总控程序,也可以称为驱动程序。对所有的 LR 分析器总控程序都是相同的。
E N D
第7章 LR分析法 LR分析法的归约过程是规范推导的逆过程,所以LR分析过程是一种规范归约过程。本章主要介绍LR(K)分析技术 L——从左到右扫描输入串 R——构造一个最右推导的逆过程 K——向右顺序查看输入串的K个(K≥0)符号就可唯一地确定分析器的动作是移进还是归约和用哪个产生式归约
7.1 LR分析概述 • 一个LR分析器由3个部分组成: • 总控程序,也可以称为驱动程序。对所有的LR分析器总控程序都是相同的。 • 分析表或分析函数,不同的文法分析表将不同,同一个文法采用的LR分析器不同时,分析表将也不同,分析表又可分为动作表(ACTION)和状态转换(GOTO)表两个部分,它们都可用二维数组表示。 • 分析栈,包括文法符号栈和相应的状态栈,它们均是先进后出栈。
Input# 栈 S1 Xm 总控程序 output … S1 … X1 ACTION GOTO 产生式表 S0 # LR分析表 状态 文法符号 分析器的动作就是由栈顶状态和当前输入符号所决定。 LR分析器工作过程示意图如图所示。 SP
其中SP为栈指针,S[i]为状态栈,X[i]为文法符号栈。状态转换表用GOTO[Si,X]=Sj表示,规定当栈顶状态为Si遇到当前文法符号为X时应转向状态Sj。X为终结符或非终结符。其中SP为栈指针,S[i]为状态栈,X[i]为文法符号栈。状态转换表用GOTO[Si,X]=Sj表示,规定当栈顶状态为Si遇到当前文法符号为X时应转向状态Sj。X为终结符或非终结符。 ACTION[Si,a]规定了栈顶状态为Si时遇到输入符号a应执行的动作。动作有4种可能: ① 移进 ② 归约 ③ 接受acc ④ 报错
① 移进: 把Sj=GOTO[Si,a]移入到状态栈,把a移入到文法符号栈。其 中i,j表示状态号。 ② 归约: 当在栈顶形成句柄为β时,则用β归约为相应的非终结符A, 即文法中有A→β的产生式,若β的长度为r(即|β|=r),则从 状态栈和文法符号栈中自栈顶向下去掉r个符号,即栈指针SP 减去r。并把A移入文法符号栈内,Sj=GOTO[Si,A]移进状态, 其中Si为修改指针后的栈顶状态。 ③ 接受acc:当归约到文法符号栈中只剩文法的开始符号S时,并且输入符 号串已结束即当前输入符是‘#’,则为分析成功。 ④ 报错: 当遇到状态栈顶为某一状态下出现不该遇到的文法符号时,则 报错,说明输入串不是该文法能接受的句子。
7.2 LR(0)分析 LR(0)分析表构造的思想和方法是构造其它LR分析表的基础。我们回顾在第6章中曾给出例6.1文法G[S]为: (1) S→aAcBe (2) A→b (3) A→Ab (4) B→d
3) #ab bcde# 归约(A→b) 5) #aAb cde# 归约(A→Ab) S 8) # aAcd e# 归约(B→d) A B 10) #aAcBe # 归约 A S aAcBe aAcde aAbcde abbcde 文法G[S]:(1) S → aAcBe(2) A → b(3) A → Ab(4) B → d 步骤 符号栈 输入符号串 动作 1) # abbcde# 移进 2) #a bbcde# 移进 4) #aA bcde# 移进 6) #aA cde# 移进 7) #aAc de# 移进 9) #aAcB e# 移进 11) #S # 接受 对输入串abbcde#的移进-规约分析过程 a b b c d e 符号串abbcde是否是G[S]的子
对输入串abbcde#用自底向上归约的方法进行分析,当归约到第5步时栈中符号串为#aAb,我们采用了产生式(3)进行归约而不是用产生式(2)归约,而在第3步归约时栈中符号串为#ab时却用产生式(2)归约,虽然在第2步和第5步归约前栈顶符号都为b,但归约所用产生式却不同,为什么?对输入串abbcde#用自底向上归约的方法进行分析,当归约到第5步时栈中符号串为#aAb,我们采用了产生式(3)进行归约而不是用产生式(2)归约,而在第3步归约时栈中符号串为#ab时却用产生式(2)归约,虽然在第2步和第5步归约前栈顶符号都为b,但归约所用产生式却不同,为什么? 其原因在于已分析过的部分在栈中的前缀不同,为了说明这个问题并引进一些概念和术语。
1、文法的规范句型的‘活前缀’和‘可归前缀’的概念1、文法的规范句型的‘活前缀’和‘可归前缀’的概念 字的前缀是指该字的任意首部。 例:字abc 的前缀有 ,a,ab,abc 在LR分析工作过程中的任何时候,栈里的符号(自栈底而向上)X1X2…Xn应该构成活前缀,把输入串的剩余部分配上就成为规范句型。 所谓活前缀:是指规范句型的一个前缀,这种前缀不含句柄之后的任何符号。 可归前缀:每次归约动作之前的活前缀称为可归前缀
文法G[S]:(1) S → aAcBe(2) A → b(3) A → Ab(4) B → d 例: 问abbcde是否是它的句子? 最右推导过程 S aAcBe[1] aAcd[4]e[1] aAb[3]cd[4]e[1] ab[2]b[3]cd[4]e[1] 归约前句型的前缀(可归前缀) 归约前可在栈里的规范句型(不含句柄之后 的任何符号的前缀称为活前缀) ab[2] ,a,ab aAb[3] ,a,aA,aAb aAcd[4] ,a,aA,aAc,aAcd aAcBe[1] ,a,aA,aAc,aAcB,aAcBe
活前缀与句柄之间的关系有三种情况: (1)活前缀已经含有句柄的全部符号,表明产生式A→β的右部β已出现在栈顶 (2)活前缀只含有句柄的部分符号,表明A→β1β2的右部子串β1已出现在栈顶,期待从输入串中看到β2推出的符号 (3)活前缀不含句柄的任何符号,此时期望A→β的右部所推出的符号串 为了刻划这种分析过程中文法G中的每个产生式的右部已有多大部分被识别(已经出现在栈顶)我们在产生式某处加上圆点“.”来指示位置,对上述三种情况标出圆点的产生式: (1)A . (2) A 1. 2 (3) A .
构造LR(0)项目集规范族 (1) LR(0)项目在文法G中每个产生式的右部适当位置添加一个圆点构成项目。 例:A xyz 对应4个项目: A.xyz Ax.yz Axy.z Axyz. 如:S→aAd 对应的项目: S→.aAd S→a .Ad S→aA .d S→aAd . 对于A→ε的LR(0)项目只有A→.
注意: (1)凡是圆点在最右端的项目,称为归约项目。 如:Axyz. 用r表示归约 (2)对文法开始符号的归约项目称为接受项目,用acc表示 如:S . S 是开始符 (3)形如A . B β的项目称为待归约项目,即表明所对 应状态正等待分析完非终结符B所能推出的串归约成B, 才能分析A的右部 (4)形如A . a β的项目称为移进项目,即终结符a移进 符号栈。移进用S表示
2) 构造识别活前缀的NFA如果把文法的所有产生式的项目都引出,每个项目都为NFA的一个状态。 • 将文法G拓展为G’,目的是为了使文法有且仅有一个接受项目。 • 例 :文法G: • E→aA|bB A→cA|d B→cB|d拓展后变为: (1)S′→E(2)E→aA (3)E→bB(4)A →cA (5)A →d (6)B →cB (7) B →d
构造该文法的项目有: 1. S′→·E 10. A→d· 2. S′→E· 11. E→·bB 3. E→·aA 12. E→b·B 4. E→a·A 13. E→bB· 5. E→aA· 14. B→·cB 6. A→·cA 15. B→c·B 7. A→c·A 16. B→cB· 8. A→cA· 17. B→·d 9. A→·d 18. B→d·
1. S′→·E 10. A→d·2. S′→E· 11. E→·bB3. E→·aA 12. E→b·B4. E→a·A 13. E→bB·5. E→aA· 14. B→·cB6. A→·cA 15. B→c·B7. A→c·A 16. B→cB·8. A→cA· 17. B→·d9. A→·d 18. B→d· 识别活前缀的NFA
对于图中识别活前辍的NFA我们可以利用第4章讲过的子集法将其确定化。对确定化后的DFA如果把每个子集中所含状态集对应的项目写在新的状态中,结果见P132如7.8图所示。对于图中识别活前辍的NFA我们可以利用第4章讲过的子集法将其确定化。对确定化后的DFA如果把每个子集中所含状态集对应的项目写在新的状态中,结果见P132如7.8图所示。
(3) LR(0)项目集规范族的构造 对于构成识别一个文法活前缀的DFA项目集(状态)的全体称为这个文法的LR(0)项目集规范族,我们可以分析图7.8中每个状态中项目集的构成,不难发现如下规律:若状态中包含形如A→α·Bβ的项目,则形如B→·γ的项目也在此状态内。例如:0状态中项目集为{S′→·E,E→·aA, E→·bB}。 若文法G已拓广为G′,而S为文法G的开始符号,拓广后增加产生式S′→S,如果I是文法G′的一个项目集,定义和构造I的闭包CLOSURE(I)如下:a) I的项目均在CLOSURE(I)中。b) 若A→α·Bβ属于CLOSURE(I),则每一形如B→·γ 的项目也属于CLOSURE(I)。 c) 重复b)直到不出现新的项目为止。即CLOSURE(I)不 再扩大。 由此,我们可以很容易构造出初态的闭包,即 S′→·S 属于I,再按上述三点求其闭包。
有了初态的项目集,其它状态的项目集如何求出?有了初态的项目集,其它状态的项目集如何求出? 由于识别活前缀的DFA的每个状态是一个项目集,项目集中的每个项目都不相同,每个项目圆点后的符号不一定相同,因而对每个项目圆点移动一个位置后,箭弧上的标记也不会完全相同,这样,对于不同的标记将转向不同的状态。例如初态{S′→·E,E→·aA,E→·bB}对第一个项目圆点右移一个位置后变为S′→E·箭弧标记应为E,对第二个项目E→·aA,圆点右移一个位置后,项目变为E→a·A,箭弧标记为a,同样第三个项目为圆点右移一个位置后变为E→b·B,箭弧标记为b,显然,初态可发出三个不同标记的箭弧,因而转向三个不同的状态,也就由初态派生出三个新的状态,对于每个新的状态我们又可以利用前面的方法,若圆点后为非终结符则可对其求闭包,得到该状态的项目集。圆点后面为终结符或在一个产生式的最后,则不会再增加新的项目。
由前面可知LR(0)项目集规范族的项目类型分为四种:a) 移进项目b) 归约项目c) 待约项目d) 接受项目一个项目集中可能包含以上四种不同的项目,但是一个项目集中不能有下列情况存在:1) 移进和归约项目同时存在: 形如:A→α·aβ B→γ·由于这时面临输入符号为a时不能确定移进a还是把γ归约为B,因为LR(0)分析是不向前看符号,所以对归约的项目不管当前符号是什么都应归约。对于在一个项目集中同时存在移进和归约项目时称该状态含有移进-归约冲突。 2) 归约和归约项目同时存在。 形如:A→β· B→γ·因这时不管面临什么输入符号都不能确定归约为A,还是归约为B,对于在一个项目集中同时存在两个以上归约项目时称该状态含有归约-归约冲突。对一个文法的LR(0)项目集规范族不存在移进-归约,或归约-归约冲突时,称这个文法为LR(0)文法。
按上述方法建立识别活前缀的DFA结果与7.8图相同按上述方法建立识别活前缀的DFA结果与7.8图相同 构造上例文法的LR(0)分析表见P136表7.3所示 对输入串bccd#的LR(0)分析过程见P136表7.4所示
例:G[S]为: S a A c B e A b A Ab B d 1)构造识别活前缀的DFA 2)构造它的LR(0)分析表。 3)分别给出对输入符号串abbcde和 abbbce的LR(0)分析步骤。
G[S]拓广为: • S’ S • S a A c B e • A b • A Ab • B d I4 :A b • I6 :A A b • b b I2 :S a • A c B e A •b A • Ab I1 :S’ S • A I3 :S a A •c B e A A •b S a c I0 : S’ • S S •a A c B e B I5 :S a A c • B e B •d I7 :S a A c B •e e d I9 :S a A c B e • I8 :B d •
对输入串abbcde#的分析过程 Stepstates. Syms. The rest of inputaction goto 1 0 # abbcde# s2 2 02 #a bbcde# s4 3 024 #ab bcde# r2 3 4 023 #aA bcde# s6 5 0236 #aAb cde# r3 3 6 023 #aA cde# s5 7 0235 #aAc de# s8 8 02358 #aAcd e# r4 7 9 02357 #aAcB e# s9 10 023579 #aAcBe # r1 1 11 01 #S # acc
对输入串abbce#的分析过程 Stepstates. Syms. The rest of inputaction goto 1 0 # abbce# s2 2 02 #a bbce# s4 3 024 #ab bce# r2 3 4 023 #aA bce# s6 5 0236 #aAb ce# r3 3 6 023 #aA ce# s5 7 0235 #aAc e# 出错 说明abbce#不是文法 G[S]的句子
SLR(1)分析 由于大多数适用的程序设计语言的文法不能满足LR(0)文法的条件,即使是描述一个实数变量说明这样简单的文法也不一定是LR(0)文法。
现举实型变量说明文法为例: <实型变量说明>→ real<标识符表> <标识符表>→<标识符表>,i <标识符表>→i 将该文法缩写后并拓广为G′如下: (0) S′→S (1) S→rD (2) D→D,i (3) D→i LR(0)项目 1. S`→.S 2. S`→S. 3. S→.rD 4. S→r.D 5. S→rD. 6. D→.D,i 7. D→D.,i 8. D→D,.i 9. D→D,i. 10. D→.i 11. D→i.
LR(0)项目集规范族 I0: S`→.S I3: S→r D. S→.r D D→D.,i I1: S`→S. I4: D→i. I2: S→r.D I5: D→D.,i D→.D, i I6: D→D,i. D→.i 其中I3中含有移进/归约冲突 文法不是LR(0)的,如何解决?
状态 实数说明文法的LR(0)分析表 ACTION GOTO r , i # S D 0123456 S2..r1r3.r2 ...r1, S5r3.r2 ..S4r1r3S6r2 .acc.r1r3.r2 1 ..3 I3: S →rD. D →D.,i , I5: D →D,.i I1:S’→S. i D S I6:D →D,i. I2: S →r.D D →.D,i D →.i I0: S’→.S S →.rD r i I4: D →i. 首先构造该文法G′的识别活前缀的DFA如图
因此本节将介绍对于LR(0)规范族中有冲突的项目集(状态)用向前查看一个符号的办法进行处理,以解决冲突。这种办法将能满足一些文法的需要,因为只对有冲突的状态才向前查看一个符号,以确定做那种动作,因而称这种分析方法为简单的LR(1)分析法,用SLR(1)表示。因此本节将介绍对于LR(0)规范族中有冲突的项目集(状态)用向前查看一个符号的办法进行处理,以解决冲突。这种办法将能满足一些文法的需要,因为只对有冲突的状态才向前查看一个符号,以确定做那种动作,因而称这种分析方法为简单的LR(1)分析法,用SLR(1)表示。 因此假定一个LR(0)规范族中含有如下的项目集(状态)I I={X→α·bβ,A→γ·,B→δ·}也就是在该项目集中含有移进-归约冲突和归约-归约冲突。其中α,β,γ,δ为文法符号串,b为终结符。那么只要在所有含有A或B的句型中,直接跟在A或B后的可能终结符的集合即FOLLOW(A)和FOLLOW(B)互不相交,且都不包含b,也就是只要满足FOLLOW(A)∩FOLLOW(B)= FOLLOW(A)∩{b}= FOLLOW(B)∩{b}=
I={X→α·bβ,A→γ·,B→δ·} 那么,当在状态I时面临某输入符号为a时,则动作可由下规定决策。 1) 若a=b,则移进。 2) 若a∈FOLLOW(A),则用产生式A→γ进行归约。 3) 若a∈FOLLOW(B),则用产生式B→δ进行归约。 4) 此外,报错。 在上例中的I3如下: 因为I3中存在移进个归约的冲突,采用SLR(1)的方法看看是否可以解决: Follow(S) ∩ {,}={#} ∩ {,}= 所以遇到‘,’就移进,遇到#就归约。 I3:S→rD·.. D→D·,i
实数说明文法的SLR(1)分析表 状态 ACTION GOTO r , i # S D 0123456 S2...r3.r2 ...S5r3.r2 ..S4.r3S6r2 .acc.r1r3.r2 1 ..3
如果对于一个文法的LR(0)项目集规范族的某些项目集或LR(0)分析表中所含有的动作冲突都能用上述方法解决,则称这个文法是SLR(1)文法,所构造的分析表为SLR(1)分析表,使用SLR(1)分析表的分析器称为SLR(1)分析器。如果对于一个文法的LR(0)项目集规范族的某些项目集或LR(0)分析表中所含有的动作冲突都能用上述方法解决,则称这个文法是SLR(1)文法,所构造的分析表为SLR(1)分析表,使用SLR(1)分析表的分析器称为SLR(1)分析器。
例如,我们可以构造算术表达式文法的LR(0)项目集规范族,然后分析它是LR(0)文法还是SLR(1)文法,现将表达式文法拓广如下: (0) S′→E (1) E→E+T (2) E→T (3) T→T*F (4) T→F (5) F→(E) (6) F→i
该文法的LR(0)项目集规范族为: I5: F→i·I6: E→E+·T T→·T*F T→·F F→·(E) F→·i I7: T→T*·F F→·(E) F→·i I8: F→(E·) E→E·+T I9: E→E+T· T→T·*F I10: T→T*F· I11:F→(E)· I0: S′→·E E→·E+T E→·T T→·T*F T→·F F→·(E) F→·i I1: S′→E· E→E·+T I2: E→T· T→T·*F I3: T→F· I4: F→(·E) E→·E+T E→·T T→·T*F T→·F F→·(E) F→·i
与此相应的识别该文法活前缀的有限自动机如P139图7.10所示。 不难看出在I1,I2,I9中存在移进-归约冲突,因而这个表达式文法不是LR(0)文法,也就不能构造LR(0)分析表,现在分别考查这三个项目集(状态)中的冲突是否能用SLR(1)方法解决。 在I1中:S′→E· E →E·+T由于FOLLOW(S′)={#},而S′→E·是唯一的接受项目,所以当且仅当遇到句子的结束符"#"号时才被接受。又因{#}∩{+}= ,因此I1中的冲突可解决。
在I2中: E→T· T→T·*F我们可计算非终结符E的FOLLOW集为:FOLLOW(E)={+,),#}所以FOLLOW(E)∩{*}={+,),#}∩{*}= ,因此面临输入符为'+',')'或'#'号时,则用产生式E→T进行归约。当面临输入符为'*'号时,则移进,其它情况则报错。 在I9中: E→E+T· T→T·*F与I2中的情况类似因归约项目的左部非终结符E的后跟符集合FOLLOW(E)={+,),#}与移进项目圆点后终结符不相交,所以冲突可以用SLR(1)方法解决,与I2不同的只是在面临输入符为'+',')'或'#'号时用产生式E→E+T归约。
由以上考查该文法在I1,I2,I9三个项目集(状态)中存在的移进-归约冲突都可以用SLR(1)方法解决,因此该文法是SLR(1)文法。 SLR(1)分析表的构造与LR(0)分析表的构造类似,仅在含有冲突的项目集中分别进行处理。如果对所有归约项目都采取SLR(1)的处理思想,即对所有非终结符都求出其FOLLOW集合,这样凡是归约项目仅对面临输入符号包含在该归约项目左部非终结符的FOLLOW集合中,才采取用该产生式归约的动作。这种处理的好处是对某些不该归约的动作可提前发现错误。对于这样构造的SLR(1)分析表我们不访称它为改进的SLR(1)分析表,我们可构造上例中相应的改进的SLR(1)分析表P142表7.8所示。 对输入串i+i*i#进行分析见P142表7.9所示
LR(1) 分析 本节介绍比SLR(1)功能更强的LR(1)分析法。 例如下列文法G′为: (0) S′→S (1) S→aAd (2) S→bAc (3) S→aec (4) S→bed (5)A →e
我们首先用S′→·S作为初态集的项目,然后用闭包函数和转换函数构造识别文法G′的识别活前缀的有限自动机DFA见P143如图7.11所示,可以发现在项目集I5和I7中存在移进和归约冲突。I5:S→ae·c I7:S→be·d A→e· A→e·而归约项目左部非终结符的FOLLOW(A)={c,d}在I5中,FOLLOW(A)∩{c}={c,d}∩{c}≠ 在I7中,FOLLOW(A) ∩{d}={c,d}∩{d}≠ 因此I5,I7中冲突不能用SLR(1)方法解决。只能考虑用下面将要介绍的LR(1)方法解决。
由于用SLR(1)方法解决动作冲突时,对于归约项目A→α·,只要当前面临输入符为a∈FOLLOW(A)时,就确定采用产生式A→α进行归约,但是如果栈中的符号串为βα,归约后变为βA,再移进当前符a,则栈里变为βAa,而实际上βAa未必为文法规范句型的活前缀。由于用SLR(1)方法解决动作冲突时,对于归约项目A→α·,只要当前面临输入符为a∈FOLLOW(A)时,就确定采用产生式A→α进行归约,但是如果栈中的符号串为βα,归约后变为βA,再移进当前符a,则栈里变为βAa,而实际上βAa未必为文法规范句型的活前缀。 例如:在识别表达式文法的活前缀DFA中,(见图7.10)在项目集I2存在移进-归约冲突,即{E→T· T→T·*F}若栈顶状态为2,栈中符号为#T,当前输入符为‘)’,而‘)’属FOLLOW(E)中,这时按SLR(1)方法应用产生式E→T进行归约,归约后栈顶符号为#E,而再加当前符‘)’后,栈中为#E)不是表达式文法规范句型的活前缀。 因此这个归约是多余的。 因此可以看出SLR(1)方法虽然相对LR(0)有所改进,但仍然存在着多余归约,也说明SLR(1)方法向前查看一个符号的方法仍不够确切,LR(1)方法恰好是要解决SLR(1)方法在某些情况下存在的无效归约问题。
若[A→α·Bβ]∈项目集I,则[B→·γ](B→γ为一产生式)也包含在I中,不妨考虑,把FIRST(β)作为用产生式B→γ归约的搜索符,称为向前搜索符,作为归约时查看的符号集合,用以代替SLR(1)分析中的FOLLOW集,把此搜索符号的集合也放在相应项目的后面,这种处理方法即为LR(1)方法。若[A→α·Bβ]∈项目集I,则[B→·γ](B→γ为一产生式)也包含在I中,不妨考虑,把FIRST(β)作为用产生式B→γ归约的搜索符,称为向前搜索符,作为归约时查看的符号集合,用以代替SLR(1)分析中的FOLLOW集,把此搜索符号的集合也放在相应项目的后面,这种处理方法即为LR(1)方法。
LR(1)项目集族的构造 构造LR(1)项目集的闭包函数CLOSURE(I)按如下方式构造:a) I 的任何项目都属于CLOSURE(I) b) 若有项目[A→α·Bβ,a ]属于CLOSURE(I), B→γ 是文法中的产生式,β∈V*,b∈FIRST(βa), 则 [B→·γ,b]也属于CLOSURE(I)中。c) 重复b)直到CLOSURE(I)不再增大为止。
例:已知拓展文法为: (0) S′→S(1) S→aAd (2) S→bAc (3) S→aec(4) S→bed (5)A →e S I1: S′→S·,# I0: S′→·S,# S→·aAd,# S→·bAc,# S→·aec,# S→·bed,# d a A I4: S→aA·d,# I8: S→aAd·,# I2: S→a·Ad,# S→a·ec,# A→·e,d e c I5: S→ae·c,# A→e·,d I9: S→aec·,# b I10: S→bAc·,# I3: S→b·Ac,# S→b·ed,# A→·e,c A c I6:S→bA·c,# e I7: S→be·d,# A→e·,c d I11: S→bed·,# LR(1)项目集和转换函数如下: 构造LR(1)分析表:
如果一个文法的LR(1)分析表中不含多重入口时(或任何一个LR(1)项目集中无移进—归约或归约—归约的冲突,则称该文法为LR(1)文法.如果一个文法的LR(1)分析表中不含多重入口时(或任何一个LR(1)项目集中无移进—归约或归约—归约的冲突,则称该文法为LR(1)文法.
例:G(S):S BB BaB B b I0:S’.S S .BB B .aB B .b I1:S’ S. I2:S B.B B.aB B.b I3:Ba.B B.aB B.b I4:BaB. I5: Bb. I6: SBB.
例:G(S):S BB BaB B b 拓展文法 : (0)S’ S (1) S BB (2) BaB (3) B b I0:S’ S,# S BB,# B aB,a/b B b,a/b s I1:S’ S,# b B B I2:S BB,# B aB,# B b,# I5:S BB,# a a I4:B b,a/b a I6:S aB,# B aB,# B b,# a b b b I3:B aB,a/b B aB,a/b B b,a/b B I7:B b,# I9:B aB,# B I8:B aB,a/b LR(1)项目集和转换函数
对于该例题,只要仔细分析该文法的LR(1)每个项目集的项目,不难发现,即使不考察搜索符,它的任何项目都没有冲突,因此它实际上是一LR(0)文法,可以构造一个LR(0)项目集.可以得知它的LR(0)分析器只含7个状态,而现在LR(1)分析器却含有10个状态,其中I3和I6,I4和I7,I8和I9分别为同心集。对于该例题,只要仔细分析该文法的LR(1)每个项目集的项目,不难发现,即使不考察搜索符,它的任何项目都没有冲突,因此它实际上是一LR(0)文法,可以构造一个LR(0)项目集.可以得知它的LR(0)分析器只含7个状态,而现在LR(1)分析器却含有10个状态,其中I3和I6,I4和I7,I8和I9分别为同心集。