编译原理

ch17-LR(1)-LR(1) 语法分析器

编译原理
目录

# ch17-LR(1)-LR(1) 语法分析器

# SLR(1)

# 文法FOLLOW(E)

SLR(1) 分析表

  • 算一下FOLLOW(A)后面能跟哪些终结符,这些终结符所对应的单元格才填规约,其他的都不规约

# 分析表和两种冲突

# 非 SLR(1) 文法举例

指针文法

  • 看到=,先移入,=也属于follow®,所以也要规约,所以冲突

  • 即使考虑了= ∈ Follow®, 对该文法来说仍然不够

  • 因为, 这仅仅说明 = 可能跟在 R 后面, 是一种 “粗糙” 的估计

实际上, 该文法没有以 R = · · · 开头的最右句型

  • FIRST(γ)肯定包含在FOLLOW(A)中,所以缩小了范围

  • 规约的时候的依据
  • 是怎么来的,follow(A)
  • 来的时候谁跟在后面,first(γ)

# LR(1)

核心是看a怎么计算

每一个项,都要计算 , 后面的部分

  • 求闭包closure
  • 从一个状态goto到另一个状态

  • β有可能是空,所以FIRST(βa) != FIRST(a)
  • 这是唯一区别

  • 增广的文法,期望输入以S开头,$结束

# 实例演示

  • 先算FIRST和FOLLOW

# 构造规则:

  • 可能的句柄能不能规约只看是不是a,只在a这个位置上规约他
  • a可能是集合,比如之前例子里的c/d,那么只在c和d那两个终结符的单元格里规约他

Definition (LR(1) 文法)

如果文法 G 的LR(1) 分析表是无冲突的, 则 G 是 LR(1) 文法

对应的正则表达式:L(G) = c ∗ dc∗ d

输入ccdcd$过程:

  • 移入0$
  • 移入c3
  • 移入c3
  • 看到d,d4
  • 看到c,弹出d,状态3,加入C,状态8
  • 看到c,规约,弹出c,C,状态0,压入C,状态2
  • 看到c,状态6
  • 看到d,状态7
  • 看到$,弹出d,状态6,移入C,状态9
  • 看到$,弹出C,c,状态,2,移入C,状态5
  • 看到$,弹出CC,状态0,移入S,状态1

LR(1) 虽然强大, 但是生成的 LR(1) 分析表可能过大, 状态过多

LALR(1) : 合并具有相同核心 LR(0)项的状态 (忽略不同的向前看符号)

  • 但是合并完并不是完全的LR(0),比如例子里的0125状态都比LR(0)有更多的信息

  • 36状态合并,出边都是相同的C,c,d( LR(0)相同,决定了出边相同)

  • 47合并状态也是一样的,36通过d去往47,同理89状态也可以合并

  • 合并时先选没有出边的状态

LALR(1)能力比LR(1)弱,但事实上很多语言的实现都是LALR(1)

# 关于冲突的证明

  • 不可能同时包含下面的两个状态,因为A表示规约,B表示移入
  • 还有一段没听懂(

Q: 但是你却通过 LR(1) 自动机构造 LALR(1) 项集族?

第 4.7.5 节 (本科教学版): 高效构造 LALR(1) 语法分析表的方法

与直觉上认知矛盾