文章目录
1. 对于词法分析器的要求(掌握)
词法分析
- 定义:输入源程序,根据构词规则对构成源程序的字符串进行扫描和分解,识别出一个个单词符号。
- 输入:源程序
- 输出:单词符号(为二元组 : < 种类,属性值 >)
单词符号的种类:
- 基本字:如 begin、do、for
- 标识符:如变量名、数组名,以字母开头的字符串
- 常数:各种类型的常数
- 运算符:如 + - * /
- 界符:如逗号、分号、括号
单词种类通常用整数编码表示
- 若一个种类只有一个单词符号,则种类编码就代表该单词符号。假定基本字、运算符和界符都是一符一种。
- 若一个种类有多个单词符号,则对于每个单词符号,给出种类编码和属性值。
- 标识符单列一种;标识符自身的值表示成按机器字节划分的内部码。(因为难以编码枚举)
- 常数按类型分种;常数的值则表示成标准的二进制形式。(先按整型、浮点型等划分,再按自身值区分)
![](https://i-blog.csdnimg.cn/blog_migrate/4e8b9ee38b92b7ba03934507a0b22a00.png)
- 有的时候还为标识符增加一个符号表项,如下面这个例子:
![](https://i-blog.csdnimg.cn/blog_migrate/157f43e8247ebcbf918068eee1fd0fc4.png)
词法分析器在编译器中地位
- 词法分析是一个独立的阶段,但是不作为一遍,而将其作为一个独立子程序。
- 作为独立阶段的优点:结构简洁、清晰和条理化,有利于集中考虑词法 分析一些枝节问题。
2. 词法分析器的设计(重点)
![](https://i-blog.csdnimg.cn/blog_migrate/adaa7ba07b8b5211400d18414e8d6345.png)
输入、预处理
- 扫描缓冲区
一个缓冲区终究是有限的,末尾很有可能会出现一个单词不能全部进入的情况,导致数据丢失。解决办法是将一个缓冲区拆为两半互补使用(独立刷新),再规定单词长度不得长于半区长度即可。
![](https://i-blog.csdnimg.cn/blog_migrate/43483c9879edb346c6c136505253657e.png)
-
超前搜索
- 基本字识别
不超前搜索无法区别到底是用户定义的标识符还是基本字。
- 标识符识别
字母开头的字母数字串,后跟界符或算符。 - 常数识别
识别出算术常数并将其转变为二进制内码表示。有些也要超前搜索。 - 算符和界符的识别
把多个字符符合而成的算符和界符拼合成一个单一单词符号。也需要超前搜索,比如区别+和++。
- 基本字识别
-
几点限制——不必使用超前搜索
- 所有基本字都是保留字 ,用户不能用它们作自己的标识符。
- 基本字作为特殊的标识符来处理,使用保留字表。
- 如果基本字、标识符和常数 ( 或标号 ) 之间没有 确定的运算符或界符作间隔,则必须使用一个空白符作间隔。
- 如DO99K=1,10 要写成 DO 99 K=1,10
-
状态转换图
- 状态转换图是一张有限方向图。
- 结点代表状态,用圆圈表示。
- 状态之间用箭弧连结,箭弧上的标记 ( 字符 ) 代表射出结状态下 可能出现的输入字符或字符类。
- 一张转换图只包含有限个状态, 其中有一个为初态,至少要有一个终态。
- 状态转换图可用于识别 ( 或接受 ) 一定的字符串。
- 若存在一条从初态到某一终态的道路,且这条路 上所有弧上的标记符连接成的字等于
α
α
α,则称
α
α
α为 该状态转换图所识别 ( 接受 )。
(黑圈星号代表回退最后一个字符这样就能识别一个字母开头的字母数字串。)
- 若存在一条从初态到某一终态的道路,且这条路 上所有弧上的标记符连接成的字等于
α
α
α,则称
α
α
α为 该状态转换图所识别 ( 接受 )。
-
词法分析器设计实例
![](https://i-blog.csdnimg.cn/blog_migrate/48aab6b8be41e02ceaa259006d8fa206.png)
![](https://i-blog.csdnimg.cn/blog_migrate/148ae68d9cfa675f185687677bf43073.png)
![](https://i-blog.csdnimg.cn/blog_migrate/4f7b0b6d5fa01008bb93bb026298a11a.png)
![](https://i-blog.csdnimg.cn/blog_migrate/afcba47ddff07a332b39335045283e94.png)
![](https://i-blog.csdnimg.cn/blog_migrate/a4789a2e22e56e8e82f9c7622eafa58d.png)
![](https://i-blog.csdnimg.cn/blog_migrate/204f46a17f7613d5ef9f7f7eb8e35be7.png)
![](https://i-blog.csdnimg.cn/blog_migrate/204f46a17f7613d5ef9f7f7eb8e35be7.png)
3. 正规表达式与有限自动机
3.1 正规式与正规集(掌握)
正规式和正规集的关系
- 正规集可以用正规表达式(简称正规式)表示。
- 正规式是表示正规集一种方法。
- 一个字集合是正规集当且仅当它能用正规式表示。
正规集和正规式的递归定义
![](https://i-blog.csdnimg.cn/blog_migrate/34d35c2dd861dae33c912eb2a784847d.png)
我的理解
初学这里感觉很抽象,难以理解。后来查阅了一些资料,斗胆做出以下通俗理解(学到以后感觉不对再回来改):
- 程序语言都有一定的词法规则,按照这些词法规则产生的单词符号都是一些特殊的字符串。
- 目前为止我们还没有将程序语言的词法形式化,无法引入自动机。
- 因此,可以搞出一个东西形式化地描述词法规则,即描述了词法规则对应的单词集合。
- 正规式即是词法规则一种形式化描述,对应的单词集合称为正规集。
- 第二章提到的正规文法产生的语言就是正规集。
简单举例
![](https://i-blog.csdnimg.cn/blog_migrate/29b66ae6b7947396bc50b1cb1fb3dd4d.png)
具体点的例子
![](https://i-blog.csdnimg.cn/blog_migrate/b7cd48c7f1629150689cf4450b4d4f48.png)
再具体点的例子
![](https://i-blog.csdnimg.cn/blog_migrate/4720df6c85638c7479c268c07568f699.png)
- 假如上图中右边是某个语言的单词表
- 左上是该语言的正规集,第一行是基本字,第二行是标识符举例,第三行是常数举例,第四行是运算符。
- 左下是该语言的正规式,注意标识符和常数。
几点注意
- ε ε ε 是 Σ Σ Σ 上的一个字,且是正规集{ ε ε ε }的正规式,可识别字 ε ε ε
- ∅ 是一个集合,也是正规式,表示是的正规集是{ ∅ }
- 任何 a ∈ Σ a∈Σ a∈Σ, a a a 既是 Σ Σ Σ 中的字符,又是 Σ Σ Σ 上的字,还是 Σ Σ Σ 上的正规式,表示的正规集是{ a a a }
- 所有词法结构一般都可以用正规式描述
正规式的等价
若两个正规式所表示的正规集相同,则称这两个正规式等价。
![](https://i-blog.csdnimg.cn/blog_migrate/70665938686ea24de4d35a831eabce18.png)
正规式的运算律
![](https://i-blog.csdnimg.cn/blog_migrate/0c718d1e37b5378ed55a208432c33c6b.png)
注意: 运算的优先级为:< ∗ * ∗ >、< ⋅ · ⋅ >、< ∣ | ∣ >。
3.2 确定有限自动机(DFA)(重点)
定义
![](https://i-blog.csdnimg.cn/blog_migrate/abf08cfda2437e7b294bab0ab9bc31de.png)
- 若存在一条从初态到某一终态的道路,且这条路上所有弧上 的标记符连接成的字等于 α α α,则称 α α α 为DFA M所识别 ( 接收 )。
- DFA M 所识别的字的全体记为 L(M)。
例子1
![](https://i-blog.csdnimg.cn/blog_migrate/f5821261b283d6c00ca9f3730f79a0e9.png)
例子2
![](https://i-blog.csdnimg.cn/blog_migrate/50e31302b88e12953920146ae95e5f3a.png)
- 答案是B,带个aab自己想想就明白了。
例子3
![](https://i-blog.csdnimg.cn/blog_migrate/57fe2ca49ce156eec68f7b3d94e54481.png)
- 答案是A, q 0 q_0 q0 既是初态也是终态,空字就可以接收,所以A可以识别包含空字的集合。对于B,它没有终态,所以识别的是空集。这两个是比较特殊的DFA。
3.3 非确定有限自动机(NFA)(重点)
定义
![](https://i-blog.csdnimg.cn/blog_migrate/276b333e2fe5ca89ee683c0429a4c1b3.png)
- 2 S 2^S 2S:S的幂集,即S所有的子集构成的集合。
![](https://i-blog.csdnimg.cn/blog_migrate/1d71f31ea73d8bce30ae6d0b7b8d08ba.png)
- 注意 NFA 中弧上的标记可以是 ε ε ε ,DFA不可以。
- 若存在一条从初态到某一终态的道路,且这条路上所有弧上的标记字连接成的字等于 α α α ( 忽略那些标记为 ε ε ε 的弧 ) ,则称 α α α 为 NFA M 所识别 ( 接收 )。
- NFA M 所识别的字的全体记为 L(M)。
示例
![](https://i-blog.csdnimg.cn/blog_migrate/2e97c8c90c0c68ce04647be87c3950cd.png)
NFA 与 DFA
- 定义:对于任何两个有限自动机 M 和 M’,如果 L(M) = L(M’) ,则称 M 与 M’ 等价。(无论是NFA还是DFA)
- 自动机理论中一个重要的结论:判定两个自动机等价性的算法是存在的。
- 对于每个 NFA M 存在一个 DFA M’ ,使得 L(M) = L(M’)。
- DFA 与 NFA 描述能力相同,NFA更适合人工设计,DFA更适合代码实现。
证明DFA和NFA的等价性
- 正如前文所述,NFA和DFA差距有三点:初态、弧上标记、后继状态,下面对这三个差别分别进行分析。
- 假定 NFA M = <
S
,
Σ
,
δ
,
S
0
,
F
S, Σ, δ, S_0, F
S,Σ,δ,S0,F > ,我们对 M 的状态转换图进行以下改造:
- 引进新的初态结点 X X X 和终态结点 Y Y Y (X,Y ∉ \notin ∈/S),从 X X X 到 S 0 S_0 S0 中任意状态结点连一条 ε ε ε 箭弧, 从 F F F 中任意状态结点连一条 ε ε ε 箭弧到 Y Y Y 。(建立唯一初态和唯一终态)
- 对 M 的状态转换图进一步施行替换,其中 k 是新引入的状态。(正规式、字都转换为字符)
- 到此为止差别一可以完全消除,差别二只剩下 ε ε ε ,差别三还没动,下面引入子集法。
- 把上述 NFA 确定化 — 采用子集法
- 设 I 是状态集的一个子集,定义 I 的
ε
ε
ε - 闭包
ε
−
c
l
o
s
u
r
e
(
I
)
ε - closure(I)
ε−closure(I) 为:
ε − c l o s u r e ( I ) = I ⋃ { S ′ ∣ 从 某 个 S ∈ I 出 发 经 过 任 意 条 ε 弧 能 到 达 S ′ } ε - closure(I) = I \bigcup\{ S'|从某个S\in I出发经过任意条 ε 弧能到达S' \} ε−closure(I)=I⋃{S′∣从某个S∈I出发经过任意条ε弧能到达S′} - 通俗点理解就是把通过 ε ε ε 弧相连的状态包裹起来形成一个整体。
- 再将范围扩大,设 a 是
Σ
Σ
Σ 中的一个字符,设 J 是 I 中的某个状态出发经过一条 a 弧而到达的状态集合。定义:
I a = ε − c l o s u r e ( J ) I_a = ε - closure(J) Ia=ε−closure(J)即 Ia 是 J 的闭包。 - 则 I 和 Ia 的关系是通过 I 中某个字符可以通过一条 a 弧和若干条
ε
ε
ε 到达 Ia。这么做的意义在于现在从 I 和 Ia 之间所描述的有限自动机识别字的能力就是识别一个 a 的能力。
- 举例
- 设 I 是状态集的一个子集,定义 I 的
ε
ε
ε - 闭包
ε
−
c
l
o
s
u
r
e
(
I
)
ε - closure(I)
ε−closure(I) 为:
- 确定化的过程
- X 是第一步中我们建立的唯一初态。
- 在第一列出现过的条件是完全相同,不是包含关系。
- 子集的数目是有限的,所以这张表肯定会停下来。
- 该过程将 NFA 上状态之间识别字符的能力转换为了状态集之间的关系。
- 举例
- 把这张表看成一个状态转换矩阵,把其中的每个子集看成一个状态(原来NFA的状态集)。
- 到此为止就得到和原来的 NFA 等价的 DFA 。
3.5 正规式与有限自动机的等价性(重点)
定理
- 对任何 FA M ,都存在一个正规式 r ,使得 L(r) = L(M) 。
- 对任何正规式 r ,都存在一个 FA M ,使得 L(M) = L(r) 。
- 注意:上式中两个L的意义不同,L(r)是将正规式映射到正规集上面,L(M) 是将自动机映射到字的集合上,等价即这两个集合相等。
证明
-
对 Σ上任一 NFA M ,构造一个 Σ 上的正规
式 r ,使得 L(r) = L(M) 。- 第一步也是建立唯一初态和唯一终态,显然L(M) = L(M’)。
- 第二步和前文中相反,是将字符尽量转换为正规式,最后只剩下 X 和 Y 。如:
- 最后, X 到 Y 的弧上标记的正规式即为所构造的正规式 r,显然L(r) = L(M) = L(M’)。
-
对于 Σ 上的正规式 r,构造一个 NFA M,使 L(M) = L(r) ,并且 M 只有一个终态,而且没有从该终态出发的箭弧。用关于 r 中运算符数目的数学归纳法证明。
- 若 r 具有零个运算符,则 r =
ε
ε
ε 或 r = Ø 或 r = a,其中 a
∈
Σ
\inΣ
∈Σ 。此时下图所示的三个有限自动机显然符合上述要求。
- 假设结论对于少于 k( k
≥
\geq
≥ 1 ) 个运算符的正规式成立。当 r 中含有 k 个运算符时, r 有三种情形:
- 情形1:r = r1 | r2 , r1 和 r2 中运算符个数少于 k。根据假设,有两个自动机 M1、M2 和 r1、r2等价。不妨设 S1 ∩ S2 = Ø,在 S1 ∪ S2 中加入两个新状态 q0,f0 。
- 情形2:r = r1r2, 和 r2 中运算符个数少于 k。和情形1类似:
- 情形3:r = r1*。
- 情形1:r = r1 | r2 , r1 和 r2 中运算符个数少于 k。根据假设,有两个自动机 M1、M2 和 r1、r2等价。不妨设 S1 ∩ S2 = Ø,在 S1 ∪ S2 中加入两个新状态 q0,f0 。
- 上述证明过程实质上是一个将正规表达式转换为有限自动机的算法。
- 首先,把正规式 V 表示成:
- 然后拆分。
- 逐步把这个图转变为每条弧只标记为 Σ 上的一个字符或 Σ,最后得到一个 NFA M’,显然L(M’) = L(V)。
- 首先,把正规式 V 表示成:
- 举例
这样就从正规式得到了NFA,再进行转换可以得到DFA。
- 若 r 具有零个运算符,则 r =
ε
ε
ε 或 r = Ø 或 r = a,其中 a
∈
Σ
\inΣ
∈Σ 。此时下图所示的三个有限自动机显然符合上述要求。
3.6 确定有限自动机的化简(重点)
目标
- 寻找一个状态数比 M 少的 DFA M’ ,使得 L(M) = L(M’)。
状态等价
- 假设 s 和 t 为 M 的两个状态,如果从状态 s 出发能读出某个字 α α α 而停止于终态,那么同样,从 t 出发也能读出 α α α 而停止于终态;反之亦然。( α α α 是任意的)
- 两个状态不等价,则称它们是可区别的。
DFA M 最少化的基本思想
- 把 M 的状态集划分为一些不相交的子集,使得任何两个不同子集的状态是可区别的,而同一子集的任何两个状态是等价的。最后,让每个子集选出一个代表,同时消去其他状态。
化简过程
-
把 S 划分为终态和非终态两个子集,形成基本划分 Π Π Π。
-
Π Π Π 已含 m 个子集,记为 Π Π Π = { I ( 1 ) I^{(1)} I(1), I ( 2 ) I^{(2)} I(2),…, I ( m ) I^{(m)} I(m) },检查 Π Π Π 中的每个子集看是否能进一步划分:
-
对于某个 I ( i ) I^{(i)} I(i),令 I ( 1 ) I^{(1)} I(1) = { s 1 , s 2 , . . . , s k s_1,s_2,...,s_k s1,s2,...,sk },若存在一个输入字符 a 使得 I a ( i ) I_a^{(i)} Ia(i) 不会包含在现行 Π Π Π 的某个子集 I ( j ) I^{(j)} I(j) 中,则至少应把 I ( i ) I^{(i)} I(i) 分为两个部分。(通俗点讲就是 Π Π Π 的一个子集 I I I 经过 a 弧能到达的集合 I a I_a Ia 分布在 Π Π Π 的多个子集中,说明 I I I 需要再分)
证明:
那到底如何划分呢?
(其实这里也不难理解,本来判定需要划分的依据是子集 I I I 经过 a 弧能到达的集合 I a I_a Ia 分布在 Π Π Π 的多个子集中,那么只要把子集 I I I 中的这些状态按照经过 a 弧到达子集划分就行。) -
第三点说的分成两半并不准确,一般地,对某个 a 和 I ( i ) I_{(i)} I(i) ,若 I a ( i ) I_a^{(i)} Ia(i) 落入现行 Π Π Π 中 N 个不同子集,则应把 I ( i ) I^{(i)} I(i) 划分成 N 个不相交的组,使得每个组 J J J 的 J a J_a Ja 都落入的 Π Π Π 同一子集。这样构成新的划分。
-
重复上述过程,直到 Π Π Π 所含子集数不再增长。
-
对于上述最后划分 Π Π Π 中的每个子集,我们选取每个子集 I 中的一个状态代表其他状态,则可得到化简后的 DFA M’。
-
若 I 含有原来的初态,则其代表为新的初态,若 I 含有原来的终态,则其代表为新的终态。
4 词法分析器的自动产生 — LEX(掌握)
LEX的工作流程
- 首先,对每条识别规则 Pi 构造一个相应的非确定有限自动机 Mi ;
- 然后,引进一个新初态 X ,通过
ε
ε
ε 弧,将这些自动机连接成一个新的 NFA ;
- 最后,把 M 确定化、最小化,生成该 DFA 的状态转换表和控制执行程序。
5. 正规文法与有限自动机的等价性(补充)
这里老师没有设置要求。
定理
- 对每一个右线性正规文法 G 或左线性正规文法 G ,都存在一个有限自动机 (FA) M ,使得 L(M) = L(G) 。
- 对每一个 FA M ,都存在一个右线性正规文法 GR 和左线性正规文法 GL ,使得 L(M) = L(GR) = L(GL) 。
最后做个总结: