编译原理冲刺 · 第 04 课 ⏱ 冲刺模式 · ≤1周

DFA 最小化 与 词法分析器

把 DFA 化到最简,并看懂扫描器怎么工作。对应教材第 3 章 3.1、3.2、3.3。
🎯 本课唯一目标
会用分割法把一个 DFA 最小化(状态合并);理解词法分析器用状态转换图识别单词的过程。
为什么学它? 最小化常跟在上一课"构造 DFA"后面一起考,是送分的后半题;词法分析器设计则是第 3 章的简答/概念来源。两个都不难,拿稳。

一、DFA 最小化(分割法)

目标:得到状态数最少、但识别同一语言的等价 DFA。做法是把"行为相同"的状态合并[1]

⚑ 分割法 步骤

① 先删掉不可达状态

② 初始分两组:终态组 F非终态组 (S−F)

③ 细化:检查同一组里的状态,对某输入符 a 转到的目标若落在不同的现有组,就把这一组按"目标所属组"裂开

④ 重复③直到没有组能再分。每个最终组并成一个状态。

二、老师示范一题

例题 最小化下面的 DFA(Σ={0,1},初态 A,终态 {B, D})。
状态01
A(初)CB
B(终)CB
CCD
D(终)CD
① 初始划分:非终态组 G1={A, C},终态组 G2={B, D}。
② 查 G1={A,C}:
A: 0→C(在G1), 1→B(在G2)
C: 0→C(在G1), 1→D(在G2)
两者“0 进 G1、1 进 G2”签名相同 → 不分裂。
③ 查 G2={B,D}:
B: 0→C(G1), 1→B(G2)
D: 0→C(G1), 1→D(G2)
签名相同 → 不分裂。
④ 没有组能再分,最终两组:{A,C}→记作 P,{B,D}→记作 Q。最小化 DFA(2 个状态):
      0     1
P(初) → P   → Q
Q(终) → P   → Q
结论:原 4 状态化简为 2 状态(它识别的正是"以 1 结尾的 0/1 串")。∎
💡 关键动作:每轮都问"这一组里的状态,对每个输入符是不是都进同一个现有组?",不一致就裂开。

三、词法分析器(扫描器)

功能:读入字符流,输出单词 token。token 通常是二元组 (种别码, 属性值)。它还顺带:滤掉空白与注释、查/填符号表、报词法错误[2]

用状态转换图实现:节点是状态、边标字符;读一个字符走一条边,到达终态 = 识别出一个单词

识别"标识符 = 字母(字母|数字)*"的状态转换图
          字母                字母/数字
 (0) ───────────→ (1) ⟲ ───────────┐
 start            终态 ←────────────┘
                   │ 其它字符(退回1个)
                   ↓
              识别出一个标识符
驱动伪代码:
state0: c = getchar();
        if c 是字母 then goto state1 else error;
state1: c = getchar();
        if c 是字母或数字 then goto state1
        else { retract(c);  // 超前搜索:退回一个字符
               返回 (标识符, 词文); }

四、你来做

1. DFA 最小化(分割法)的初始划分是?
2. 词法分析器输出的单词 token 通常是?
3. 词法分析中"超前搜索(并退回字符)"的目的是?
4. 在词法分析的状态转换图里,到达"终态"意味着?
5. 下列哪一项不是词法分析器的任务?
得分:0 / 5
最小化:先分终态/非终态,再"看转向是否同组"反复裂
扫描器:读字符→走状态图→到终态吐单词(必要时超前搜索退回)
📺 主源推荐 哈工大《编译原理》词法分析讲 — 中国大学MOOC[2]
🙋 分割法的"裂开"判断容易绕晕——拿一道你做的题来,我帮你逐轮核对分组。
  1. [1] DFA 最小化(分割法):陈火旺《程序设计语言编译原理》3.3;交叉印证 龙书讲义
  2. [2] 词法分析器功能、状态转换图、超前搜索:陈火旺 3.1–3.2;哈工大 MOOC词法分析讲。