1、第五章 语法分析自下而上分析,本章内容 自下而上分析基本问题 直观算符优先分析法 算符优先分析LR分析法,自下而上分析法从输入串开始,逐步进行“归约”,直至 归约到文法的开始符号; 一、自下而上分析基本问题,1 、归约利用栈,输入符号移进栈,当栈顶形成P的候选式时,就归约为它的左P符号,例5.1 文法G2: S-aAcBe A-b A-Ab B-d 输入串:abbcde,自下而上法,即“移进-归约”法,最右推导:,a,a,b,a,A,a,A,b,a,A,a,A,c,a,A,c,d,a,A,c,B,a,A,c,B,e,S,1,2,3,4,5,6,7,8,9,10,栈,S,= aAcBe,= aA
2、cde,=aAbcde,= a b b c d e,S-aAcBe,输入串:abbcde,A-Ab,B-d,A-b,S,a,A,c,B,e,A,b,d,b,分 析 树,最左归约:,= S,= aAcBe,= aAcde,= aAbcde,a b b c d e,S-aAcBe,输入串:abbcde,A-Ab,B-d,A-b,2 规范归约,短语:令G是一个文法,S是文法的开始符 号,若是文法G的一个句型, 如果有S A且 A ,则称 是句型相对于非终结符A的 短语。,句柄:一个句型的最左直接短语称为该句型 的句柄。,规范推导:即最右推导; 规范句型:由规范推导所得的句型称为规范 句型; 规范归约
3、:是关于句型的一个最右推导的 逆过程,也称最左归约。,例5.2 文法GE T | E +TT F | T * FF i |(E) 的一个句型 i1*i2+i3,语 法 树,T,F,E,E,F,F,+,T,*,i1,i2,i3,T,i1 ,i2 ,i3 , i1*i2 , i1*i2+i3,i1 ,i2 ,i3,i1,短语:,直接短语:,句柄:,3 符号栈的使用,规范归约用来作语法分析需要解决的问题:如何在句型中找出句柄? 在相同的右部有不止一个产生式时,选哪一个?,实现移进-归约分析的一个方便途径是用一个栈和一个输 入缓冲区,用#表示栈底和输入的结束, 分析程序的动作移进: 下一输入符号移进栈
4、顶 归约: 把句柄按产生式的左部进行归约 接收: 分析程序报告成功 出错: 发现了一个语法错,调用出错处理程序,注意: 可归约的串在栈顶,不会在内部,二 直观算符优先分析法1 定义:任二个相继出现的终结符a与b(可能中间有VN),可能有以下优先关系:a b a的优先性低于ba b a的优先性等于ba b a的优先性高于b,2 例5.3 文法G: E E + E | E * E | EE | ( E ) | i 的终结符的优先关系见下表。,优 先 表,E E+E | E*E | EE |( E )| i,3 使用如上分析表,构造分析算法(直观算符优先分析法),分析算法步骤: 下一个输入符号读至a
5、中; 若a为i,则aOPND,转第一步; 若 a,则调用关于的处理程序(语义程序),处理子表达式 :E(1)E(2) ;然后重新进入第3步;(其中, E(1) 、E(2)分别为OPND栈的次栈顶和栈顶),a,OPTR,OPND,#,E (1),E (2),E(3),=,若 a,则 若=(,a=),则逐出OPTR栈顶的(,放弃a中的 ),转第 1步; 若=a=#,分析成功结束; 若 a,aOPTR栈,转第1步; 与a不存在优先关系,则输入串错误,调出错处理,),OPTR,OPND,#,(,E (1),E (2),a,#,成功!,2 例5.4 由文法G: E E + E | E * E | EE
6、| ( E ) | i 的终结符的优先关系表及上述分析算法 分析算术表达式 i1 + i2 * i3 # 的过程。,OPTR,OPND,分析过程, OPND栈为空,# -OPTR栈, i1-OPND# OPTRi2-OPND,#,+,i1,i2,i3,*,t,e,输入串 :,i1 + i2 * i3 #,+OPTRi3-OPND,* # ,*弹出OPTR栈;i2 * i3 = t -OPND, + # ,+弹出OPTR栈;t + i1 = e -OPND, # =# ,分析成功;e 为整个表达式的结果,1 算符优先文法定义一如果一个文法的任何产生式右部都不含两个相继(并列)的非终结符,即不含有
7、如下形式的产生式右部: QR 则我们称该文法为算符文法。,三 算符优先分析,定义二假定G是一个不含-产生式的算符文法。对于任何一对终结符a、b,我们说: a b, 当且仅当文法G中含有形如P-ab 或P-aQb的产生式;(如:(E),则( ) a b, 当且仅当G中含有形如P-aR的产生式,而R b 或 R Qb; a b, 当且仅当G中含有形如P-Rb的产生式,而R a 或 R aQ。,定义三如果一个算符文法G中的任何终结符对(a,b)至多只满足下述三种关系之一: a b,a b,a b 则称G是一个算符优先文法。,2 从算符优先文法构造优先关系表,构造优先关系表,就是要找出所有VT对之间的
8、三种关系,而对于 可以直接检查所有的G中P来得到。而 , 关系不易检查,故要定义二个集合。 FIRSTVT(P)=a|P a或P Qa,aVT 而QVN LASTVT(P)=a|P a或P aQ,aVT 而QVN 如该二集合成功,检查P,就可确定满足 , 的(a,b)对。 这是因为,假定有个产生式候选式:aP,那么对任何 bFIRSTVT(P),有a b;Pb,那么对任何 aLASTVT(P),有a b;,构造该二个集合的算法,对每一 VN的 FIRSTVT(P) 、LASTVT(P) 使用每个VN的FIRSTVT(P) 、LASTVT(P),检 查每一个产生式,找出所有(a,b)的关 系,就
9、完成了构造优先关系表。,因此,问题归结为:,3 构造集合FIRSTVT(P)的算法 P-a或P-Qa,则aFIRSTVT(P); 若aFIRSTVT(Q),且有产生式P-Q,则aFIRSTVT(P),4 构造集合LASTSTVT(P)的算法 P-a 或 P-aQ,则aLASTVT(P); 若aLASTVT(Q),且有产生式P-Q,则aLASTVT(P),5 构造优先表方法 对形如 P-ab和形如P-aQb,有a b; 对形如 P-aR,而bFIRSTVT(R),有a b; 对形如 P-Rb,而aLASTVT(R),有a b; 对文法开始符号S,有# FIRSTVT(S),LASTVT(S) #
10、,且对 #S#,有# #。,FIRSTVT(P)的自动构造,过程INSERT:PROCEDURE INSERT(P,a)IF NOT FP,a THENBEGIN FP,a := TRUE;把(P,a)下推进STACK栈 END;,主程序:,BEGINFOR 每个非终结符P和终结符a DO FP,a := FALSE;FOR 每个形如P-a 或P-Qa的产生式 DO INSERT(P,a);WHILE STACK 非空 DOBEGIN把STACK的顶项,记为(Q,a),弹出去FOR 每条形如P-Q的产生式 DOINSERT(P,a)END OF WHILE; END,LASTVT(P)的自动构
11、造,过程INSERT:PROCEDURE INSERT(P,a)IF NOT LP,a THENBEGIN LP,a := TRUE;把(P,a)下推进STACK栈END;,主程序:,BEGINFOR 每个非终结符P和终结符a DO LP,a := FALSE;FOR 每个形如P- a 或P- aQ的产生式 DO INSERT(P,a);WHILE STACK 非空 DOBEGIN把STACK的顶项,记为(Q,a),弹出去FOR 每条形如P- Q的产生式 DOINSERT(P,a)END OF WHILE; END,优先表的自动构造,FOR 每条产生式P-X1X2Xn DOFOR i := 1
12、 TO n-1 DOBEGINIF Xi和Xi+1均为终结符 THEN 置Xi Xi+1IF in2且Xi和Xi+2都为终结符但Xi+1为非终结符 THEN 置Xi Xi+2;IF Xi为终结符而Xi+1为非终结符THENFOR FIRSTVT(Xi+1)中的每个a DO置 Xi a;IF Xi为非终结符而Xi+1为终结符 THENFOR LASTVT(Xi)中的每个a DO置 a Xi+1 END,6 算符优先分析算法的设计 定义 1)文法G,开始符号S,若S A ,如果 S 且 A , 则称是句型A的一个短语。 2)所谓素短语是指这样一个短语,它至少含有一个终结符,并且,除自身之外,不再含
13、任何更小的素短语。 3)句型最左边的那个素短语叫最左素短语。,最左素短语满足以下条件的最左子串 Njaj NiaiNi+1, aj-1 aj aj aj+1 , , ai-1 aiai ai+1,定理 算符优先文法的句型一般形式: #N1a1N2a2NnanNn+1# 其中,ai VT,Ni VN|,算法分析:,也即:aj-1 ai+1Nj aj ai Ni+1,2 例5.5 i1 *( i2 + i3) # # i1 * ( i2 + i3 ) # i1,i2,i3是素短语;i1是最左素短语。,IF Sj a OR Sj a THENBEGINk:=k+1;Sk:=aENDELSE ERRO
14、RUNTIL a=#,k:=1; Sk:=#; REPEAT把下一个输入符号读进a中;IF SkVT THEN j:=k ELSE j:=k-1;WHILE Sj a DOBEGINREPEATQ:=Sj;IF Sj-1VT THEN j:=j-1 ELSE j:=j-2UNTIL Sj Q把Sj+1Sk归约为某个N;k:=j+1;Sk:=N;END OF WHILE;,7 优先函数 定义:我们把每个终结符与两个自然数f() 和g()相对应,使得:若1 2,则f(1)g(2) 函数 f 称为入栈优先函数,g 称为比较优先函数。,使用优先函数的优缺点: 优:便于比较运算;节省存储空间。 缺:对不
15、存在优先关系的两个终结符,由于与自然数相 对应,变成可比较。,优先函数的性质: 1)正确性:优先函数掩盖了矩阵中出错元素对,若f(id)g(id),暗示id id,但id之间无优先关系,因此失去发现错误能力,但并未严重到妨碍在可解地方使用优先函数。,2)存在性:并非总能把表映射到优先函数。 例5.6 对于下述关系表就不存在优先函数 f 和 g :,不然,应有: f(a) = g(a) f(a) g(b) f(b) = g(a) f(b) = g(b) 那么,f(a)g(b)=f(b)=g(a)=f(a),矛盾。,3)唯一性:存在一个优先函数,就有无数多对,加一常数,不等式也成立。,构造优先函数
16、的方法(如果优先函数存在的话),对每个a(包括)VT,对应两个符号fa,ga。 把所建立的符号尽可能划分为许多组:若a b,则fa和gb就在一组;若a b,c b,则fa和fc同组; 建立一个有向图,其结点是上一步中找出的组。对于任何a和b,若 a b,画 fagb 弧,意味着f(a)g(b);若 a b,画 gbfa 弧,意味着f(a)g(b)。 如果上一步结果构成环,则f,g不存在;否则 f(a)= 从fa组开始的路径和;g (b) = 从gb组开始的路径和。,例5.7 根据文法G:E E+E | E*E | EE | ( E ) | i的终结符的优先关系表,构造优先函数。,由优先关系表,
17、得:,+,),(,*,+,*,其余类同,4,6,6,2,9,3,5,8,8,2,LR分析法,语法分析概述(见图1)LR分析程序(器):自左向右扫描,识别句柄,自下而上归约的 语法分析程序。LR分析程序生成器:自动生成LR分析程序的程序。LR分析程序(见图2),图 1(返回),图 2(返回),分析表的构造方法(见图3),图 3,1、 LR分析程序 A、LR分析程序的实质:分析栈DFA(见图4),图 4,B、LR分析的核心分析表,分析表由ACTION表和GOTO表两部分组成。 ACTION(s,a):表示当状态s面临输入a时的动作 GOTO(s,x):表示面对文法符号x的下一状态,ACTIONs,
18、a表中的动作种类: 移进 归约 接受 报错,C、给出下述文法G的LR分析表, 文法G(1)EE+T (2) ET(3) TT *F (4) TF(5) F(E) (6) Fi, 分析表(图 5), 分析表中记号的含义 sj: 把下一状态 j 和现行输入符号 a 移进栈; rj: 按第 j 个产生式进行归约; acc: 接受; 空白格:出错标志,报错,图 5,例 5.8 利用上述分析表,假定输入串为 i * i + i ,描述LR分析器的工作过程。,状 态,符 号,输入串,(1) 0 # i * i + i # (2) 05 #i * i + i # (3) 03 #F * i + i # (4
19、) 02 #T * i + i # (5) 027 #T* i + i # (6) 0275 #T*i + i # (7) 02710 #T*F + i # (8) 02 #T + i # (9) 01 #E + i #,ACTION 0, i =s5 移进 5 和 i,ACTION 5, * =r6 按第6个产生式进行归约,即: (6) Fi,GOTO0,F=3 移进状态3,ACTION 10, + =r3 按第3个产生式进行归约,即 (3) TT *F,GOTO0,T=2 移进状态2,例5.8 利用上述分析表,假定输入串为 i * i + i ,描述LR分析器的工作过程。(续),状 态,符
20、 号,输入串,(10) 016 #E+ i # (11) 0165 #E+i # (12) 0163 #E+F # (13) 0169 #E+T # (14) 01 #E #,ACTION1,#=acc 接受输入串!,D、LR文法, LR(k)文法:一个文法,如果能用一个每步顶多向前检查k个输入符号的LR分析器进行分析,则这个文法就称为LR(k)文法。,定义:对于一个文法,如果能够构造一张分析表,使得它的每个入口均是唯一确定的,则我们把这个文法称为LR文法。,A、LR(0)分析表的构造步骤确定G的LR(0)项目 以LR(0)项目为状态,构造一个能识别文法G的所有活前缀的NFA利用子集法,将NF
21、A确定化,成为以项目集合为状态的DFA根据上述DFA可直接构造出LR分析表,2、LR(0)分析表的构造,定义:文法G每一个产生式的右部添加一个圆点,称为G的一个LR(0)项目。如:AXY对应三个项目:AXY AXY AXY而: A的项目 A,B、LR(0)项目(简称项目),项目的意义:指明在分析过程的某时刻,我们看到产生式多大一部分项目在计算机中的表示:(m,n)int m,nm:代表产生式编号n:指出圆点的位置,如:abc前缀:,a,ab,abc 活前缀:规范句型的一个前缀,该前缀是不含句柄之后的任何符号。,C、字的前缀:指该字的任意首部,D、对文法G,构造能识别G的所有活前缀的NFA,NF
22、A的状态:是一个LR(0)项目 构造方法:,a.文法开始符号的形如SS的项目为NFA的唯一初态;b.若状态i和j出自同一个产生式,而且j的圆点只落后于I的圆点一个位置,就从i画一条标志为Xi的弧到j。(即,i:XX1Xi-1XiXnj:XX1 Xi-1XiXn)c.若状态i的圆点之后的符号为非终结符,如I为XA,其中A属于VN,就从状态i画弧到所有A状态。,例2.构造以下文法的NFA,文法G的所有LR(0)项目,文法 G S EE aA|bBA cA|dB cB|d,1.S E 2. S E 3. E aA 4. E a A 5. E aA 6. A cA 7. A c A 8. A cA 9
23、. A d 10. A d 11. E bB 12. E b B 13. E bB 14. B cB15. B c B 16. B cB 17. B d 18. B d ,利用上述规则a,b,c构造NFA,如图所示:,E、使用子集方法,将NFA确定化,使之成为一个以项目集合为状态的DFA。相关定义: LR(0)项目集规范族:构成识别一个文法活前缀的DFA的项目集(状态)的全体。 归约项目:A 接受项目:S(S文法的开始符号) 移进项目:Aa(a终结符) 待约项目:AB(B非终结符),利用CLOSURE方法构造LR(0)项目集规范族拓广文法,CLOSURE(I)算法(其中I为G的任一项目集) I
24、的任何项目都属于CLOSURE(I); 若A-B属于CLOSURE(I),那么,对任何关于B的产生式B-,项目B-也属于CLOSURE(I); 重复执行上述两步骤直至CLOSURE(I)不再增大为止。,构造项目集规范族方法(见下页),步骤一:令NFA的初态为I,求其CLOSURE(I),得到初态项目集。即:求CLOSURE(SS)步骤二:对所得项目集I和文法G的每个文法符号X(包括VT和VN) 计算GO(I,X) =CLOSURE(J),得到新的项目集。其中J=任何形如A X 的项目| A X 属于I步骤三:重复步骤二,直至没有新的项目集出现。 经过以上步骤构造出的项目集的全体即为LR(0)项
25、目集规范族。,利用LR(0)项目集规范族和GO函数画出DFA, 相关定义:LR(0)文法:不存在以下两种冲突的文法移进归约冲突归约归约冲突LR(0)表:由LR(0)文法得到的分析表LR(0)分析器:使用LR(0)表的分析器,F、LR(0)分析表的构造,分析表的构造方法 如下:a、若项目Aa属于Ik且GO(Ik,a) Ij,a为终结符,且置 ACTIONk,a为“把(j,a)移进栈”,简记为“sj”;b、若项目A属于Ik,那么,对任何输入符号a(或者结束符)置ACTIONk,a为“用产生式A进行归约”,简记为“rj”;其中,假定A为文法G的第j个产生式;c、若项目SS属于Ik,则置ACTIONk
26、,为“接受”,简记为“acc”;d、若GO(Ik,A)Ij,A为非终结符,则置GOTOk,Aj;e、分析表中凡不能使用规则1至4填入信息的空白格均置上“出错标志”。,例3.根据例2的结果,将其NFA确定化 ,并构造该文法的LR(0)分析表。假定这个文法的各个产生式的编号如下:0、S E 1、E aA2、E bB 3、A cA 4、A d 5、B cB6、B d,DFA构造:(部分),CLOSURE ( S-E ) = S-E, E-aA, E-bB 此即为DFA的状态0,令I = S-E, E-aA, E-bB GO( I, a ) = CLOSURE( E-aA ) /即I中所有圆点之后紧跟
27、a的= E-aA, A-cA, A-d GO( I, b ) = CLOSURE( E-bB ) = E-bB, B-cB, B-d GO( I, E ) = CLOSURE( S-E )= S-E ,同上步骤,依次对各项目集进行计算(略) LR(0)分析表构造,(DFA部分图,全图见下页),该文法的LR(0)分析表如下所示:,A、若LR(0)规范族中含有冲突项目,采用向前展望方法解决例4. 若I=Xb,A,B若当前输入符号为b,则含有移进归约冲突;而A和B,又含有归约归约冲突。解决办法:考察FOLLOW(A)和FOLLOW(B)(设FOLLOW(A)FOLLOW(B)为空,且均不含b),3、
28、SLR表的构造方法,则当 I 面临任何输入符号a时,可做出如下“移进归约 决策:若a=b,移进;若a属于FOLLOW(A),则用A归约;若a属于FOLLOW(B),则用B归约;此外,报错。B、回顾FOLLOW(A)的计算。(其中A是非终结符)注:FIRST集是针对终结符、非终结符和产生式构造的; FOLLOW集仅对非终结符构造。,C、SLR表的构造方法若项目Aa属于Ik且GO(Ik,a) Ij,a为终结符,且置ACTIONk,a为“把状态j和符号a移进栈”,简记为“sj”;若项目A属于Ik,那么,对任何输入符号a, aFOLLOW(A),置ACTIONk,a为“用产生式A进行归约”,简记为“r
29、j”;其中,假定A为文法G的第j个产生式;若项目SS属于Ik,则置ACTIONk,为“接受”,简为“acc”;若GO(Ik,A)=Ij,A为非终结符,则置GOTOk,A= j;分析表中凡不能使用规则1至4填入信息的空白格均置上“出错标志”。,只在归约时 展望,即已到产生式末尾,则去判断FOLLOW(A),文法 G: (0) SE(1) EE+T(2) ET(3) TT*F(4) TF(5) F(E)(6) Fi,例4:对如下文法构造其SLR分析表。,该文法的LR(0)项目集规范族 由这些项目集的转换函数GO表示成的DFA 文法G的非终结符的FOLLOW集如下: FOLLOW(S)= # FOL
30、LOW(E)= +,),# FOLLOW(T)= +, * , ) , # FOLLOW(F)= +, * , ) , # SLR分析表,文法 G 的SLR分析表如下所示:,问题:有些无二义文法会产生“移进/归约”冲突或“归约/归约”冲突 产生原因:SLR分析法未包含足够多的“展望”信息 解决办法:让每个状态含有更多的“展望”信息,4、规范LR分析表的构造,方法:重新定义项目,使得每个项目都附带有k个终结符; 即每个项目的形式为:A- , a1a2ak,向前搜索符串仅对归约项目A-, a有意义; 归约项目A-, a意味着:当它所属的状态呈现在栈顶且后续的k个输入符号为a1a2ak 时,才可以把
31、栈顶上的归约为A 只研究k1的情形,定义:如上形式的项目称为一个LR(k)项目。,说明:,A、构造规范LR分析表的步骤:,确定LR(1)项目; 根据LR(1)项目构造NFA; 利用函数CLOSURE和GO求DFA; 根据DFA,构造LR分析表。,B、确定LR(1)项目,确定LR(1)项目的方法: 对S和S,只向前搜索 # ; 其它产生式,对每一个VT均向前搜索。,由: S-S,# S-S,# S-BB,# S-BB,# S-BB,#,由: B-aB,a B-aB,b B-aB,# B-aB,a B-aB,b B-aB,# B-aB,a B-aB,b B-aB,# B-b,a B-b,b B-b
32、,# B-b,a B-b,b B-b,#,C、 利用LR(1)项目构造NFA 构造方法:同LR(0)构造识别活前缀的NFA方法相同,D、构造有效的LR(1)项目集族(即求DFA),项目集I的闭包CLOSURE(I)构造方式 函数GO(I,X)的定义 LR(1)项目集族C的构造算法,E、根据DFA,构造LR分析表,a、若项目Aa,b属于Ik且GO(Ik,a) Ij,a为终结符,则置 ACTIONk,a为“把(j,a)移进栈”,简记为“sj”;b、若项目A,a属于Ik,则置ACTIONk,a为“用产生式A归约”,简记为“rj”;其中,假定A为文法G的第j个产生式;c、若项目SS,#属于Ik,则置A
33、CTIONk,为“接受”,简记为“acc”;d、若GO(Ik,A)Ij,A为非终结符,则置GOTOk,Aj;e、分析表中凡不能使用规则1至4填入信息的空白格均置上“出错标志”。,5、LALR分析表的构造,问题:对于一般的语言,规范LR分析表要用几千个状态,无法实际应用 分析:由例6中可以看到,有些状态集除了搜索符不同外是两两相同的 解决办法:合并同心集,构造LALR分析表,我们称两个LR(1)项目集具有相同的心,如果除去搜索符之后,这两个集合是相同的。,将所有同心的LR(1)项目集合并后,得到一个心就是一个LR(0)项目集。,说明:,合并同心集不会产生新的移进-归约冲突,但有可能产生新的“归约
34、-归约”冲突。,对于同一个文法,LALR分析表和SLR分析表永远具有相同数目的状态,却能处理一些SLR所不能对付的事情。,合并项目集时不用修改转换函数,即GO(I,X);动作ACTION应进行修改,使得能够反映各被合并的集合的既定动作。,A、构造LALR分析表的第一个算法,步骤: 构造文法G的LR(1)项目集族C=I0,I1,In 把所有的同心集合并在一起,记C=J0,J1,Jm为合并后的新族。那个含有项目S-S,#的Jk为分析表的初态 从C构造ACTION表 构造GOTO表 分析表中凡不能用3、4天入信息的空白格均填上“出错标志”,a、若项目Aa,b属于Jk且GO(Jk,a) Jj,a为终结
35、符,则置ACTIONk,a为 “sj”;b、若项目A,a属于Jk,则置ACTIONk,a为“用产生式A归约”,简记为“rj”;其中,假定A为文法G的第j个产生式;c、若项目SS,#属于Jk,则置ACTIONk,为“接受”,简记为“acc”;,从C构造ACTION表,把状态3,6、4,7和8,9分别合并成,I36: B-aB,a /b/#B-aB,a /b/#B-b,a /b/#I47: B-b,a /b/#I89: B-aB,a /b/#,由合并后的集族所构成的LALR分析表,B、构造LALR分析表的另一算法,问题:对任何文法G,通过构造它的LR(1)项目集,合并同心集,最后形成LALR(1)
36、项目集 ,该算法太费存储空间。 解决办法:注意到各种项目集都是以一定项目为核的闭包。若用核代替闭包,则不论哪一种项目集都将大大缩小它的存储空间,相关定义,使用核构造分析表,任何项目集的核是由此集中所有那些圆点不在最左端的项目组成的。初态项目集的核含有(而且只含有)项目S-S,#,通过核构造GOTO表:若GO(I,X)=J,I的核为K,J的核为L。显然,若A- X,a属于K,则A- X,aA- X,a属于L。,对每对非终结符C和A都预先计算出它们是否有关系:C A ,通过核构造ACTION表:令I是一个项目集,K是它的核。若ACTIONI,a为用“A-归约”。那么, 若,则项目 A- 必属于K;
37、 若=,则K中必有某个项目B- C,b, 其中C A,且a属于FIRST(b)。,为每个LR(0)集核的每个项目都配上一个搜索符集,使得这个核成为一个LALR(1)集的核,SPONSOR算法LR(0)初态集核的唯一项目 S-S 具有搜索符#;应用SPONSOR算法从初态集核开始计算每个核各个项目的全部自生搜索符。,LALR(1)项目集(核)的构造算法利用三元式(I,A- ,a)栈来跟踪由前述算法产生的自生搜索符的传播;,构造G的所有LR(0)集的核;从CLOSURE(S-S,#)开始,利用SPONSOR算每个状态的核的自生搜索符;利用LALR(1)项目集核构造算法逐个进行传播计算。,综上,构造
38、拓广文法的LALR(1)项目集(核)的步骤如下:,从初态开始: I0:CLOSURE S-S,# = S-S,# S-L=R,# S-R,# L-*R,=L-i,= R-L,# L-*R,# L-i,# ,初态中具有搜索符#的 S-S 进栈;即:( I0, S-S, # ) 入栈,I0:CLOSURE S-S,# = S-S,# S-L=R,#S-R,# L-*R,=L-i,= R-L,# L-*R,# L-i,# ,( I0, S-S, # ),( I4, L-*R, = ),( I5, L-i, = ),( I7, L-*R, = ),( I8, R-L, = ),( I2,S-L=R,
39、# ),( I3, S-R, # ),( I2,R-L, # ),( I4, L-*R, # ),( I5, L-i, # ),( I1, S-S, # ),( I8,R-L, # ),( I9, S-L=R, # ),栈的变化状态,( I6,S-L=R, # ),I4:CLOSURE L-*R, = = L-*R, = R-L,= L-*R,= L-i,= ,I2:CLOSURE S-L=R, # = S-L=R, # ,I6:CLOSURE S-L=R, # = S-L=R, # R-L,# L-*R,# L-i,# ,I4:CLOSURE L-*R, # = L-*R, # R-L,# L-*R,# L-i,# ,( I7, L-*R, # ),最终得到该文法的LALR(1)集核为:,参考资料,陈火旺,程序设计语言编译原理(第三版),国防工业出版社,83129 冯博琴译,现代编译程序设计,邮电出版社,2.2.3,2.2.4 Kenneth C. Louden,冯博琴 等译,编译原理与实践,机械工业出版社,