要求
- 用C++ 实现;
- input.txt描述正规式,需要编程加以解析,该文件规定的格式为:第一行写处正规式的符号集,规定符号集为0-9共10个数字符,第二行写正规式,如:
- 0123456789
- (0|1)*0.10* (注:*表示闭包运算,.表示连接该符号可省略)
- output.txt为描述非确定有穷自动机的文件,有程序生成,生成时需按如下格式:
- 第一行写出状态集,用大写字母A-Z表示,如:ABCD
- 第二行描述自动机的符号集为0-9共10个数字符,如:0123456789
- 第三行写初态集,如:A
- 第四行写终态集,如:CD
- 第五行写出转移函数,如(A,0,B)表示A状态的出边0到达B状态。上例正规式可表为(A,0,A)(A,1,A)(A,0,B)(B,1,C)(C,0,D)(D,0,D)。
思路
使用Thompson构造法,输入为字母表Σ上的正规式,输出为相等的NFA。具体方法为:
首先将构成r的各个元素分解,对于每一个元素,按下述规则1和规则2生成NFA。(注意:如果r中记号a出现了多次,那么对于a的每次出现都需要生成一个单独的NFA。)之后依照正规表达式r的文法规则,将生成的NFA按照下述规则3组合在一起。
- 规则1 对于空记号ε,生成下面的NFA。
- 规则2 对于Σ的字母表中的元素a,生成下面的NFA。
- 规则3 令正规表达式R和S的NFA分别为N(R)和N(S)。
- 对于R|S,按照以下的方式生成NFA N(R|S)。
- 对于RS,按照以下的方式生成NFA N(RS)。
- 对于R*,按照以下的方式生成NFA N(R*)。
流程图
- 总体流程图
- 在正规式中加入省略的连接符
- 将式子转为后缀表达式
- 将后缀表达式转换成NFA
数据结构
struct edge
{
char weight;
char next;
};
string option,expression, suffix, infix, postion;
map<char, int> precedence;
map<char, vector<edge>> nfa;
vector<string> tfunction;
// 具体解释如下:
// edge:NFA图中的边;
// option:输入的符号集;
// expression:输入的正规式;
// infix:增加连接符的正规式;
// suffix:转换成的后缀表达式;
// postion:状态集;
// precedence:规定运算符优先级;
// nfa:生成的NFA(使用map生成了一个char与edge向量的映射,char代表NFA中的顶点,也就是生成了一个顶点与从顶点出发边的集合的映射);
// tfunction:转移函数。
代码详见 Github上,欢迎star!