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

SLR(1)

文法FOLLOW(E)

image-20230623144436433

SLR(1) 分析表

image-20230623144505895

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

分析表和两种冲突

image-20230623162238320

非 SLR(1) 文法举例

指针文法

image-20230623162311620

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

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

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

image-20230623162747639

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

image-20230623163057551

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

image-20230623164005201

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

LR(1)

image-20230623164317410

核心是看a怎么计算

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

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

image-20230623164938536

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

image-20230623165244815

image-20230623165301238

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

实例演示

image-20230623165522966

  • 先算FIRST和FOLLOW

构造规则:

image-20230623165538722

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

Definition (LR(1) 文法)

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

image-20230623171716722

对应的正则表达式: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

image-20230623171816213

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

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

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

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

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

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

image-20230623172636378

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

关于冲突的证明

image-20230623172840842

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

image-20230623173217112

image-20230623173404935

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

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

image-20230623175153629

与直觉上认知矛盾

image-20230623195442549

image-20230623195453068

image-20230623195500871

image-20230623195510420