最近参照一些资料实现了一个非常简易的正则表达式引擎,支持基本的正则语法 | + * ()等。
实现思路是最基本的:正则式->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. Angular.js入门

    一.引入angular.js  <script type="text/javascript" src="../plugins/angularjs/angular.m ...

  2. Oracle掌管权限和角色

    转自:https://blog.csdn.net/without_bont/article/details/79862112 掌管权限和角色 这一部分我们主要看oracle中如何管理权限和角色,权限和 ...

  3. Redis list 数据类型

    lpush()先进后出  //从头部加入元素   //栈      lrange 元素集合   0    -1 lpop  从list头部删除元素,并返回删除元素 rpush()先进先出 //从尾部加 ...

  4. requirements.txt 的使用与创建

    1. requirements.txt  主要是记录你的python 解释器安装了那些第三方模块,这样好方便项目迁移,自动解决掉项目的依赖关系 2. 网上找的那些关于 requirements 的文档 ...

  5. PhotoShop阵列功能

    阵列有两种,如下.但是PS没有阵列这一工具,一定要用ps的话,可以参照以下两条: 1:方形阵列 先按CTRL+ALT+T 会出现一个自由变换选取 但是这个是多重复制的选取只要一动就能复制了 确定 然后 ...

  6. Java 判断当前系统为Window或者Linux

    public static boolean isOSLinux() {         Properties prop = System.getProperties();         String ...

  7. mingw编译ffmpeg 错误:Unknown option "--enable-memalign-hack"

    据说mingw编译ffmpeg的话需要添加 --enable-memalign-hack 开关 但如果源码是最新版比如:ffmpeg4.0.2 的话 好像已经禁用了该开关. “我可以确认新的ffmpe ...

  8. jq动画分析

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  9. Leetcode 题解 Combinations:回溯+求排列组合

    罗列出从n中取k个数的组合数组. 首先,求C(n,k)这个实现,很粗糙,溢出也不考虑,好的方法也不考虑.笨蛋.心乱,上来就写.. 另外,发现在递归中,不能申请太大的数组?貌似不是这个问题,是我自己越界 ...

  10. 初识AutoMapper

    在开始本篇文章之前,先来思考一个问题:一个项目分多层架构,如显示层.业务逻辑层.服务层.数据访问层.层与层访问需要数据载体,也就是类.如果多层通用一个类,一则会暴露出每层的字段,二者会使类字段很多,而 ...