最近参照一些资料实现了一个非常简易的正则表达式引擎,支持基本的正则语法 | + * ()等。
实现思路是最基本的:正则式->AST->NFA->DFA。

以下是具体步骤:

一. 正则式->AST:

这一步没什么好说的,因为正则表达式的语法较为简单,使用编译原理中的递归下降的方法, 可以很容易的构造出一个语法分析器。

二. AST->NFA:

这里的NFA准确的来说应该是ε-NFA,即带有ε边的非确定的有穷状态自动机。ε边是指可以在不接受任何字符的情况下转移的边。其存在的意义是状态与状态之间的组合。从而更方便的将AST转化成ε-NFA。

正则的基本元素及状态的构造方法:

1.字符集







2.串联



从这里开始,我们便要使用ε边,以便将不同状态连接起来。






3.并联







4.重复(>0次)







5.可选(>=0次)



将重复的start删除,再让原end同时具备start和end即可。



在此处,我犯了一个错误。对于重复,我直接将要重复的子状态的end与start间建立了一条ε边,实现了同样的功能。我想将同样的思路应用于可选,便在重复的基础上在start与end间建立ε边,而这导致了状态通过ε边形成环路,从而使得下一步骤中ε闭包的寻找陷入死循环。

三. 消除ε边及无效状态

  1. 找到有效状态
    有效状态的是开始状态加上所有存在非ε边的输入的状态。结束状态不一定是有效状态,但是如果存在一个有效状态可以仅通过ε边到达结束状态的话,那么这个状态应该被标记为结束状态。
  2. 添加必要的边
    对所有有效状态,寻找其ε闭包。ε闭包是指从该状态仅通过ε边所能到达的状态集合(不包含该状态),此处使用BFS即可。并将闭包看做整体,将从闭包延伸出的边复制到该有效状态上。
  3. 删除所有ε边和无效状态

四. NFA->DFA

此处使用子集构造算法,主要思路就是将一个状态经过相同的转移条件所能到达的状态合并,看做一个DFA状态,再对这个DFA状态采取相同做法,重复执行。最后得到DFA状态表。

五. DFA->状态转移表

这一步就是将上一步得到的DFA表转换成一个字符表,记录每个状态接收某个字符能够转移到的状态。

最后,该引擎我还未完成,目前还不支持贪婪、非贪婪,捕获,边界,以及各种“黑魔法”(这么看来好像有点太简陋了)。只能说自己的编码水平还远远不够吧_(:з」∠)_。
代码:https://github.com/CknightX/Regex (好多bug未修复。。)
(本文的内容和图片主要参考自vczh《构造可配置词法分析器》和《正则表达式》)

【C++】正则表达式引擎学习心得的更多相关文章

  1. 我的MYSQL学习心得(一) 简单语法

    我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据类型 我的MYSQL学习心得(五) 运 ...

  2. 我的MYSQL学习心得(四) 数据类型

    我的MYSQL学习心得(四) 数据类型 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(五) 运 ...

  3. 我的MYSQL学习心得(五) 运算符

    我的MYSQL学习心得(五) 运算符 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据 ...

  4. 我的MYSQL学习心得(七) 查询

    我的MYSQL学习心得(七) 查询 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据类 ...

  5. 我的MYSQL学习心得(八) 插入 更新 删除

    我的MYSQL学习心得(八) 插入 更新 删除 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得( ...

  6. 我的MYSQL学习心得(九) 索引

    我的MYSQL学习心得(九) 索引 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据类 ...

  7. 我的MYSQL学习心得(十四) 备份和恢复

    我的MYSQL学习心得(十四) 备份和恢复 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) ...

  8. 我的MYSQL学习心得(十六) 优化

    我的MYSQL学习心得(十六) 优化 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据 ...

  9. 我的MYSQL学习心得(十七) 复制

    我的MYSQL学习心得(十七) 复制 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据 ...

随机推荐

  1. PL/SQL将sql脚本数据导入Oracle

    PL/SQL将sql脚本数据导入数据库: 1.首先,使用plsql登录到需要导入数据的数据库.在[tools]--[Import tables] 2.选择第二个[SQL Inserts],在下面,点击 ...

  2. 重识linux-关于selinux

    重识linux-关于selinux 1 selinux是一个内核模块,有美国国家安全局研发,主要在基因redhat分支的系统上实现,当初的设计是未了避免用户资源的误用, 而SELINUX使用的是MAC ...

  3. 45.更新一下scrapy爬取工商信息爬虫代码

    这里是完整的工商信息采集代码,不过此程序需要配合代理ip软件使用.问题:1.网站对ip之前没做限制,但是采集了一段时间就被检测到设置了反爬,每个ip只能访问十多次左右就被限制访问.2.网站对请求头的检 ...

  4. pl/sql学习笔记---马士兵教程38-48

    Procedure Language/Structure query Language 一.关于语言学习 1.数据类型 2.语法   通过例子来学习很快就能明白 set serverputout on ...

  5. 安装 docker管理 工具 页面 portainer

    sudo docker run -d -p 7998:9000 -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data ...

  6. ubuntu 使用sudo apt-get update命令的时候会报http://archive.ubuntukylin.com:10006/ubuntukylin/dists/xenial/InRelease 无法连接

    参考:  https://blog.csdn.net/xiaoyan94/article/details/52404539 于是找到一个包含 http://archive.ubuntukylin.co ...

  7. Linux 硬链接、软链接

    索引节点 inode(index node) 我们知道文件都有文件名与数据,这在 Linux 上被分成两个部分:用户数据 (user data) 与元数据 (metadata).用户数据,即文件数据块 ...

  8. Mysql IN语句查询

    语法: WHERE column IN (value1,value2,...) WHERE column NOT IN (value1,value2,...) 1.in 后面是记录集,如: selec ...

  9. day17-函数装饰器

    一.什么是装饰器 装饰器可以让其他函数在不需要做任何代码改变的前提下,增加额外的功能,装饰器的返回值也是一个函数对象.在 Python 中,函数是第一类对象,也就是说,函数可以做为参数传递给另外一个函 ...

  10. 在Ubuntu 16.04 上编译安装OpenCV3.2.0(Cmake + python3 + OpenCV3)(转)

    1 安装CMAKE sudo apt-get install cmake 2 安装python及其所依赖的软件包 sudo apt-get install build-essential sudo a ...