编译原理实验:XLEX - 词法自动生成器
本实验为华南师范大学编译原理实验二
作者:关竣佑
编译环境 Qt 4.3.0
代码仓库:https://github.com/guanjunyou/LexicalAnalysisGenerator
实现将正则表达式–>NFA—>DFA–>DFA最小化–>词法分析程序
-
正则表达式 支持单个字符,运算符号有: 连接、选择(|)、闭包(*)、括号()、可选(? )、正闭包(+ )
-
用户输入一行(一个)或多行(多个)正则表达式(可保存、打开正则表达式文件)
-
用户可以查看转换得到的NFA(用状态转换表呈现)
-
用户可以查看转换得到的DFA(用状态转换表呈现)
-
用户可以查看转换得到的词法分析程序(该分析程序用C++语言描述)
输入正则表达式可换行,换行默认在两行间加 选择(|)
可保存正则表达式 (默认保存为 regex.txt 在 release 目录下)
可选择任意正则表达式文件 (TXT格式) 载入为正则表达式输入
核心思路:
-
读入正则表达式,使用双栈法生成 NFA 图。类似于算术表达式的计算,一个栈存储正则表达式的运算符,另一个栈存储图的结构。
另外,为了方便后续的操作,还要存储每个NFA结点针对 # 边的出度和入度(不是所有的出度和入读都计入!) -
NFA转DFA图: 对每个 # 入度为0的边开始 DFS ,知道遍历到边缘点,把所有遍历到的NFA点合成为一个DFA结点,因为经历了上面的合并操作后,会出现一个DFA点有两条相同字母的出边分别连向不同的DFA点的情况,然而这是不允许的(因为路径将是不确定的),所以接着要将两条相同字母边指向的 DFA点合并为一个DFA点。
-
DFA图化简: 首先将DFA结点划分为 终态和非终态两个大的新DFA结点。放入队列中。对于每个正则表达式运算符,“过滤”一遍队列,队头弹出一个DFA点,针对该运算符求出分裂后的新的DFA点(如果对于这个运算符的边到达了不同的之前的DFA点则分裂为两个),将分裂后的DFA结点插入队尾。(可参考二叉树层序遍历的思路,逐层操作)
- 通过最简的DFA点生成C++代码
界面示意