SLR(1)分析
1.SLR(1)解决的问题
LR(0)文法的要求是①不同时含有移进项目和归约项目,即不存在移进-归约冲突。②不含有两个以上归约项目,即不存在归约-归约冲突。
例如项目集Ii中存在: Ii ={A->α•bγ , B→ γ•,C→β• }
,此时就同时存在移进-归约冲突和归约-归约;因为你不知道下一步是选择归约还是移进,选择归约的话选择哪个产生式归约。
而事实上一般文法满足这种要求有一定难度,但是假如在归约时出现了移进-归约冲突或者归约-归约冲突,我们可以通过在待分析的字符串中向后再看一位,大多数情况下通过这一位字符就可以确定,选择哪一个表达式归约,或是移进操作。
这种方法就叫做SLR(1)分析法,即简单的LR(1)分析法。
2.SLR(1)分析的解决方法
如上面所述,我们需要知道下一位待分析的字符,然后和现有项目进行比较。
分析过程与LR(0)一样,但是需要解决分析表上的冲突问题。
假如LR(0) 项目集规范族中有项目集 Ii 含有移进-归约冲突和归约-归约冲突: Ii ={A1->α1•b1γ1 ,… , Am->m•bm γm, B1->β 1 • ,…, Bn-> β n • }
,若集合{b1 ,b2,… ,bm }
、FOLLOW(B1)
、 FOLLOW(B2)
,…,FOLLOW(Bn)
均两两不相交,则可用SLR(1)解决方法解决分析表上第i行上的冲突问题。
假设下一个移进的字符为b
,若``b∈ {b1 ,b2,… ,bm },则移进输入符; 若
b∈FOLLOW(Bj) ,j=1 ,… ,n,则用
Bj-> βj` 归约;
通过这个方法,就可以在知道下一位待分析的字符的情况下,解决冲突。
继续采用SLR(1)分析的方法,我们可以对出错情况进行优化:
在LR(0)和SLR(1)分析中,我们在可以归约且没有冲突时(假如归约成A),是不关心下一位待分析的字符a
和和follow(A)
的关系的,假如a!∈follow(A)
则当前字符串是不被接受的,当然这会在之后的继续移进字符过程中发现错误,但是如果不管是否有冲突看,将SLR(1)分析方法应用到所有分析表的构建过程中,可以提前发现字符串的错误。
综上,我们可以在构建分析表时做出如下改变:
- 若项目
A ->α • aβ
属于 Ik 且GO (Ik, a)= Ij,
期望字符a 为终结符,则置ACTION[k, a] =sj
(j表示新状态Ij); - 若项目
A ->α • Aβ
属于 Ik,且GO (Ik, A)= Ij
,期望字符 A为非终结符,则置GOTO(k, A)=j
(j表示文法中第j个产生式); - 若项目
A ->α •
属于Ik, 那么对任何终结符a,当满足a属于follow(A)时, 置ACTION[k, a]=rj
;其中,假定A->α
为文法G 的第j个产生式; - 若项目
S’ ->S •
属于Ik, 则置ACTION[k, #]=“acc”
; - 分析表中凡不能用上述规则填入信息的空白格均置上“出错标志”
3.SLR(1)分析的例子
算术表达式文法G[E]:
E→E +T | T
T→T * F | F
F→ (E)| i
求此文法的识别规范句型活前缀的DFA,分析句子i+i *i。
将文法拓广为G’[E’]:
(0) E’ ->E
(1) E-> E +T
(2) E ->T
(3) T ->T * F
(4) T ->F
(5) F ->(E)
(6) F ->i构造识别规范句型活前缀的DFA
-
判断有无冲突:
I1 ,I2 ,I9有移进_归约冲突。
I1:E´ ->E· E ->E·+T
I2: E ->T · T ->T · *F
I9: E ->E+T· T ->T · *F -
考虑能否用SLR(1)方法解决冲突:
对于I1:
{ E´ ->E· E ->E·+T}
因为:{+} ∈FOLLOW(E´)= {+} ∩ {#} =∅
, 所以可用SLR(1)方法 解决I1的冲突。对于I2:
{E ->T· T ->T·*F}
因为:{*} ∈ FOLLOW(E)= {*} ∩ {#,),+} = ∅
所以可用SLR(1)方法解决I2的冲突。对于I9:
{E ->E+T· T ->T ·*F}
因为:{*} FOLLOW(E)= ∅
, 所以可用SLR(1)方法解决I9的冲突。 构建分析表:
6.句子i+i *i的分析过程:
步骤 | 状态栈 | 符号栈 | 输入符 | 剩余输入串 | 查表 | 操作 |
---|---|---|---|---|---|---|
1 | 0 | # | i | i+i*i# | Action[0,i]=S5 | 移进i |
2 | 0 5 | # i | + | +i*i# | Action[5,+]=r6,GOTO(0,F)=3 | 用F -> i 归约 |
3 | 0 3 | # F | + | +i*i# | Action[3,+]=r4,GOTO(0,T)=2 | 用F -> T归约 |
4 | 0 2 | # T | + | +i*i# | Action[2,+]=r4,GOTO(0,E)=1 | 用F -> E归约 |
5 | 0 1 | # E | + | +i*i# | Action[1,+]=S6 | 移进+ |
6 | 0 1 6 | # E + | i | i*i# | Action[6,i]=S6 | 移进+ |
7 | 0 1 6 5 | # E + i | * | *i# | Action[5,*]=r6,GOTO(6,F)=3 | 用F -> i 归约 |
8 | 0 1 6 3 | # E + F | * | *i# | Action[3,*]=r6,GOTO(6,T)=9 | 用F -> F 归约 |
9 | 0 1 6 9 | # E + T | * | *i# | Action[9,*]=S7 | 移进* |
10 | 0 1 6 9 7 | # E + T * | i | i# | Action[7,i]=S5 | 移进i |
11 | 0 1 6 9 7 5 | # E + T * i | # | # | Action[5,#]=r6,GOTO(7,F)=10 | 用F -> i 归约 |
12 | 0 1 6 9 7 10 | # E + T * F | # | # | Action[10,#]=r3,GOTO(6,T)=9 | 用T -> T+F归约 |
13 | 0 1 6 9 | # E + T | # | # | Action[9,#]=r1,GOTO(0,E)=1 | 用E -> E+T归约 |
14 | 0 1 | # E | # | # | Action[1,#]=acc | 接受 |