【编译原理】First集和Follow集
2017-05-19 22:06
411 查看
编译原理课上实验
first集和follow集求法:
First集合:First集合顾名思义就是求一个文法符号串所可能推导出的符号串的第一个终结符的集合。
First(X)就是求X所有推导出的符号串的第一个符号的集合。
求First集合可分如下几种情况:
1、单个符号的First集合:单个终结符的First集合就是它自己。
2、单个非终结符的First集合:
X-->a… 产生式右部以终结符开头,根据定义,这种情况下显然可以看出a属于First(X)。 X-->A… 产生式右部以非终结符开头,根据定义,也可以看出First(A)属于First(X)。这是一个递归的推导。
3、多个符号形成的符号串的First结合:
X -> ABC…,并且A不能推导出空串ε,显然根据定义First(ABC…)=First(A) X -> ABC…,并且A可能推导出空串ε,当A不是空串的时候,显然First(A)属于First(ABC…),但当A是空串的时候,ABC…就成了BC…,此时根据B是否能推出空串来决定是否将First(B)加入First (ABC…)。这是一个递归的推导,综上所述,符号串中的第一个不能推出空串的符 号前面所有符号的First集合减去空串ε都属于First(ABC…),第一个不能推出空串的 符号的First集合也属于First(ABC…)。也就是假设A、B都可以推出空串,C不能推出空串,First(X)=(First(A)- ε) ∪ (First(B)- ε) ∪ (First(C))。 特殊的,符号串ABC...,A、B、C都可以推导出 ε ,那么把 ε 也加到First(X)中。 注意:First集合中的符号一定是终结符,终结符也包括空串ε。
Follow集合:
Follow集合也是顾名思义的,就是文法符号后面可能跟随的终结符的集合(不包括空 串ε)。 Follow(X)就是求X后面可能跟随的符号集合。 求Follow集合可分如下几种情况: 终结符的Follow集合没有定义,只有非终结符才会有Follow集合。
如果 U 是文法的开始符号,则置 # 于 Follow(U) 中。
A–>…Ua… 要求的Follow集合的非终结符后跟终结符
根据定义,显然a属于Follow(U)。这种情况下,Follow(U) 和A没有任何关系,产生式左边是什么无所谓。
A–>…UP… 要求的Follow集合的非终结符后跟非终结符
根据定义,显然P的第一个符号属于Follow(U),也就是First(P)属于Follow(U)。
A–>…UP 要求的Follow集合的非终结符后跟非结尾的终结符, 并且结尾非终结符的First集合包含空串。
这是上一种情况的一种特例,除了要按上一种情况处理,First(P)属于Follow(U) 以外还要进行分析;因为当P推导为空串时,空串不能出现在Follow集合中,所以 U 后面跟随的应该是P后面的东西,可P已经是结束的符号,此时U后面显然就是A后 面跟随的东西了。所以在这种情况下Follow(A)也属于Follow(U)。
A–>…U 要求的Follow集合的非终结符在产生式结尾
这时候又要递归推导,U是A的结尾,所以U后面跟随的东西也就是A后面跟随的东 西。所以Follow(A)属于Follow(U)。
代码实现
这里我的 first集的 后面跟多个非终结符且非终结符能推导出 ε 的情况没有实现import java.util.Scanner; public class firstAndFollow { static String TSTR_FIRST = ""; static String TSTR_FOLLOW = ""; static int size = 0; static String[][] preResult = null; static String[][] first = null; static String[][] follow = null; public static void main(String[] args) { preResult = input(); size = preResult.length; first = getFirst(); System.out.println("first集:"); for (String[] strings : first) { System.out.print("First(" + strings[0] + ")={"); int i = 0; for (i = 0; i < strings[1].length() - 1; i++) { System.out.print(strings[1].charAt(i) + ","); } System.out.println(strings[1].charAt(i) + "}"); } follow = getFollow(); System.out.println("follow集:"); fo 4000 r (String[] strings : follow) { System.out.print("Follow(" + strings[0] + ")={"); int i = 0; if (strings[1].length() == 1) { System.out.println(strings[1].charAt(i) + "}"); }else if (strings[1].length() > 1) { for (i = 0; i < strings[1].length() - 1; i++) { System.out.print(strings[1].charAt(i) + ","); } System.out.println(strings[1].charAt(i) + "}"); }else { System.out.println("}"); } } } private static String[][] getFirst() { String[][] first = new String[size][2]; for (int i = 0; i < size; i++) { first[i][0] = preResult[i][0]; try { getF(preResult[i][0], preResult[i][1]); } catch (Exception e) { System.out.println("存在递归"); } first[i][1] = TSTR_FIRST; TSTR_FIRST = ""; // System.out.println("---------------------------------------"); } return first; } private static String getF(String str1, String str2) { String temp = ""; if (str2.contains("|")) { String[] strtemp; strtemp = str2.split("\\|"); for (int i = 0; i < strtemp.length; i++) { // System.out.println("getF:" + str1 + "," + strtemp[i]); getF(str1, strtemp[i]); } } else { if ('A' <= str2.charAt(0) && str2.charAt(0) <= 'Z') { for (int i = 0; i < size; i++) { if (preResult[i][0].equals(String.valueOf(str2.charAt(0)))) { // System.out.println(preResult[i][0] + " = "+ str2.charAt(0)); if (!str1.equals(String.valueOf(str2.charAt(0)))) // System.out.println(str1 + " != " + str2.charAt(0)); getF(preResult[i][0], preResult[i][1]); // System.out.println("i:" + i); } } } else { temp = String.valueOf(str2.charAt(0)); if (!TSTR_FIRST.contains(temp)) TSTR_FIRST = TSTR_FIRST.concat(String.valueOf(str2.charAt(0))); // System.out.println("tstrFirst:" + TSTR_FIRST); } } return temp; } private static String[][] getFollow() { String[][] Follow = new String[size][2]; for (int i = 0; i < size; i++) { Follow[i][0] = preResult[i][0]; getFo(preResult[i][0]); Follow[i][1] = TSTR_FOLLOW; TSTR_FOLLOW = ""; //System.out.println("-------------------------------------------------" + Follow[i][1]); } for (int i = 0; i < size; i++) { StringBuffer sb = new StringBuffer(Follow[i][1]); for (int j = 0; j < sb.length(); j++) { String temp = sb.toString(); if (sb.charAt(j) == 'ε') { sb.deleteCharAt(j); temp = sb.toString(); } Follow[i][1] = temp; //System.out.println("Follow:" + Follow[i][1]); } } return Follow; } // 递归求follow private static String getFo(String str3) { if (str3.equals(preResult[0][0])) { //System.out.println("开始符号加 # "); if (!TSTR_FOLLOW.contains("#")) TSTR_FOLLOW = TSTR_FOLLOW.concat("#"); //System.out.println("现在的follow:" + TSTR_FOLLOW); } for (int i = 0; i < size; i++) { if (preResult[i][1].contains(str3)) { char[] ch = preResult[i][1].toCharArray(); for (int j = 0; j < ch.length; j++) { if (str3.equals(String.valueOf(ch[j]))) {/*&& ch[j + 1] != '|'*/ if (j + 1 < ch.length && ch[j + 1] != '|') { if ('A' <= ch[j + 1] && ch[j + 1] <= 'Z') {//下一个是非终结符 for(int k =0;k < size; k++){ if (first[k][0].equals(String.valueOf(ch[j + 1]))) { if (first[k][1].contains("ε")) { if (first[k][0].equals(str3)) break; String strr = getFo(first[k][0]); if (!TSTR_FOLLOW.contains(strr)) TSTR_FOLLOW = TSTR_FOLLOW.concat(String.valueOf(strr)); } } } //System.out.println(ch[j + 1] + " 是非终结符,找first " + ch[j + 1]); // 把后面的first集加到该follow集中 for (int k = 0; k < size; k++) { if (first[k][0].equals(String.valueOf(ch[j + 1]))) { if (!TSTR_FOLLOW.contains(first[k][1])) TSTR_FOLLOW = TSTR_FOLLOW.concat(first[k][1]); //System.out.println("把first " + ch[j + 1] + "加进去,follow现在是:" + TSTR_FOLLOW); break; } } } else if (isT(String.valueOf(ch[j + 1]))) {//下一个是终结符 if (!TSTR_FOLLOW.contains(String.valueOf(ch[j+1]))) { TSTR_FOLLOW = TSTR_FOLLOW.concat(String.valueOf(ch[j + 1])); } //System.out.println("现在的follow:" + TSTR_FOLLOW); } } else { if (preResult[i][0].equals(str3)) break; String strr = getFo(String.valueOf(preResult[i][0])); if (!TSTR_FOLLOW.contains(strr)) TSTR_FOLLOW = TSTR_FOLLOW.concat(String.valueOf(strr)); } break; } } } } //System.out.println("我要return:" + TSTR_FOLLOW); return TSTR_FOLLOW; } private static boolean isT(String tmp){ for (int i = 0; i < size; i++) { if (tmp.equals(preResult[i][0])) return false; } return true; } private static String[][] input(){ Scanner in = new Scanner(System.in); StringBuffer sb = new StringBuffer(); String temp = null; while(!(temp = in.next()).equals("end")){ sb.append(temp); } in.close(); String[] wenfas = sb.toString().split(";"); String[][] chaifen = new String[wenfas.length][2]; int tmp = 0; for (String string : wenfas) { chaifen[tmp] = string.split("->"); tmp++; } char xx = 'A'; for(int m = 0; m < chaifen.length; m++){ if (chaifen[m][0].contains("’")) { String temp1 = chaifen[m][0]; for (int n = 0; n < chaifen.length; n++) { if (chaifen [1].contains(temp1)) { chaifen [1] = chaifen [1].replaceAll(temp1, xx+""); } if (chaifen [0].equals(temp1)) { chaifen [0] = xx + ""; } } xx++; } } return chaifen; } }
测试数据:
E->TE’; E’->+TE’|ε; T->FT’; T’->*FT’|ε; F->(E b034 )|i; end
测试数据的输出结果:
first集: First(E)={(,i} First(A)={+,ε} First(T)={(,i} First(B)={*,ε} First(F)={(,i} follow集: Follow(E)={#,)} Follow(A)={#,)} Follow(T)={#,),+} Follow(B)={#,),+} Follow(F)={#,),+,*}
总结
蜜汁缩进很难受,需要改进。相关文章推荐
- 编译原理中LL(1)文法求FIRST集和FOLLOW集的方法
- 编译原理 FIRST集和FOLLOW集的求法
- <编译原理>——first集、follow集、firstvt集及lastvt集
- 编译原理FIRST集、FOLLOW集、SELECT集求法通俗解释 & LL(1)文法判定
- 编译原理 First集 Follow集 select集 通俗易懂的讲解 + 实例
- 编译原理之--FIRST集、FOLLOW集 和 SELECT集
- 编译原理:求First集与Follow集的方法
- 编译原理 First集和Follow集的求法
- 编译原理 FIRST集和FOLLOW集的求法
- 编译原理:怎样求FIRST集与FOLLOW集 PS:整合转载大全
- 【编译原理】求First集和Follow集
- 编译原理-First集和Follow集
- 编译原理 FIRST集和FOLLOW集的求法
- 编译原理中的first集,follow集和selec集的小解
- 怎么求编译原理中的first集,follow集和selec集
- 软件构造编译原理程序自动生成First和Follow集
- 编译原理中Follow集的求法
- 关于编译原理中的follow集的计算
- 「编译原理」“根据LL(1)求FIRST集” 书本算法的解析及改进
- 编译原理LL1文法Follow集算法实现