编译原理-正则式转化为NFA代码

实验要求:
(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

================================
获取更多内容关注:信小颜
在这里插入图片描述

  • 4
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值