正则表达式的边界
我们在日常当中使用正则表达式搜索各种字符串,但是手里有这么厉害的一个工具,我们也必须知道它的局限所在。
RegExp背后对应的是Finite Automaton,有限状态自动机。这种自动机的特点就是Memoryless,也就是”无内存”。这种自动机的总是从一种状态移动到下一种状态,而不会去记录之前的状态。
因此,我们根据这个特点,可以判断出正则表达式必然有它的局限性,而这个局限性肯定是和它这种Memoryless的特点相关。事实也确实如此:正则表达式表达不了nested结构。
我们无法用正则表达式表达一个任意深度的nested结构。比如这样的字符串:
{1 {2 {3 { ... } 3} 2} 1}
假设上面的字符串是由任意多的{}
这样的大括号对来组成,我们没法写一个正则表达式来匹配这个结构。也就是说,我们可以匹配固定层数的nest结构,但我们不能写一个通用的表达式,表达一种抽象的nest结构。
其实我们从正则表达式背后的有限状态机,也就是Finite Automaton
这个名字就可以看出来,它能匹配的是有限状态。因为这种状态机是Memoryless
的,只会从一个状态转移到另一个状态,因此它无法记录nest结构,也就无法匹配nest结构。
因此,我们不能使用正则表达式表示nest结构。实际上我们多写写正则表达式就可以很容易理解这点:我们写的正则表达式都是一个模式接着另一个模式,每一个模式内部可以用|
来表达”或”的关系,但其实正则表达式表达不了nest的模式。
在语言领域,Chomsky早已经把正则表达式背后所能表达的语法给规范化了。实际上,正则表达式所能表达的语法,叫做Regular grammar1。
我们可以看看Chomsky对语言的规范化分类:
如上图所示,Type-3 Grammar就是对应的Regular Grammar,并且可以看到对应的Abstract machine
是Finite
。
Regular Grammar
是Context-Free Grammar
,也就是Type-2 Grammar
的一个子集。我们并不能使用正则表达式匹配所有的Context-Free Grammar
,因为Context-Free Grammar
是允许nest
结构存在的。
首先我们必须知道,我们所使用的计算机语言都是context-free grammar
,也就是说,我们的编程语言里面都有nest结构存在的。这个是非常容易理解的,比如下面Java语言的代码里面的Nested Class:
class OuterClass {
...
class NestedClass {
...
}
}
实际上Parser在分析语法的时候,是必须要支持匹配这种很常见的nested结构的,这个和Lexer阶段使用正则表达式来匹配Token来讲,要求更高。因此Parser是无法使用正则表达式来完成Rules匹配工作的。
我们可以看看上面的图,看看Context-Free Grammar
对应的Abstract Machine是什么,可以看到对应的是Pushdown Automaton
,简称PDA
,也就是中文翻译过来的”下推自动机”。
PDA
在FA
的基础上加入了stack,具有了内存,不再是Memoryless
,因此它可以匹配nest结构,这对于语法分析至关重要:因为除了匹配nest结构,Parser在做语法分析的时候,不光要匹配某个字符串,还要把字符串前后关联,匹配具体的语法规则,而不只是状态的变化。
接下来想给大家讲讲各种自动机的边界。先看下面这幅图2:
上面的图展示了各种自动机的边界,最里面是Combinational logic
:基础的逻辑是所有自动机的基石,比如”or”还有”and”这些逻辑关系。
然后是最基础的自动机:Finite-state machine
,这种自动机是可以进行状态的跃迁,但没有内存,无法进行语义分析。
给Finite-status machine
加上一个stack内存,就变成了Pushdown automaton
,这样的自动机不但可以进行状态的跃迁,还可以访问stack内存。这样就可以对context-free language
进行语法规则分析。
如果我们把PDA
的stack
内存变成可以随机访问的内存,就得到了Turning Machine
:不但可以进行状态的跃迁,还可以有随机的存取空间。
因此图灵机就是一个完备的计算机,我们的程序往往是图灵完备的,也是要运行在图灵机上。举个例子,我们的电脑当然是图灵机,然后很多虚拟机其实也是图灵机,比如Java的JVM也是图灵机。
同样的道理,如果只是运行正则表达式引擎,我们就不需要内存。如果只是运行PDA Parser,我们就只需要stack型内存而不需要随机访问内存。
希望给大家通过这篇文章,能够理清楚了知识的脉络,各种自动机的边界,以及它们的适用范围,有了这个知识基础,很多时候可以帮助大家明白自己面对什么问题该用什么工具。这种选择工具的能力无比重要。