自顶向下语法分析

1186 字
6 分钟
自顶向下语法分析
Warning

含AI生成内容

第四章 自顶向下语法分析 · 知识点详解#

🔴 核心(必背/必算) 🟡 理解(会说清) 🟢 了解(有印象) 本章性质:计算大题(约 20 分),改文法 + 判 LL(1) + 预测分析。


一、语法分析概述(🟡 理解)#

  • 任务:检查扫描器输出的单词序列是否是该文法的句子。
    • 输入:单词符号序列;输出:分析树;出错时定位并续编译。
  • 两大类方法
    • 自顶向下:确定的(递归下降法、预测分析法)、不确定的(带回溯)。
    • 自底向上:算符优先、LR 分析(LR(0)、SLR(1)、LR(1)、LALR(1))。
  • LL 文法用递归下降/预测分析、多用于手工实现;LR 文法用 LR 分析、多用于自动生成

自顶向下基本思想#

面向目标,寻找输入串的最左推导:从开始符(根)出发,按最左推导顺序,试图根据当前输入单词选择产生式,逐步构造分析树。


二、FIRST / FOLLOW / SELECT 集(🔴 核心)#

FIRST(α)——首符号集#

FIRST(α) = { a | α ⇒* aβ, a∈V_T },若 α⇒*ε 则 ε∈FIRST(α)。

计算规则

  1. X∈V_T:FIRST(X)={X}。
  2. X→a…(a∈V_T):a∈FIRST(X)。
  3. X→ε:ε∈FIRST(X)。
  4. X→Y₁Y₂…Yₙ
    • 把 FIRST(Y₁)−{ε} 加入 FIRST(X);
    • 若 Y₁⇒*ε,再加 FIRST(Y₂)−{ε};依次类推;
    • 若 Y₁…Yₙ 全部能⇒ε,则把 ε 也加入 FIRST(X)。
  5. 反复迭代直到所有 FIRST 集不再变化。

FOLLOW(A)——后继符号集#

FOLLOW(A) = { a | S ⇒* …Aa…, a∈V_T };若 S⇒*…A,则 #∈FOLLOW(A)。

计算规则(对所有出现在右部的非终结符反复迭代):

  1. #∈FOLLOW(S)(S 为开始符,# 为结束符)。
  2. A→αBβ 且 β 不能⇒ε:FOLLOW(B) ⊇ FIRST(β)
  3. A→αBFOLLOW(B) ⊇ FOLLOW(A)
  4. A→αBβ 且 β⇒*ε:FOLLOW(B) ⊇ (FIRST(β)−{ε}) ∪ FOLLOW(A)

注意:FOLLOW 集中永远不含 ε(要么是终结符,要么是 #)。

SELECT(A→α)——选择集#

  • α 不能⇒ε:SELECT(A→α) = FIRST(α)
  • α ⇒*ε:SELECT(A→α) = (FIRST(α)−{ε}) ∪ FOLLOW(A)

三、LL(1) 文法(🔴 核心)#

含义#

  • 第一个 L:从左到右扫描输入串。
  • 第二个 L:生成最左推导
  • 1:向前看 1 个符号即可确定用哪个产生式。

判定充要条件#

对每个非终结符 A 的任意两个不同候选式 A→α | βSELECT(A→α) ∩ SELECT(A→β) = ∅(且 α、β 不能同时⇒ε)。

判别步骤#

  1. 列出各非终结符能否⇒ε。
  2. 计算 FIRST、FOLLOW 集。
  3. 计算各规则 SELECT 集。
  4. 检查同一左部各规则的 SELECT 集是否两两不相交——全不相交则为 LL(1) 文法。

🧮 判定例(表达式文法 G[E] 是 LL(1))#

E→TE' E'→+TE'|ε T→FT' T'→*FT'|ε F→(E)|i
  • SELECT(E’→+TE’)={+},SELECT(E’→ε)={#,)},交集=∅ ✓
  • SELECT(T’→FT’)={},SELECT(T’→ε)={+,#,)},交集=∅ ✓
  • SELECT(F→(E))={(},SELECT(F→i)={i},交集=∅ ✓
  • G[E] 是 LL(1) 文法

四、非 LL(1) → LL(1) 的改造(🔴 核心)#

1. 消除左递归#

直接左递归 A→Aα|β

A → βA'
A' → αA'|ε

一般式 A→Aα₁|…|Aαₙ|β₁|…|βₘ

A → β₁A'|…|βₘA'
A' → α₁A'|…|αₙA'|ε

间接左递归:先按非终结符排序,用代入法把间接左递归化成直接左递归,再消除,最后删除多余产生式

例:S→Qc|c, Q→Rb|b, R→Sa|a,按 S,Q,R 排序,代入得 R→Rbca|bca|ca|a,消直接左递归得 R→bcaM|caM|aM, M→bcaM|ε

2. 提取左公共因子#

A→αβ|αγ

A → αA'
A' → β|γ

一般式 A→αβ₁|…|αβₙ|γ₁|…|γₘ

A → αA'|γ₁|…|γₘ
A' → β₁|…|βₙ

提取后可能出现不可达的多余产生式,必须删除


五、预测分析法(🔴 核心)#

预测分析器三部分#

  1. 预测分析表(矩阵) M[A,a]
  2. 先进后出栈(分析栈,存语法符号)
  3. 预测分析程序(总控)

构造预测分析表 M[A,a]#

对产生式 A→α,凡 a∈SELECT(A→α),就把 →α 填入 M[A,a]。所有空格填 error

表达式文法 G[E] 的预测分析表

i+*()#
E→TE’→TE’
E’→+TE’→ε→ε
T→FT’→FT’
T’→ε→*FT’→ε→ε
F→i→(E)

预测分析算法#

初始化:#、S 进栈(# 在底,S 在顶)
do {
X = 栈顶符号;a = 当前输入符号;
if (X∈V_T ∪ {#}) {
if (X==a) { 若 X≠#,弹栈并前移输入指针; }
else error();
} else { // X 是非终结符
if (M[X,a]==Y₁Y₂…Yₖ) { 弹出 X; 把 Yₖ…Y₂Y₁ 逆序压栈; }
else error();
}
} while (X≠#)

🧮 分析 i+i*i# 过程(片段)#

分析栈剩余输入所用规则
1#Ei+i*i#E→TE’
2#E’Ti+i*i#T→FT’
3#E’T’Fi+i*i#F→i
4#E’T’ii+i*i#匹配 i
17##成功接受

⚠️ 易错点汇总#

  • α⇒*ε 时 SELECT 一定要并上 FOLLOW(A),别只写 FIRST。
  • FOLLOW 集不含 ε(只含终结符和 #)。
  • 消左递归 / 提公因子后常出现不可达(多余)产生式,必须删除
  • 递归下降要求文法必须是 LL(1);直接左递归会导致死循环
  • 预测分析压栈要逆序(右部最左符号最后压,处于栈顶)。

📝 常考题型#

  1. 改写文法使其适合自顶向下(消左递归 + 提公因子)。
  2. 判断改写后是否 LL(1)(写依据:SELECT 交集为空)。
  3. 构造预测分析表。
  4. 对输入串(如 i+i*i#)写出预测分析过程。

🟢 了解#

  • 递归下降法:为每个非终结符写一个递归子程序;用 EBNF({α}=α*[α] 可选)画语法图后实现。优点直观易扩充;缺点效率低、要求 LL(1)、难自动生成。
  • 引起回溯的三个原因:右部 FIRST 相交、能推空且 FOLLOW 与其他右部 FIRST 相交、含左递归。

文章分享

如果这篇文章对你有帮助,欢迎分享给更多人!

自顶向下语法分析
https://lingluoa.icu/posts/编译原理/知识点-第4章-自顶向下语法分析/
作者
lingluoa
发布于
2026-07-04
许可协议
CC BY-NC-SA 4.0

评论区

Profile Image of the Author
lingluoa
Hello, I'm lingluoa.
公告
欢迎来到我的博客!不定期更新中。
文章目录
标签
站点统计
文章
53
分类
9
标签
75
总字数
175,771
运行时长
0
最后活动
0 天前
站点信息
构建平台
ESA Pages
博客版本
Firefly v6.15.6
文章许可
CC BY-NC-SA 4.0