基本正则引擎的实现

本文介绍了一个基本正则引擎的实现过程,包括解析正则表达式、构造NFA和DFA,以及状态最小化。引擎支持多种元字符和范围匹配,采用C++实现,具有更好的扩展性和功能,如星号、加号、问号等操作符。虽然不包含所有高级功能,但相较于之前的实现,功能更加强大,匹配速度更快。同时,还介绍了如何构建词法分析器,并提供了错误提示和宽字符支持。
摘要由CSDN通过智能技术生成

介绍

  这个篇文章是对我的一个基本功能的正则引擎的实现过程的大致介绍与讨论,实际上在之前的文章中我已经对正则引擎的实现有所涉及,当时是翻译了有关Thompson NFA的文章,文章及其附带的源代码中已经对如何实现一个简单的正则引擎有了详细的说明,但是该文章对正则引擎的介绍并不深入,同时实现方式也过于简单化,虽然最终的结果是高效可靠的,但是这个实现不便于扩展,同时支持的功能也比较有限,因此在这一次的实现中,我采用了更加主流的方法,这样支持了更多的功能,同时也易于扩展。该项目使用的语言为C++,完整项目请移步regexEngine2

引擎功能介绍

下面简单地介绍一下这一次的正则的一些功能(并联串联功能不再赘述):

1.’*’:零个或多个

2.’+’:一个或多个

3.’?’:零个或一个

4.’ . ‘:匹配任意一个字符

5.{a}:重复a次;{a,b}:重复次数大于等于a小于等于b;{a,}:重复次数大于等于a

6.[m-n]:匹配范围内的字符(例如:[a-g]等价于a|b|c|d|e|f|g等价于[abcdefg])

7.[^m-n]:匹配不是范围内的字符

同时还加入了一些特殊的转义字符:

1.\d:等价于[0-9]

2.\D:等价于[^0-9]

3.\s:等价于[\t\n\r\f]

4.\S:等价于[^\t\n\r\f]

5.\w:等价于[a-zA-Z0-9_]

6.\W:等价于[^a-zA-Z0-9_]

  由此可见,这一次的正则引擎的功能相较于之前的实现有了更多的加强,这样一来使得正则匹配更加方便易用,但就如同我刚开始说的,这也仅仅是一个基本的功能,因为真正工业级别的正则引擎还有许多高级但是实用的功能,例如:贪婪匹配与非贪婪匹配(其实这个实现起来比较简单),正向预查,反向预查等等,这些功能使得正则表达式更加强大,但是实现起来也更加的复杂,由于我的本意并不是做一个完备的正则引擎,因此这些高大上的功能就跳过。下图大致展示了程序匹配时的情况:

match_example1

图中的match方法的第二个参数为匹配的模式,第一种是ALL_MATCH,第二种是SUB_MATCH,前者将整个给定的字符串作为输入进行匹配,后者会将给定字符串中与表达式匹配的地方筛选出,并存储到result属性中。

同时这一次的实现我也加入了对宽字符的支持:

match_example2

最后当书写的正则表达式出现错误时,错误的提示也会更加详细(有一个背景反色的提示,并没有什么用,正儿八经的正则引擎不会搞这种东西出来,只是好玩儿而已):

error_example1

既然正则引擎已经实现了,那顺便实现一个词法分析器的模块也是比较轻松的事情,在头文件analyzer.h文件中定义了两个类,一个是MatchUnit,一个是LexicalAnalyzer,在使用词法分析器的时候,需要实例化MatchUnit类,之后使用MatchUnit的实例来初始化LexicalAnalyzer,在设定好所需要分析的文件之后,便可以通过调用get_next_token(命名方式有点乱)方法获取词法单元。

analyzer

实现

  这一次引擎的实现我采用了比较主流的方法,即首先对正则表达式进行解析,形成抽象语法树,通过抽象语法树得到表达式的字符集以及NFA,通过子集构造法将NFA转换为DFA,最后通过将DFA中的相同状态合并,得到最小化的DFA,这样得到的状态转换表便最终用来进行字符串的匹配。实际上之前的Thompson NFA的实现方法是将正则表达式转换为NFA,之后使用该NFA进行匹配,这种方法实现简单,但是当正则表达式很复杂时,生成的NFA的状态是很多的,这样匹配速度会下降,特别是在重复进行匹配时,时间的消耗很大。而最小化后的DFA状态转换相较于NFA会少了很多的不必要的状态,这样匹配速度会得到大幅提升。接下来我会分别对上述的几个处理过程进行介绍。

解析正则表达式

  实现的第一步是解析正则表达式,而解析的时候文法是必不可少的,以下是我从网上找到的正则表达式的文法:

RE::= union | simple-RE                 
union::= RE "|" simple-RE               
simple-RE::= concatenation | basic-RE
concatenation::= simple-RE basic-RE
basic-RE::= star | plus | ques | elementary-RE
star::= elementary-RE "*"
plus::= elementary-RE "+"
ques::= elementary-RE "?"
elementary-RE::= group | any | eos | char | set
group::= "(" RE ")"
any::= "."
eos::= "$"  //end of string
char::= any-non-metacharacter | "\" metacharacter
set::= positive-set | negative-set
positive-set::= "[" set-items "]"
negative-set::= "[^" set-items "]"
set-items::= set-item | set-item set-items
set-item::= char-range | char
char-range::= char "-" char

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值