编译原理读书笔记(3/12)

第3章 词法分析

词法分析的作用是扫描源程序,识别程序中的一个个单词,如变量标识符、程序的保留字等。

3.1 词法分析程序的设计

3.1.1 词法分析程序与语法分析程序的接口方式

词法分析是先于语法分析的,是语法分析的基础。两者的结合有两种方式:第一种是先扫描一遍源程序,只进行词法分析,词法分析的结果存放到一个中间文件中,这个中间文件作为语法分析的输入。第二种方式是将词法分析构建成一个调用方法,在语法分析过程中随时调用词法分析程序。本书介绍的PL/0编译程序属于第二种方式,在这种方式下,词法分析和语法分析放在同一遍里,不需要存储中间文件。

3.1.2 词法分析的程序的输出

词法分析的结果是单词符号,使用二元式表示:(单词种类,单词自身的值)。其中单词种类是使用整数编码表示,如单词种类有:标识符、常数、关键词、运算符、界符,分别使用1,2,3,4,5进行编码,则程序片段“if i=5 then x=y;"经过词法分析后的返回结果是:

		if: (3,"if"),
		i: (1,指向i的符号表入口)
		=:(4,"=")
		 5:(2,"5")
		  then:(3,"then)
		   x:(1,指向x的符号表入口)
		   =:(4,"=")
		    y:(1,指向y的符号表入口)
		    ;:(5,";").

其中,对于标识符,还有其他的一些属性信息存放在符号表中,所以返回其在符号表中的地址。

3.1.3 词法分析独立出来的原因

之所以把词法分析从语法分析中分离出来作为一个独立的阶段基于如下的因素:

  1. 使得整个编译程序的结果更加简洁、清晰和条理化。就像流水线工作中一样,将一个工作分解为一道道工序,然后每道工序犹具体的人负责,除了问题也更容易发现。
  2. 编译程序的效率会改进。只要分解适当,流水线工作的效率会大大提高。
  3. 增强编译程序的可移植性。譬如有的编译程序可能就词法部分不同,那么只需要改变一些词法分析的处理就能够很快的进行移植。

除了识别单词以外,词法分析以后完成一些其他的工作,例如过滤空白符,记录行号以便于错误分析中的错误定位等。

3.1.4 词法分析如何识别单词

词法分析需要借助编程语言词法规则。这些规则通常由形式化或半形式化描述工具进行描述。如有效状态自动机、正规表达式以及正规文法。实际的编程语言中的单词的集合都是正规语言,因此,以描述正规语言的正规文法以及与其等价的正规表达式、有效状态自动机来设计词法分析程序的自动构造工具是目前普遍采取的方法。

3.2 PL/0编译程序中词法分析程序的设计与实现

PL/0编译程序中需要识别的单词有保留字、运算符、标识符、无符号整数和界符5个大类。除了是识别这些单词以为,词法分析程序还要完成滤空格的工作。

PL/0编译程序设置了一个getsym()方法,语法分析过程中调用该方法获取单词。

3.3 单词的形式化描述工具

在词法分析中,首先要有单词的定义即词法构造规则,使用形式化描述工具进行描述。有了单词的形式化描述,才能更进一步基于该描述构建词法分析规则。

3.3.1 正规文法

多数程序设计语言单词的语法都能用正规文法(3型文法)进行描述,即产生式中的左部是一个非中介费,右部是一个终结符或终结符+非终结符且终结符在左边。正规文法所描述的是终结符上的正规集。

3.3.2 正规式

正规式也称为正则表达式,是表示正规集的一种工具。正规集是正规文法所描述的集合,正规式(正则表达式)直接从终结符出发,通过一些符号的运算符对符号组合,也能形成 类似正规及集的集合。

3.3.3 正规文法和正规式的等价性

对任意一个正规文法,存在一个与之等价的正规式。相当于一个正则集,既可以用正则文法进行描述,又可以使用正则式进行表示。但对于同一正则集,两者的描述难度不一样。有的使用正则文法更容易,有的使用正则式更容易。

正规文法与正规式之间可以进行转化。将正规式转为为正规文法,首先将启始符号定义为正则式,然后对正则式不断进行分解,直到最后每一个产生式都是符合正规文法的要求。将正规文法转化为正规式,就是不断地合并产生式,直到最后开始富豪的右端即正规式。

3.4 有穷自动机

有穷自动机是一种识别装置,是用来识别正规文法所定义的语言和正规式所表示的集合。它有有限的状态,其中包括初始状态和终结状态。系统每次根据当前所处的状态和输入决定后继的状态。有穷状态机分为确定的有穷状态机(DFA)和不确定的有穷状态机(NFA)。

3.4.1 确定的有穷自动机

形式上,一个DFA包括五个部分:有穷的状态集、有穷的字母表、转换函数、初始状态和终结状态。对于DFA,有三种具体的表示形式,第一种是直接定义上述五个部分的五元组。第二种和第三种是状态图和矩阵表示。其中状态图方式是通过图形化的方式表示DFA,矩阵表示是使用矩阵方法进行表示,他们都包含定义中的五个部分。

DFA 接受的语言:是从初态出发,沿着一条路径到达终态过程中的符号串。

3.4.2 不确定的有穷自动机

不确定的有穷自动机(NFA)与DFA的区别在于NFA中每个状体对于同一输入能够抵达不同的状态,也就是状态和输入相同,下一个状态可以不同。

3.4.3 NFA转换为等价的DFA

设L为一个由不确定的有穷自动机接受的集合,则存在一个接受L的确定的有穷自动机。即对一个不确定的有穷自动机,它所形成语言,存在一个确定的有穷自动机形成同样的语言。

将NFA转换为接受同样语言的DFA的算法称为子集法。子集法相关的几个状态集合运算:状态集合I的 ϵ \epsilon ϵ闭包,状态集合I的 α \alpha α弧转换 。

  1. 状态集合I的 ϵ \epsilon ϵ-闭包,表示为 ϵ \epsilon ϵ-closure(I),即一个状态集中的状态经过任何条 ϵ \epsilon ϵ弧而能达到的状态的集合。
  2. 状态集合I的 α \alpha α弧转换,表示为move(I,a),定义为所有可从状态I中经过一条a弧而可到达的状态的全体。

由NFA N构造DFA M的算法思想:分别从表示的五元组进行考虑,M的状态集是N的状态集合的子集。子集的构造方法首先使用N中一个元素随机初始化集合,然后使用 ϵ \epsilon ϵ-闭包计算,对所有的终结符计算 α \alpha α弧转换,转换的结果不断求 ϵ \epsilon ϵ-闭包,循环直到集合中不在增加新的元素为止。M的字母表与N的相同。转换函数有固定的方法。开始状态也是N中开始状态的 ϵ \epsilon ϵ-闭包的结果。

3.4.4 DFA的化简

DFA化简是消除多余的状态且使得DFA中没有两个状态是等价的。包含两个要点:没有多余无用的状态和没有等价的状态。所谓多余无用的状态也就是该状态是不可达的,无法从其他状态通过输入串到达该状态。对于无用状态,直接删除该状态以及由该状态射出的弧。

状态的等价性表现有两点:第一两个状态必须同时为可接受或不可接受状态,这被称为一致性条件,即两个状态在接受属性上维持一致。第二对于所有的输入符号,两个状态必须转换到等价的状态里。这被称为蔓延性条件,即对任意输入,两个状态的输出状态也必须是等价的。如果两个状态不等价,就被称为可区别的。对于个不含多余状态的DFA,有一个分割法,可以将DFA的状态分割成一些不相交的子集,使得任何两个子集都是可区分的,同一个子集内都是等价的。该方法首先将状态集分成终态集和非终态状态,这两个状态集是可区分的。然后对于任何状态集,分别使用不同的输入字符看集合中中元素是否达到了不等价的状态,以此逐步向下分割。

3.5 正规式和有穷自动机的等价性

对于字母表上的有穷自动机,可以构造正规式,使得它们的语言相同。同样,对于字母表上的正规式,可以构造其上的有穷自动机,使得它们表达的语言相同。

从有穷自动机到相应的正规式的构造方法,增加虚拟x和y节点,通过将中间结点替换为表达式的方法不断消除x与y之间的结点,最后x与y之间的表达式即为正规式。

相反地,由正规式到有穷自动机的转化被称为语法制导的方法,该方法将正规式分解成一系列子表达式,然后使用规则构造NFA.

3.6 正规文法和有穷自动机的等价性

由于正规式和正规文法是等价的,正规式又与有穷自动机是等价的,可以推导出正规文法与有穷自动机的等价性。

对于一个正规式G转化为有穷自动机N的方法是:对正规式中的所有非终结符构建一个状态,开始符作为初始状态。正规式中的每个形如A->aB的产生式,构造一条状态A到状态B的转换函数,输入就是终结符a。对于右边只有终结符的状态A->a,构建一个终结状态,在状态A接收终结符a作为输入,到达此终结状态。

上述过程的逆过程即将有穷自动机转化为正规文法。

3.7 词法分析程序的自动构造工具

词法规则通常使用正规文法或正规表示式进行描述,第一步需要将其转化为等价的有穷自动机,再转化为确定的有穷自动机,并化简为最小化的确定有穷自动机。第二步基于最小化的确定有穷自动机构建词法分析程序。程序书写如下:每次读入输入串中的一个字符,由状态和输入字符确定下一个状态。所有的状态使用一个变量进行保存,对于某个输入,使用分支确定状态下对于该输入的转换情况。

词法分析程序可以有程序自动生成,以及存在生成词法分析程序的程序。如LEX编译系统,LEX使用使用LEX语言编写,输入形式化表示的正规式或正规文法,输出相应的词法分析程序。

lex工具是读入用户输入的描述文件,生成名为lex.yy.c的c源程序文件。lex.yy.c中包含一个核心函数yylex(),它是一个扫描子程序,读入源程序的字符串,识别并返回下一个单词符号。lex描述文件中包含每一种词法单元的规则。

lex的描述文件具体包括三个部分:辅助定义部分、规则部分、用户子程序部分。辅助定义部分定义变量或宏。规则部分是正则表达式以及对应的操作规则。调用子程序部分会被插入到lex.yy.c文件中。

lex的使用首先使用lex命令和描述规则生成lex.yy.c文件,然后对该文件进行编译,形成可执行程序,最后可运行该可执行程序得到结果。

lex作为词法分析程序,需要与语法分析程序配合使用,例如yacc(一个语法分析程序的生成器),yacc生成语法分析程序.

总结

编译原理的词法分析与自然语言处理差不多,自然语言处理中的词法分析主要是分词、词性标注等词级别的分析工作。编译原理中的词法分析识别源代码中的单词,包括标识符、保留字、分隔符等等。方法上自然语言处理上由于词汇量较大,并且词的组成复杂,大多采取统计机器学习的。但是在编译原理中,由于词的类型较少,通过正则式或正规文法对词进行描述。解析的过程采用有穷状态自动机。首先通过词法描述的正则式或正规文法构建有穷自动机,然后将有穷自动机转化为确定的最小状态自动机,最后根据该自动机构建词法分析工具。目前存在自动构建词法分析程序的程序,即给定词法描述文件,该程序能够自动生成词法分析程序,属于程序的程序,典型的如lex词法分析构造工具。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值