【编译原理】第三章 词法分析
词法分析器的设计
词法分析的主要工作:
从源程序的第一个字符开始,从左到右扫描源程序, 一次读一个字符,根据词法规则将有关字符组合成单词, 并识别各类单词,当确定单词类别后,将单词输出。
在词法分析过程中还要完成其它任务,如:
- 过滤掉源程序中的注释和空白;
- 记录读入字符的行号,以便发现错误后能报告出错位置;
- 进行预编译工作(对宏进行展开等工作);
- 符号表操作。
- 错误处理等。
词法分析与语法分析的接口方式:
(1)词法分析作为一遍
将词法分析器的输出结果放入一个中间文件上(外存)或直接存放在内存中,后面的语法分析程序将它作为输入进行语法分析,这样通过一遍加工就可以将以字符串形式的源程序加工成单词串形式的源程序。
(2)词法分析与语法分析安排在同一遍中
将词法分析编成一个子程序,该子程序由语法分析程序调用。当语法分析程序需要一个新单词时,调用该程序,每调用一次,则从源程序中读出一个单词,这样避免了中间文件的生成,可以提高编译效率。
源程序的输入:
(1)一次性输入:
当内存较大时,把源程序一次性输 入到内存的用户数据区,每个字符占一个字节,词法分 析程序从数据区中依次读入字符。
(2)分批次输入:
当内存不够大时,在内存开辟一个 适当大小的输入缓冲区,输入时,把源程序分批输入到 输入缓冲区,词法分析程序从缓冲区中读取字符,当缓 冲区的字符全部读完以后,再从外存上读入下一批,直 到全部源程序字符读完为止。
(3)超前搜索:
词法分析程序在组合单词的时候,为了进一步判明情况和确定下一步要做什么以及为了处理上的方便等,常采取向前假读字符的办法(超前搜索),即向前读取字符和判别字符是什么,不马上处理,当情况判明后,再回来处理已读过的字符。
例如: for(fore=0; fore<10; fore++) if(fore%3==0) break;
(4)输入缓冲区的处理:
无论缓冲区设定为多大,都不能保证单词不会被它的边界打断。
为此,我们可将缓冲区分成相等的两个区域:
- 两个半区互补使用
- 两个指针协同工作
为什么要将缓冲区分成相等的两个区域,两个半区如何互补,两个指针如何协同工作的?
【编译原理】为什么要将缓冲区分成相等的两个区域-CSDN博客
单词的输出:
(1)单词的种类:
关键字:例如:while、for、break等
例如:程序名、变量名、常量名、类型名等
例如:125、0.745、15.2E+5
例如:+、– 、*、/、等
(2)词法分析器的输出形式:
(单词类别,单词值)
单词类别
单词值
已知类别码:“1”表示标识符;“2”表示常数; “3”表示关键字;“4”表示运算符;“5”表示界符。
单词类别 | 单词值 |
3 | “if” |
5 | ( |
1 | 指向i的符号表入口 |
4 | “==” |
2 | (5)2 |
5 | ) |
1 | 指向x的符号表入口 |
4 | “=” |
1 | 指向y的符号表入口 |
5 | “;” |
词法分析的分离:
实际上,词法也是语法的一部分,词法描述完全可以归并到语法描述中去,只不过词法规则更简单些。进一步说,在编译程序中可以将词法分析包含在语法分析之中,那么为什么把编译过程的分析工作划分成词法分析和语法分析两个阶段?主要考虑的因素为:
(1)使整个编译程序的结构更简洁、清晰和条理化;
(2)编译程序的效率会改进;
(3)增强编译程序的可移植性。
正则文法与状态转换图
状态转换图
状态转换图TG(简称状态图或转换图)是一张定义在 字母表Σ上的有限方向图。在状态转换图中 :
- 结点代表状态,用圆圈表示;
- 状态之间用有向弧连结;
- 有向弧上的标记(字符)表示在射出结点(有向弧的开始 结点)所代表的状态下可能出现的输入符号或符号串。
- 用带有符号“
”的圆圈表示状态转换图的初始状态
- 用
表示终止状态。
正则文法的状态转换图表示
对于右线性文法G[S],状态转换图的表示方法如下:
(1)用状态表示G[S]中的非终结符,G[S]的开始符号 S对应状态转换图的开始状态S;
(2)增加一个新状态Z,作为状态转换图的终止状态;
(3)对于G[S]中形如U→xV的每条产生式,画一条从状态U到状态V的方向弧,弧上的标记为x;
(4)对于G[S]中形如U→y的每条产生式,画一条从状态U到终态Z的方向弧,弧上的标记为y 。
正则文法与状态转换图等价,是指正则文法所确定 的语言L(G),与状态转换图所接受的语言L(TG)相同:
L(G)=L(TG)
对于左线性文法G[Z],状态转换图的表示方法如下:
(1)用状态表示G[Z]中的非终结符,G[Z]的开始符号 Z对应状态转换图的终止状态Z;
(2)增加一个新状态S,作为状态转换图的初始状态;
(3)对于G[Z]中形如U→Vx的每条产生式,画一条从状态V到状态U的方向弧,弧上的标记为x;
(4)对于G[Z]中形如U→y的每条产生式,画一条从初态S到状态U的方向弧,弧上的标记为y 。
右线性文法状态图的识别过程,是为串w建立一个 推导Sw的过程。 左线性文法状态图的识别过程,是从串w出发的归约过程,最后归约为开始符号S。
正规表达式与有限自动机
正规式和正规集
为了识别正则语言,我们引入了状态转换图和有限 自动机,有限自动机所接受的语言正是正则文法产生的 语言(正则语言),程序设计语言中的单词也大多是由正 则文法产生的。作为单词的语法除了用正则文法描述外, 我们还可以用一种更有效的工具——正规式加以描述。
采用正规式有以下几个原因:
1.词法规则简单,无需上下文无关文法那样强有力的表 示法,用正规式表示法去理解正被定义的是什么样的符 号集合比领会由产生式集合定义的语言更为容易;
2.借助正规式构造高效的识别程序比上下文无关文法更容易;
3.可以从某个正规式自动构造识别程序,它识别的正是用该正规式表示的字符串集合中的字符串,从而减轻实现词法分析时工作的单调乏味程度。
正规式和正规集的定义
正规集
正规式
具体地:
(1)ε和ф是Σ上的正规式,它们所表示的正规集分别为{ε}和ф;
(2) 若a∈Σ,则a是Σ上的正规式,它所表示的正规集为{a};
(3)若e1和e2都是Σ上的正规式,且它们所表示的正规集分别为 L(e1)和L(e2),那么:
(e1) 是正规式,表示的正规集为L(e1);
e1|e2 是正规式,表示的正规集为L(e1)∪L(e2) ;
e1.e2 是正规式,表示的正规集为L(e1)L(e2) ;
e1* 是正规式,表示的正规集为(L(e1))*。
(4)仅由有限次使用上述三步骤而定义的表达式才是Σ上的正规式, 仅由这些正规式所表示的字集(符号串集合)才是Σ上的正规集。
有限自动机
确定的有限自动机DFA
定义:一个确定有限自动机(DFA)M是一个五元组:
M=(S,Σ,f,S0,F),其中:
确定的有限自动机(DFA)
(1) S是一个非空有限集,它的每个元素称为一个状态;
(2) Σ是一个有限的输入字母表,它的每个元素称为一个输入字符;
(3) f是转换函数,它是从S ×Σ到S的单值部分映射,即如果f(ki,a)=kj(ki∈S, kj∈S,a∈Σ)就意味着,当前状态为ki,输入字符为a时,将转换到下一个状态kj,kj成为新的当前状态,我们把kj称为ki的 一个后继状态;
(4) S0∈S,是唯一的初始状态;
(5) F S,是终止状态集合。