编译原理:如何根据DFA生成正则表达式

编译原理:如何根据语言/DFA生成正则表达式

前言

最近在复习编译原理,遇到了给出语言,生成正则表达式的题目,发现呆坐法并不能成功解决类似题目,并发现大多此类问题都可以先根据语言画出一个DFA,但是DFA如何转正则表达式呢?
网上和书本上只有正则表达式如何转换成NFA,DFA的方法,遍历整个网络,也没有找到反向转换的方法……

但是书本上说,DFA和正则表达式又是一一对应的。

所以!!一定存在某种方法!功夫不负有心人,终于让笔者发现啦哈哈哈

两种方法

有两种比较流行的转换方法,分别是:

  1. Arden’s Method ,但是我没有研究这个方法,我们研究第二种吧!
  2. State Elimination Method,状态终结法,终结它吧!!从此将语言转换为正则表达式再也不用使用瞪眼找规律法了!

let us begin!

对于任何给出的DFA,我们只需要经过以下几步,就可以得到正则表达式!

step 1

The initial state of the DFA must not have any incoming edge.

DFA自动转换机的初始状态不可以有任何的入边,如果有入边,就要新产生一个初始状态,以空指向原来的初始状态!
初始状态不可以有任何的入边

step2

If there exists multiple final states in the DFA, then convert all the final states into non-final states and create a new single final state.

如果DFA有多个终态(接受态),那么要把所有接受态以空边指向新的接受态,使得DFA只有一个接受态
DFA只有一个接受态

step 3

If there exists any outgoing edge from the final state, then create a new final state having no outgoing edge from it.

DFA自动转换机的终态如果有任何出边,创建一个新的终态没有出边
在这里插入图片描述

step 4

Eliminate all the intermediate states one by one.

These states may be eliminated in any order.

In the end,

  • Only an initial state going to the final state will be left.
  • The cost of this transition is the required regular expression.

可以以任意顺序终结状态,只留下从初态到终态,转换边上的表达式即为所求正则表达式。

  • 10
    点赞
  • 47
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
这是一段识别gbk中文和英文的标识符正则表达式 ([a-zA-Z_]|[\x81-\xfe][\x40-\xfe])([a-zA-Z0-9_]|[\x81-\xfe][\x40-\xfe])* 原理是通过正则表达式的AST直接构造DFA自动机 下面是elalr解析形如 add(1, add(...) , ...) + (12*4) *4 这样的表达式的文法 通过这样的文法 LALR(1)可以描述几乎所有的CFG文法 也就是说可以解析 HTML JSON XML C/C++ JAVA 基本上所有的语言 网上也有很多他们的文法 可以比着写一下 %左结合 '+' '-' '*' '/'; //定义优先级与结合性%开始符 表达式; // 这句的意思是 文法的开始就是 '表达式'表达式 -> 表达式 '+' 表达式  [表达式_相加] |  // 这是表达式的5个产生式 也就是说表达式可以用5种格式组成 [] 中包括的内容就是遇到这个形式的产生式将会调用什么子程序               表达式 '-' 表达式   [表达式_相减] |               表达式 '*' 表达式  [表达式_相乘] |               表达式 '/' 表达式  [表达式_相除] |               '(' 表达式 ')'         [表达式_括号] ;表达式 -> 数字 | 函数调用 ; // 这里是表达式的另外两个产生式 表达式可以是函数调用 也可以是数字数字 -> "[0-9]+" [表达式_值] ;函数调用 -> 标识符 '(' 参数列表 ')' [表达式_函数调用] ; // 函数调用的产生式 用来表述函数调用的形式参数列表 -> 参数列表 ',' 表达式 [参数表_加入] |  // 这个产生式是左递归的 只要后面出现 ',' 就会调用 参数表_加入 向数据中加入后面的表达式                   表达式 [参数表_创建] ; 标识符 -> "([a-zA-Z_]|[\x81-\xfe][\x40-\xfe])([a-zA-Z0-9_]|[\x81-\xfe][\x40-\xfe])*"; // 中文标识符 %无结合 为没有结合性但会定义优先级 %左结合 为左结合性以及定义优先级 %右结合 为左结合性以及定义优先级 'xxx' 单引号包裹的是 文本字面量 如 'if' 注意:内含转义 "xxx" 双引号包裹的是正则表达式 bracket 支持的正则语法比较简单 但也可以描述大部分正则了 不支持negative bracket () . * + ? []

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值