随笔-19  评论-21  文章-0  trackbacks-0
一. 简介

    该正则表达式暂时能识别 *,|,(,)等特殊符号,如(a|b)*abc。不过扩展到其他符号(如?)也相对比较容易,修改NFA中的构建规则即可。

二. 引擎的构建

    该正则表达式引擎的构建以《Compilers Principles,Techniques & Tools》3.7节为依据,暂时只能识别*,|,(,)这几个特殊的字符,其工作过程为:构建NFA -> 根据NFA构建DFA -> 用DFA匹配。

1. 构建NFA
该NFA的构建以2条基本规则和3条组合规则为基础,采用归纳的思想构建而成。
1)2条基本的规则是:
a. 以一个空值ε构建一个NFA

b. 以一个字符a构建一个NFA

2) 3条组合规则是:
a. r = s | t (其中s和t都是NFA)

b. r = s t(其中s和t都是NFA)

c. r = s *(其中s为NFA)

3) 如果需要识别如”?”等特殊符号,则可再加一些组合规则。

在具体的程序中,可以以下面的BNF为结构来实现。(具体见源程序regexp.cpp)

-> r '|' s | r
-> s t | s
-> a '*' | a
-> token | '(' r ')' | ε   

2. 构建DFA
主要是求ε闭包的过程,从一个集合的ε闭包转移到一个集合的ε闭包。
以a*c为例,其NFA图如下所示(用dot画的)

为例:
起始结点3的ε闭包集为 A = {3,1,4}
A遇上字母a的转移为MOV(A,a) = { 2 },其ε闭包集为B = { 2,1,4 }
A遇上字母c的转移为MOV(A,c) = { 6 },其ε闭包集为B = { 6 }
同理可求出其他转移集合,最后得到的DFA如下所示:

3. 匹配
每匹配成功一个字符则DFA移动到下个相应的结点。

三. 改进

1. 如龙书中所说,有时候模拟NFA而不是直接构建DFA可能达到更好的效果。
2. 每次匹配不成功都需要回溯,这个地方也可以借鉴KMP算法(不过KMP对此好像有点不适用)
3. 其他改进方法可以看看《柔性字符串匹配》和龙书《Compilers Principles,Techniques & Tools》3.7节。

四. 代码下载

svn checkout http://regexp.googlecode.com/svn/trunk/ regexp-read-only

regexp.rar
posted on 2010-06-17 20:50 hex108 阅读(665) 评论(2)  编辑 收藏 引用 所属分类: Program

评论:
# re: 构建正则表达式引擎 2010-06-18 18:23 | 木头奎
发现一处代码问题:
NFA *construct_nfa_and(NFA *s,NFA *t)函数体里面,
delete( t->get_head() ); //释放t的头结点
这句话
应该放到s->set_tail( t->get_tail() );的后面去

VC6下测试发现的。  回复  更多评论
  
# re: 构建正则表达式引擎 2010-06-18 21:01 | hex108
@木头奎
谢谢! 刚改正了呵  回复  更多评论
  

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理