一、状态转换图
我们已经找到了匹配词法单元的工具——正则表达式。
接下来的问题就是怎么匹配?如何判定一个串匹配某个正则表达式?如何形式化地描述这个匹配过程?
还是上节的例子。
在上节中,我粗略地介绍了有限自动机这个概念。有限自动机就是形式化判定是否匹配的工具。
在介绍有限自动机前,先介绍状态转换图。
我们可以用状态转换图来匹配词法单元。例如下面三个例子。
像上面这种状态转换图可以去匹配一个串,并且结合状态转化图的匹配过程,我们不难发现,我们可以用swicth语句和条件判断语句去实现。
举个例子。
现在抛出两个问题。
问题一:匹配标识符时存在多种匹配情况。
我们规定采用最长匹配规则来解决该问题。
问题二:匹配一个串时,既匹配关键字又匹配标识符。
我们规定采用优先匹配规则来解决该问题。
二、有限自动机 (FA)
现在,我们有了正则表达式这个工具去匹配词法单元,而匹配过程可以用状态转换图表示,并且可以根据状态转换图得到形式化的匹配方法。其中,状态转换图是基于正则表达式的。
那么问题来了,我们如何由正则表达式得到状态转换图呢?
解决这个问题的工具是有限自动机。
有限自动机可以分为确定的有限自动机(DFA)和不确定的有限自动机(NFA)。
(一)NFA
NFA的定义如下。
NFA的转换函数:
该函数意为:从一个状态出发,在匹配输入字符集(可包含空串)后,可得到多个状态P(S),❌号代表匹配的意思。
这也就是不确定的的含义,即NFA的实际结果是不确定的,是可多选的。
举个例子,用图表示如下。
而在图中,不确定性就体现在图中的这个部分。
从状态0出发,匹配到字符"a"后,既可以到达状态0,也可以到达状态1。
NFA除了可用图表示外,还可以用表表示。
上面这个表与前面的图是等价的。
表的不确定性体现在这里。
而由正则表达式得到NFA的过程是比较简单的,包括手工绘制NFA。
NFA的缺点也显而易见,由于转换结果是不确定的,存在多条匹配路径,但正确结果只有一条,所以NFA可能会匹配出错,这就涉及到错误处理(回退,即回溯一步重新匹配),这就会带来额外的开销,并且可能大部分路径都是错误的,所以效率也很低。
因此,我们希望通过正则表达式得到一个转换结果确定的的有限自动机,这就是DFA。
(二)DFA
DFA的定义。
举个DFA的例子。
DFA也是由正则表达式得来的,但它的构造过程比NFA要复杂得多(因为DFA由NFA得来)。
(三)NFA vs DFA
同样一个正则表达式:
NFA如下:
DFA如下:
虽然DFA比NFA复杂,但由于确定性,DFA的执行速度快于NFA。