一、基本概念
- 短语:在一个句型对应的语法树中, 以某非终结符为根的一棵子树的所有叶子自左至右排列起来形成一个相对于子树根的短语。
- 直接短语:仅有父子两代的一棵子树,它的所有叶子自左至右排列起来所形成的符号串。
- 句柄:仅有父子两代的一棵子树,它的所有叶子自左至右排列起来所形成的符号串。
- 素短语:一个文法G的句型的素短语是指这样一个短语,它至少含有一个终结符,并且,除它自身之外不再含任何更小的素短语。
- 最左素短语:是指处于句型最左边的那个素短语。
二、算符优先分析法
-
算符优先文法定义
假定G是一个不含e-产生式的算符文法。对于任何一对终结符a、b,我们说:
1. a = b 当且仅当文法G中含有形如P→…ab…或P→…aQb…的产生式
2. a < b 当且仅当G中含有形如P→…aR…的产生式, 而R加推导b…或R加推导Qb…
3. a > b 当且仅当G中含有形如P→…Rb…的产生式,而 R加推导…a或R加推导…aQ
如果一个算符文法G中的任何终结符对(a,b)至多只满足下述三关系之一:
a = b,a < b,a > b
则称G是一个算符优先文法。
-
FIRSTVT(P)的构造
1. 若有产生式P→a…或P→Qa…,则a∈FIRSTVT(P);
2. 若a∈FIRSTVT(Q),且有产生式P→Q…,则a∈FIRSTVT(P)。
-
LASTVT(P)的构造
1. 若有产生式P→… a或P→ … aQ,则a∈ LASTVT(P);
2. 若a∈LASTVT(Q),且有产生式P→… Q ,则a∈LASTVT(P)。
-
造优先表构造算法
FOR 每条产生式P→X1X2…Xn DO
FOR i:=1 TO n-1 DO
BEGIN
IF Xi和Xi+1均为终结符 THEN 置Xi = Xi+1
IF i≤n-2且Xi和Xi+2都为终结符
但Xi+1为非终结符 THEN 置Xi = Xi+2;
IF Xi为终结符而Xi+1为非终结符 THEN
FOR FIRSTVT(Xi+1)中的每个a DO
置 Xi < a;
IF Xi为非终结符而Xi+1为终结符 THEN
FOR LASTVT(Xi)中的每个a DO
置 a > Xi+1
END
-
优先函数
把每个终结符q与两个自然数f(q)与g(q)相对应,使得
若q1 < q2,则f(q1) < g(q2)
若q1 = q2,则f(q1) = g(q2)
若q1 > q2,则f(q1) > g(q2)
f称为入栈优先函数,g称为比较优先函数。
三、LR(0)文法
-
LR(0)项目集规范族
假定I是文法G'的任一项目集,定义和构造I的闭包CLOSURE(I)如下:
1. I的任何项目都属于CLOSURE(I);
2. 若A→a·Bβ属于CLOSURE(I),那么,对任何关于B的产生式B→γ,项目B→·γ也属于CLOSURE(I);
3. 重复执行上述两步骤直至CLOSURE(I) 不再增大为止。
-
LR(0)文法定义
假若一个文法G的拓广文法G'的活前缀识别自动机中的每个状态(项目集)不存在下述情况:
1) 既含移进项目又含归约项目,
2) 含有多个归约项目
则称G是一个LR(0)文法。
-
LR(0)分析表的构造
1. 若项目A→a·ab属于Ik且GO(Ik, a)=Ij,a为终结符,则置ACTION[k,a] 为“sj”。
2. 若项目A→a·属于Ik,那么,对任何终结符a(或结束符#),置ACTION[k,a]为 “rj”(假定产生式A→a是文法G'的第j个产生式)。
3. 若项目S'→S·属于Ik,则置ACTION[k,#]为 “acc”。
4. 若GO(Ik,A)=Ij,A为非终结符,则置GOTO[k,A]=j。
5. 分析表中凡不能用规则1至4填入信息的空白格均置上“报错标志”。
四、SLR(1)文法
-
SLR(1)文法定义
假定LR(0)规范族的一个项目集I={A1→a·a1b1,A2→a·a2b2,…,Am→a·ambm,B1→a·,B2→a·,…,Bn→a·} 如果集合{a1,…,am},FOLLOW(B1),…,FOLLOW(Bn)两两不相交(包括不得有两个FOLLOW集合有#),则:
1. 若a是某个ai,i=1,2,…,m,则移进;
2. 若a∈FOLLOW(Bi),i=1,2,…,n,则用产生式Bi→a进行归约;
3. 此外,报错。
冲突性动作的这种解决办法叫做SLR(1)解决办法。
-
SLR(1)项目集规范族
其构造方法与LR(0)文法构造相同
-
SLR(1)分析表的构造
1. 若项目A→a·ab属于Ik且GO(Ik,a)=Ij,a为终结符,则置ACTION[k,a]为 “sj”;
2. 若项目A→a·属于Ik,那么,对任何终结符a,a∈FOLLOW(A),置ACTION[k,a]为 “rj”;其中,假定A→a为文法G'的第j个产生式;
3. 若项目S'→S·属于Ik,则置ACTION[k,#]为“acc”;
4. 若GO(Ik,A)=Ij,A为非终结符,则置GOTO[k,A]=j;
5. 分析表中凡不能用规则1至4填入信息的空白格均置上“出错标志”。
五、LR(1)文法
-
LR(1)项目集规范族
项目集I 的闭包CLOSURE(I)构造方法:
1. I的任何项目都属于CLOSURE(I)。
2. 若项目[A→a·Bb, a]属于CLOSURE(I),B→x 是一个产生式,那么,对于FIRST(ba) 中的每个终结符b,如果[B→·x, b]原来不在CLOSURE(I)中,则把它加进去。
3. 重复执行步骤2,直至CLOSURE(I)不再增大为止。
-
LR(1)分析表的构造
1. 若项目[A→a·ab, b]属于Ik且GO(Ik, a)=Ij, a为终结符,则置ACTION[k, a]为 “sj”。
2. 若项目[A→a·,a]属于Ik,则置ACTION[k, a]为 “rj”;其中假定A→a为文法G'的第j个产生式。
3. 若项目[S¢→S·, #]属于Ik,则置ACTION[k, #]为 “acc”。
4. 若GO(Ik,A)=Ij,则置GOTO[k, A]=j。
5. 分析表中凡不能用规则1至4填入信息的空白栏均填上“出错标志”。
-
LR(1)文法定义
按上述算法构造的分析表,若不存在多重定义的入口(即,动作冲突)的情形,则称它是文法G的一张规范的LR(1)分析表。具有规范的LR(1)分析表的文法称为一个LR(1)文法。
六、LALR(1)文法
-
LALR(1)分析表的构造
步骤:
- 构造得到LR(1)项集族C={I0,I1,…,In}。
- 对于LR(1)中的每个核心,找出所有具有这个核心的项集,并把这些项集替换为它们的并集
- 令C’={J0,J1,…,Jn}是得到的LR(1)项集族。按照LR分析表的构造方法得到ACTION表。(如果存在冲突,则这个文法不是LALR的)
GOTO表的构造:设J是一个或者多个LR(1)项集(包括I1)的并集,令K是所有和GOTO(I1,X)具有相同核心的项集的并集,那么GOTO(J,X)=K
-
各文法之间的包含关系
LR(0)∈SLR ∈LALR(1)∈ LR(1)