编译原理课程总结--第三章:词法分析

对于词法分析的任务就是从左至右逐个字符的对源程序进行扫描,产生一个个的单词符号,把作为字符串的源程序改造成为由单词符号串组成的程序,执行这个程序的就叫做词法分析器
所以词法分析器从功能上看就是输入源程序得到单词符号
源程序就是我们编写的程序,这里的单词符号指的是一个程序语言的基本语法符号,一般包括关键字、标识符、常数、运算符、界符五种。
而词法分析器输出的单词符号的形式常常用二元式来表示如: <单词种别,单词符号的属性值>
【单词种别: 通常用整数编码来表示;

注意:
(1)若一个种别只包含一个单词符号(一种一字),对于该单词符号,种别编码就可以代表它自身了。例如:关键字,运算符,界符
(2)若一个种别包含有多个单词符号(一种多字),对于该种别的每个单词符号,除了给出种别编码,还需给出单词符号的属性值
例如:整型常数,实型常数,布尔常数,标识符

单词符号的属性:指单词符号的特性或特征
单词符号的属性值:反映单词特性或特征的值

举例说明如下:

1)基本字,运算符,界符(一字一种)只给其种别编码,不给出它的属性值
   例:基本字while表示成: <$WHILE, - > 
(2)常数
  表示成标准的二进制形式
 例:1024表示成:<$CONST, 1024的二进制表示> 
(3)标识符
用字符串编码或对应的符号表项地址
例:name表示成:<$ID,“name”>
        或<$ID, 指向name的符号表项的指针>

然后关于词法分析器的设计,首先看到词法分析器的结构:
编译原理课程总结--第三章:词法分析_第1张图片

  1. 输入缓冲区、预处理子程序
    (1)输入源程序文本,放入输入缓冲区中,词法分析工作可在这个输入缓冲区中工作
    (2)剔除无用的空白,跳格(TAB),回车,换行等编辑性字符;若空白符号为单词符号的界符,就将若干空白和并为1个
    (3)剔除注释行,比如//
    (4)源程序的出错列表打印
    (5)将预处理好的子程序放到扫描缓冲区中

2、2.扫描缓冲区、扫描器
(1)扫描缓冲区 设两个半区,可互补使用(因为不论扫描缓冲区设得多大都不能保证单词符号不会被它的边界所打断,因此使用一分为二的区域)
这里写图片描述
设两个指针
起点指针:指出正在识别单词起点位置
搜索指针:向前搜索以寻找单词终点
(2)扫描器:扫描缓冲区,直接进行单词的识别

在识别单词的具体中主要有三种方法 超前搜索、直接分析法、状态转换图
(1)超前搜索
在单词识别的过程中,通过向前多读几个符号的形式,准确的进行单词的识别
一旦确定识别到的单词之后,需要进行扫描指针的回退,保证单词识别工作的顺利进行
(2)直接分析法
根据读来的第一个字符的种类分别转到各种子程序处理。这些子程序功能就是识别以相应字符开头的各种单词。
(分析流程图)
编译原理课程总结--第三章:词法分析_第2张图片

(3)状态转换图
1. 它是一张有限方向图;
2. 功能:识别(或接受)一定的符号串(单词)

状态转换图的结构
①结点:代表状态,用圆圈表示
②箭弧:状态之间用箭弧连接
③箭弧上的标记:代表在射出节点下可能出现的字符或字符串
例:
编译原理课程总结--第三章:词法分析_第3张图片
注意:一个完整的状态转换图有n个状态,其中有一个初态,至少要有一个终态(用双圆圈表示)

正规表达式与有限状态自动机

首先知道正规式与正规集的概念
因为词法分析器需要识别语言中具有不同特征的字 例如: 识别“标识符”、识别“数” ,等等。
我们可以把具有相同特征的字放在一起组成一个集合,即所谓的正规集
然后使用一种形式化的方法来表示正规集,即所谓的正规式

注意:
正规式是描述单词结构的一种形式;
正规集是该类单词的全集。

正规式与正规集的定义(递归的定义方法) (1)ε和φ是∑上的正规式,它们所表示的正规集分别为{ε}和φ
(2)任何a∈∑,是∑上的一个正规式,他所表示的正规集为{ a }
(3)假定U和V都是∑上的正规式,他们所表示的正规集分别记为L(U)和L(V),那么 (a)
(U|V)是正规式,所表示的正规集为L(U)∪L(V) (b) (UV)是正规式,所表示的正规集为L(U) · L(V)(连接积)
(c) (U)是正规式,所表示的正规集为 (L(U))(闭包)
仅由有限次使用(1)(2)(3)所得到的表达式才是∑上的正规式,仅由这些正规式所表示的字集才是∑上的正规集。 注:|(或)、
·(连接)、*(闭包,任意有限次的自重复连接)
运算的优先级为:“ * ” > “ · ” > “ | ”

编译原理课程总结--第三章:词法分析_第4张图片

关于正规式还有

正规式的等价:若两个正规式U和V所表示的正规集相同,则认为二者等价,记为: U = V

正规式的性质:
设U,V,W是上的∑正规式,则
(1) U | V = V | U 或的交换律
(2) U | ( V|W ) = ( U|V ) | W 或的结合律
(3) U ( VW ) = ( UV ) W 连接积的结合律
(4) U ( V | W ) = ( UV ) | ( UW ) 分配律
( V | W ) U = VU | WU
(5) εU = Uε = U

将状态转换图再形式化一下及所谓的有限自动机
有两种:
确定的有限自动机(DFA) (Deterministic Finite Automata)
非确定的有限自动机(NFA) (Non-deterministic Finite Automata)

确定的有限自动机(DFA)

1.定义:一个确定有限自动机(DFA)M是一个五元式:
M = (S, ∑, f, s0, F),其中
(1)S是一个有限的状态集合,它的每个元素我们称为一个状态
(2)∑是一个有穷的输入符号的字母表,它的每个元素我们称为一个输入字符
(3)f是从 S×∑ →S的单值部分映射
(4)s0是S的一个元素,为初始状态,它是唯一的
(5)状态集合F是终止状态的集合,它是S的子集(可空)

 注意:
(1)所谓的自动机不是指一台实际的机器,而是一种数学模型(集合,函数,序列…),利用它模拟计算机识别的功能
(2)所谓确定性是指,f(s, a) = s’ 是单值函数。 对任何状态s∈S,和输入符号 a∈∑ , f(s, a) 唯一的确定下一个状态
(3)所谓有限性是指,S是一个有限的状态集合,并且∑是一个有限的输入符号的字母表
(4)用上述5条,来定义一个DFA,来完成识别一个序列是否被机器所接受

编译原理课程总结--第三章:词法分析_第5张图片

对于DFA 的表示方法有
(1)状态转换矩阵表示法(用一个“表”来表示)
设矩阵的行表示状态,列表示输入字符,矩阵元素是
f(s,a)的值
(2)用状态转换图来表示

DFA M的识别功能
对于∑*中任何字α,如果存在一条从初态结点到某个终态结点的道路,这条路上所有的标识符连成的字等于α ,则α可被DFA M所识别(接受,读出)

注意:
(1)若M的初态结点同时又是终态节点,则空字可被M识别
(2)DFA M所能识别的字的全体记为L(M)
(3)如果一个DFA M的输入字母表为∑,则我们称M是∑上的一个DFA
(4)若V是∑上的一个正规集,当且仅当存在一个∑上的DFA M,使得V = L(M)

非确定的有限自动机(NFA)
1.定义:一个非确定有限自动机(NFA)M是一个五元式
M = (S, ∑, f, S0, F),其中
(1)S是一个有限的状态集合,它的每个元素我们称为一个状态
(2)∑是一个有限的输入符号的字母表,它的每个元素我们称为一个输入字符
(3)f是从S×∑*→2S 的部分映射,其中,2S表示S的幂集合(所有S的子集组成的集合)
(f是非单值的->M是非确定)
(4)状态集合S0是初始状态集合,它是S的子集
(5)状态集合F是终止状态的集合,它是S的子集

对于NFA 的表示方法与DFA相同
(1)状态转换矩阵表示法
(2)用状态转换图来表示

关于有限自动机的等价即对任何两个有限的自动机M1和M2,若有L(M1)=L(M2),则称M1与M2等价。

 **注:**  (1) 若M的某些结点既是初态结点又是终态结点,或者存在一条从某初态结点到某个终态结点的ε通路,那么空字ε可为M所识别
(2) DFA是NFA的一个特例,对于每个NFA M存在一个DFA M’使得L(M) = L(M’),也就是说M和M’是等价的

正规式与有限自动机的等价性

(看 ppt 中的例题参考!!)

定理1:

对于任何∑上NFA M都可构造一个∑上的正规式V,使得 L(V) = L(M) 。
L(M)是∑上NFA M所能识别的字的全体;L(V)是∑上的正规集

问题:如何由一个NFA M,构造一个正规式V
方法:
(1)在M转换图上加进X结点和Y结点,从X结点用弧ε连接M的所有初态结点,M的所有终态结点用弧ε连接到Y,得到一个NFA M’,且L(M) = L(M’)
(2)使用替换规则逐步消去M’的所有结点,直到只剩下X结点和Y结点,在消去过程中,逐步使用正规式来标记箭弧

编译原理课程总结--第三章:词法分析_第6张图片

定理2:

对于∑上的每一个正规式V,存在一个∑上的DFA M,使得L(M) = L(V)

 问题:如何由一个正规式V,构造一个DFA M
 思路:分两步走
1.根据V,构造一个NFA M’,使得L(M’) = L(V)
2.将M’确定化,变为DFA M (子集法)
两个定义

定义1:
(a)若q∈I,则q∈ε_CLOSURE(I)
(b)若q∈I,那么从q出发经任意条ε弧而能到达的任何状态q’都属于ε_CLOSURE(I) ;


定义2:假定I是M’的状态集的子集,a ∈ ∑,定义 Ia =ε_CLOSURE(J)
其中,J是所有那些可从I中的某一状态结点出发经过一条a弧而到达的状态结点的全体

解释:根据定义
2、求Ia
(1)可以分为两步:
(2) 求J的ε闭包ε_CLOSURE(J),即是Ia

确定有限自动机的化简(最少化)

(ppt 例题看)

化简的概念 :寻找一个状态比DFA M少的DFA M’,使得 L(M’) = L(M)
也就是要保证化简后的状态与之前的等价
那么对于两个状态等价的概念

   设s和t是M两个不同的状态,从s出发能读出某个字而停于终态,那么同样,从t出发也能读出同一个字而停在终态,反之亦可


两个状态是可区别的
若DFA M的两个状态s和t不等价,则称这两个状态是可区别的

注:终态和非终态是可区别的,因为终态可以读出空字ε,而非终态不能读出空字ε

化简DFA的一般步骤
(1) 检查状态转换函数是否为全函数。
所谓全函数,是指每个状态对每个输入符号都有转换
若不是全函数,可以引入一个“死状态”d,d对所有输入符号都转换到d,如果状态s对输入符号a没有转换,那么加上从s到d的a转换。
(2) 用化简算法进行化简
(3) 去掉死状态

第二步中的化简算法
(1) 基本思想
把M的状态集分割为一些不相交的子集,使得任何不同的两个子集状态都是可区别的,而同一个子集中的任何状态都是等价的,最后让每个子集选一个代表,同时消去其他等价状态
(2) 化简算法
①对M的状态集S进行划分:
把S的终态和非终态分开,分成终态集合非终态集,形成基本分划П,显然这两个子集是可区别的。
②假定到某个时候П含有m个子集,
记П={I(1),I(2),… I(m)}
并且,属于不同子集的状态是可区别的。
检查П中的每个I(i)看能否进一步划分:
对于某个I(i)
另I(i)={q1 ,q2 ,…,qk}
若存在一个输入字符a使得I(i)a不全包含在现行П的某个子集I(j)中,就将I(i)一分为二

[例如,假定状态s1和s2经a弧分别到达状态t1和t2,而t1和t2属于现行П的两个不同的子集,那就将I(i)分成两半I(i1)和I(i2) 使得一半含有s1:
I(i1)={s|s∈ I(i)且s经a弧到达t1所在的子集中的某状态}
另一半含有s2:
I(i2)= I(i) - I(i1) ]
注意:由于t1和t2是可区别的,即存在一个字w,t1将读出w而停于终态,而t2或读不出w或虽然可读出w但不到达终态;或者情形恰好相反。因而字aw就将状态s1和s2区别开来。也就是说I(i1)中的状态与I(i2)中的状态是可区别的
③一般地,若I(i)a落入现行П中N个不同子集,则应将I(i)划分为N个不相交的组,使得每个组J的Ja都落入П的同一子集,这样再形成新的分划
④重复上述过程,直至分划中所含的子集数不再增长为止。至此,П中的每个子集已不可再分。也就是说,每个子集中的状态是互相等价的,而不同子集中的状态则是互相可区别的。
⑤经过上述过程后,得到一个最后分划П.对于这个П中的每个子集,选取子集中的一个状态代表其它状态。
[例如,假定I={q1 ,q2 ,…,qk}是这样一个子集,可挑选q1代表这个子集。在原来的自动机中,做:
a.凡导入到q2 ,…,qk的弧都改成导入q1
b.将q2 ,…,qk从原来的状态集S中删除
c.若I中含有原来的初态,则q1是新初态
d.若I中含有原来的终态,则q1是新终态]

到此,得到一个化简得DFA M’,使得

L( M )=L( M’)

课后题
编译原理课程总结--第三章:词法分析_第7张图片

编译原理课程总结--第三章:词法分析_第8张图片

编译原理课程总结--第三章:词法分析_第9张图片

你可能感兴趣的:(编译原理课程)