1、SLR(1)分析
大多数实用的程序设计语言的文法不能满足LR(0)文法的条件
简单的LR(1)分析法,用SLR(1)表示:对冲突的状态向前查看一个符号,确定动作(是移进还是归约,按哪一个产生式归约)
假定文法G的一个项目集 I 含有:
如果集合{a1,a2,…,am}和集合FOLLOW(B1)……FOLLOW(Bn)两两不相交,则项目集I中的冲突可按以下原则解决,设a是下一输入符号:
(
1
)
若
a
∈
a
1
,
a
2
,
…
,
a
m
,
则
移
进
a
;
(
2
)
若
a
∈
F
O
L
L
O
W
(
B
i
)
,
i
=
1
,
2
…
n
;
则
用
B
i
→
γ
i
⋅
归
约
;
(
3
)
此
外
,
报
错
。
(1)若a∈{a1,a2,…,am},则移进a;\\ (2)若a∈FOLLOW(Bi),i=1,2…n;则用Bi→γi·归约;\\ (3)此外,报错。
(1)若a∈a1,a2,…,am,则移进a;(2)若a∈FOLLOW(Bi),i=1,2…n;则用Bi→γi⋅归约;(3)此外,报错。
SLR(1)文法:如果一个文法的LR(0)项目表中所含冲突都能用上述方法解决,则这个文法是SLR(1)文法,所构造的分析表为SLR(1)分析表,使用SLR(1)分析表的分析器称为SLR(1)分析器
SLR(1)分析表的构造方法:
KaTeX parse error: Unexpected character: '' at position 248: …;\\ (4)若项目S′→S ̲属于Ik,则置ACTION[k…
例
如
:
拓
广
文
法
G
′
:
S
′
→
S
[
0
]
S
→
r
D
[
1
]
D
→
D
,
i
[
2
]
D
→
i
[
3
]
例如:拓广文法 G′:S′→S [0]\\ S →rD [1]\\ D →D,i [2]\\ D →i [3]
例如:拓广文法G′:S′→S[0]S→rD[1]D→D,i[2]D→i[3]
2、LR(1)分析
2.1、LR(1)项目集族的构造
LR(0)不考虑后继符(搜索符),SLR(1)仅在分析时考虑后继符(搜索符),因此,对后继符(搜索符)所含信息量的利用有限
S′→ ·S,# 属于初始项目集,‘#’为向前搜索符。针对初始项目S′→ ·S,#,求闭包后再用转换函数逐步求出整个文法的LR(1)项目集族,具体构造步骤如下:
(1)构造LR(1)项目集的闭包函数
1
)
I
的
任
何
项
目
都
属
于
C
L
O
S
U
R
E
(
I
)
;
2
)
若
有
项
目
A
→
α
⋅
B
β
,
a
∈
C
L
O
S
U
R
E
(
I
)
,
B
→
γ
是
产
生
式
,
β
∈
V
∗
,
b
∈
F
I
R
S
T
(
β
a
)
,
则
B
→
⋅
γ
,
b
也
属
于
C
L
O
S
U
R
E
(
I
)
;
3
)
重
复
2
)
,
直
到
C
L
O
S
U
R
E
(
I
)
不
再
增
大
为
止
。
1)I的任何项目都属于CLOSURE(I);\\ 2)若有项目A→α·Bβ,a ∈CLOSURE(I),B→γ是产生式,β∈V*,b∈FIRST(βa),则B→·γ,b 也属于CLOSURE(I);\\ 3)重复2),直到CLOSURE(I)不再增大为止。
1)I的任何项目都属于CLOSURE(I);2)若有项目A→α⋅Bβ,a∈CLOSURE(I),B→γ是产生式,β∈V∗,b∈FIRST(βa),则B→⋅γ,b也属于CLOSURE(I);3)重复2),直到CLOSURE(I)不再增大为止。
(2)转换函数的构造
L
R
(
1
)
转
换
函
数
的
构
造
与
L
R
(
0
)
的
相
似
,
G
O
(
I
,
X
)
=
C
L
O
S
U
R
E
(
J
)
其
中
I
是
L
R
(
1
)
的
项
目
集
,
X
是
文
法
符
号
。
J
=
任
何
形
如
[
A
→
α
X
⋅
β
,
a
]
的
项
目
∣
[
A
→
α
⋅
X
β
,
a
]
∈
I
LR(1)转换函数的构造与LR(0)的相似,GO(I,X)=CLOSURE(J)\\ 其中I是LR(1)的项目集,X是文法符号。J = { 任何形如 [A→αX·β,a] 的项目 | [A→α·Xβ,a] ∈I}
LR(1)转换函数的构造与LR(0)的相似,GO(I,X)=CLOSURE(J)其中I是LR(1)的项目集,X是文法符号。J=任何形如[A→αX⋅β,a]的项目∣[A→α⋅Xβ,a]∈I
S ′ → S [ 0 ] S → a A d [ 1 ] S → b A c [ 2 ] S → a e c [ 3 ] S → b e d [ 4 ] A → e [ 5 ] S′→S [0]\\ S→aAd [1]\\ S→bAc [2]\\ S→aec [3]\\ S→bed [4]\\ A→e [5] S′→S[0]S→aAd[1]S→bAc[2]S→aec[3]S→bed[4]A→e[5]
2.2、LR(1)分析表的构造
LR(1)分析表的构造与LR(0)分析表的构造大部分相同,对归约项目的归约动作取决于该归约项目的向前搜索符集,只有当面临输入符属于向前搜索符的集合,才做归约动作,其它情况均出错。具体构造过程如下:
若
已
构
造
出
某
文
法
的
L
R
(
1
)
项
目
集
族
C
,
C
∈
I
0
,
I
1
,
…
,
I
n
,
其
中
I
k
的
k
为
分
析
器
的
状
态
,
则
A
C
T
I
O
N
表
和
G
O
T
O
表
构
造
方
法
如
下
:
(
1
)
若
项
目
[
A
→
α
⋅
a
β
,
b
]
∈
I
k
,
且
G
O
(
I
k
,
a
)
=
I
j
,
其
中
a
∈
V
T
,
则
置
A
C
T
I
O
N
[
k
,
a
]
=
S
j
;
(
2
)
若
项
目
[
A
→
α
⋅
,
a
]
∈
I
k
,
则
置
A
C
T
I
O
N
[
k
,
a
]
=
r
j
,
其
中
a
∈
V
T
,
j
为
A
→
α
编
号
;
(
3
)
若
项
目
[
S
′
→
S
⋅
,
井
字
符
]
∈
I
k
,
则
置
A
C
T
I
O
N
[
k
,
井
字
符
]
=
“
a
c
c
”
;
、
、
(
4
)
若
G
O
(
I
k
,
A
)
=
I
j
,
其
中
A
∈
V
N
,
置
G
O
T
O
[
k
,
A
]
=
j
;
(
5
)
凡
不
能
用
上
述
规
则
填
入
的
元
素
,
均
置
“
报
错
标
志
”
,
也
可
以
使
用
空
白
表
示
。
若已构造出某文法的LR(1)项目集族C,C∈{I0,I1,…,In},其中Ik的k为分析器的状态,则ACTION表和GOTO表构造方法如下: \\ (1)若项目[A→α·aβ,b] ∈Ik,且GO(Ik,a)=Ij,其中a∈VT,则置ACTION[k,a]=Sj; \\ (2)若项目[A→α·,a] ∈Ik,则置ACTION[k,a]=rj,其中a∈VT,j为A→α编号; \\ (3)若项目[S′→S· ,井字符]∈Ik,则置 ACTION[k,井字符]=“acc”;、、 (4)若GO(Ik,A)=Ij,其中A∈VN,置 GOTO[k,A]=j;\\ (5)凡不能用上述规则填入的元素,均置“报错标志”,也可以使用空白表示。
若已构造出某文法的LR(1)项目集族C,C∈I0,I1,…,In,其中Ik的k为分析器的状态,则ACTION表和GOTO表构造方法如下:(1)若项目[A→α⋅aβ,b]∈Ik,且GO(Ik,a)=Ij,其中a∈VT,则置ACTION[k,a]=Sj;(2)若项目[A→α⋅,a]∈Ik,则置ACTION[k,a]=rj,其中a∈VT,j为A→α编号;(3)若项目[S′→S⋅,井字符]∈Ik,则置ACTION[k,井字符]=“acc”;、、(4)若GO(Ik,A)=Ij,其中A∈VN,置GOTO[k,A]=j;(5)凡不能用上述规则填入的元素,均置“报错标志”,也可以使用空白表示。
如果一个文法的LR(1)项目集中无移进—归约冲突或归约—归约冲突,则称这个文法为LR(1)文法,所构造的分析表为LR(1)分析表。能使用LR(1)分析表的分析器称为LR(1)分析器或规范的LR分析器。
LR(1)分析法的缺点:在多数情况下,同一个文法的LR(1)项目集的个数比LR(0)项目集的个数多,甚至可能多好几倍,导致存储量的急剧增加,使应用受到一定限制。
一个文法是LR(0)文法一定也是SLR(1)文法,也是LR(1)文法,反之则不一定成立。
3、自底向上分析总结
移进归约分析
核心:在句型中寻找句柄进行归约
控制算法:
- 基于算符优先关系表
- 基于 LR 分析表(动作和状态转移)
各LR分析法的不同点主要在归约动作的选择:
- LR(0) 分析:归约时不用向前搜索,不管哪个终结符或#都归约
- SLR(1) 分析:归约时依据FOLLOW 集和“#”
- LR(1) 分析:归约时仅考虑 LR(1)项目中的后向前搜索符
文法包含关系:
需要pdf文件或md文件的小伙伴可以前往gitee:https://gitee.com/a-chuchu-cat/principles-of-compilation自行获取。