编译原理的LL(1)分析过程,从求first和follow到建立预测分析表,再到文法分析

package com.xaut.bianyiyuanli.cherry;


import java.util.ArrayList;




/*
 * E->TE'
 * E'->+E|?
 * T->FT'
 * T'->T|?
 * F->PF'
 * F'->*F|?
 * P->(E)|a|b|^
 * 说明:?表示的是 ε
 * time:2017/06/26
 * */
public class CourseDesign {
static ArrayList<String> productionType = new ArrayList<String>();//产生式集合
static ArrayList [] Single = new ArrayList[productionType.size()];  //拆分每个非终结符对应的产生式
static ArrayList<String> NoTerminator = new ArrayList<String>();    //未变化的 非终结符集合
static ArrayList NoTerminatorlist = new ArrayList(); //非终结符集合
static ArrayList Terminator = new ArrayList();       //终结符集合
static ArrayList<String> right = new ArrayList<String>();//产生式右边的字符串
static ArrayList<String> first = new ArrayList<String>();//定义first 集合
static ArrayList<String> follow = new ArrayList<String>();//定义follow集合
static String [][] tablelast = new String[NoTerminatorlist.size()][Terminator.size()+1];//预测分析表

public static void main(String[] args) {
// TODO Auto-generated method stub
production();
Follow();
createTable();
boolean result = analyse("a*");
System.out.println("针对文法a*的结果是:"+result);
// System.out.println(inversion("abc"));
}
/*
* 输入产生式集合
* 并根据产生式得到非终结符和终结符的集合,以及产生式右边的式子
* */
public static void production(){
productionType.add("E->TE'");
productionType.add("E'->+E|?");
productionType.add("T->FT'");
productionType.add("T'->T|?");
productionType.add("F->PF'");
productionType.add("F'->*F|?");
productionType.add("P->(E)|a|b|^");


String medium;
ArrayList [] Single1 = new ArrayList[productionType.size()];//用于存放每个非终结符的产生式,一拆开的
for(int i = 0;i<productionType.size();i++){
Single1[i] = new ArrayList();
}
String [] chanshengshi = new String [4];
//获取到产生式的非终结符和产生式右边的字符串
for(int i = 0; i< productionType.size() ;i++){
medium = productionType.get(i);
NoTerminator.add(medium.substring(0, medium.indexOf('-')));//根据产生生获取到非终结符
right.add(TurnName(medium.substring(medium.indexOf('>')+1)));
chanshengshi = right.get(i).split("\\|");//注意此处不能用split("|")
// for(int j = 0;j<chanshengshi.length;j++){
// System.out.println(j+"   " +chanshengshi[j]);
// }

// System.out.println("对右边的产生式进行处理");
for(int j =0;j<chanshengshi.length;j++){
if(chanshengshi[j]!=null){
Single1[i].add(chanshengshi[j]);//此处出现空指针异常,是因为上面没有对每一个ArrayList进行初始化,初始化代码为49~51
}
}
// System.out.println(right.get(i));   //产生式右边的字符串
}
System.out.println("------------------");
System.out.println("每个非终结符所对应的单独的产生式");
//输出每个产生式,单独的,对应的Single的下标是对应非终结符的
for(int i = 0;i<Single1.length;i++){
for(int j = 0;j<Single1[i].size();j++){
System.out.println("Single["+i+"].get("+j+")  "+Single1[i].get(j));

}
// System.out.println(Single[i].size());
// System.out.println();
}
// System.out.println(Single.length);
// System.out.println("------------------");
//还需要对每个非终结符的产生式进行划分,右边的|

Single = Single1;
/*  right:
*  TE'
*  +E|?
*  FT'
* T|?
* PF'
* *F|?
* (E)|a|b|^
* */
//对right进行处理,得到终结符集合
StringBuffer strCollection = new StringBuffer();
for(int i = 0; i < right.size() ; i++){
strCollection.append(right.get(i));
}
String strRight = TurnName(strCollection.toString());//对于产生式右边的式子组成的字符串,进行替换E'=>M  T'=>N  F'=>W
strRight = strRight.replace("|", "");
// System.out.println(strRight);

StringBuffer strmedium = new StringBuffer();
for(int i = 0;i<NoTerminator.size();i++){
strmedium.append(NoTerminator.get(i));
}
// 最后生成的非终结符的字符串数组
for(int  i =0;i<TurnName(strmedium.toString()).length();i++){
NoTerminatorlist.add(TurnName(strmedium.toString()).charAt(i)); //非终结符的动态数组的赋值
// System.out.println("非终结符"+NoTerminatorlist.get(i));
}
// System.out.println(NoTerminatorlist.get(0).getClass());
char []NoTerminators = TurnName(strmedium.toString()).toCharArray();//替换之后的非终结符
// System.out.println(TurnName(strmedium.toString()));
//求终结符的集合 ,即在产生式右边组成的字符串中把非终结符产生的字符串中相同的字符去掉

char [] rightChar = strRight.toCharArray();
for(int i  =0;i<rightChar.length ;i++){
for(int j = 0;j<NoTerminators.length ; j++){
if(rightChar[i] == NoTerminators[j]){
strRight = strRight.replace(String.valueOf(rightChar[i]),"");
}
}
}
// System.out.println(strRight);


//去掉上面处理过之后重复的
strRight = deleteRepeat(strRight);
// System.out.println(strRight);
for(int i = 0;i<strRight.length();i++){
Terminator.add(strRight.charAt(i));  //终结符集合赋值
// System.out.println(Terminator.get(i));
}
//求first  针对每个非终结符产生其对应的first集合
/*
* 非终结符集合是NoTerminatorlist   终结符集合Terminator
* 产生式右边的是Single,是动态数据的数组,数组下标和非终结符的下标一致的为产生式左侧是该非终结符
* first 分两种情况:以终结符开头和以非终结符开头
* 1:E->a
* 2: E->F
* 需要选取每个单独的产生式右部的第一个字符,判断是终结符还是非终结符
* a:终结符   则把该终结符添加到该非终结符对应的first集合里面
* b:非终结符   则寻找该非终结符,并进行递归过程
* */
char firstChar;//每个产生式右部的第一个字符
StringBuffer firstMedium = new StringBuffer();
System.out.println("------------------");
//此处两个嵌套的for循环只是产生了只有一个产生式或者是第一个产生式的第一个字符是非终结符
int indexi;
char [] firstCh = new char[4];
for(int  i =0;i<NoTerminatorlist.size();i++){
indexi = i;

for(int w = 0;w<Single1[i].size();w++){
firstCh[w] = Single1[i].get(w).toString().charAt(0);
if(Terminator.contains(firstCh[w])){
firstMedium.append(firstCh[w]);
}
}
for(int  j = 0;j<Single1[i].size();j++){
firstChar = Single1[i].get(j).toString().charAt(0);
// System.out.println(firstChar);
if(Terminator.contains(firstChar)){//首字符是终结符
firstMedium.append(firstChar);
// System.out.println(firstMedium.toString());
}else{
for(int m = 0;m<NoTerminatorlist.size();m++){
if(NoTerminatorlist.get(m)==(Character)firstChar){
i = m;
j = -1;
break;
}
}
}


}
first.add(delete(deleteRepeat(firstMedium.toString())));
firstMedium.delete(0, firstMedium.toString().length());
i = indexi;
}
System.out.println("文法的first集合");
for(int i = 0;i<first.size();i++){
System.out.println(NoTerminatorlist.get(i)+"  "+first.get(i));
}
System.out.println("----------------");



// System.out.println(Single[0].size());

}
//对字符串进行处理把E'=>M  T'=>N  F'=>W
public static String TurnName(String str){
str = str.replaceAll("E'", "M");
str = str.replaceAll("T'", "N");
str = str.replaceAll("F'", "W");
return str;
}
//去除掉字符串中重复的字符   特殊字符的去重
/*
* problem:exception:  Dangling meta character '?' near index 0
*      +、*、|、/等符号在正则表达示中有相应的不同意义。
*      一般来讲只需要加[]、或是//即可
* */
public static String deleteRepeat(String str){
char [] strToChar = str.toCharArray();
char [] repeatChar = new char[strToChar.length];
int index = 0;
for(int  i =0;i<strToChar.length ; i++){
for(int j = i+1;j<strToChar.length;j++){
if(strToChar[i] == strToChar[j]){
strToChar = str.toCharArray();  //因为每次变化之后str都会变
str = str.replaceAll("\\"+String.valueOf(strToChar[i]),"" );
repeatChar[index] = strToChar[i];
index ++;
}
}
}
for(int i =0;i<index ;i++){
str = str + repeatChar[i];
}
return str;

}
//删去字母中重复的部分
public static String delete(String str){
char [] strToChar = str.toCharArray();
char [] repeatChar = new char[strToChar.length];
int index = 0;
for(int  i =0;i<strToChar.length ; i++){
for(int j = i+1;j<strToChar.length;j++){
if(strToChar[i] == strToChar[j]){
strToChar = str.toCharArray();  //因为每次变化之后str都会变
str = str.replaceAll(String.valueOf(strToChar[i]),"" );
repeatChar[index] = strToChar[i];
index ++;
}
}
}
for(int i =0;i<index ;i++){
str = str + repeatChar[i];
}
return str;
}
/*
* 求follow集合
* 1.直接收取:形如“……Ua”的组合,直接把啊收入到follow(U)中
* 2.直接收取:形如“……UP……”的组合,(P是非终态符);把firth(P)除去ε直接收入到follow(U)中.
     * 3.反复传递:形如“P-……U”的产生式,follow(P)的全部内容传递到follow(U)中
*   或者说是P-……UB且first(B)包含ε,则把first(B)除去ε直接收入到follow(U)中,同时吧follow(P)的全部内容传送到follow(U)中...
* */
public static void Follow(){
char ch,chmedium,strlast;
String str;
StringBuffer [] followStr = new StringBuffer[NoTerminatorlist.size()];
for(int i = 0;i<NoTerminatorlist.size();i++){
followStr[i] = new StringBuffer();
}
for(int i  = 0;i<Single.length;i++){
ch = (char) NoTerminatorlist.get(i);
if(i==0){
followStr[i].append('#');
}
// System.out.println(ch);
for(int  j = 0;j<Single.length;j++){
for(int w = 0;w<Single[j].size();w++){
str = Single[j].get(w).toString();
if(IsContains(str,ch)&&(str.indexOf(ch)+1)<str.length()){
chmedium = str.charAt(str.indexOf(ch)+1);
if(Terminator.contains(chmedium)){//符合1.直接收取  后面直接跟终结符
followStr[i].append(chmedium);
}else{ //符合2.直接收取   后面直接跟非终结符
followStr[i].append(deleteAChar(chmedium));
}
}
}
}
// System.out.println(NoTerminatorlist.get(i)+"  "+followStr[i].toString());
}
//3.反复传递:形如“P-……U”的产生式,follow(P)的全部内容传递到follow(U)中
System.out.println("---------------------");
for(int z = 0;z<=1;z++){
for(int i = 0;i<NoTerminatorlist.size();i++){
for(int j = 0;j<Single[i].size();j++){
str = Single[i].get(j).toString();
strlast = str.charAt(str.length()-1);
if(NoTerminatorlist.contains(strlast)){
// System.out.println(NoTerminatorlist.get(i)+"  "+strlast);
followStr[getIndex(strlast)].append(followStr[getIndex((char)NoTerminatorlist.get(i))]); 
}
}
}
//P-……UB且first(B)包含ε,则把first(B)除去ε直接收入到follow(U)中,同时吧follow(P)的全部内容传送到follow(U)中...
char []chlastTwo = new char[2];//存放产生式后两位
for(int i =0;i<NoTerminatorlist.size();i++){
for(int j = 0;j<Single[i].size();j++){
str = Single[i].get(j).toString();
if(str.length()>=2){
chlastTwo = str.substring(str.length()-2).toCharArray();
if(NoTerminatorlist.contains(chlastTwo[0])&&NoTerminatorlist.contains(chlastTwo[1])){//判断产生式后两个字符都是非终结符
if(IsContains(first.get(getIndex(chlastTwo[1])),'?')){//最后面那个非终结符的first里面含有空
followStr[getIndex(chlastTwo[0])].append(followStr[i]);
}
}

}
}
}
}


System.out.println("对应的follow集合");
String followstring ="";
for(int i = 0;i<NoTerminatorlist.size();i++){
followstring = deleteAfterrepeat(followStr[i].toString());
follow.add(followstring);
// System.out.println(followstring);
}
for(int i  = 0;i<follow.size();i++){
System.out.println(follow.get(i).toString());
}
System.out.println("---------------------");
}
/*
* 判断一个字符串中是否含有某个字符
* */
public static boolean IsContains(String str,char ch){
char [] charstr = str.toCharArray();
for(int i = 0;i<charstr.length;i++){
if(charstr[i] == ch){
return true;
}
}
return false;
}
/*
* 字符串中除去一个字符'?'
* 在求follow中用到first的非空
* 把firth(P)除去ε直接收入到follow(U)中
* */
public static String deleteAChar(char ch){
int index = 0;
for(int i  = 0;i<NoTerminatorlist.size();i++){
if((char)NoTerminatorlist.get(i) == ch){
index = i;
}
}
String str = first.get(index);
StringBuffer strBuffer = new StringBuffer();
for(int i = 0;i<str.length();i++){
if(str.charAt(i)!='?'){
strBuffer.append(str.charAt(i));
}
}
return strBuffer.toString();
}
//获取字符对应的非终结符的下标
public static int getIndex(char ch){
int index = 0;
for(int  i = 0;i<NoTerminatorlist.size();i++){
if((char)NoTerminatorlist.get(i)==ch){
index = i;
}
}
return index;
}
public static String deleteAfterrepeat(String str){
char [] charstr = str.toCharArray();
for(int i  = 0;i<charstr.length;i++){
for(int j =i+1;j<charstr.length;j++){
if(charstr[i]==charstr[j]){
charstr[j]=0;
}
}
}
StringBuffer str1 = new StringBuffer();
for(int i = 0;i<charstr.length;i++){
if(charstr[i]!=0){
str1.append(charstr[i]);
}
}
return str1.toString();

}
//生成预测分析表
/*
* 行:+ * ( ) a b ^ #
* 列:E M T N F W P
* */
public static void createTable(){
// System.out.println("给产生式划标号:");
// int index = 0;
// for(int  i = 0;i<NoTerminatorlist.size();i++){
// for(int j = 0;j<Single[i].size();j++){
// System.out.println(index+" : "+NoTerminatorlist.get(i)+"->"+Single[i].get(j));
// index ++;
// }
// }
System.out.println("产生的预测分析表:");
char [] showTableRow = {'+','*','(',')','a','b','^','#'};
StringBuffer str = new StringBuffer();
char chright;//产生式右侧第一个字符
String [][] table = new String[NoTerminatorlist.size()][Terminator.size()+1];
for(int  i = 0;i<NoTerminatorlist.size();i++){
for(int z = 0;z<Single[i].size();z++){
str.append(Single[i].get(z)+"|");
}
// System.out.println(i+"  "+str.toString());
for(int j = 0;j<showTableRow.length;j++){
if(IsContains(first.get(i).toString(),showTableRow[j])){//first 里面含有该终结符
for(int z = 0;z<Single[i].size();z++){
chright = Single[i].get(z).toString().charAt(0);
if(chright == showTableRow[j]){
table[i][j] = NoTerminatorlist.get(i)+"->"+Single[i].get(z);
}else if(IsContains(NoTerminatorlist.toString(),chright)){
table[i][j] = NoTerminatorlist.get(i)+"->"+Single[i].get(z);
}
}
}else if(IsContains(follow.get(i).toString(),showTableRow[j])&&IsContains(str.toString(),'?')){//第二种情况,产生式里面含有空,看follow表
table[i][j] = NoTerminatorlist.get(i)+"->?";
}
}
str.delete(0, str.length());
}
for(int i = 0;i<showTableRow.length;i++){
System.out.print("    "+showTableRow[i]+"    ");
}
System.out.println();
for(int  i = 0;i<NoTerminatorlist.size();i++){
System.out.print(NoTerminatorlist.get(i)+"  ");
for(int j = 0;j<showTableRow.length;j++){
// if(table[i][j]==null){
// table[i][j]="";
// }
System.out.print(table[i][j]+"     ");
}
System.out.println();
}

tablelast = table;
}
    //分析文法的过程
/*
* 针对文法a*  进行分析
* str = "a*"
* 当分析栈和输入串均只有#是结束
* */
public static boolean analyse(String str){
System.out.println("-----------------------------------------------------------");
System.out.println("针对文法a*的分析过程:");
StringBuffer analysisStack = new StringBuffer();
StringBuffer inputString = new StringBuffer();
StringBuffer appendix = new StringBuffer();
String strtable="";//用于存放产生式右部
char [] showTableRow = {'+','*','(',')','a','b','^','#'};
char chAnalysis,chInput;
analysisStack.append("#E");
inputString.append("a*#");
System.out.println("分析栈                                     输入串                                      附注");
System.out.println("-----------------------------------------------------------");
System.out.println(analysisStack.toString()+"                  "+inputString.toString()+"                 "+appendix.toString());
while(analysisStack.toString()!=inputString.toString()){
chAnalysis = analysisStack.toString().charAt(analysisStack.toString().length()-1);//分析栈的最后一个字符
chInput = inputString.toString().charAt(0);//输入串的第一个字符
if(chAnalysis==chInput){
analysisStack.delete(analysisStack.length()-1, analysisStack.length());
inputString.delete(0, 1);
}else{
strtable = tablelast[returnIndex(NoTerminatorlist,chAnalysis)][returnIndex(showTableRow,chInput)];
appendix.append(strtable);
if(strtable==null){
return false;
}
strtable = strtable.substring(strtable.indexOf('>')+1);//只得到对应产生式的右部
analysisStack.delete(analysisStack.length()-1, analysisStack.length());
analysisStack.append(inversion(strtable));
}
System.out.println(analysisStack.toString()+"                  "+inputString.toString()+"                 "+appendix.toString());
appendix.delete(0, appendix.length());

}
return true;
}
//是字符串倒置
public static String inversion(String str){
StringBuffer strbuffer = new StringBuffer();
for(int i = str.length()-1;i>=0;i--){
strbuffer.append(str.charAt(i));
}
return strbuffer.toString();
}
//用于找到非终结符所对应的下标
public static int returnIndex(ArrayList list,char ch){
int index = 0;
for(int i = 0;i<list.size();i++){
if((char)list.get(i)==ch){
index = i;
}
}
return index;
}
//用于找到终结符对应的下标,用于预测分析表'+','*','(',')','a','b','^','#'
public static int returnIndex(char [] charArray,char ch){
int index = 0;
for(int i = 0;i<charArray.length;i++){
if(charArray[i]==ch){
index = i;
}
}
return index;
}

}



实验结果:

------------------
每个非终结符所对应的单独的产生式
Single[0].get(0)  TM
Single[1].get(0)  +E
Single[1].get(1)  ?
Single[2].get(0)  FN
Single[3].get(0)  T
Single[3].get(1)  ?
Single[4].get(0)  PW
Single[5].get(0)  *F
Single[5].get(1)  ?
Single[6].get(0)  (E)
Single[6].get(1)  a
Single[6].get(2)  b
Single[6].get(3)  ^
------------------
文法的first集合
E  (ab^
M  +?
T  (ab^
N  ?(ab^
F  (ab^
W  *?
P  (^ab
----------------
---------------------
对应的follow集合
#)
#)
+#)
+#)
(ab^+#)
(ab^+#)
*(ab^+#)
---------------------
产生的预测分析表:
    +        *        (        )        a        b        ^        #    
E  null     null     E->TM     null     E->TM     E->TM     E->TM     null     
M  M->+E     null     null     M->?     null     null     null     M->?     
T  null     null     T->FN     null     T->FN     T->FN     T->FN     null     
N  N->?     null     N->T     N->?     N->T     N->T     N->T     N->?     
F  null     null     F->PW     null     F->PW     F->PW     F->PW     null     
W  W->?     W->*F     W->?     W->?     W->?     W->?     W->?     W->?     
P  null     null     P->(E)     null     P->a     P->b     P->^     null     
-----------------------------------------------------------
针对文法a*的分析过程:
分析栈                                     输入串                                      附注
-----------------------------------------------------------
#E                  a*#                 
#MT                  a*#                 E->TM
#MNF                  a*#                 T->FN
#MNWP                  a*#                 F->PW
#MNWa                  a*#                 P->a
#MNW                  *#                 
#MNF*                  *#                 W->*F
#MNF                  #                 
针对文法a*的结果是:false

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值