词法分析
一种词法分析器的自动生成过程是 RE - NFA - DFA
正则表达式id
可以使用 RE 定义为
digit -> 0 | 1 | 2 | ... | 9
letter_ -> _ | A | B | ... | Z | a | b | ... | z
id -> letter_ (letter_ | digit)^*
正则表达式通过最长匹配
使用有穷自动机可以判定一个字符串是否被某一正则表达式描述的语法规则接受
-
非确定性有穷自动机
Nondeterministic Finite Automata( NFA, ) -
确定性有穷自动机
Deterministic Finite Automata( DFA, )
它们的区别在于
- 是否允许包含 $\varepsilon-moves$
这是一种特殊的状态转换方式。 表示自动机可以不读入任何输入而将其状态由一个转换到另一个, 允许包含该状态转换方式的有穷自动机称为非确定性有穷自动机 NFA。 。 - 是否允许在状态 s 下
读入字符, 'a'
存在多种状态转换方式, 。
有穷自动机可以用转换图与转换表表示
图中
没有任何修饰的圆圈表示中间状态1
和 2
有一个无源箭头指向的圆圈表示初始/开始状态0
有两个圆圈的状态表示终止/接收状态3
状态之间的箭头表示状态转换
上面的 FA 接收所有以 "ybb"
结尾的'y'
和 'b'
的组合
RE -> NFA
RE -> NFA 的过程的一种方法是 Thompson 算法
- 对基本的 RE 直接构造
$\varepsilon$ 与 $a$: 。 - 对复合 RE 递归构造
$st$: $s|t$ 与 $s^*$, - 这样构造出的 NFA 只有一个终止状态
并且转换图中没有出边, 。
对每种结构的构造法则如下图所示
src:https://rainoftime.github.io/teaching/index.html
NFA -> DFA
NFA 在判断一个串是否被接收的时候需要多种路径试探以及失败回退
一种 NFA -> DFA 的方法是子集构造法
这种方法定义了在 NFA 上的两种操作
操作 | 含义 | 描述 |
---|---|---|
$\varepsilon-closure(s)$ | NFA 状态 $s$ 的 $\varepsilon$-闭包 | $s$ 经过 $\varepsilon$ 转换能够到达的所有状态的集合 |
$\varepsilon-closure(T)$ | $\bigcup_{s \in T} [\varepsilon-closure(s)]$ | $T$ 中所有状态的$\varepsilon$-闭包之并集 |
子集构造法按以下过程运行
- NFA 的初始状态的 $\varepsilon-closure$ 对应于 DFA 的初始状态
。 - 针对已有的 DFA 的每一个状态所对应的 NFA 状态子集 $A$
求输入每一个 $a_i$ 后能够到达的 NFA 状态的 $\varepsilon-closure$ 之并集, $\varepsilon-closure(move(A, a_i))$: 这个并集要么对应于 DFA 中的一个已有状态。 要么是 DFA 中将要新加入的状态, 。 - 迭代第二步
构造 DFA 的状态转换表, 直至不动点, 。
整个过程如下图所示
src:https://rainoftime.github.io/teaching/index.html
DFA 的简化
一个 RE 可以对应多个识别此 RE 对应的正则语言的 DFA
用等价类划分的方法可以化简任何一个给定的 DFA
这个等价类划分是指根据可区分的状态
如果存在串 x
s
与 状态 t
出发x
区分了状态 s
与 状态 t
由此出发
- 一致性条件
状态: s
与 状态t
同时为终态或非终态。 - 蔓延性条件
对于所有的输入: 状态, s
与 状态t
必须能够转换到等价的状态集中 同时具有传递性, 。
DFA 等价算法根据上面的条件迭代地划分等价类
初始划分为接收状态组与非接收状态组