LALR(1) 分析
LALR(1)(Look-Ahead LR)通过合并 LR(1) 的同心项目集来压缩状态数。
同心项目集
同心项目集:LR(0) 部分相同、仅搜索符不同的 LR(1) 项目集。
示例:
和 同心(LR(0) 部分相同),可合并为:
GO 函数合并
合并后 GO 函数也相应合并:若 、 且 、 也同心,则 。
合并的性质
不引入移进-规约冲突
若合并前无移进-规约冲突,合并后也不会引入(反证法证明)。
证明思路:若合并后某状态对输入 有移进-规约冲突,则合并前至少有一个同心项目集对 有冲突,与前提矛盾。
可能引入规约-规约冲突
合并可能将不同搜索符合并,导致同一状态下多个规约项目共享搜索符,产生规约-规约冲突。
重点 LALR(1) 合并不引入移进-规约冲突,但可能引入规约-规约冲突。
LALR(1) 错误延迟
相比 LR(1),LALR(1) 合并后可能延迟发现错误:在错误状态下多执行若干步规约后才报告错误,但不会漏报。
LALR(1) 完整示例
文法 :
LR(1) 项目集规范族(共 9 个状态 ):
| 状态 | 内容 |
|---|---|
| [S' \to ·S, \], [S \to ·L=R, $], [S \to ·R, $], [L \to ·*R, =/$], [L \to ·I, =/$], [R \to ·L, $]$ | |
| [S' \to S·, \]$ | |
| [S \to L·=R, \], [R \to L·, $]$ | |
| [S \to R·, \]$ | |
| [L \to *·R, =/\], [R \to ·L, =/$], [L \to ·*R, =/$], [L \to ·I, =/$]$ | |
| [L \to I·, =/\]$ | |
| [S \to L=·R, \], [R \to ·L, $], [L \to ·*R, $], [L \to ·I, $]$ | |
| [L \to *R·, =/\]$ | |
| [R \to L·, \]$ |
同心项目集: 和 (LR(0) 部分相同,仅搜索符不同 =/\$$ vs $$),可合并。
合并后 LALR(1) 将 9 状态压缩为 8 状态( 与 合并),分析表也相应合并。
四种方法选择流程
LR(0) → 有冲突?
├── 无冲突 → LR(0) 文法 ✓
└── 有冲突 → 尝试 SLR(1)
├── 无冲突 → SLR(1) 文法 ✓
└── 有冲突 → 尝试 LR(1)
├── 无冲突 → 尝试 LALR(1) 合并
│ ├── 无冲突 → LALR(1) 文法 ✓
│ └── 有冲突 → LR(1) 文法 ✓
└── 有冲突 → 文法不是 LR 文法 ✗- LR(0):能力最弱,冲突最多
- SLR(1):用 FOLLOW 集部分解决冲突
- LR(1):能力最强,但状态数最多
- LALR(1):接近 LR(1) 能力,状态数接近 SLR(1)
⚠️ LR 分析环环相扣,前步错后步全错。