编译原理LL(1)型文法的操作——判空,First 集,Follow集,select集,预测分析表,预测过程

                       编译原理实验之LL(1)型文法

        这个实验是我们编译原理的一个作业,我花了不少时间,问了很多同学,参考了老师给的文档终于把实验做了出来,在这里我打算把整个实验解决的过程来分享一下,也希望大家分享更好,更优质的算法和代码。这个实验我最早打算用C语言去写,但是后来发现如果用C语言写会非常麻烦,所以后来右改用了Java,但是算法思路是一样的。然后就是实验过程。

package Then;

import java.util.*;

public class Main {
	public static void main(String[] args) {//主函数,用于程序的基本运行
		grammar gra = new grammar();//声明一个grammar类,这个类里边有所有需要用到的数据结构,方法。
		gra.find_empty();//首先进行判空
		gra.find_first();//找first 集
		gra.find_follow();//找follow 集
		gra.find_select();//找select集
		System.out.print("Select:");//输出select集
		System.out.println(gra.select_map);
		System.out.println();//输出换行,格式需求
		System.out.println();
		System.out.println();
		System.out.println();
		System.out.print("First:");//输出first 集
		System.out.println(gra.first_map);
		System.out.println();
		System.out.println();
		System.out.println();
		System.out.println();
		System.out.print("Follow:");//输出follow 集
		System.out.println(gra.follow_map);
		System.out.println();
		System.out.println();
		System.out.println();
		System.out.println();
		System.out.print("判空:");//输出判空情况
		System.out.println(gra.empty_map);
		gra.get_it();//进行预测分析
	}
}

class grammar{//grammar类的定义,里面有存储结构,各种方法
	Scanner sc = new Scanner(System.in);
	List<String> gram = new ArrayList<String>();
	Map <String,Integer> empty_map = new HashMap<String, Integer>();
	Map <Character,Set<Character>> first_map = new HashMap<Character,Set<Character>>();
	Map <Character,Set<Character>> follow_map = new HashMap<Character,Set<Character>>();
	Map <String,Set<Character>> select_map = new HashMap<String,Set<Character>>();
	List <Character> unend = new ArrayList<Character>();
	List <Character> end = new ArrayList<Character>();
	
	public grammar(){
		System.out.print("请输入文法:");
		int n = sc.nextInt();
		for(int i=0;i<n;i++){
			String a_gram = sc.next();
			gram.add(a_gram);
			Set<Character> list2 = new HashSet<Character>();
			select_map.put(a_gram, list2);
				for(int j=0;j<a_gram.length();j++){
				if(a_gram.charAt(j)>='A'&&a_gram.charAt(j)<='Z'){
					String ch = Character.toString(a_gram.charAt(j));
					empty_map.put(ch, 2);
					Set<Character> list = new HashSet<Character>();
					//list.add('#');
					
					Set<Character> list1 = new HashSet<Character>();
					//list1.add('#');
					first_map.put(a_gram.charAt(j), list);
					follow_map.put(a_gram.charAt(j),list1);
					if(!this.unend.contains(a_gram.charAt(j)))
					unend.add(a_gram.charAt(j));
				}
				else if(a_gram.charAt(j)!='-'&&a_gram.charAt(j)!='>'&&a_gram.charAt(j)!='@'){
					if(!this.end.contains(a_gram.charAt(j)))
					end.add(a_gram.charAt(j));
				}
			}
		}
		this.follow_map.get(this.gram.get(0).charAt(0)).add('#');
	}

	public void out_put(){
		for(int i=0;i<this.gram.size();i++){
			System.out.println(this.gram.get(i));
		}
	}
	public void find_empty(){//判空方法
		int flag_buff=0,bf=1;
		int flag_sing_empty=0,fse=0;
		int point=3;
		char b;
		while (flag_buff!=bf) {
			flag_buff = bf;
			for(int i=0;i<this.gram.size();i++){
				if(flag_sing_empty!=fse){
					point++;
					b = this.gram.get(i).charAt(point);
				}
				else{
					point=3;
					b = this.gram.get(i).charAt(point);
				}
				
				
				if(this.empty_map.get(Character.toString(this.gram.get(i).charAt(0)))==0){
					continue;
				}
				if(b=='@'){
					if(this.empty_map.get(Character.toString(this.gram.get(i).charAt(0)))!=0){
						this.empty_map.put(Character.toString(this.gram.get(i).charAt(0)),0);
						flag_buff++;
					}
					flag_sing_empty=fse;
				}
				else if(b>='a'&&b<='z'){
					if(this.empty_map.get(Character.toString(this.gram.get(i).charAt(0)))==2){
						this.empty_map.put(Character.toString(this.gram.get(i).charAt(0)),1);
						flag_buff++;
					}
					flag_sing_empty=fse;
				}
				else if (b>='A'&&b<='Z') {
					if(this.empty_map.get(Character.toString(b))==2){
						flag_sing_empty=fse;
					}
					else if(this.empty_map.get(Character.toString(b))==1){
						if(this.empty_map.get(Character.toString(this.gram.get(i).charAt(0)))==2){
							this.empty_map.put(Character.toString(this.gram.get(i).charAt(0)),1);
							flag_buff++;
						}
						flag_sing_empty = fse;
					}
					else if(this.empty_map.get(Character.toString(b))==0){
						flag_sing_empty++;
						i--;
					}
				}
				else if(b=='#'){
					if(this.empty_map.get(Character.toString(this.gram.get(i).charAt(0)))!=0){
						this.empty_map.put(Character.toString(this.gram.get(i).charAt(0)),0);
						flag_buff++;
					}
					flag_sing_empty = fse;
				}
			}
		}
		for (String key : empty_map.keySet()) {
			if(empty_map.get(key)==2){
				empty_map.put(key, 0);
			}
		}
		
		
	}


	public void find_first(){//找first集的方法
		int flag=0,fg=1;
		int nu=3;
		char point;
		for(int j=0;j<this.gram.size();j++){
			flag=fg;
			for(int i=0;i<this.gram.size();i++){
				if(flag!=fg){
					nu++;
					point=this.gram.get(i).charAt(nu);
				}
				else {
					nu=3;
					point = this.gram.get(i).charAt(nu);
				}
				if(point>='a'&&point<='z'){
					this.first_map.get(this.gram.get(i).charAt(0)).add(point);
					flag=fg;
				}
				else if(point=='@'){
					this.first_map.get(this.gram.get(i).charAt(0)).add('@');
				}
				else if(point>='A'&&point<='Z'){
					this.first_map.get(this.gram.get(i).charAt(0)).addAll(this.first_map.get(point));
					this.first_map.get(this.gram.get(i).charAt(0)).remove('@');
					if(this.empty_map.get(Character.toString(point))==0){
						flag++;
						i--;
					}
					else {
						flag=fg;
					}
				}
				else if(point=='#'){
					this.first_map.get(this.gram.get(i).charAt(0)).add('@');
					flag=fg;
				}
			}
		}
	}
	public void find_follow(){//找follow集的方法
		int flag_buff=0,fb=1;
		int number;
		for(int z=0;z<this.gram.size();z++){//最外层的状态判断
			for(int i=0;i<this.gram.size();i++){//单次循环,一次对每个产生式进行一次操作
				for(int j=3;j<this.gram.get(i).length();j++){//产生式操作
					char p = this.gram.get(i).charAt(j);
					if(p>='A'&&p<='Z'){
						number = j+1;
						char ls;
						while(true){
							ls = this.gram.get(i).charAt(number);
							if(ls>='a'&&ls<='z'){
								this.follow_map.get(p).add(ls);
								//flag_buff++;
								break;
							}
							else if(ls>='A'&&ls<='Z'){
								Set<Character> ls1 = this.first_map.get(ls);
								ls1.remove('@');
								this.follow_map.get(p).addAll(ls1);
								//flag_buff++;
								if(this.empty_map.get(Character.toString(ls))==0){
									number++;
								}
								else {
									break;
								}
							}
							else if (ls=='#') {
								this.follow_map.get(p).addAll(this.follow_map.get(this.gram.get(i).charAt(0)));
								//flag_buff++;
								break;
							}
						}
						
					}
				}
			}
		}
	}
	public void find_select(){//找select集的方法
		int flag=1,fg=0;
		int point=3;
		char p;
		for(int j=0;j<this.gram.size();j++){
			flag=fg;
			for(int i=0;i<this.gram.size();i++){
				if(flag!=fg){
					point++;
					p = this.gram.get(i).charAt(point);
				}
				else{
					point=3;
					p = this.gram.get(i).charAt(point);
				}
				if(p>='a'&&p<='z'){
					this.select_map.get(this.gram.get(i)).add(p);
					flag=fg;
				}
				else if(p=='@'){
					this.select_map.get(this.gram.get(i)).addAll(this.follow_map.get(this.gram.get(i).charAt(0)));
					flag=fg;
				}
				else if(p>='A'&&p<='Z'){
					this.select_map.get(this.gram.get(i)).addAll(this.first_map.get(p));
					this.select_map.get(this.gram.get(i)).remove('@');
					if(this.empty_map.get(Character.toString(p))==0){
						//i--;
						flag=fg;
					}
					else
						flag=fg;
				}
				else if(p=='#'){
					this.select_map.get(this.gram.get(i)).addAll(this.follow_map.get(this.gram.get(i).charAt(0)));
					flag=fg;
				}
			}
		}
	}
	public void get_it() {//预测表生成及预测分析
		int a = this.end.size();
		int b = this.unend.size();
		for(int i=0;i<this.end.size();i++) {
			System.out.print(this.end.get(i)+"                  ");
		}
		System.out.println("");
		String[][] yuce = new String[b][a];
		for(int i=0;i<this.unend.size();i++) {
			for (String key : this.select_map.keySet()) { 
				if(key.charAt(0)==this.unend.get(i)) {
					for(int j=0;j<this.end.size();j++) {
						if(this.select_map.get(key).contains(this.end.get(j))) {
							yuce[i][j] = key;
						}
					}
				}
			} 
		}
		for(int i=0;i<b;i++) {
			for(int j=0;j<a;j++) {
				System.out.print(yuce[i][j]+"              ");
			}
			System.out.println("");
		}
		//开始进行分析
		System.out.println("请输入你要进行分析的句子");
		String abc1 = sc.nextLine();//由于输入问题
		String abc = sc.nextLine();
		
		Stack<Character> fenxi = new Stack<Character>();
		fenxi.push('#');
		fenxi.push(this.gram.get(0).charAt(0));
		int i=0;
		char A = abc.charAt(i);
		
		
		while(true) {
			System.out.print(fenxi+"                ");
			System.out.println(abc.substring(i));
			char X = fenxi.pop();//栈顶符号放入X
			
			if(this.end.contains(X)) {//X在终结符里吗
				if(X==A) {//X等于临时输入符
					i++;
					if(i==abc.length())
						break;
					A = abc.charAt(i);//读入下一符号,重复
				}else {
					System.out.print("cuo");
					break;//否则出错
				}
			}//以上是在非终结符里的情况
			else {
				if (X=='#') {
					if(X==A) {
						System.out.print("END!");
						break;
					}
					else {
						System.out.print("cuo");
						break;
					}
				}
				else {
					int h,l;
					h = this.unend.indexOf(X);
					l = this.end.indexOf(A);
					String ls = yuce[h][l];
					if(this.gram.contains(ls)) {//是一个产生式
						for(int k=ls.length()-2;k>=3;k--) {
							if(ls.charAt(k)!='@')
							fenxi.push(ls.charAt(k));
						}
					}
					else {
						System.out.println("cuo");
						break;
					}
				}
			}
		}
		
	}
	
}
/*测试用例1
S->AB#
S->bC#
A->@#
A->b#
B->@#
B->aD#
C->AD#
C->b#
D->aS#
D->c#
测试用例2
E->TZ#
Z->aTZ#
Z->@#
T->FN#
N->bFN#
N->@#
F->i#
F->cEd#

 */

  • 0
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值