作者:@cherish.
课程学习内容为作者从学校的PPT处摘抄,仅供自己学习参考,若需转载请注明出处:https://www.cnblogs.com/cherish-/p/16382392.html
LR分析
LR分析概述
【例】

假设文法G[S]和分析表M,状态(0,#)为开始状态,(q,a)为栈顶元素(q为状态,a为输入符号),则总控程序的算法如下:
【例】


LR(0)分析
定义:将符号串的任意含有头符号的子串称为前缀。特别地,空串ε为任意串的前缀。
定义:设文法G[S],如果S∗⇒αAω⇒αβω是句型αβω的规范推导,则αβ称为可归前缀,αβ的前缀称为活前缀。
【例】

识别活前缀DFA
技术路线是根据文法G,构造识别活前缀NFA M
。之后通过子集法,将NFA M
确定化,得到识别活前缀DFA M
。
识别G=(VN,VT,P,S)活前缀的NFA
:
-
文法G等价改写成G′:文法G′=(VN∪{S′},VT,P∪{S′→S},S′);VN∩{S′}=∅;
-
每个规则A→α构造等价一个NFAMA→α:
令α=x1x2...xn,增加n+1个状态q1,q2,...,qn+1;
f(qi,xi)={qi+1}(1≤i≤n),q1为开始状态,qn+1为结束状态,∑={x1,x2,...,xn};
-
合并所有规则的NFAM→α,构造成一个NFA M
:
如果MA→α有f(q,B)={p},B∈VN,且NFABB→β对应开始状态为q′,增加转换f(q,ε)⊇{q′};最后仅保留NFAMS′→S的开始状态为NFA M
的开始状态。
【例】


M(A→α)的状态可以直接由A→α规则来命名,对于规则:A→αβγ有:



通过LR(0)
项目集(规范族)直接构造识别活前缀的DFA
:

LR(0)
项目的分类:
- 移进项目:A→α⋅aβ;
- 待约项目:A→α⋅Xβ;
- 归约项目:A→α⋅;
- 接受项目:S′→α⋅;
- 其中α,β∈(VN∪VT)∗,a∈VT,X∈VN;
- 特别地,空规则A→ε对应
LR(0)
项目为A→⋅。
DFA→LR(0)分析表:

LR(0)项目的MOVE运算定义
定义:设I是文法G的LR(0)
项目子集,则MOVE(I,X)定义如下:
MOVE(I,X)={A→αX⋅β|A→α⋅Xβ∈I}
【例】
I={S→a⋅AcBe,A→⋅Ab,A→⋅b};
MOVE(I,A)={S→aA⋅cBe,A→A⋅b};
MOVE(I,b)=A→b⋅。
LR(0)项目的CLOSURE运算
定义:设I是文法G的LR(0)
项目子集,则closure(I)
定义如下:
- I⊂closure(I);
- {B→⋅γ|A→α⋅Bβ∈closure(I)}⊂closure(I);
- 重复上一步,直到
closure(I)
不再扩大为止。
【例】
I={S→a⋅AcBe};
则closure(I)={S→a⋅AcBe,A→⋅Ab,A→⋅b};
LR(0)识别活前缀DFA M构造方法
设文法G=(VN,VT,P,S),且已等价改写成文法G′,即G′=(VN∪{S′},VT,P∪{S′→S},S′);VN∩{S′}=∅;则识别活前缀DFAM=(K,∑,f,S,Z),其中:
- K⊆p,(LR(0)项目集);
- ∑=VN∪VT;
- f(I,X)=closure(MOVE(I,X)),I∈K,X∈∑;
- S=closure(S′→S);
- Z={q|q∈K,q含有归约项目};
定义:文法G的识别活前缀DFAM的状态集称为文法G的LR(0)项目集规范族。
【例】

LR(0)分析表的构造
设文法G的LR(0)项目集规范族C={I0,I1,...,In},且f为转换函数,则对每一个LR(0)项目,依据下列情况分别填分析表:
- 如果移进项目A→α⋅aβ∈Ik,f(Ik,a)=Ij,则置ACTION[k,a]=Sj;
- 如果归约项目A→α⋅∈Ik,A→α标号为i,∀a∈(VT∪{#}),置ACTION[k,a]=ri;
- 如果接受项目S′→S⋅∈Ik,则置ACTION[k,#]=acc;
- 如果f(Ik,A)=Ii,A∈VN,则置GOTO[k,A]=j;
凡按上述过程没能填入分析表元素ACTION[k,a]和GOTO[k,a]置为et,t为错误编号。
【例】

移进-归约冲突:项目集中同时出现移进和归约项目如A→α⋅aβ,B→γ⋅;
归约-归约冲突:项目集中同时出现多个归约项目如A→α⋅,B→β⋅;
定义:如果文法G的LR(0)项目集规范族不存在移进-归约冲突或归约-归约冲突的项目集,则文法G称为LR(0)文法。
- 如果文法G是LR(0)文法,则G可采用LR(0)分析法。
- 如果文法G是LR(0)文法,则G是无二义性的。
- LR(0)分析表
ACTION
表中每格仅会是移进、归约和报错3种动作之一。
SLR(1)分析
不是LR(0)文法时,可以采用简单地向后看1个输入符号的方法,解决移进-归约冲突或归约-归约冲突。
假设文法LR(0)项目集规范族有一个并存移进-归约或归约-归约冲突的项目集Ik={A→α⋅aβ,A→γ⋅,B→δ⋅,...};若{a}∩FOLLOW(A)∩FOLLOW(B)=∅则冲突可解决:
- 如果下一个符号ai∈移入符号集,移入;
- 如果下一个符号ai∈FOLLOW(A),用A→γ归约;
- 如果下一个符号ai∈FOLLOW(B),用B→δ归约。
这种分析方法称为SLR(1)分析法
。
SLR(1)分析表的构造
对每一个LR(0)项目,依据下列情况分别填分析表:
- 如果移进项目A→α⋅aβ∈Ik,f(Ik,a)=Ij,则置ACTION[k,a]=Sj;
- 如果归约项目A→α⋅∈Ik,A→α标号为i,∀a∈FOLLOW(A),则置ACTION[k,a]=ri;
- 如果接受项目S′→S⋅∈Ik,则置ACTION[k,#]=acc;
- 如果f(Ik,A)=Ij,A∈VN,则置GOTO[k,A]=j;
凡按上述步骤没能填入分析表元素ACTION[k,a]和GOTO[k,a],置为et,t为错误编号。
定义:设文法G的LR(0)项目集规范族C中任意含有m个移进项目和n个归约项目的冲突项目集Ik的一般形式为:Ik={A1→α1⋅a1β1,...,Am→αm⋅amβm,B1→γ1⋅,...,Bn→γn⋅,...};其中Ai,Bj∈VN,ai∈VT,αi,βj,γq∈(VN∪VT)∗,...表示剩下的待约项目。
如果移进符号集a1,a2,...,αm和FOLLOW(B1),FOLLOW(B2),...,FOLLOW(Bn)两两相交均为空集,则文法G称为SLR(1)文法
。
SLR(1)文法
,可用SLR(1)分析法
;
SLR(1)文法
,是无二义性的;
LR(0)文法
,一定也是SLR(1)文法
。
【例】




LR(1)分析
SLR(1)分析法存在的问题
- SLR只是简单地考察下一个输入符号b是否属于与规约项目A→α相关联的FOLLOW(A),但b∈FOLLOW(A)只是归约α的一个必要条件,而非充分条件;
- 对于产生式A→α的归约,在不同的使用位置,A会要求不同的后继符号;
- 在特定位置,A的后继符号集合是FOLLOW(A)的子集。
LR(1)分析法在构造项目时,将特定位置的后继符信息一并纳入考量范围。
LR(1)的基本思想

在状态Ii:下一个符号属于FOLLOW(B)而不属于FIRST(β),即便归约到B,最终也会面临此路不通。
把FIRST(β)作为产生式作为B→γ归约时向前查看的符号集合(向前搜索符号集,前瞻符号集),代替SLR(1)分析法
中的FOLLOW(B),并将向前搜索符号集也放在LR(0)项目的后面:
[A→α⋅β,a],a称为向前搜索符(展望符)-LR(1)项目
LR(1)项目
定义:附加搜索符(∈VT∪{#})的LR(0)项目称为LR(1)项目。记为[LR(0)项目,搜索符]。LR(1)项目中LR(0)项目部分称为LR(1)项目的心。对于同心的LR(1)项目简记为[LR(0)项目,搜索符1|搜索符2|...|搜索符m]。后者称为搜索集。
形如[A→α⋅,a]的项表示仅在下一个输入符号等于a时才可以按照A→α进行归约。
这样的a的集合总是FOLLOW(A)的子集,通常是真子集。
P68
定义:设I是文法G的LR(1)项目子集,则MOVE1(I,X)定义如下:
MOVE1(I,X)={[A→αX⋅β,a]|[A→α⋅Xβ,a]∈I}
定义:设I是文法G的LR(1)项目子集,closure1(I)
定义如下:
- I⊂closure1(I);
- {[B→⋅γ]|[A→α⋅Bβ,a]∈closure1(I),b∈FIRST(βa)}⊂closure1(I);
- 重复上一步,直到closure1(I)不再扩大为止。
LR(1)识别活前缀的DFA M构造
设文法G=(VN,VT,P,S),等价改写文法G′=(VN∪{S′},VT,P∪{S′→S},S′);其中VN∩{S′}=∅,则识别活前缀DFAM=(K,∑,f,S,Z),其中:
- K⊆p(LR(1)项目集);
- ∑=VN∪VT;
- f(I,X)=closure(MOVE1(I,X)),I∈L,X∈∑;
- S=closure1([S′→⋅S,#]);
- Z={q,q∈K,q含有归约项目}。
定义:文法G的LR(1)识别活前缀DFA M
的状态集称为文法G的LR(1)项目规范族。
LR(1)分析表的构造
设文法G的LR(1)项目集规范族C={I0,I1,...,In};
对C中每个Ii构造得到状态i,状态i的语法分析动作按照下面的方法决定:
- 如果[A→α⋅aβ,b]∈Ii并且f(Ii,a)=Ij,则ACTION[i,a]=Sj;
- 如果[A→α⋅Bβ,b]∈Ii并且f(Ii,B)=Ij,则ACTION[i,B]=Sj;
- 如果[A→α⋅,a]∈Ii并且A≠S′,则ACTION[i,a]=rj;(j是产生式 的编号)
- 如果[S′→S⋅,#]∈Ii,则ACTION[i,#]=acc;
- 所有没有定义的条目都设置为et,t是错误编号。
定义:设文法G的LR(1)项目集规范族C中任意含有m个移进项目和n个归约项目的冲突项目集Ik的一般形式为:Ik={[A1→α1⋅a1β1,S′1],...,[Am→αm⋅amβm,S′m],[B1→γ1⋅,S1],...,[Bn→γn⋅,Sn],...}。
其中Ai,Bj∈VN,ai∈VT,αi,βj,γq∈(VN∪VT)∗,...表示剩下的待约项目,S′i,Sj为搜索集。
如果移进符号集{a1,a2,...,αm}和搜索集S1,...,Sn两两相交均为空集,则文法G称为LR(1)文法。
- 如果文法G是LR(1)文法,则G可采用LR(1)分析法;
- 如果文法G是LR(1)文法,则G是无二义性的;
- 如果文法G是SLR(1)文法,则G一定是LR(1)。
【例】



LALR(1)分析
定义:如果采用同心项目集合并方法,进行合并后的文法G的LR(1)项目集规范族,没有LR(1)项目冲突,则称文法G为LALR(1)文法。
关于LALR(1)文法,可以得出下列几个结论:
- 如果文法G是LALR(1)文法,则G可采用LALR(1)分析法;
- 如果文法G是LALR(1)文法,则G是无二义性的;
- 如果文法G是LALR(1)文法,则G一定是LR(1)文法。
【例】




LALR(1)的特点
- 形式上与LR(1)相同;
- 大小上与LR(0)/SLR相当;
- 分析能力介于SLR和LR(1)二者之间;
- 合并后的向前搜索符集合仍为FOLLOW集的子集。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)