【C++】正则表达式引擎学习心得
最近参照一些资料实现了一个非常简易的正则表达式引擎,支持基本的正则语法 | + * ()等。
实现思路是最基本的:正则式->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间建立ε边,而这导致了状态通过ε边形成环路,从而使得下一步骤中ε闭包的寻找陷入死循环。
三. 消除ε边及无效状态
- 找到有效状态
有效状态的是开始状态加上所有存在非ε边的输入的状态。结束状态不一定是有效状态,但是如果存在一个有效状态可以仅通过ε边到达结束状态的话,那么这个状态应该被标记为结束状态。 - 添加必要的边
对所有有效状态,寻找其ε闭包。ε闭包是指从该状态仅通过ε边所能到达的状态集合(不包含该状态),此处使用BFS即可。并将闭包看做整体,将从闭包延伸出的边复制到该有效状态上。 - 删除所有ε边和无效状态
四. NFA->DFA
此处使用子集构造算法,主要思路就是将一个状态经过相同的转移条件所能到达的状态合并,看做一个DFA状态,再对这个DFA状态采取相同做法,重复执行。最后得到DFA状态表。
五. DFA->状态转移表
这一步就是将上一步得到的DFA表转换成一个字符表,记录每个状态接收某个字符能够转移到的状态。
最后,该引擎我还未完成,目前还不支持贪婪、非贪婪,捕获,边界,以及各种“黑魔法”(这么看来好像有点太简陋了)。只能说自己的编码水平还远远不够吧_(:з」∠)_。
代码:https://github.com/CknightX/Regex (好多bug未修复。。)
(本文的内容和图片主要参考自vczh《构造可配置词法分析器》和《正则表达式》)
【C++】正则表达式引擎学习心得的更多相关文章
- 我的MYSQL学习心得(一) 简单语法
我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据类型 我的MYSQL学习心得(五) 运 ...
- 我的MYSQL学习心得(四) 数据类型
我的MYSQL学习心得(四) 数据类型 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(五) 运 ...
- 我的MYSQL学习心得(五) 运算符
我的MYSQL学习心得(五) 运算符 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据 ...
- 我的MYSQL学习心得(七) 查询
我的MYSQL学习心得(七) 查询 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据类 ...
- 我的MYSQL学习心得(八) 插入 更新 删除
我的MYSQL学习心得(八) 插入 更新 删除 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得( ...
- 我的MYSQL学习心得(九) 索引
我的MYSQL学习心得(九) 索引 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据类 ...
- 我的MYSQL学习心得(十四) 备份和恢复
我的MYSQL学习心得(十四) 备份和恢复 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) ...
- 我的MYSQL学习心得(十六) 优化
我的MYSQL学习心得(十六) 优化 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据 ...
- 我的MYSQL学习心得(十七) 复制
我的MYSQL学习心得(十七) 复制 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据 ...
随机推荐
- Maven的下载和配置
一.下载 打开 链接地址 http://maven.apache.org/download.cgi 下载 Maven, 下载加压打开以后目录: 二.配置环境变量 我的电脑 -> 属性->高 ...
- Android 组合控件
前言 自定义组合控件就是多个控件组合起来成为一个新的控件,主要用来解决多次重复的使用同一类型的布局.比如我们应用的顶部的标题栏,还有弹出的固定样式的dialog,这些都是常用的,所以把他们所需要的控件 ...
- js window.open隐藏参数提交
1.采用form方式提交 var url = "page/public/exportExcel.jsp"; //create a form var tempForm = docum ...
- 利用STM32CubeMX之SPI
现在我们继续使用STM32CubeMX来生成SPI工程.我们的硬件平台还是我们熟悉的STM32F103C8开发板. 设置时钟树中的配置 现在打开SPI的设置 如果想修改管脚的名字可以红色框中进行修改, ...
- Django models模型(1)
1)使用模型需要在INSTALLED_APPS中注册 2)模型字段(字段类型和字段选项) 1.字段类型 常用: CharField,TextField: 对应字符串对象 DateTimeField和D ...
- 模板引擎Dot
Dot.js 很轻,处理速度也快,作为将json数据赋值到html页面的最好帮手. html5新引入的<template></template>就不用原先的<script ...
- 构建模式--Adapter模式(JAVA)
适配器模式: 适配器就相当于我们的转接头,比如手机充电器插头(小米和华为的手机充电器不能共用,这时候就可以给华为的充电器按一个转接头,就可以给小米手机充电). 同理,当一个类(充电器 HuaweiCh ...
- java序列化问题
今天无意中看到了 redistemplet封装的类中,出现了序列化的字眼 ,了解下序列化的知识 1.什么是序列化 我们把变量从内存中变成可存储或传输的过程称之为序列化,(java中一般是用来保 ...
- js 正则函数初级
1.test :正则匹配字符串,如果成功则返回true,若果失败则返回false 格式:/正则表达式/.test(字符串) 默认吗匹配规则,区分大小写:如果不区分大小写,则加修饰符 i 例子: < ...
- python学习笔记之斐波拉契数列学习
著名的斐波拉契数列(Fibonacci),除第一个和第二个数外,任意一个数都可由前两个数相加得到: 1, 1, 2, 3, 5, 8, 13, 21, 34, ... 如果用Python的列表生成式, ...



