实验要求:
(1)程序接受文本文件中输入的正则表达式,生成该正则表达式对应的NFA,在屏幕上显示出这个NFA。
(2)统计并输出该NFA中的节点个数和边的个数;
(3)输入的正则表达式中包含的运算符包括:连接运算符”.”,闭包运算符“*”,逻辑或运算符“|”,左括号“(“,右括号“)”。
(4)输入的正则表达式中的字符限于大写英文字母,小写英文字母,数字0~9;
(5)NFA使用图的邻接链表或者邻接矩阵存储;
(6)程序的调试者和执行者保证输入的正则表达式正确,程序不检查正则表达式的正确性。
定义运算符优先关系表
import java.util.ArrayList;
import java.util.Stack;
class Arrow
{
public int nEndStateID; //箭弧终点的节点状态ID
public char chLetter; //箭弧上标注的字符
public Arrow pNextArrow; //与当前边有相同开始接点的下条箭弧
public Arrow(int a,char b,Arrow c) {
nEndStateID=a;
chLetter=b;
pNextArrow=c;
}
public Arrow() {
}
}
class state{
public int nStateID; //顶点编号,在整个NFA中定点编号是唯一的
public Arrow pFirstArrow; //当前顶点的连接的第一条箭弧的指针
public state(int a,Arrow b) {
nStateID=a;
pFirstArrow=b;
}
public state() {
}
}
public class RegToNFA {
public static void main(String[] args) {
Stack<state> pStateList=new Stack<state>(); //状态栈
Stack<Character> operatorStack=new Stack<Character>(); //符号栈
ArrayList<state> list=new ArrayList<state>();
String reg="(a|b)*.a.b.b.(a|b)*"; //a*.b*
String operator="*.|()#";
int a[][]= { //0:无优先级 1:< 2:> 3:=
//优先关系表 //* . | ( ) #
{2,2,2,1,2,2}, //*
{1,1,2,1,2,2}, //.
{1,1,1,1,2,2}, //|
{1,1,1,1,3,2}, //(
{2,2,2,0,2,2}, //)
{1,1,1,1,0,3} //#
};
int stcnt=0;
operatorStack.push('#');
reg=reg+'#';
state begin=new state(stcnt++,null);
list.add(begin);
int index=0,n=reg.length(),arrowcnt=0;
char ch=reg.charAt(index);
System.out.println(reg);
out:
while(index<n) {
if(Character.isDigit(ch)||Character.isLetter(ch)) {
state beginst=new state(stcnt++,null); //产生新节点
state endst=new state(stcnt++,null);
Arrow line=new Arrow(endst.nStateID,ch,null); //拉上箭弧
list.add(beginst);
list.add(endst);
arrowcnt++;
line.pNextArrow=beginst.pFirstArrow;
beginst.pFirstArrow=line;
pStateList.push(beginst);
pStateList.push(endst);
index++;
ch=reg.charAt(index);
}
else {
if(a[operator.indexOf(operatorStack.peek())][operator.indexOf(ch)]==3){
if(operatorStack.peek()=='('&&ch==')') {
operatorStack.pop();
index++;
ch=reg.charAt(index);
}
else if(operatorStack.peek()=='#'&&ch=='#') {
break out;
}
}
else if(a[operator.indexOf(operatorStack.peek())][operator.indexOf(ch)]==2) {
char tempch=operatorStack.peek();
operatorStack.pop();
if(tempch=='.') {
state beginA,endA,beginB,endB;
endA=pStateList.peek();
pStateList.pop();
beginA=pStateList.peek();
pStateList.pop();
endB=pStateList.peek();
pStateList.pop();
beginB=pStateList.peek();
pStateList.pop();
Arrow t=new Arrow(beginA.nStateID,'?',null);
t.pNextArrow=endB.pFirstArrow;
endB.pFirstArrow=t;
arrowcnt++;
pStateList.push(beginB);
pStateList.push(endA);
}
else if(tempch=='|') {
state beginA,endA,beginB,endB,beginC,endC;
endA=pStateList.peek();
pStateList.pop();
beginA=pStateList.peek();
pStateList.pop();
endB=pStateList.peek();
pStateList.pop();
beginB=pStateList.peek();
pStateList.pop();
beginC=new state(stcnt++,null);
endC=new state(stcnt++,null);
Arrow t1=new Arrow(beginA.nStateID,'?',null);
Arrow t2=new Arrow(beginB.nStateID,'?',null);
Arrow t3=new Arrow(endC.nStateID,'?',null);
Arrow t4=new Arrow(endC.nStateID,'?',null);
t1.pNextArrow=beginC.pFirstArrow;
beginC.pFirstArrow=t1;
t2.pNextArrow=beginC.pFirstArrow;
beginC.pFirstArrow=t2;
t3.pNextArrow=endA.pFirstArrow;
endA.pFirstArrow=t3;
t4.pNextArrow=endB.pFirstArrow;
endB.pFirstArrow=t4;
list.add(beginC);
list.add(endC);
arrowcnt+=4;
pStateList.push(beginC);
pStateList.push(endC);
}
else if(tempch=='*') {
state beginA,endA,beginC,endC;
endA=pStateList.peek();
pStateList.pop();
beginA=pStateList.peek();
pStateList.pop();
beginC=new state(stcnt++,null);
endC=new state(stcnt++,null);
Arrow t1=new Arrow(beginA.nStateID,'?',null);
Arrow t2=new Arrow(endC.nStateID,'?',null);
Arrow t3=new Arrow(beginA.nStateID,'?',null);
Arrow t4=new Arrow(endC.nStateID,'?',null);
t1.pNextArrow=beginC.pFirstArrow;
beginC.pFirstArrow=t1;
t2.pNextArrow=endA.pFirstArrow;
endA.pFirstArrow=t2;
t3.pNextArrow=endA.pFirstArrow;
endA.pFirstArrow=t3;
t4.pNextArrow=beginC.pFirstArrow;
beginC.pFirstArrow=t4;
list.add(beginC);
list.add(endC);
arrowcnt+=4;
pStateList.push(beginC);
pStateList.push(endC);
}
}
else if(a[operator.indexOf(operatorStack.peek())][operator.indexOf(ch)]==1) {
operatorStack.push(ch);
index++;
ch=reg.charAt(index);
}
}
}
//开始结点与状态栈中的结点连接
state beginA,endA;
Arrow temp;
endA=pStateList.peek();
pStateList.pop();
beginA=pStateList.peek();
pStateList.pop();
Arrow t=new Arrow(beginA.nStateID,'?',null);
begin.pFirstArrow=t;
arrowcnt++;
System.out.println("stcnt="+stcnt);
System.out.println("arrowcnt="+arrowcnt);
for(int i=0;i<stcnt;i++) {
System.out.print(i);
temp=list.get(i).pFirstArrow;
while(temp!=null) {
System.out.print("[-"+temp.chLetter+"->"+temp.nEndStateID+"]");
temp=temp.pNextArrow;
}
System.out.println();
}
}
}
运行结果:
(a|b).a.b.b.(a|b)#
stcnt=23
arrowcnt=28
0[-?->7]
1[-a->2]
2[-?->6]
3[-b->4]
4[-?->6]
5[-?->1][-?->3]
6[-?->5][-?->8]
7[-?->8][-?->5]
8[-?->9]
9[-a->10]
10[-?->11]
11[-b->12]
12[-?->13]
13[-b->14]
14[-?->21]
15[-a->16]
16[-?->20]
17[-b->18]
18[-?->20]
19[-?->15][-?->17]
20[-?->19][-?->22]
21[-?->22][-?->19]
22
================================
获取更多内容关注:信小颜