消除文法中一切左递归算法

第一次写博客。。。编译原理课的一个实验,觉得挺有意思的,跟大家分享一下。如果有BUG可以随时提出。。。反正我也不一定改《消除文法中一切左递归算法》

感觉自己花了挺长的时间,所以作为博客保留下来,挺有纪念意义的  (因为我是菜鸟《消除文法中一切左递归算法》

注释比较多,大家凑合着看看吧。。。

package com.insist.entity;

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
/**
 * 
 * @author SNOOPY
 *消除一切左递归
 */
public class EliminateLeftRecursion {

	private static int n;//实际输入产生式个数
	public static void main(String[] args) {
		Scanner scan = new Scanner(System.in);
		System.out.println("请输入产生式个数:");
		n = scan.nextInt();
		//创建产生式数组存放输入的产生式
		List<Regular> regulars = new ArrayList<Regular>();
		for (int i=0;i<n;i++) {
			Regular reg = new Regular();
			System.out.println("请输入产生式左部:");
			String left = scan.next();
			reg.setLeft(left);
			System.out.println("请输入产生式的右部:");
			String right = scan.next();
			reg.setRight(right);
			regulars.add(reg);
		}
		/*测试输出------->成功
		for (Regular reg: regulars) {
			System.out.println(reg.getLeft()+"---->"+reg.getRight());
		}*/
		
		//构造一个字符型的数组用来存放排序好的非终结符
		String[] Vn = new String[50];
		//对所有的产生式按照一定的顺序存放
		Vn[0] = regulars.get(0).getLeft();//把产生式第一个非终结符放到集合中
		int flag=0;
		int count=0;
		for (int i = 1; i < n; i++) {//对非终结符排序并存取   1、遍历产生式数组
			for (int j = 0; j < i; j++) {
				//如果产生式左部等于在它前面的产生式的左部
				if(regulars.get(i).getLeft().equals(regulars.get(j).getLeft())){//说明有重复的
					flag++;
				}
			}
			if(flag == 0){//说明没有重复,则加入非终结符数组中
				count++;
				Vn[count] = regulars.get(i).getLeft();
			}
			flag=0;
		}
		/*测试非终结符数组------------>成功
		for (int i = 0; i < Vn.length; i++) {
			if(Vn[i]!=null){
				System.out.println(Vn[i]);
			}
		}
		*/
		for (Regular reg: regulars) {
			if(reg != null){
				System.out.println(reg.getLeft()+"---->"+reg.getRight());
			}
		}
		regulars = subFunction(regulars, Vn, count);
		for (Regular reg: regulars) {
			if(reg != null){
				System.out.println(reg.getLeft()+"---->"+reg.getRight());
			}
		}
	}
	
	public static List<Regular> subFunction(List<Regular> regulars , String[] Vn , int count){
		int flag=0;
		//判断是否存在间接左递归并转化为直接左递归
		for( int i=0;i <= count;i++){//对每一个非终结符    迭代
			for(int j=0;j < i;j++){//对每一个小于i的非终结符遍历
				for(int k=0;k < regulars.size();k++) //对每一个产生式
					if(Vn[i].equals(regulars.get(k).getLeft())){//i非终结符与第k产生式左边第一个字母相等-->锁定非终结符集合中的一个非终结符的产生式
						if(regulars.get(k).getRight().substring(0,1).equals(Vn[j])){  //g产生式右边产生式第一个符号与第j个非终结符相等-->说明存在间接左递归
							for(int h=0;h < regulars.size();h++){
								if(regulars.get(h).getLeft().equals(Vn[j])){//进行替换
									String str;
									str=regulars.get(k).getRight().substring(1);//截取右边第一个以后的字符
									Regular reg = new Regular();
									reg.setLeft(regulars.get(k).getLeft());
									reg.setRight(regulars.get(h).getRight()+str);
									regulars.add(reg);
								}
							}
							regulars.remove(k);
						}
					}
				}
			}
		//消除所有直接左递归
		for(int  i=0;i <= count;i++) {
			flag=0;
			for(int j=0;j < regulars.size();j++){//判断是否存在直接左递归
				if(regulars.get(j).getLeft().equals(Vn[i])){
System.out.println(regulars.get(j).getLeft()+" ======= "+Vn[i]);
					if(regulars.get(j).getLeft().equals(regulars.get(j).getRight().substring(0, 1))){
System.out.println("消除间接左递归后存在直接左递归");
						flag++;
					}
				}
			}
			if(flag !=0 ){//存在直接左递归
				for(int j=0;j < regulars.size();j++){
					if(regulars.get(j).getLeft().equals(Vn[i])){//寻找与存在直接左递归的非终结符左部相同的的产生式
						if(regulars.get(j).getLeft().equals(regulars.get(j).getRight().substring(0,1))){
							//直接左递归的产生式
							String str=regulars.get(j).getRight().substring(1);
							String temp=regulars.get(j).getLeft();
							String temp1="'";
							regulars.get(j).setLeft(temp+temp1);
							regulars.get(j).setRight(str+regulars.get(j).getLeft());
							Regular reg = new Regular();
							reg.setLeft(regulars.get(j).getLeft());
							reg.setRight("ε");
							regulars.add(reg);
							
						}else{
							String temp=regulars.get(j).getLeft();
							String temp1="'";
							temp=temp+temp1;
							regulars.get(j).setRight(regulars.get(j).getRight()+temp);
						}
					}
				}
			}
		}
		return regulars;
	}
}
package com.insist.entity;

import java.io.Serializable;

/**
 * 
 * @author SNOOPY
 *
 */
public class Regular implements Serializable{

	private static final long serialVersionUID = 1L;

	private String right;//定义产生式右部
	
	private String left;//定义产生式左部

	public String getRight() {
		return right;
	}

	public void setRight(String right) {
		this.right = right;
	}

	public String getLeft() {
		return left;
	}

	public void setLeft(String left) {
		this.left = left;
	}
}

    原文作者:递归算法
    原文地址: https://blog.csdn.net/u012931415/article/details/46052487
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞