2019编译原理实验报告存档(2)

LL(1)分析器,借鉴了别人的代码
LL(1)部分

/* (1)E->TG
 * (2)G->+TG|-TG
 * (4)G->@
 * (5)T->FS
 * (6)S->*FS|/FS
 * (8)S->@
 * (9)F->(E)
 * (10)F->i
 * */
package e1902;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.*;
public  class e1902 {
    static char vn[] ;
    //创建非终结符数组
    static char vt[] ;
     //终结符,并加入了#方便follow集时查找,@代表空
    boolean first[][] = new boolean [vn.length][vt.length+1];
    //所有非终结符first集的集合,每行最后一个元素用来判断是否求过first集
    boolean follow[][] = new boolean [vn.length][vt.length+1];
    //所有非终结符follow集的集合,每行最后一个元素用来判断是否求过follow集
    String analyse[][] = new String [vn.length][vt.length-1];
	//创建预测分析表
	static String verbs[] ;
	  //文法
	static window windows;
	static String rowdata[][] = new String[50][5];//添加到窗口表格里的数组
	static final String path ="D://Eclipse/e1902.txt";
	e1902(String verbs[],char vn[],char vt[]) {
		first_final(vn,vt,verbs);//求first集
		follow_final(vn,vt,verbs);//求follow集
		create(verbs,vn,vt);//建分析表
	}//class e1902的构造方法
	public static void main(String args[]) throws Exception{
		int i ,j ,k=0,flag=0;
		char c;
		char temp2[] = {'0','0','0','0','0','0','0','0','0','0'};
		ArrayList<String> list = new ArrayList<String>();
		File file = new File(path);
	    BufferedReader br = new BufferedReader(new FileReader(file));
		String temp;
	    while((temp = br.readLine())!= null){
			list.add(temp);
		}
		br.close();//关闭文件
		verbs = new String[list.size()];
		for( i =0;i < list.size();i++){
			verbs[i] = list.get(i);
		}
		for(i = 0 ;i<verbs.length;i++){
			c = verbs[i].charAt(0);
			for(j=0;j<10;j++){
				if(c == temp2[j]){
					flag = 1;
					break;
				}
			}
			if(flag == 0){
				temp2[k] = c;
				k++;
			}
			flag = 0;
		}
		k=0;
		for(i=0;i<10;i++){
			if(temp2[i] != '0'){
				k++;
			}
		}
		vn = new char[k];
		for(i= 0;i<k;i++){
			vn[i] = temp2[i];
		}
		k=0;
		flag = 0;
		char temp3[] = {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
		for(i=0;i<verbs.length;i++){
			for(j=3;j<verbs[i].length();j++){
				if( verbs[i].charAt(j) != '|' && (verbs[i].charAt(j)<'A' || verbs[i].charAt(j)>'Z') && verbs[i].charAt(j) != '@' ){
					temp3[k] = verbs[i].charAt(j);
					k++;
				}
			}
		}
		int len = 0;
		char temp4[] =  {'0','0','0','0','0','0','0','0','0','0'};
		for(i=0;i<k;i++){
			c = temp3[i];
			flag = 0;
			for(j=0;j<10;j++){
				if( c == temp4[j]){
					flag = 1;
					break;
				}
			}
			if(flag == 0){
				temp4[len]=c;
				len++;
			}
		}
		k=0;
		for(i=0;i<10;i++){
			if(temp4[i] != '0'){
				k++;
			}
		}
		vt = new char[k+2];
		for(i= 0;i<k;i++){
			vt[i] = temp4[i];
		}
		vt[k] = '#';
		vt[k+1] = '@';
		
		
		window windows = new window(rowdata,vn,vt,verbs);
		
        if(isleft(verbs,vn,vt) == true){
			windows.textshow.append("文法包含左递归,ERROR!");
			return;
		}
		
		e1902 e = new e1902(verbs,vn,vt);
		for(i = 0;i<vn.length;i++){
			temp = "  FIRST("+vn[i]+")={ ";
			for(j= 0 ;j<vt.length;j++){
				if(e.first[i][j] == true){
					if(vt[j] == '@'){
						temp = temp + 'ε' + " ";
					}
					else{
						temp = temp + vt[j] + " ";
					}
				}
			}
			temp = temp + "}\n";
			windows.textshow.append(temp);
		}//向窗口输出FIRST集
		for(i = 0;i<vn.length;i++){
			temp = "  FOLLOW("+vn[i]+")={ ";
			for(j= 0 ;j<vt.length;j++){
				if(e.follow[i][j] == true){
					temp = temp + vt[j] + " ";
				}
			}
			temp = temp + "}\n";
			windows.textshow.append(temp);
		}//向窗口输出FOLLOW集
		temp = "analyze table:\n";
		windows.textshow.append(temp);
		temp = "\n";
		windows.textshow.append(temp);
		temp = "             ";
		windows.textshow.append(temp);
		for(i = 0;i<vt.length-1;i++){
			temp =  vt[i]+"                         ";
			windows.textshow.append(temp);
		}//输出表头
		temp = "\n";
		windows.textshow.append(temp);
		for(i = 0; i< vn.length;i++){
			temp = "\n";
			windows.textshow.append(temp);
			temp = "  " + vn[i] + "          ";
			for(j = 0; j < vt.length -1; j++){
				if(e.analyse[i][j] != null){
					temp = temp + vn[i] + "->" + e.analyse[i][j] +"              ";
				}
				else{
					temp = temp + "                          ";
				}
			}
			temp = temp + "\n";
			windows.textshow.append(temp);
		}
	}	
	static boolean isleft(String verbs[],char vn[],char vt[]){
		int i,j,k;
		for(i =0;i < verbs.length;i++){
			j=3;
			k = indexofor(3,verbs[i]);
			if(k == -1){
				k = verbs[i].length();
			}
			while(j < verbs[i].length()){
				if(verbs[i].charAt(0) == verbs[i].charAt(j)){
					return true;//直接左递归
				}
				j = k+1;
				k = indexofor(j,verbs[i]);
				if(k == -1){
					k = verbs[i].length();
				}
			}
		}
		int m,p;
		char u ;
		String temp;
		for(i=0;i<verbs.length;i++){
			j = 3;
			u = verbs[i].charAt(0);
			k = indexofor(3,verbs[i]);
			if(k == -1 ){
				k = verbs[i].length();
			}
			while(j < verbs[i].length()){
				if(vn(verbs[i].charAt(j),vn) != -1){
					//右侧第一个字符是非终结符
					temp = verbs[vn(verbs[i].charAt(j),vn)];
					m=3;
					p = indexofor(3,temp);
					if(p == -1 ){
						p = temp.length();
					}
					while(m < temp.length()){
						if(u == temp.charAt(m)){
							//含有间接左递归
							return true;
						}
						m = p+1;
						p = indexofor(m,temp);
						if(p == -1 ){
							p = temp.length();
						}
					}
				}
				j = k+1;
				k = indexofor(j,verbs[i]);
				if(k == -1 ){
					k = verbs[i].length();
				}
			}
		}
		return false;
	}
    //判断是否含有左递归,若含有左递归,直接终止程序,报错
	int indexofx(char c, String s){
		int i;
		for(i = 3;i<s.length();i++){
			if(s.charAt(i) == c){
				return i;//返回C的位置
			}
		}
		return -1;//没有c返回-1
	}
	//对于String类的求字符位置
	static int indexofx(char c, char s[]){
		int i;
		for(i = 3;i<s.length;i++){
			if(s[i] == c){
				return i;
			}
		}
		return -1;//没有c返回-1
	}
	//对于char[]类的求字符位置
	static int indexofor (int i,String s){
		for(i=i+1;i<s.length();i++){
			if(s.charAt(i) == '|'){
				return i;
			}
		}
		return -1;//-1表示没有‘|’
	}
	 //indexofor函数返回产生式右边‘|’的位置	
	static int vn(char a,char c[]){
		int i ;
		for(i=0;i<c.length;i++){
			if(c[i] == a){
				return i;
			}
		}
		return -1;//-1表示a不是非终结符
	}
	 // vn 函数返回a在非终结符数组中的位置	
	static int vt(char a, char c[] ){
		int i ;
		for(i=0;i<c.length;i++){
			if(c[i] == a){
				return i;
			}
		}
		return -1;//-1表示a不是终结符
	}
	// vt 函数返回a在终结符数组中的位置
	void fir(String s,int i , char vn[],char vt[],String verbs[]){
		int c = vn(s.charAt(0),vn);
		//c是这一条产生式左侧的非终结符,c为非终结符数组中的位置,同时也是first[][]中行数
		int k;
		if(vt(s.charAt(i),vt) != -1){
			first[c][vt(s.charAt(i),vt)] = true;//写入first集
		}//右侧第一个字符是终结符,直接写入first集
		else{
			//当前判断的字符式是非终结符
			if(first[vn(s.charAt(i),vn)][vt.length] == false){
				first(s.charAt(i),vn,vt,verbs);//i是非终结符,并且还未求first集,先求出first集
			}
			for(k=0;k<vt.length;k++){
				if(first[vn(s.charAt(i),vn)][k] == true && vt[k] != '@'){
					first[c][k] = true;//把i的first集中除了空串的终结符给c的first集
				}
			}
			if(first[vn(s.charAt(i),vn)][vt('@',vt)] == true){
				//此时i的first集中有空串
				if(i == s.length() - 1){
					//i是产生式最后一位
					first[c][vt('@',vt)] = true;
					return;//这条产生式结束。准备扫描下一条
					//规则四:A->BCD......,BCD...的first集中都含有空,则把空写入c的first集中
				}
				if( s.charAt(i+1) != '|'){
					//规则四:A->BCD......,将BCD...的first集-@写入c的first集中
					i++;//指向后一个字符
					fir(s,i,vn,vt,verbs);//迭代将产生式中所有连续非终结符的first集都求出来
				}
				else{
					//i+1是 | ,这条产生式暂时结束,同上一个if,每个first集都有@,写入@
					first[c][vt('@',vt)] = true;
				}
			}
		}
	}
	//求某一条产生式的first集,此时并不是某一个非终结符的first集,因为有的非终结符有多条产生式	
	void first(char c,char vn[],char vt[],String verbs[]){
		int i,j;
		String s;
		for(i=0;i< verbs.length;i++){
			s = verbs[i];
			if( c == s.charAt(0)){
				//找到c的产生式
				j=3;
				if(s.charAt(0) != s.charAt(j)){
					fir(s,j,vn,vt,verbs);//求关于这条产生式的first集
				}
				while( indexofor(j,s) != -1 && j < s.length()){
					//判断这条产生式有没有‘|’
					j = indexofor(j,s);//定位到下一条‘|’
					j++;
					if(s.charAt(0) != s.charAt(j)){
						fir(s,j,vn,vt,verbs);//求关于这条产生式的first集
					}
				}
			}
		}
		first[vn(c,vn)][vt.length] = true;//标记已经求过这个非终结符的first集
	}
	 //求某一个非终结符的first集	
	void first_final(char vn[],char vt[],String verbs[]){
		int i;
		for(i=0;i<vn.length;i++){
			if(!first[i][vt.length] ){
				//当这个非终结符的first集还没求,求first集
				first(vn[i],vn,vt,verbs);
			}
		}
	}
	//求所有非终结符的first集
	void fol(String s,int j,char vn[],char vt[],String verbs[]){
		int i;
		if(j == s.length()-1 ||(j < s.length()&& s.charAt(j+1) == '|')){
			if(s.charAt(0) != s.charAt(j)){
				if(follow[vn(s.charAt(0),vn)][vt.length] == false){
					//如果左边非终结符的follow集还没求,先求左边
					follow(s.charAt(0),vn,vt,verbs);
				}
				for(i=0;i<vt.length;i++){
					if(follow[vn(s.charAt(0),vn)][i] == true){
						//把左侧非终结符的follow集给i
						follow[vn(s.charAt(j),vn)][i] = true;
					}
				}
				
			}	
		}
		if(j<s.length()-1 && s.charAt(j+1) != '|'){
			//i右侧还有字符
			if(vt(s.charAt(j+1),vt) != -1){
				//右侧字符是终结符
				if(vt[vt(s.charAt(j+1),vt)] != '@'){
					//同时右侧字符不是空,将右侧字符写入i的follow集中
					follow[vn(s.charAt(j),vn)][vt(s.charAt(j+1),vt)] = true;
				}
			}
			else{
				//右侧字符是非终结符
				for(i=0;i<vt.length;i++){
					if(first[vn(s.charAt(j+1),vn)][i] == true && vt[i] != '@'){
						//把右侧字符的first集-@给i的follow集
						follow[vn(s.charAt(j),vn)][i] = true;
					}
				}
				if(s.charAt(0) == s.charAt(j)){
					return;
				}
				boolean flag = true;//右侧非终结符的first集中有@时为true
				for(i=j+1;i<s.length();i++){
					if(vt(s.charAt(i),vt) != -1){
						//右侧字符有终结符
						flag = false;
						break;
					}
					if(s.charAt(i) == '|'){
						break;//遇到‘|’跳出
					}
					if(first[vn(s.charAt(i),vn)][vt('@',vt)] == false){
						flag = false;
					}
				}
				if(flag){
				    //当前字符的右侧字符的first集里有@
					if(follow[vn(s.charAt(0),vn)][vt.length] == false){
						//左侧非终结符的follow集还未求
						follow(s.charAt(0),vn,vt,verbs);
					}
					else{
						for(i=0;i<vt.length;i++){
							if(follow[vn(s.charAt(0),vn)][i] == true){
								follow[vn(s.charAt(j),vn)][i] = true;
								//把左侧字符的follow集给右侧字符
							}
						}
					}
			    }
			}
			
		}
	}
	//求某一行产生式的follow集
    void follow(char c,char vn[],char vt[],String verbs[]){
    	if(c == 'E'){
    		follow[vn('E',vn)][vt('#',vt)] = true;
    		//开始符号E的follow集中有#
    	}
    	int i,j;
    	String s;
    	for(i=0;i<verbs.length;i++){
    		s = verbs[i];
    		for(j=3;j<s.length();j++){
    			if(c == s.charAt(j)){
    				fol(s,j,vn,vt,verbs);//此条产生式右侧有c
    			}
    		}
    	}
    	follow[vn(c,vn)][vt.length] = true;//标记此非终结符的follow集已经求过
    }
    //求某一个非终结符的follow集
    void follow_final(char vn[],char vt[],String verbs[]){
    	int i;
    	for(i=0;i<vn.length;i++){
    		if(follow[i][vt.length] == false){
    			follow(vn[i],vn,vt,verbs);//当这个非终结符的follow集还没求,求follow集
    		}
    	}
    }
    //求所有非终结符的follow集
    void ana(int j ,int i , String s ,int m,char vn[],char vt[],String verbs[]){
    	char u = verbs[i].charAt(0);//u为此条产生式左边字符
    	int k;
    	if(vt(verbs[i].charAt(j),vt) != -1){
    		//j是终结符
    		if(verbs[i].charAt(j) != '@'){
    			//且不是@
    			analyse[vn(u,vn)][vt(verbs[i].charAt(j),vt)] = s;//写入s
    		}
    		else{
    			//是@
    			for(k=0;k<vt.length-1;k++){
    				if(follow[vn(u,vn)][k] == true){
    					analyse[vn(u,vn)][k] = s;
    					//是@就代表左侧first集有@,就要把左侧的follow集加到表中
    				}
    			}
    		}
    	}
    	else{
    		//i是非终结符
    		for(k=0;k<vt.length-1;k++){
    			//为了避免写入@
    			if(first[vn(verbs[i].charAt(j),vn)][k] == true){
    				//右侧是非终结符,他的first集就是左侧的first集,写进表里
    				analyse[vn(u,vn)][k] = s;
    			}
    		}
    		if(first[vn(verbs[i].charAt(j),vn)][vt('@',vt)] == true){
    			//右侧的first集里有@,就是左侧first集有@,左侧follow集写进表里
    			if(j == m-1){
    				//i为|前的最后一个字符或产生是最后一个字符
    				//此时已到最后一个,可以判断每个字符的first集中都有@
    		        //即:左侧字符的first集 中有@
    				for(k=0;k<vt.length-1;k++){
    					if(follow[vn(u,vn)][k] == true){
    						//左侧follow集
    						analyse[vn(u,vn)][k] = s;
    					}
    				}
    			}
    			else{
    				j++;
    				ana(j,i,s,m,vn,vt,verbs);
    				//规则四,此时扫描判断右侧每个非终结符的first集中都有@
    			}
    		}
    	}
    }
    //将某一个产生式填入表中
    void create(String verbs[],char vn[],char vt[]){
    	int i,j,k;
    	String s;
    	for(i=0;i<verbs.length;i++){
    		j=3;
    		while(j<verbs[i].length()){
    			k=indexofor(j,verbs[i]);
    			//k是|
    			if(k == -1){
    				k = verbs[i].length();
    			}
    			s = verbs[i].substring(j,k);//s是一个没有‘|’的产生式
    			ana(j,i,s,k,vn,vt,verbs);
    			j=k+1;
    		}
    	}
    }
      //生成预测分析表
    void words(String s,char vn[],char vt[]){
    	String rule = new String();
    	String action = new String();
    	String m = new String();
    	Stack<Character> temp = new Stack<Character>();//分析栈
    	temp.setSize(20);//初始化大小
    	temp.push(new Character('#'));//初始化将#入栈
    	temp.push(new Character('E'));//将开始符号入栈
    	rule = " ";
    	action = "初始化";
    	char u,v;
    	char str[] ;
    	String test ;
    	int i=0,j,k=-1,n;
    	while(i<s.length()){
    		n=0;
    		k++;
    		str= new char[10];
    		for(j=0;j<10;j++){
    			str[j]=' ';
    		}
    		rowdata[k][0]=""+k;
    		for(j=0;j<temp.size();j++){
    			if(temp.get(j)!= null){
    			   str[n] = temp.get(j);
    				    n++;
    			    }
    		}
    		test = new String(str);
    		rowdata[k][1]=""+test;
    		rowdata[k][2]=s.substring(i);
    		rowdata[k][3]=rule;
    		rowdata[k][4]=action;
    		u = s.charAt(i);
    		v=temp.pop();
    		action="pop"+v;
    		if(vn(v,vn) != -1){
    			//栈顶元素为非终结符时
    			if(analyse[vn(v,vn)][vt(u,vt)] != null ){
    				//分析表中有产生式
    				m = analyse[vn(v,vn)][vt(u,vt)];
    				rule = v+"->"+m;
    			    if(!m.equals("@") ){
    			    	//产生式不是@
    			    	action=action+",push(";
    			    	for(j=m.length()-1;j>-1;j--){
    			    	//倒序入栈
    			    	action = action + m.charAt(j);
    			    	temp.push(new Character(m.charAt(j)));
    			        }
    			    action = action + ")";
    			    continue;
    			    }
    			    else if(m.equals("i")){
    			    	action = action+"popF";
    			    	temp.push(m.charAt(0));
    			    	continue;
    			    }
    			    else{
    			    	//产生式是@
    			    	rule = v +"->ε";
    			    	continue;
    			    }
    			    
    			}
    			else{
    				//表内没有产生式
    				rule = "   ";
    				action = "error1!";
    				rowdata[k+1][0]=" ";
    	    		rowdata[k+1][1]=" ";
    	    		rowdata[k+1][2]=" ";
    	    		rowdata[k+1][3]=" ";
    	    		rowdata[k+1][4]=action;
    				return;//出错返回
    			}
    		}
    		else{
    			//栈顶元素是终结符
    			rule = "";
    			if(v == u){
    				//匹配
    				if(v == '#'){
    					//结束,成功
    					action = "accept!";
    					rowdata[k+1][0]=" ";
        	    		rowdata[k+1][1]=" ";
        	    		rowdata[k+1][2]=" ";
        	    		rowdata[k+1][3]=" ";
        	    		rowdata[k+1][4]=action;
    					return;
    				}
    				else{
    					i++;
    					
    					action = "pop,getnext(I)";
    					
    					continue;
    				}
    			}
    			else{
    				//不匹配
    				action = "error2!";
    				rowdata[k+1][0]=" ";
    	    		rowdata[k+1][1]=" ";
    	    		rowdata[k+1][2]=" ";
    	    		rowdata[k+1][3]=" ";
    	    		rowdata[k+1][4]=action;
    				return ;//出错返回
    			}
    		}
    	}
    }
}

窗口部分和LR没什么区别

发布了7 篇原创文章 · 获赞 0 · 访问量 40

猜你喜欢

转载自blog.csdn.net/Hireath_/article/details/104572575