【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学习心得(四) 数据 ...
随机推荐
- java中的排序--排序容器_TreeSet与TreeMap
1.TreeSet:数据元素可以排序且不可重复. 对比: (1)Set接口:HashSet,元素必须重写hashcode和equals方法. (2)TreeSet:只要可以排序即可.去重:比较等于0即 ...
- 图解HTTP / HTTPS
http://kb.cnblogs.com/page/155287/ 我们都知道HTTPS能够加密信息,以免敏感信息被第三方获取.所以很多银行网站或电子邮箱等等安全级别较高的服务都会采用HTTPS协议 ...
- Retrofit添加自定义转换器
Retrofit2开始支持多种 Converter 并存,在之前,如果你遇到这种情况:一个 API 请求返回的结果需要通过 JSON 反序列化,另一个 API 请求需要通过 proto 反序列化,唯一 ...
- Flex4学习笔记2--代码保存在单独的文件中
1 <!--调用外部as文件--> <fx:Script> <![CDATA[ import mx.controls.Alert; import a.Test3; ]]& ...
- dockerfile 镜像 指定虚拟机的内存
dockerfile eg: # sea, FROM frolvlad/alpine-oraclejdk8:slim #add volume VOLUME /tmp #add project ADD ...
- win8换win7的操作方法
详细参考UEFI与 Legacy BIOS两种启动模式详解 BIOS的两种引导模式 win8更换win7的方法的两个步骤: (1).设置BIOS支持Legacy启动,具体目标就是设置secur ...
- hadoop动态添加删除节点datanode及恢复
1. 配置系统环境 主机名,ssh互信,环境变量等 本文略去jdk安装,请将datanode的jdk安装路径与/etc/hadoop/hadoop-evn.sh中的java_home保持一致,版本ha ...
- <基础> PHP 数据类型
PHP三大数据类型 标量 字符串 单引号:不能解析变量 效率高 双引号 :可以解析变量 效率稍微低一些 heredoc : 大文本 整形 浮点 不能用于比较运算 布尔 复合 数组 超全局数组 ...
- oracle登陆认证方式
转自:http://blog.itpub.net/14359/viewspace-683064/ 案例: 1,发现此时操作系统认证不成功: C:\Users\Administrator.WIN-201 ...
- centos如何安装tomcat
1 通过 SecureCRT 连接到阿里云 CentOS7 服务器; 2 进入到目录 /usr/local/ 中: cd /usr/local/ 3 创建目录 /usr/local/tools,如果有 ...