正则表达式解析器的编写

引言

我在正则表达式基础使用一文中介绍了正则表达式的基本使用,编写这篇文章的过程中,我的头脑中冒出了一个问题,正则表达式到底是如何匹配给定字符串的?当然,仅仅把其匹配机制当作是一种“魔法”是完全不行的。在进行一番搜索和文献阅读之后,我有了一些思路,如果你也曾思考过类似的问题,希望本篇文章能够给你带来一些启发。

本文首先对正则表达式(Regular Expressions)、有限自动机(finite automata)、非确定性有限状态自动机(NFA)、确定性有限状态自动机(DFA)、汤普森构造法(Thompson’s construction)、汤普森(Thompson)提出的正则表达式搜索算法进行介绍,并且基于该算法,实现了一个正则表达式解析器,本人使用 Python 作为实现语言(因为 Python 足够简单易懂),但算法背后的思想却是适用于任何语言的。

正则表达式(Regular Expressions)

正则表达式用于描述字符串的集合,在普通搜索功能的基础上,提供了基于模式/规则的匹配。

  1. 除了字符 *?+()| 外,所有字符对自身进行匹配,对于特殊字符,需要使用转义字符 \ 进行转义
  2. 如果 e1 匹配 a,e2 匹配 b,那么 e1e2 匹配 ab,e1|e2 匹配 a 或 b
  3. 字符 *?+ 为数量修饰符,e* 表示匹配 0 或多个 e,e+ 表示匹配 1 或多个 e,e? 表示匹配 0 或 1 个 e
  4. 运算符优先级为:选择(e1|e2)< 组合(e1e2)< 数量修饰符(*?+)

以上为对正则表达式语法的简要介绍,除此之外,现代正则表达式还添加了许多特性,但为了简化我们的讨论,本文按下不表,事实上,为了使我们的注意力更集中于算法本身的思想而不是正则表达式的复杂实现上,本文后续也仅针对以上语法实现我们的正则表达式解析器(当然同时也是为了简化实现,可想而知,完整的实现十分复杂,而这篇文章本质是为了使读者初步了解正则表达式背后的实现原理,若不加限制,其复杂性背离了本人的初衷)。

有限自动机(Finite Automata)

有限自动机是描述字符串集合的另一种方式,有限自动机由一个有限的内部状态集和一组控制规则组成,其通过当前状态和下一个输入信号确定下一个状态。其中非确定性有限状态自动机(NFA)和确定性有限状态自动机(DFA)均是有限自动机的子集,后面我们还会发现,DFA 也是 NFA 的子集。

数学描述

DFA 可表示为五元组:

A = ( I , S , f , Q , s 0 ) A = (I, S, f, Q, s_0) A=(I,S,f,Q,s0)

其中:

  1. I I I 为所有输入字符,其是有限的
  2. S S S 为 NFA 的状态集,每一个元素被称为状态
  3. f f f 为转换函数,定义从 S ∗ I → S S * I \rightarrow S SIS 的单值映射,即 f ( p , a ) = q f(p,a)=q f(p,a)=q,即当前状态为 p p p ,输入信号为 a a a 时,将转换到下一个状态 q q q
  4. Q Q Q 为终止状态(接受状态),为 S 的子集
  5. s 0 s_0 s0 为初始状态

NFA 与 DFA 的数学定义几乎一致,二者差别在于转换函数 f f f,NFA 的转换函数为 $S*I \rightarrow p(S)$ 的映射,其中 p ( S ) p(S) p(S) S S S 的幂集(即 S S S 的所有子集组成的集合),即 f ( p , a ) = { q 1 , q 2 , . . . q k } f(p,a)=\{q_1,q_2,...q_k\} f(p,a)={ q1,q

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值