词法分析:从RE(正则表达式)到DFA(确定的有限状态机)

正则表达式和自动机(DFA&NFA) 文章目录一 正则表达式匹配原理1.1 正则表达式1.2 DFA1.3 正则表达式和DFA的关系1.4 正则匹配过程二 DFA的构建三 DFA与正则的转化3.1 DFA转正则表达式3.2 正则表达式转DFA3.2.1 正则表达式转NFA3.2.2 NFA确定化四 js中的正则 一 正则表达式匹配原理 1.1 正则表达式 正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑。例如,筛选所有以包含连续 阅读详情

模式识别(Pattern recognization)是现在非常流行的一个词,我们对词法的分析也是基于模式(pattern-based)的。我们用正则表达式(Regular Expression)来定义单词的模式,而在词法分析时,有限状态机(Finite Automata)更便于我们分析。本文介绍将正则表达式(RE)转为确定的有限状态机(DFA)的方法。
首先,什么是确定的有限状态机,什么是非确定的有限状态机(NFA)?用通俗的语言讲,在面对相同的输入参数时,NFA可能会跳转到多种状态,而DFA只会跳转到特定的状态,有DFA类似于函数,而NFA类似一对多的映射。
DFA用程序可以描述为:

state = 1;
while (true) {
    ch = getChar();
    switch(state) {
    case 1:
        if (ch == 'a')
            state = 1;
        else if (ch == 'b')
            state = 2;
        else error();
        break;
    case 2://终止状态
        if (ch == 'a') state = 2;
        if (ch == '1') state  =2;
        else {
            ungetChar();//把取出的字符放回去
            return ID;
        }
    }
}

从上面的代码段,我们需要知道:

  • DFA=>program:从确定的有限状态机可以生成确定的程序
  • Each state=>a fragment of code:每个状态对应一个case。
  • Each edge=>a judgement:每条边对应一个if判断

从RE推出DFA的步骤:RE=>NFA=>DFA=optimization=>DFAo=>program

1. 从RE到NFA

从正则表达式到非确定的有限状态机对于人来说非常好理解,但是对于机器来说确比较复杂。从RE到DFA有两种方法:自顶向下逐步分解法和自下而上组合方法(Thompson方法)。

自顶向下逐步分解法:Top-down stepwise refinement according to the structure of RE

这种方法符合人的思维习惯,首先我们从最简单的情况开始考虑。
base
以(a|b)* a (a|b) (a|b)为例,这个正则表达式符合上面的αβ特征,因此第一步可以变成:
base1
而对于(a|b)*,又符合上面的a*特征,因此(a|b)*可以继续分解为
base2
可以看到a|b还可以继续分解,类似这样的分解过程到所有边的标记只剩下ε或字母表的单一字符为止。
然而,对于计算机来说,字符是一个一个读入的,计算机不能从整体把握情况逐步向下分解,因此我们还需要适合计算机的方法。

自下而上组合法:Bottom-up combination(Thomson方法)

这种比前一种方法稍微复杂一点,但其实想法也很简单,我试着换一种表述来解释这个方法。
在遇到单个的字符时,我们直接构造转换图,比如遇到a时,我们就构造这样的转换图:
a
这样,我们就形成了一个单元U,这个U就是上面已经生成的转换图。
在遇到操作符时,我们所有的处理都是针对单元的,在下面的图示中,我们用虚线圆圈表示一个单元。
op
在处理完操作符后形成的仍是一个单元,处理完后的整体变成单元U’参与下一次处理。这里类似于一种递归的过程。
但是,像a|b这样的式子,在处理‘|’这个操作符时,我们显然需要两个单元,但计算机在读到‘|’操作符时,我们在为a构造了转换图,计算机还不知道b的存在,也就不能做上面这样的处理,所以这种方法需要以下条件:

  • 正则表达式(RE)需要处理为后缀表达式
  • 正则表达式(RE)中需要写明操作符‘.’,如ab需要写为a.b

满足以上条件后,计算机可以用这种方法自动生成NFA。

2. 从NFA到DFA

对于一个已经形成的NFA,我们需要定义新的状态来形成DFA。首先要解释两种方法和他们对应的使用情形。
NFA之所以为NFA而不是DFA,主要是因为以下两个原因,解决以下的两种情形,就能将NFA转为DFA。

边上的ε:ε闭包

dfa
遇到这种情况,后面的三个状态完全可以合并,如果将后面的三个状态合为一个,那这个转换图里就没有ε边,也就满足了DFA的条件。
对应的解决方法是找出ε闭包,也就是先找出该状态的ε边推出的所有状态,再找那些状态的ε边推出的状态,是一个迭代的过程,直到找出一个状态的ε闭包。如果是从状态x开始的,我们将通过该过程找到的所有状态集称为以x状态为核的ε闭包,记为ε-closure({x}),或ε-c({x})。从定义可以知道,核相同,推出的ε闭包一定相同。

不确定的后续状态:子集构造法

dfa
遇到这种情况,如果能将状态2和状态3合并到一起,就不会出现“面对相同的输入状态可能跳转到多种状态的情形了”,合并状态2和状态3这样类似的状态的方法叫做子集构造法,若从状态Ii开始,以a边推出的所有状态集合为B,我们记为Ii–a–>B,比如上图可以记为1-a->{2,3}

综合使用:表驱动法

上面只是简单介绍了两种情形,说明了从NFA转化到DFA的重点是重新组合NFA状态。下面我们讨论系统的可编程的过程来将NFA转化为DFA,运用的还是上面的两种方法,我们需要构建一张表来展示构建的DFA里的所有状态。
以下图中的NFA为例:
nfa example

DFA State Ii (这里是新生成的DFA里的状态)a(这个状态从a边推出什么状态)b (这个状态从b边推出什么状态)
I0=ε-c({x})={x,5,1}ε-c(I0-a->{5,3})={5,3,1}=I1ε-c(I1-b->{5,4})={5,4,1}=I2
I1={5,3,1}……
I2={5,4,1}……

解释:首先从起点x开始构造新的DFA里的第一个状态I0,也就是寻找以x为核的ε闭包ε-c({x}),然后构造新的I0从a、b边推出的状态,方法是先使用子集构造法,再寻找构造后的子集的ε闭包。这样我们就找到了新的状态I1,I2,第二行、第三行就是寻找I1,I2以a、b边推出的状态,这样就能找到更多的状态,当没有新的状态产生时,这样的过程终止。这类似于一种迭代的过程。
这题最终的结果是:
resut

3. 从DFA到DFAo(DFA优化)

在上面生成的DFA中,每个状态都有以a、b推出的状态,有时候这可能意味着多余。DFA优化(Optimization of a DFA)的思想是减少DFA中的状态,我们用到离散数学中等价类划分的思想,如果两个状态等价,那么他们属于同一个等价类,我们只需要选择其中的一个代表即可。
如何划分等价类呢?

1)找出终止状态

什么样的状态可以被称为终止状态呢?在上例的NFA图中,y状态为终止状态。我们要做的是在I0~I6中找出终止状态。我们这样定义新的DFA中的终止状态:若Ii∩y ≠∅,则Ii为DFA中的终止状态。
因此第一步我们将上面的状态分为两类:终止状态和非终止状态。
optimization

2)划分等价类

第一步已经将状态分为了两类,下面我们要继续拆分。我们规定这样的这样的状态Ii,Ij属于同一个等价类:

  • Ii,Ij发出的边数相同。
  • Ii,Ij发出的边相同。
  • 对应相同的边连接的状态属于同一个等价类。

如I0和I1,他们对应的a边发出的状态分别是I1和I3,而在第一步中这两个状态已经被划分到了两类里,一定不是等价的,所以我们将I0,I1拆分,也就是将I0单独分出去。
op

3)回头看

在划分完后面的等价类时,我们还要回头看一下前面的等价类还可不可以划分。有时候前面在比较时后面的类还没有划分,因此判断属于同一个等价类不拆分,而到后面等价类判断时拆分了这个等价类,前面判断的两个状态可以就到了不同的等价类里,这就需要我们回头检查是不是所有的类都不能再拆分了。

4)选取代表

分好等价类后每个类选取一个状态作为代表,这个类的其他状态都用这个代表代替,重新构造DFA转化图。

这样,我们就将RE转换成优化后的DFA,尽管过程比较复杂,但是这样机械而固定的过程是可以编程解决的。在构造完DFA后,我们可以开始做更多的词法分析工作。

C++实现正则表达式转最小化DFA过程详解 目前学校正在开编译原理这门课。为了加深对正则表达式转最小化DFA的理解,利用c++编写了这个程序。现在把我的程序及实现的方法分享出来,希望能对大家的学习有所帮助。 本文主要从以下几个方面进行讲解正则表达式操作数运算符算法流程1.正则表达式的预处理2.中缀表达式转后缀表达式3.后缀表达式创建NFA4.NFA转化为DFA5.DFA的最小化合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片... 阅读详情

相关推荐

南开编译原理期末核心:词法分析与LL(1)语法分析实战精要

词法分析器与LL(1)语法分析是编译原理课程的两大基石,其本质是将正则表达式和上下文无关文法转化为可执行的状态机与预测分析表。理解DFA构造过程与FIRST/FOLLOW集计算逻辑,不仅关乎理论正确性,更直接影响语法分析器的可调试性与工程落地能力。在教学实践中,手写状态迁移、显式填表、冲突标注等规范操作,已成为高校期末考核与考研复试的关键能力指标。本文聚焦南开大学编译原理真题场景,以词法分析器实现和LL(1)预测分析表构建为双主线,系统拆解从正则表达式到token序列、从文法定义到推导步骤的完整技术链路,助

weixin_33766805的博客 346

正则表达式转NFA(C++代码)

#include <iostream> #include <vector> #include <string> #include <map> #include <stack> #include <fstream> using namespace std; class NFA { string name; // NFA name string re; // 正则表达式 string re_

qq_44951010的博客 6235

正则式转成最小DFA C++编写 设计含文档

正则式转成最小DFA C++编写 设计含文档 正则式转成最小DFA C++编写 设计含文档

正则到DFA

将正则表达式翻译成DFA的最简单算法是通过中间构造,在它之中,正则表达式派生出一个NFA,接着就用该NFA构造一个同等的DFA。。因此我们只关心两个算法:一个是将正则表达式翻译成N FA,另一个是将N FA翻译成D FA。构造一个扫描程序的自动过程可分为3步,如下所示:    (1)利用Thompson结构将正则表达式转换成NFA 基本正则表达式 基本正则表达式格式a、 或,其

Gikieng的奋斗路 2349

树莓派5安装ROS2小白指南避坑攻略

手把手教你如何在树莓派5上顺利安装ROS2,避开常见问题与陷阱,提升配置效率。针对树莓派5安装ros2过程中的依赖冲突、源配置错误等高频难题提供解决方案,适合新手快速上手。

weixin_35754962的博客 1004

基于4G cat.1的低功耗车牌识别摄像头模组介绍

在消费类摄像头领域,4G低功耗相机已经非常普遍,在可视门锁,婴儿看护,户外监控等领域都获得了很好的应用.但是在工业领域,低功耗相机的应用还不是那么广泛.这里要介绍一款基于4G cat.1的低功耗车牌识别摄像头模组,在待机状态只有MCU和毫米波雷达以1Hz的频率工作,功耗低至500uA,并可以通过4G模块远程唤醒模组.

bindaz的专栏 1647

正则表达式(RE)、有限自动机(FA)和词法分析(LA)

关键词:正则表达式、RE、有限自动机、DFA、NFA、词法分析器、Thompson算法、子集构造算法、Hopcroft算法

Dong_HFUT的博客 7646

Centos7搭建OpenStack+创建iaas云主机

主要说明在控制节点和计算节点上,通过脚本的形式,安装OpenStack的iaas安装步骤和创建可运行的云主机。提供实施简单、可大规模扩展、丰富、标准统一的云计算管理平台。

weixin_48218106的博客 1万+

编译原理:词法分析(正则表达式->NFA->DFA->最小化DFA)

本文是作者对之前编译原理课程项目中词法分析模块的正则表达式->NFA->DFA->最小化DFA功能的总结归纳和思路整理展示,并结合一个具体用例帮助读者更好地了解其中转化思路和算法设计。

weixin_50833596的博客 2217

Windows平台MuJoCo仿真环境配置与Qt集成实战

本文详细介绍了在Windows平台上配置MuJoCo物理仿真环境并与Qt框架集成的完整实战流程。内容涵盖从环境准备、库文件配置、项目创建到核心代码编写的每一步,重点解决了Windows下常见的编译链接错误和路径问题,帮助开发者在Windows系统中高效搭建机器人仿真与可视化控制开发环境。

weixin_29221753的博客 171

薛定谔虚拟筛选实战:如何用PDB文件快速构建受体格点(避坑指南)

本文提供了薛定谔虚拟筛选实战指南,聚焦于如何从PDB文件快速、精准地构建受体格点。文章详细解析了可变残基的理性处理策略、基于配体尺寸的盒子量化设置方法,并分享了高级约束与排除体积的实战技巧,旨在帮助用户避开常见陷阱,提升虚拟筛选的成功率与效率。

weixin_28419039的博客 252

编译原理之正则表达式RE和词法分析NFA(第一篇)

编译器,词法分析器,NFA,DFA

Lue的博客 1584

虚幻引擎5 AR开发教程02:构建和测试AR Android App

在本教程中,我们将学习如何在虚幻引擎 5 上构建和测试 AR 安卓应用。

mopanchun的博客 2650

【编译原理】编译原理知识点汇总·词法分析器(正则式到NFA、NFA到DFA、DFA最小化)

通过上面的学习,我们已经对文法和词法有了更深入的理解。 词法就是字母如何组成单词———采用正则表达式就可以定义组成规则。 文法就是单词如何组成句子———采用产生式+推导就可以定义文法。 词法分析器的任务 判断单词是否符合正则表达式的规则。 明确给出合法单词的属性Token(保留字、标识符、运算符、界符、常量等)。

十二月的猫 2698

基于simulink的智能驾驶领域--智能车道保持辅助系统仿真

LKAS通过摄像头等传感器检测车辆相对于车道线的位置,并自动调整转向,以帮助驾驶员保持在车道内行驶。将摄像头传感器模块的输出连接到车道线检测模块的输入端口,再将车道线检测模块的输出连接到转向控制器模块的输入端口,最后将转向控制器模块的输出连接到车辆动力学模型的转向输入端口,形成闭环控制系统。上升时间是指系统从初始转向角上升到目标转向角所需的时间,调节时间是指系统进入并保持在目标转向角一定范围内的所需时间。该控制器将根据摄像头传感器的数据调整车辆的转向角,以保持车辆在车道内行驶。

xiaoheshang_123的博客 162

【网络安全】浅谈数据库攻击复现及相关安全优化

4、准备数据库服务器为了安全正式环境应该把数据库单独放一台服务器,只允许让应用服务器 IP 来访问数据库服务器,通过独立两者,就算其中一台发生问题,另一台也是好的,进一步降低了危险性。5、定时备份数据库开发定时备份功能,可以使用 Crontab,或者其他框架,设定周期备份数据,哪怕是数据丢失或被删除也可以快速恢复。

2401_88545587的博客 221

INT201 决策,计算,语言 笔记

xjtlu INT201 课程的个人总结笔记

sanmusen_wu的博客 5708

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

C++ 正则表达式

正则表达式 正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑。 正则引擎主要可以分为两大类:一种是DFA,一种是NFA。主流的正则引擎又分为3类:1. DFA引擎 DFA 引擎在线性时状态下执行,因为它们不要求回溯(并因此它们永远不测试相同的字符两次)。DFA 引擎还可以确保匹配

singebogo的博客 880

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

Engineering a Compiler读书笔记(2):词法分析器

词法分析器 简介: || 词法分析流程: 读取字符流,,并应用一组规则来判断每个单词在源语言中是否合法,如果单词判断为有效,则会给它分配一个词类,将其聚合形成单词流。 || 手工编写的词法分析器因为避免了很多不必要的开销,故比生成的词法分析器,带来极大的性能优势的好处,往往超出了自动生成语法分析器的便利性带来的好处 || 程序设计语言的词法结构(微语法):规定了如何将字符组合为单词 (注意:语法是...

fang 0 jun的博客 774

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

编译器的编译基本过程

编译器最基本的功能就是把高级语言(例如C/Fortran)编写的代码转化为机器指令(就是01串),从这个角度来说它本质上是个转换过程。经典的编译过程主要包括: 1、词法分析(Lexical Analysis) 词法分析就是从输入代码中识别出各种记号(token),例如对于C语言我们就需要知道if,else等是语言的关键字,myvar是个标识,而123myvar不能被识别为一个标识。负责实现

u012388497的专栏 643

编译器基本过程

编译器最基本的功能就是把高级语言(例如C/Fortran)编写的代码转化为机器指令(就是01串),从这个角度来说它本质上是个转换过程。经典的编译过程主要包括: 1、       词法分析(Lexical Analysis) 词法分析就是从输入代码中识别出各种记号(token),例如对于C语言我们就需要知道if,else等是语言的关键字,myvar是个标识,而123myvar不能被识别为一个标识

Heron——Linux & ARM 1907

【编译原理】编译器的编译基本过程

编译器的编译基本过程 原文出处: 崤嶙的博客 编译器最基本的功能就是把高级语言(例如C/Fortran)编写的代码转化为机器指令(就是01串),从这个角度来说它本质上是个转换过程。经典的编译过程主要包括: 1、词法分析(Lexical Analysis) 词法分析就是从输入代码中识别出各种记号(token),例如对于C语言我们就需要知道if,else等是语言的关键字,myvar

CPP工程师的专栏 3366
上一篇: 补充:消除epsilon产生式等
下一篇: 从上下文无关文法(CFG)到语法分析树——LL(1)分析法
cuiods
博客等级 码龄12年 41粉丝 15原创
评论 17
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值