编译原理实验——正则表达式转化为NFA

1、实验目的与内容

输入:一个正则表达式(例如“(a|b)*abb”)

输出:对应的一个NFA的mermaid语法

graph LR
0((0))-->|a| 1((1))
1((1))-->|$| 5((5))
2((2))-->|b| 3((3))
3((3))-->|$| 5((5))
4((4))-->|$| 2((2))
4((4))-->|$| 0((0))
5((5))-->|$| 4((4))
5((5))-->|$| 7((7))
6((BEG))-->|$| 4((4))
6((BEG))-->|$| 7((7))
7((7))-->|$| 8((8))
8((8))-->|a| 9((9))
9((9))-->|$| 10((10))
10((10))-->|b| 11((11))
11((11))-->|$| 12((12))
12((12))-->|b| 13((END))

对应的NFA:

a
$
b
$
$
$
$
$
$
$
$
a
$
b
$
b
0
1
2
3
4
5
BEG
7
8
9
10
11
12
END

2、程序总体设计思路和框架

总程序分为两份代码,第一份代码将一个正则表达式(regular expression)转化为后缀形式,第二份代码把得出的后缀式转化为NFA并且输出对应NFA图形的mermaid语法。

如下图:

ReExToNFA.cpp

ReExToNFA2.cpp

一个正则表达式中有四种运算符号:闭包运算符(*)、连接符(.)、或运算符(|)和括号,运算符的优先级依次递减,在中缀形式中连接符通常被省略,所以构建出的后缀式要补上连接符。得到后缀式之后,使用MYT算法根据后缀式构建NFA。

这里简单讲一下中缀转后缀的算法流程:

yes
no
yes
no
建个栈
遍历中缀式,取字符ch
ch是操作数(operand)
输出
ch是操作符(operator)
栈空?
优先:ch>top?
ch入栈
pop,输出

3、主要的数据结构和流程描述

结构体NFA的定义如下:

struct NFA
{
    set<int> Q;                  //状态集合
    set<char> sigma;             //输入字符集合
    vector<int> delta[128][128]; //状态转化函数,一个状态对应的一个输入可能有两个以上的转移,使用数组不行!!!
    int q0;                      //开始状态
    set<int> F;                  //接收状态的集合
    NFA()                        //构造函数
    {
        //memset(delta, -1, sizeof(delta));//-1表示为此状态没有此输入。
    }
} NFAinstance;

注释中已经有了详尽的说明。

4、测试结果与说明

测试结果以及输出见第2部分。

5、实验收获与反思

本实验的关键点在于:

1、中缀式到后缀式的转化。

2、MYT算法将后缀式转化为NFA。

解决了这两个问题,代码就能顺利写出了。

附录

ReExToNFA.cpp

ReExToNFA.cpp2

参考资料

[1] 中缀表达式转换为后缀表达式

[2] 《编译器设计原理》,西安电子科技大学出版社,谌志群,王荣波,黄孝喜

[3] 基于MYT算法和自顶向下算法从正则表达式到NFA

  • 6
    点赞
  • 61
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值