四、自动机理论与词法分析器生成器

自动机-Automation/Automata

两大要素:状态集S 和 状态转移函数δ\delta

元胞自动机-Cellular Automation/CA

根据表达/计算能力的强弱,自动机可以分为不同的层次

compilers-04-01

目标

正则表达式RE => 词法分析器

compilers-04-01

非自动性有穷自动机-NFA/Nondeteministic Finite Automaton

AA是一个五元组 A=(Σ,S,s0,δ,F)A = (\Sigma , S, s_{0},\delta,F):

1.字母表Σ\Sigma(ϵΣ)(\epsilon \notin \Sigma)

2.有穷的状态集合SS

3.唯一的初始状态s0Ss_{0} \in S

4.状态转移函数$ \delta $

δ:S×(Σ{ϵ})2S\delta : S \times (\Sigma \cup \lbrace \epsilon \rbrace) \to 2^S

5.接受状态集合FSF \subseteq S

约定:所有没有对应出边的字符默认指向一个不存在的空状态\varnothing

compilers-04-01

(非确定性)有穷自动机是一类极其简单的计算装置

它可以识别(接受/拒绝)$\Sigma $上的字符串

Definition(Accept)()Axs0fF,xDefinition(接受-Accept) \\\\ (非确定性)有穷自动机A接受字符串x,当且仅当存在一条从开始状态s_{0}到某个状态 f \in F ,标号为x的路径

因此, AA 定义了一种语言 L(A)L(A): 它能接受的所有字符串构成的集合

Example

compilers-04-01

自动机的两个基本问题

Membership问题

给定x,xL(A)x \in L(A)?

L(A)L(A)究竟是什么

确定性有穷自动机-DFA /Deterministic Finite Automaton

Definition

确定性有穷自动机AA是一个五元组A=(Σ,S,s0,δ,F)A=(\Sigma ,S, s_{0}, \delta ,F)

1.字母表Σ\Sigma(ϵΣ)(\epsilon \notin \Sigma)

2.有穷的状态集合SS

3.唯一的初始状态s0Ss_{0} \in S

4.状态转移函数$ \delta $

δ:S×ΣS\delta : S \times \Sigma \to S

5.接受状态集合FSF \subseteq S

约定:所有没有对应出边的字符默认指向一个死状态

NFA与DFA

NFA 简洁易于理解, 便于描述语言L(A)L(A)

DFA 易于判断 xL(A)x \in L(A), 适合产生词法分析器

用 NFA 描述语言, 用 DFA 实现词法分析器

RENFADFARE \to NFA \to DFA \to 词法分析器

compilers-04-01

RE到NFA:Thompson构造法

Thompson构造法的基本思想

Definition

给定字母表Σ\Sigma,$ \Sigma$上的正则表达式有且仅有以下规则定义:

1.$ \epsilon $是正则表达式

2.aΣ\forall a \in \Sigma,aa是正则表达式

3.如果ss是正则表达式,则(s)(s)是正则表达式

4.如果sstt是正则表达式,则st,st,ss \mid t, st, s^*也是正则表达式

N(r)N(r)的性质以及Thompson构造法复杂度分析

1.N(r)N( r)的开始状态与接受状态均唯一

2.开始状态没有入边,接受状态没有出边

3.N(r)N(r)的状态数S2×r\mid S \mid \leq 2 \times \mid r \mid($ \mid r \mid $:r中运算符与运算分量的总和)

4.每个状态最多有两个ϵ\epsilon -入边与两个出边ϵ\epsilon -

出边

5.$\forall a \in \Sigma $,每个状态最多有一个a-入边与一个a-出边

Kleene构造法

compilers-04-01

从NFA到DFA的转换:子集构造法(Subset/Powerset Construction)

思想:用DFA模拟NFA

compilers-04-01

从状态ss开始,只通过ϵ\epsilon-转移可达的状态集合

ϵclosure(s)={tSNsϵt}ϵclosure(T)=sTϵclosure(s)move(T,a)=sTδ(s,a)\epsilon -closure(s) = \lbrace t \in S_{N} \mid s \stackrel{\mathrm{\epsilon^*}}{\to} t \rbrace \\\\ \epsilon-closure(T) = \underset{s \in T}{\bigcup} \epsilon-closure(s) \\\\ move(T,a)=\underset{s \in T}{\bigcup} \delta(s,a)

子集构造法(ND)(N \to D)的原理

N:(ΣN,SN,n0,δN,FN)D:(ΣD,SD,d0,δD,FD)ΣD=ΣNSD2SN(sDSD:sDSN):d0=ϵclosure(n0)aΣD:δD(sD,a)=ϵclosure(move(sD,a)):FD={sDSDfFN.fSD}N:(\Sigma_{N},S_{N},n_{0},\delta_{N},F_{N}) \\\\ D:(\Sigma_{D},S_{D},d_{0},\delta_{D},F_{D}) \\\\ \Sigma_{D} = \Sigma_{N} \\\\ S_{D} \subseteq 2^{S_{N}} (\forall s_{D} \in S_{D}:s_{D} \subseteq S_{N}) \\\\ 初始状态:d_0 = \epsilon-closure(n_0) \\\\ 转移函数: \forall a \in \Sigma_{D}: \delta_{D}(s_{D},a) = \epsilon - closure(move(s_D,a)) \\\\ 接受状态集:F_{\mathcal{D}} = \lbrace s_{D} \in S_{\mathcal{D}} \mid \exists \mathcal{f} \in F_N . \mathcal{f} \in S_D \rbrace

闭包(closure):fclosure(T)\mathcal{f} - closure(T)

ϵclosure(T)Tf(T)f((T))...\epsilon-closure(T) \\\\ T \to f(T)\to f((T)) \to ...

直到找到x使得f(x) = x(x称为f的不动点)

DFA最小化

compilers-04-01

Example

compilers-04-01

DFA最小化算法基本思想:等价的状态可以合并

如何定义等价状态

staΣ.((sas)(tat))(s=t)s \sim t \Leftrightarrow \forall a \in \Sigma.((s \stackrel{\mathrm{a}}{\to} s')\wedge (t\stackrel{\mathrm{a}}{\to} t')) \Rightarrow (s'= t')

但是这个定义是错误的

compilers-04-01

但是接受状态与非接受状态必定不等价,空串$\epsilon $区分了这两类状态