题型总结
1. LL(1)文法分析
该类题型主要包括左递归消除、回溯消除、构建预测分析表、还原递归分析过程、还原预测分析过程等。
例-1(课后习题4-3改)设文法G[S]:
S→A
A→B∣AiB
B→C∣B+C
C→)A∗∣(
(1) 将文法G[S]改写为LL(1)文法。
分析:改写LL(1)文法第一步——消除左递归。
首先发现A→AiB存在左递归,于是将第2条规则改写为:
A→BA′
A′→iBA′∣ε(注意这里不能没有ε!)
然后第3条规则显然也有左递归,继续改写:
B→CB′
B′→+CB′∣ε
至此左递归消除完成。文法变为:
S→A
A→BA′
A′→iBA′∣ε
B→CB′
B′→+CB′∣ε
C→)A∗∣(
下面查看这其中是否有回溯。对于左部相同的两条规则:
- A′→iBA′∣ε,其SELECT集分别为{i}和{∗, $ },无交集(注意这里的$是由FOLLOW集产生的,如果一个非终结符后面可以不跟任何终结符,那么就需要将符号串的结束符$包含到SELECT集中。)
- B′→+CB′∣ε,其SELECT集分别为{+}和{i,∗, $ },无交集。
- C→)A∗∣(,其SELECT集分别为{)}和{(},无交集。
注意这里的FOLLOW集计算过程。盲目去找很容易漏掉几个。找FOLLOW集不应该只是去找某一个非终结符的FOLLOW集,而是应该从头到尾将所有非终结符的FOLLOW集全部找到,因为一些非终结符的FOLLOW集可以直接加载其他非终结符的FOLLOW集之中。
对于上例中的文法。我们来使用规范化的方式寻找FOLLOW集:
- 对于S,其为开始符号,后面本来就可以不跟什么符号,因此$ ∈FOLLOW(S)。又有S→A,因此A的FOLLOW集中一定包含S的FOLLOW集中的所有元素。注意此时我们并不确定S的FOLLOW集中是否只有一个$。
|
FOLLOW集 |
S |
{ $ } |
A |
{ $ } |
- 对于文法A→BA′,有FOLLOW(A)⊆FOLLOW(A′),FIRST(A′)⊆FOLLOW(B),其中FIRST(A′)={i,ε}
|
FOLLOW集 |
S |
{ $ } |
A |
{ $ } |
A′ |
{ $ } |
B |
{i, $ } |
- 对于文法B→CB′,有FIRST(B′)⊆FOLLOW(C),其中FIRST(B′)={+,ε},且有FOLLOW(B)⊆FOLLOW(B′),FOLLOW(B′)∈FOLLOW(C)。
|
FOLLOW集 |
S |
{ $ } |
A |
{ $ } |
A′ |
{ $ } |
B |
{i, $ } |
B′ |
{i, $ } |
C |
{+, $ } |
- 对于文法C→)A∗∣(,有∗∈FOLLOW(A)。
|
FOLLOW集 |
S |
{ $ } |
A |
{∗, $ } |
A′ |
{ $ } |
B |
{i, $ } |
B′ |
{i, $ } |
C |
{+, $ } |
- 扩充被A影响的FOLLOW集:
|
FOLLOW集 |
S |
{ $ } |
A |
{∗, $ } |
A′ |
{∗, $ } |
B |
{i, $ } |
B′ |
{i, $ } |
C |
{+, $ } |
- 对于文法A′→iBA′∣ε,有FOLLOW(A′)∈FOLLOW(B)。
|
FOLLOW集 |
S |
{ $ } |
A |
{∗, $ } |
A′ |
{∗, $ } |
B |
{i,∗, $ } |
B′ |
{i,∗, $ } |
C |
{i,∗,+, $ } |
故不存在回溯问题。
最终修改完成的文法为:
S→A
A→BA′
A′→iBA′∣ε
B→CB′
B′→+CB′∣ε
C→)A∗∣(
(2) 求经过改写后的每个非终结符的FIRST集和FOLLOW集,以及每一条规则的SELECT集。
解:FIRST集和FOLLOW集如下:
|
FIRST集 |
FOLLOW集 |
S |
{),(} |
{ $ } |
A |
{),(} |
{∗, $ } |
A′ |
{i,ε} |
{∗, $ } |
B |
{),(} |
{i,∗, $ } |
B′ |
{+,ε} |
{i,∗, $ } |
C |
{),(} |
{i,∗,+, $ } |
SELECT集如下:
|
SELECT集 |
S→A |
{),(} |
A→BA′ |
{),(} |
A′→iBA′ |
{i} |
A′→ε |
{∗, $ } |
B→CB′ |
{),(} |
B′→+CB′ |
{+} |
B′→ε |
{i,∗, $ } |
C→)A∗ |
{)} |
C→( |
{(} |
(3) 写出该文法的递归下降分析程序的A′函数、B′函数和C函数:
解:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| A'(){ if(sym == 'i'){ scanner(); B(); A'(); }else if(sym != '*' && sym != '$') error(); else scanner(); }
B'(){ if(sym == '+'){ C(); B'(); }else if(sym != 'i' && sym != '*' && sym != '$') error(); }
C(){ if(sym == '('){ scanner(); A(); scanner(); if(sym != '*') error(); }else if(sym != ')') error(); scanner(); }
|
递归下降分析函数需要保证:在任何一个非终结符识别函数刚刚开始执行时,读位置始终指向该非终结符应该识别的第一个字符。因此调整指针的操作应该在上一级函数中实现,这也是A函数和C函数最后一句scanner()
的含义。
(4) 画出预测分析图。
解:可以根据SELECT集直接画出预测分析图:
|
( |
) |
* |
+ |
i |
$ |
S |
S→A |
S→A |
|
|
|
|
A |
A→BA′ |
A→BA′ |
|
|
|
|
A′ |
|
|
A′→ε |
|
A′→iBA′ |
A′→ε |
B |
B→CB′ |
B→CB′ |
|
|
|
|
B′ |
|
|
B′→ε |
B′→+CB′ |
B′→ε |
B′→ε |
C |
C→( |
C→)A∗ |
|
|
|
|
(5) 使用上面的预测分析图分析输入串)(i(+(*
。
解:画图——
分析栈 |
输入串 |
所用规则 |
$ |
)(i(+(*$ |
|
$A |
)(i(+(*$ |
S→A |
$A'B |
)(i(+(*$ |
A→BA′ |
$A'B'C |
)(i(+(*$ |
B→CB′ |
$A'B'*A) |
)(i(+(*$ |
C→)A∗ |
$A'B'*A'B |
(i(+(*$ |
A→BA′ |
$A'B'*A'B'C |
(i(+(*$ |
B→CB′ |
$A'B'*A'B'( |
(i(+(*$ |
C→( |
$A'B'*A'B' |
i(+(*$ |
|
$A'B'*A' |
i(+(*$ |
B′→ε |
$A'B'*A'Bi |
i(+(*$ |
A′→iBA′ |
$A'B'*A'B |
(+(*$ |
|
$A'B'*A'B'C |
(+(*$ |
B→CB′ |
$A'B'*A'B'( |
(+(*$ |
C→( |
$A'B'*A'B' |
+(*$ |
|
$A'B'*A'B'C+ |
+(*$ |
B′→+CB′ |
$A'B'*A'B'C |
(*$ |
|
$A'B'*A'B'( |
(*$ |
C→( |
$A'B'*A'B' |
*$ |
|
$A'B'*A' |
*$ |
B′→ε |
$A'B'* |
*$ |
A′→ε |
$A'B' |
$ |
|
$A' |
$ |
B′→ε |
$ |
$ |
A′→ε |
成功。
上面的分析流程:如果栈中最上面一个是非终结符,下一步就要根据输入串最前面的字符选择候选式。如果栈中最上面一个是终结符,就和输入串最前面的字符比较,如果相等就相消,如果不等就输出错误。
2. OG文法分析
OG文法没有讲完,后面的素短语等内容没有要求,因此只需要掌握两个集合的求解以及算符优先表的构建即可。
例-2:对于例-1中的文法,求所有非终结符的FIRSTVT集和LASTVT集,并画出算符优先表。
S→A
A→B∣AiB
B→C∣B+C
C→)A∗∣(
分析:按照构建两个集合的方法求出所有非终结符的FIRSTVT集和LASTVT集:
|
FIRSTVT |
LASTVT |
S |
{i,(,),+} |
{i,∗,(,+} |
A |
{i,(,),+} |
{i,∗,(,+} |
B |
{(,),+} |
{∗,(,+} |
C |
{(,)} |
{∗,(} |
构建算符优先表:
|
i |
( |
) |
+ |
* |
$ |
i |
⋗ |
⋖ |
⋖ |
⋖ |
⋗ |
⋗ |
( |
⋗ |
|
|
⋗ |
⋗ |
⋗ |
) |
⋗,⋖ |
⋖ |
⋖ |
⋖ |
≖ |
|
+ |
⋗ |
⋖ |
⋖ |
⋗ |
⋗ |
⋗ |
* |
|
|
|
⋗ |
⋗ |
⋗ |
$ |
⋖ |
⋖ |
⋖ |
⋖ |
|
≖ |
3. LR(0)文法
该部分包含LR(0)文法的分析表、活前缀DFA的构建。
例-3:画出例-1中文法的规范句型活前缀DFA以及LR(0)分析表,如果有冲突说明冲突来源,没有冲突说明理由。
S→A
A→B∣AiB
B→C∣B+C
C→)A∗∣(
分析:首先拓广,加一条规则:
S′→S
S→A
A→B∣AiB
B→C∣B+C
C→)A∗∣(
然后递归地构建DFA:
- 求出CLOSURE(S′→⋅S)={S′→⋅S,S→⋅A,A→⋅B,A→⋅AiB,B→⋅C,B→⋅B+C,C→⋅)A∗,C→⋅(},作为项目集I0。
- 求出GOTO(I0,S)=CLOSURE({S′→S⋅})={S′→S⋅},作为项目集I1,其没有GOTO函数。
- 求出GOTO(I0,A)=CLOSURE({S→A⋅,A→A⋅iB})={S→A⋅,A→A⋅iB},作为项目集I2。
- 求出GOTO(I0,B)=CLOSURE{A→B⋅,B→B⋅+C}={A→B⋅,B→B⋅+C},作为项目集I3。
- 求出GOTO(I0,C)=CLOSURE{B→C⋅}={B→C⋅},作为项目集I4,其没有GOTO函数。
- 求出GOTO(I0,")")=CLOSURE{C→)⋅A∗}={C→)⋅A∗,A→⋅B,A→⋅AiB,B→⋅C,B→⋅B+C,C→⋅)A∗,C→⋅(},作为项目集I5。
- 求出GOTO(I0,"(")=CLOSURE{C→(⋅}={C→(⋅},作为项目集I6,其没有GOTO函数。
- 求出GOTO(I2,i)=CLOSURE({A→Ai⋅B})={A→Ai⋅B},作为项目集I7。
- 求出GOTO(I3,+)=CLOSURE({B→B+⋅C})={B→B+⋅C,C→⋅)A∗,C→⋅(},作为项目集I8。
- 求出GOTO(I5,A)=CLOSURE({C→)A⋅∗,A→A⋅iB})={C→)A⋅∗,A→A⋅iB},作为项目集I9。
- 求出GOTO(I5,B)=CLOSURE({A→B⋅,B→B⋅+C})=I3。
- 求出GOTO(I5,C)=CLOSURE{B→C⋅}=I4。
- 求出GOTO(I5,"(")=CLOSURE({C→(⋅})=I6。
- 求出GOTO(I5,")")=CLOSURE({C→)⋅A∗})=I5。
- 求出GOTO(I7,B)=CLOSURE({A→AiB⋅})={A→AiB⋅},作为项目集I10,其没有GOTO函数。
- 求出GOTO(I8,C)=CLOSURE({B→B+C⋅})={B→B+C⋅},作为项目集I11,其没有GOTO函数。
- 求出GOTO(I8,")")=CLOSURE({C→)⋅A∗})=I5。
- 求出GOTO(I8,"(")=CLOSURE{C→(⋅}=I6。
- 求出GOTO(I9,i)=CLOSURE({A→Ai⋅B})={A→Ai⋅B,B→⋅C,B→⋅B+C,C→⋅)A∗,C→⋅(},作为项目集I12。
- 求出GOTO(I9,∗)=CLOSURE({C→)A∗⋅})={C→)A∗⋅},作为项目集I13,其没有GOTO函数。
- 求出GOTO(I12,B)={A→AiB⋅,B→B⋅+C},作为项目集I14,有GOTO(I14,+)=I8。
- 求出GOTO(I12,C)={B→C⋅}=I4。
- 求出GOTO(I12,")")=I5。
- 求出GOTO(I12,"(")=I6。
由上面的推导画出DFA(图略,太复杂)
根据上面的推导画出分析表如下:

可以看见其中有多处移进-归约冲突。
4. SLR(1)文法
例-4:使用SLR(1)文法尝试改写上一题的分析表,说明改写后是否存在冲突。如果不存在,试分析符号串)(i(+(*
分析:上图中一共有3处移进-规约冲突,下面逐一进行处理:
- 对于状态2移入符号i,状态2的两个LR(0)项目中只有{A→A⋅iB}可以接受符号i,而另一个状态{S→A⋅}无法接收符号i(FOLLOW集中不包含i)。因此此处冲突可以解决。
- 对于状态3移入符号+,状态3的两个LR(0)项目中只有{B→B⋅+C}可以接受,而另一个无法接受。因此此处状态可以解决。
- 对于状态14移入符号+,状态14的两个LR(0)项目中只有{B→B⋅+C}可以接受,而另一个无法接受。因此此处状态可以解决。

至此冲突已经完全解决,可以进行分析了。分析过程如下:
