1、5 LR分析方法,5.1 LR分析器的模型及工作过程5.2 LR(0)分析表的构造5.3 SLR(1)分析表的构造5.4 LR(1)分析表的构造5.5 LALR(1)分析表的构造,LR分析法是一种有效的自底向上的语法分析技术,一般叫LR(k)分析技术,其中的“L”是指从左至右扫描输入符号串,“R”是指构造一个最右推导的逆过程,“k”是指为了作出分析决定而向前看的输入符号的个数。,LR分析方法是当前最广义的无回溯的“移进- 归约”方法。根据栈中的符号串和向右查看输入串的k(k0)个符号,就能唯一确定分析器的动作是移进还是归约,以及用哪个产生式进行归约。,5.1 LR分析器的模型及工作过程,1)
2、适合文法类足够大,适用于所有上下文无关文法2) 分析效率高3) 报错及时4) 可以自动生成5) 手工实现工作量大,LR分析法的优缺点:,一、LR分析器的逻辑结构,1.整体结构:,(1)在总控程序的控制下,从左到右扫描输入串,根据分析栈和输入符号的情况,查分析表确定分析动作;,(2) 分析表是LR分析器的核心,它跟文法有关,它包括动作表(Action)和状态转换表(Goto)两部分,总控程序据分析表确定分析动作;,(3) 分析栈包括文法符号栈Xi和相应的状态栈Si两部分(状态是指能识别活前缀的自动机状态),LR分析器通过判断栈顶元素和输入符号查分析表确定下步分析动作。,栈顶状态符号概括了在栈中位
3、于它下边的全部信息,即从分析开始直到某一归约阶段的全部历史和展望,LR驱动程序,(1) 分析动作表以一个二维数组表示,行代表分析栈栈顶状态,列代表当前的输入符号,数组元素表示当前栈顶为状态为Si,而输入符号为aj时,所执行的分析动作ActionSi,aj。,共有4种动作:,移进:新状态Si进状态栈,输入符号a进符号栈,Si,归约:用相应的产生式进行归约rj;,r5,接受:当文法符号归约到只剩下开始符号,且输入串结束时(当前输入为#),分析成功;,acc,报警:当状态栈顶为某一状态下,出现了不该出现的文法符号时,报错。,执行移进动作,元素为产生式或产生式编号表示用它进行归约,元素为acc表示接受
4、,元素为空白表示出错,(2) 状态转换表也用一个二维数组表示,行代表分析栈栈顶状态,列代表文法符号,数组元素表示当前栈顶为状态为Si面对文法符号为Xj时,应转去的新状态GotoSi,Xj=Sk。,此处文法符号只是非终结符号,二、LR分析过程,1.LR分析算法:,(1) 将初始状态S0和输入串的左边界(#) 分别进分析栈;,(2) 根据状态栈栈顶和当前输入符号查动作表进行如下工作:,移进:若动作表中对应“移进”,那么当前输入符号移入符号栈,并将所对应的新的状态进状态栈,继续扫描,即下一个输入符号变成当前的输入符号;,LR驱动程序,输出,Xm,sm-1,Xm-1,s0,栈,sm,ai,si,动作(
5、action)表actionsm,ai 当前状态sm面临当前输入符号ai时应采取什么动作:移进(shift)、归约(reduce)、接受(accept)、出错(error)。,归约:若动作表中对应“归约”,则按指定产生式进行归约,若产生式右部的符号串长度为n,则符号栈栈顶的n个符号为句柄,所以符号栈栈顶n个符号出栈,同时,状态栈顶的n个元素也出栈,归约后的文法符号(非终结符)进符号栈,并根据状态转换表查归约后的文法符号所对应的新状态进状态栈;,LR驱动程序,输出,Xm,sm-1,Xm-1,s0,栈,sm,A Xm-1 Xm,sm-2,A,s,动作(action)表 actionsm,ai 当前
6、状态sm面临当前输入符号ai时应采取什么动作:归约(reduce) 。,接受:若动作表中对应“acc”,则分析成功;,出错:若动作表中对应空白,则报告错误信息。,(3) 重复以上(2)的工作直到接受或出错为止。,2.举例,有文法GL (1)LE , L (2)LE (3)Ea (4)Eb,要求对输入串a,b,a进行分析,即分析#a,b,a#,动作序列中包含了一个规范归约,从而为输入符号串自底向上构造了一棵分析树,1,0,#,2,03,#a,3,02,#E,4,025,#E,5,0254,#E,b,6,0252,#E,E,7,02525,#E,E,8,025253,#E,E,a,9,025252
7、,#E,E,E,10,025256,#E,E,L,11,0256,#E,L,12,01,#L,13,同行的符号栈和输入缓冲区的内容构成文法的一个右句型,LR文法,泛泛地讲,一个上下文无关文法,若构造出无冲突的LR分析表,则说明该文法是LR文法。具体说,一个上下文无关文法,若构造出无冲突的LR(k)分析表,则说明该文法是LR(k)文法。(k=0,1,) LR分析法是一种基本分析思想,LR文法是一种泛泛的文法,当k具体有确定值时,其文法和分析方法就具体了。 中心思想:从给定的文法去构造一个识别该文法所有活前缀的确定的有限自动机(DFA),然后根据DFA去构造它的分析表。,5.2 LR(0)分析及其
8、分析表的构造,1、规范句型的活前缀:,(, V+,wVT*,AVN),若是符号串的前缀,则称是G的一个活前缀,如果符号串是含句柄的活前缀,则称是文法的可归前缀(特殊活前缀)。,A为当前句型(Aw)中最右边的非终结符,文法G中有产生式A;,即活前缀中最长的一个。,活前缀的右端不超过该句型句柄的末端。,活前缀和句柄的关系?,一个规范句型的活前缀不含句柄之后的任何符号,1. 活前缀不含有句柄的任何符号; 2. 活前缀含有句柄的部分符号; 3. 活前缀已含有句柄的全部符号。,为了刻画分析过程中文法的每一个产生式的右部符号已有多大一部分被识别(出现在栈顶),在产生式的右部加上一个圆点指示位置。 1. 活
9、前缀已含有句柄的全部符号;A 2. 活前缀含有句柄的部分符号;A 1 2 3. 活前缀不含有句柄的任何符号。A ,2 LR(0)项目及其项目集规范族,一、 LR(0)项目:,1.定义:对于文法G,其产生式的右部添加一个特殊符号“”就构成文法的一个LR(0)项目。,2.例如: 对于产生式: SaAcBe,有项目:,S aAcBe Sa AcBe SaA cBe SaAc Be SaAcB e SaAcBe ,每个产生式对应的项目个数等于它右部的长度加1 A的项目为A ,每个项目中圆点的左部表示在分析过程中,要用该产生式归约时,句柄已识别的部分(进入符号栈),右部表示等待识别的部分。,希望用产生式
10、S的右部进行归约,当前的输入应为a,用产生式SaAcBe进行归约前,a已经匹配(进栈),需分析A aAcBe aAcBe,产生式SaAcBe右部分析结束,句柄已经形成,可以归约了。,对任何文法G,在G中加进一个新的符号S和一个产生式 SS,并以S代替S作为文法的开始符号,这样得到的一个与G等价的文法G 称为G的拓广文法。,二.项目的分类:,为了构造分析表,我们根据各项目的特点把项目分成不同类型,分类的原则是根据圆点所在位置和圆点之后是终结符还是非终结符进行的。,1.移进项目:圆点之后为终结符的项目, A a, ,V*, aVT,它对应的状态为移进状态;,SaAcBe,2.待约项目:圆点之后为非
11、终结符的项目, A B , ,V*,BVN ,它对应的状态为待约状态;,SaAc Be,3.归约项目:圆点之后没有符号(圆点在最后)的项目,A V*,它对应的状态为归约状态;,SaAcBe ,4.接受项目:对于拓广文法GS,有项目SS 它是一个特殊的归约项目,我们称它为接受项目,它所对应的状态为接受状态。拓广文法G 的接受项目是唯一的,即 SS ,进行分析时,对应的动作是把符号a移进符号栈。,它表明该状态等待着对非终结符B的分析。,此时,已把分析完毕,已在栈顶,可以按相应的产生式归约。,三、构造识别活前缀的NFA,根据项目定义,我们可给出文法中所有产生式的项目,而每个项目都为识别活前缀的NFA
12、的一个状态。即文法有多少个项目,它所对应识别活前缀的NFA就有多少个状态。,1.NFA的构造原则,(1)NFA的状态集:由每个项目所对应的状态组成;,(2)输入字符集合:由文法的文法符号组成包括终结符、非终结符和;,(3)初态:对于文法GS的拓广文法GS,有项目S S ,由于S仅在第一个产生式的左部出现,所以规定它为初态;,(4)终态:对于拓广文法GS,有项目Uu (即圆点在最后的项目),作为NFA的终态;,(4)转换函数f:,若文法中有项目i为:Xx1x2xi-1.xixn,SaA cBe,项目j为:Xx1x2xi-1xi.xi+1xn,SaAc Be,两个项目出自同一个产生式,且项目j的圆
13、点在项目i的基础上后移一个符号的位置。,那么,从项目i(状态i)到项目j(状态j)连接一条标记为xi的有向弧,即f(i,xi)=j,若项目i:X A AVN,项目k:A (A对应的项目中圆点在最左边的一个),则从项目i(状态i)到项目k(状态k)连接一条标记为的有向弧,即f(i, )=k,SaAc Be,SaAcB e,B d,2.举例:,有文法GE EaA|bB AcA|d BcB|d,改为拓广文法GS:,SE EaA|bB AcA|d BcB|d,文法GS的项目有:,1.S E 2.SE 3.E aA 4.EaA 5.EaA 6.A cA,7. Ac A 8. AcA 9. A d 10.
14、Ad 11.E bB 12.EbB,13.EbB 14.B cB 15.BcB 16.BcB 17.Bd 18.Bd,每个项目对应一个NFA的状态,S E对应的项目1为初态,终态有项目2,5,8,10,13,16,18,根据转换函数的规定,可画出NFA的状态图如下:,1.S.E 2.SE. 3.E.aA 4.Ea.A 5.EaA. 6.A.cA,7. Ac.A 8. AcA. 9. A.d 10.Ad. 11.E.bB 12.Eb.B,13.EbB. 14.B.cB 15.Bc.B 16.BcB. 17.B.d 18.Bd.,注意:确定化,最小化方法同前,此处从略,识别文法GE活前缀的DFA,
15、文法LR(0)项目,识别文法所有活前缀的有限自动机,识别文法所有活前缀的NFA,识别文法所有活前缀的DFA,最小化、确定化,直接构造LR(0)项目集规范族,识别文法所有活前缀的DFA,识别文法G的活前缀的DFA项目集的全体称为G的LR(0)项目集规范族。(1)文法拓广 使文法的开始符号只在一个产生左端出现,三、LR(0)项目集规范族,定义 设 I 是文法G的一个LR(0)项目集合, closure( I )是从 I 出发用下面三个规则构造的项目集: 1I 中每一个项目都属于closure( I )。 2若项目A Bclosure( I )且BP则将B 加进closure( I )中。 3重复执
16、行 (2)直到closure( I )不再增大为止。,(2)项目集闭包的计算,为了求出文法G的LR(0)项目集规范族, 引入闭包运算( closure )和转移函数( go ) 的概念。,(3)转移函数若 I 是 G 的一个LR(0)项目集, X VTVN go(I, X)=closure(J) 其中, J = AX|当AX I时 go(I, X)称为转移函数。项目AX称为AX的后继。,(4) LR(0)项目集规范族的构造PROCEDURE items(G );BEGINC:=closure( S S) ;REPEATFOR IC 和 X VT VN 把go(I,X) 加入到C中UNTIL C
17、不在增大END;,LR(0)项目集规范族的构造,(0)SS (1) S aA (2) S bB (3) A cA (4) A d (5) B cB (6) B d,例GS:S aA S bB A cA A d B cB B d,I0 = closure( S S)= S S, S aA S bB,(0)SS (1) S aA (2) S bB (3) A cA (4) A d (5) B cB (6) B d,I1 = go(I0, S) = closure( S S )= S S I2 = go(I0, a) = closure( S a A) = S a A, A cA A d I3= g
18、o(I0, b) = closure( S b B) = S b B, B cB B d,I4 = go(I2, A) = closure( S aA )= SaA I5 = go(I2, c) = closure( A c A) = A c A, A cA A d I6= go(I2, d) = closure( A d ) = A d ,I7 = go(I3, B) = closure( S bB )= SbB I8 = go(I3, c) = closure( B c B) = B c B, B cB B d I9= go(I3, d) = closure( B d ) = B d ,I
19、10 = go(I5, A) = closure( A cA )=AcA I11 = go(I5, c) = closure( A c A) = A c A, A cA A d= I5 I12= go(I5, d) = closure( A d ) = A d = I6,I11 = go(I8, B) = closure( S bB )= SbB I12 = go(I8, c) = closure( B c B) = B c B, B cB B d= I8 I13= go(I8, d) = closure( B d ) = B d = I9,GS 的LR(0)项目集规范族:I0 I1 I2 I
20、3 I4 I5 I6 I7 I8 I9 I10 I11,文法LR(0)项目,识别文法所有活前缀的有限自动机,识别文法所有活前缀的NFA,识别文法所有活前缀的DFA,最小化、确定化,直接构造LR(0)项目集规范族,识别文法所有活前缀的DFA,例.利用项目集规范族形成DFA,对拓广文法GS SE EaA|bB AcA|d BcB|d,有项目:,S.E肯定包含在S0中,S.E,求CLOSURE(S0),E.aA E.bB,S1: SE.,Ea.A,A.cA A.d,Eb.B,B.cB B.d,Ac.A,A.cA A.d,S6: EaA.,S10: Ad.,Bc.B,B.cB B.d,S7: EbB.
21、,S11: Bd.,S8: AcA.,S9: BcB.,说明:,1. 以上DFA的每个状态都是终态。,3. DFA可以识别相应文法的所有活前缀 ( DFA识别的语言是相应文法的所有活前缀),2. 每一个状态识别文法相应的活前缀。,一.LR(0)文法,1.项目集的相容性:我们已知,项目有4种类型,但在一个项目集中,不能有以下情况存在:,(1)移进项目和归约项目并存;,(2)多个归约项目并存;,若并存则不知该移进还是归约。,若并存则不知该归约为哪个非终结符。,若项目集能满足以上条件,则称为相容的项目集。,2.冲突:项目集中含有的项目不符合以上两个条件,则称为项目集中含有冲突。若移进项目和归约项目并
22、存,则称为移进归约冲突,若多个归约项目并存,则称为归约归约冲突。,3 LR(0)分析表的构造,3.LR(0)文法:若一个文法G的项目集规范族中的所有项目都是相容的,则称文法G为LR(0)文法。,判断一个文法是否是LR(0)文法?,LR(0)文法?,二 .LR(0)分析表的构造:,1.构造方法:对于文法GS,按以下规则构造LR(0)分析表:,(1)对于A xSi ,GO(Si,x)=Sj ,若xVT,则置ActionSi,x=Sj;,若xVN,则置GotoSi,x=j;,(2)对于A Si ,若A 是G中第k个产生式,则对所有输入符号xVT(包括#), 均置ActionSi,x=rk ;,(3)
23、若SS Si ,则置ActionSi,#=acc (#表示输入串右界符);,(4)其它情况均置错。,对应分析动作为:将x入符号栈,要转去的状态Sj进状态栈。,对应分析动作为:将归约后的非终结符x对应的状态Sj进状态栈。,对应分析动作为:按指定的产生式进行归约,将归约后的非终结符进符号栈。,对应分析动作为:报告分析成功。,对应分析动作为:报告出错。,返回,(0)SE (1)EaA (2)EbB (3)AcA,(4)Ad (5)BcB (6)Bd,识别活前缀的DFA,GO(Si,x)=Sj ,若xVT,置ActionSi,x=Sj,GO(Si,x)=Sj ,若xVN,置GotoSi,x=j,若SS
24、 Si ,则置ActionSi,#=acc,若A Si ,若A 是G中第k个产生式,则对所有符号,置ActionSi,x=rk,结论: 对于拓广文法G的每一个活前缀,识别它的有效项目集恰好是从它的识别活前缀的DFA的初态出发经过 道路所到达的那个状态所代表的项目集。事实上,在任何时候分析栈中的活前缀X1X2Xm的有效项目集恰恰是栈顶状态Sm所代表的那个集合。这也表示栈顶状态体现了栈里一切有用的信息。,5.3 SLR(1)分析及其分析表的构造,一.问题的提出:,前面的分析过程中已经提到,只有文法是LR(0)文法时,才能造出LR(0)分析表,即文法中所对应的各个项目集(状态)都相容时,才能采用LR
25、(0)分析方法进行分析,如果文法所对应的LR(0)项目集规范族中,有的项目集中含有冲突(不相容),则无法按LR(0)分析法进行分析。,通常的程序设计语言一般不能用LR(0)文法来描述,即其文法不能满足LR(0)文法的要求。,1.文法:,GS: SrD DD,i|i,将文法进行拓广,使它成为GS,并有如下项目:,(0) SS (1) SrD (2) DD,i (3) Di,S.S SS. S.rD Sr.D SrD. D.D,i DD.,i DD,.i DD,i. D.i Di.,若为该文法构造LR(0)分析表,则:,从分析表同样可以发现以上的冲突问题。表中Action3 ,出现了多重定义.,而
26、当输入“,”时,既要进行归约又要进行移进。因而不能做唯一选择,从而发生冲突.,解决方法:对LR(0)分析的构造算法进行改造,以避免分析表中的冲突分析动作。,当分析表出现冲突动作时,从左到右向前看一个符号。即观察下一个符号是什么,从而确定该采用什么动作。,S3: SrD DD , i,对于状态S3,如果要做归约动作,那么句柄rD已经形成,可归约为S。这时S之后不应有其他终结符号(只可以有#)。即文法中含有S的句型中,S之后只能有#,而不能含有其他输入符号。,所以我们可以这样处理:当有输入符号,时,做移进动作,当有输入符号#时做归约动作。其它输入符号无动作。即有其它输入符号输入时,产生语法错误。,
27、实际上在一个状态中,归约项目可以多个,移进项目也可以有多个(去不同状态)。只要归约成的非终结符的FOLLOW集与移进符号集不相交,则可以区分开,从而避免冲突。,在这种文法中,向右看一个符号,所以属于LR(1)方法。而它只在发生冲突时才向右看一个符号,为了与普通的LR(1)方法区别,它叫做简单的LR(1)方法SLR(1)方法。,这样,消除冲突的分析表为(SLR(1)分析表):,对于给定的文法G,若按上述方法所构造的分析表不含多重定义入口(无冲突动作)。则称文法G为SLR(1)文法。,二.SLR(1)分析表的构造,为了构造SLR(1)分析表,将刚才例中的情况一般化:根据不同的向前看符号将状态Si中
28、的各个项目所对应的动作加以区分,从而解决冲突动作。,1.设有一个LR(0)的规范族中有如下项目集(状态),Si=x b, A , B , , , , V*, bVT,显然,项目集中含有一个移进项目和两个归约项目。就是说Si是不相容的项目集,如果用LR(0)分析表的构造规则来构造分析表,将出现动作冲突,可用下面方法解决:,2.对于归约项目:A 和B ,分别求Follow(A)和Follow(B) 。若Follow(A),Follow(B)和b互不相交,则冲突可以解决.,与LR(0)不同之处,举例:以下文法是否是SLR(1)文法? 若是构造分析表并对输入串进行分析。,文法 (0) SE(1) EE
29、+T(2) ET(3) TT*F(4) TF(5) F (E)(6) Fi,分析串为 i+i*i,移进归约冲突,移进归约冲突,移进归约冲突,分析表,(3)构造SLR(1)分析表,DFA,分析过程,(0) SE(1) EE+T(2) ET(3) TT*F(4) TF(5) F (E)(6) Fi,对输入串i+i*i的SLR(1)分析过程:,步骤,状态栈S,符号栈X,输入串,分析表,1,0,#,i+i*i#,S5,2,05,#i,+i*i#,r6 , 3,3,03,#F,+i*i#,r4 , 2,4,02,#T,+i*i#,r2 , 1,5,01,#E,+i*i#,S6,6,016,#E+,i*i
30、#,S5,7,0165,#E+i,*i#,r6 , 3,8,0163,#E+F,*i#,r4 , 9,9,0169,#E+T,*i#,S7,10,01697,#E+T*,i#,S5,11,016975,#E+T*i,#,r6 , 10,12,01697(10),#E+T*F,#,r3 , 9,13,0169,#E+T,#,r1 , 1,14,01,#E,#,acc,分析表,(0) SE(1) EE+T(2) ET(3) TT*F(4) TF(5) F (E)(6) Fi,返回,(0)SE (1)EaA (2)EbB (3)AcA,(4)Ad (5)BcB (6)Bd,分析 acdd?,FOLL
31、OW(E) =#FOLLOW(A) =#FOLLOW(B) =#,分析 acdd?,如何构造LR分析表?,5.4 LR(1)分析及其分析表的构造,一:问题的提出,SLR(1)分析方法是一种较为实用的方法。大多数程序设计语言基本上都可以用SLR(1)文法来描述。在SLR(1)方法中,对于某状态Si,其项目集若不相容时,可根据SLR(1)分析表的构造规则来解决冲突。即求出归约项目所对应的非终结符号A的Follow集和移进项目的移进符号集,只要它们不相交就可以解决冲突。但是如果它们相交时,就无法通过SLR(1)分析表,也就无法进行SLR(1)分析。,例如:有文法GS(0)SS (3)Saec(1)S
32、aAd (4)Sbed(2)SbAc (5)Ae,用S . S作为初态集的项目,构造识别文法活前缀的DFA如下:,S0: S.S S.aAd S.bAc S.aec S.bed,S1: SS.,S2: Sa.Ad Sa.ec A.e,S3: Sb.Ac Sb.ed A.e,S4: SaA.d,S5: Sae.c Ae.,S6: SbA.c,S7:Sbe.d Ae.,S8: SaAd.,S9: Saec.,S10: SbAc.,S11: Sbed.,移进归约冲突,Follow(A)=c,d First(c)=c相交,移进归约冲突,Follow(A)=c,d First(d)=d相交,结论:冲突不
33、能用SLR(1) 方法解决!,(0)SS (3)Saec(1)SaAd (4)Sbed(2)SbAc (5)Ae,下面我们提出一种更强的LR分析法,即LR(1)分析方法来解决这一问题。,二.LR(1)分析表构造的思想,1.分析,在SLR(1)方法中,解决冲突时,对于归约项目A 只要当前的输入符号为aFollow(A)就进行归约。,(0)SS (3)Saec(1)SaAd (4)Sbed(2)SbAc (5)Ae,上一页,Follow(A)=c,d,在当前分析状态S5下并非FOLLOW(A)中的每一个元素都起作用,(0)SS (3)Saec(1)SaAd (4)Sbed(2)SbAc (5)Ae
34、,把First()作为用产生式A 进行归约的搜索符,用于替代SLR(1)分析法中的Follow(A),并把搜索符号的集合放在项目的后面(A.,a aFirst()。这种处理方法称为LR(1)方法。,对于当前分析状态Si S A A 注意S为开始符号,我们最关心的跟在非终结符A后的终结符号?,LR(1)分析过程中的每个状态,就是包含若干LR(1)项目的一个LR(1)项目集,特殊的,S.S,#属于初始项目集中的一个LR(1)项目,即S.S,# S0 , 它表示:归约到最后一步,必须面临输入符号#才行。所以文法的所有项目集的获得,就是从初始项目S.S,#出发,通过求其闭包再用转换函数逐步求出整个文法
35、的LR(1)项目集。,(2) LR(1)项目集的构造,定义 设I是G的一个LR(1)项目集,closure(I)是从I出发用下面三个规则构造的项目集 : 1 每一个I中的项目都属于closure(I)。2 若项目AB,a属于closure(I) 且 B P,则对任何bFIRST(a),把 B,b加进closure(I)中。 3重复执行(2)直到closure(I)不再增大为止。,LR(1)项目集的闭包,定义设I是G的一个LR(1)项目集,X是一 个文法符号,定义 go(I,X) closure(J) , 其中 J=A X,a |当A X,aI时,转移函数( go ),在LR(1)项目集规范族的
36、构造过程中,以S.S,#为初态集的基本部分(初始项目),然后对其求闭包,始其增大,再求转换函数得其它项目集的基本部分Sj,再求Sj的闭包,直到项目集不再增大。,3 举例:我们仍以GS为例,求项目集同时得到DFA,S0: S.S, #S.aAd, #S.bAc, #S.aec, #S.bed, #,S1: SS., #,S2:Sa.Ad, #Sa.ec, # A.e,d,S4: SaA.d, #,S5: Sae.c, # Ae.,d,S8:SaAd.,#,S9:Saec., #,S3: Sb.Ac, #Sb.ed, # A.e,c,S6: SbA.c, #,S10: SbAc., #,S7:Sb
37、e.d, # Ae.,c,S11; Sbed., #,First(#)=#,First(d#)=d,First(c#)=c,(0)SS (1)SaAd (2)SbAc (3)Saec (4)Sbed (5)Ae,LR文法分类与分析,LR(1)项目集及规范族的构造G(S): (0) SS (1) S CC(2) C cC (3) C d,I0,SS, #,若A ,a I 且B P 则B,b I其中b FIRST(a),S CC,#,C cC,c/d,C d,c/d,SS,# SCC,# CcC,c/d Cd,c/d,I0,S,SS,#,I1,C,SCC,# CcC,# Cd,#,I2,c,CcC
38、,c/d C cC,c/dCd,c/d,I3,d,Cd,c/d,I4,C,SCC ,#,I5,c,CcC,# CcC,# Cd,#,I6,C,CcC ,#,I9,d,Cd,#,I7,c,d,c,C,CcC ,c/d,I8,d,(0)SS (1)SaAd (2)SbAc (3)Saec (4)Sbed (5)Ae,举例:构造下面文法的LR(1)分析表:,(1)求项目集和DFA:,分析表,DFA,(0)SS (1)SaAd (2)SbAc (3)Saec (4)Sbed (5)Ae,LR(1)分析表?,构造LR(1)分析表,按上述算法构造的分析表,如果每个入口是唯一确定的,则称它为文法G的一张LR
39、(1)分析表。具有LR(1)分析表的文法称为LR(1)文法。使用LR(1)分析表的分析器称作一个LR(1)分析器。,5.5 LALR(1)分析及其分析表的构造(简介),一般而言,同一个文法G1的LR(1)项目集个数要比LR(0)项目集个数个数多,而LALR(1)项目集个数比LR(0)项目个数多,而比LR(1) 项目集个数少。,1.LALR(1)项目集的构造:,同心集:LR(1)的两个项目集的LR(0)项目全部相同,则称两个LR(1)项目集具有相同的心。具有相同心的项目集称为同心集。,某一文法的LR(1)项目集规范族合并同心集就得同一文法的LALR(1)项目集规范族。,合并方法: (1)相同的心
40、(LR(0)项目)不变 (2) 合并后项目集的搜索符等于合并前LR(0)项目搜索符的并集,合并后:,I3: Ba.B , a/b B.aB , a/b B.b , a/b,I6: Ba.B , # B.aB , # B.b , #,J3: Ba.B , a/b/# B.aB , a/b/# B.b , a/b/#,I4: Bb. , a/b,I7: Bb. , #,J4: Bb. , a/b/#,I8: BaB. , a/b,I9: BaB. , #,J6: BaB. , a/b/#,SS,# SCC,# CcC,c/d Cd,c/d,I0,S,SS,#,I1,C,SCC,# CcC,# Cd
41、,#,I2,c,CcC,c/d C cC,c/dCd,c/d,I3,d,Cd,c/d,I4,C,SCC ,#,I5,c,CcC,# CcC,# Cd,#,I6,C,CcC ,#,I9,d,Cd,#,I7,c,d,c,C,CcC ,c/d,I8,d,构造LALR(1)分析表,讨论:把同心的项目集合并为一,有可能导致冲突,不会出现新的移进- 归约冲突; 但可能引起归约-归约冲突。Ik:A,u1 Ba,b au1=Ij:A,u2 Ba,c au2=Ikj:A,u1/u2 Ba,b/c au1, u2=,例:下面文法是LR(1)的,但不是LALR(1)的。S S S aAd bBd aBe bAeA
42、c B c,S S,# S aAd, # S bBd, # S aBe, # S bAe, #,S S ,#,S a Ad, # S a Be, # A c, d B c, e,a,S,S b Bd, # S b Ae, # A c, e B c, d,b,A,S a A d, #,B,S a B e, #,c,A c , dB c , e,A c , e B c , d,c,A c,e/d Bc,e/d,若合并同心集后项目集规范族无分析动作冲突,则此表称为LALR(1)分析表。相应的文法称为LALR(1)文法。,G(S): (0) SS (1) S CC(2) C cC (3) C d,LR
43、(1)和LALR(1)分析上的差别?,构造的LR(1)分析表,构造的LALR(1)分析表,LR(1)和LALR(1)分析上的差别输入:ccd#LR: 0 c 3 c 3 d 4 报错LALR: 0 c 36 c 36 d 47 0 c 36 c 36 C 890 c 36 C 89 0 C 2 报错,思考:设有文法G,如何判定G属于哪类LR 文法?,LR分析中二义性文法的应用(简介):,二义性文法描述句型分析十分简单,例如: EE+E|E*E|E/E|E-E|(E)|i 描述了算术表达式四则运算,若采用LR分析方法进行分析这个文法的LR分析表体积小,分析器实现方便。,但是,二义性文法决不是LR
44、文法,所以,构造的项目集规范族一定会出现动作冲突。,例设有文法为: (0) SS (1) SiSeS (2) SiS (3) Sa,这是描述两种条件语句的文法,项目集除了“I4”以外无动作冲突,通过人为的规定终极符的优先级,使得冲突得以解决。,移进归约冲突,当输入e时,无法选择移进还是归约。,在构造LR分析表时,分析表中“状态4”和“e”的分析动作Action(4,e)的值,按SLR(1)分析表构造算法,是填“S5”呢?还是填“r2”。这里,Follow(S)=e,#,按照算法语言的要求,有“else”的条件语句优先,即Action(4,e)= S5,LR(k)和LL(k)的比较1. A1 2LL(k)根据FIRST(i)和follow(A)确定使用哪条产生式;而LR(k)是在识别出整个后,再往后看k个符号,然后确定使用哪条产生式。,