【编译原理】First集和Follow集

编译原理课上实验

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)- ε) ∪ (FirstC))。

特殊的,符号串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集:");
        for (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[n][1].contains(temp1)) {
                        chaifen[n][1] = chaifen[n][1].replaceAll(temp1, xx+"");
                    }
                    if (chaifen[n][0].equals(temp1)) {
                        chaifen[n][0] = xx + "";
                    }
                }
                xx++;
            }
        }

        return chaifen;
    }

}

测试数据:

E->TE’;
E’->+TE’|ε;
T->FT’;
T’->*FT|ε;
F->(E)|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)={#,),+,*}

总结

蜜汁缩进很难受,需要改进。

  • 9
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
文法的FirstFollow编译原理中的重要概念,它们可以用来帮助分析和处理文法,对于学习编译原理的同学来说是非常重要的。下面是一个简单的算法来求解文法的FirstFollow: 1. First求解算法动态演示 输入:文法G 输出:文法G的所有非终结符和对应的First 步骤: 1. 初始化每个非终结符的First为空 2. 对于文法G中的每个终结符a,将a加入到对应的非终结符的First中 3. 对于文法G中的每个产生式A -> B1B2...Bn,按照以下规则求出A的First: a. 如果B1是终结符或者空串,则将B1加入到A的First中 b. 如果B1是非终结符,则将B1的First中除空串之外的所有元素加入到A的First中 c. 如果B1可以推出空串,则将B2的First中除空串之外的所有元素加入到A的First中 d. 重复上述过程,直到Bn的First被处理完毕 4. 返回所有非终结符的First 2. Follow求解算法动态演示 输入:文法G和开始符号S 输出:文法G的所有非终结符和对应的Follow 步骤: 1. 初始化每个非终结符的Follow为空 2. 将S的Follow中加入$符号 3. 对于文法G中的每个产生式A -> B1B2...Bn,按照以下规则求出B1、B2、...Bn的Follow: a. 如果B1是非终结符,则将A的Follow中除空串之外的所有元素加入到B1的Follow中 b. 如果B1可以推出空串,则将A的Follow中的所有元素加入到B2的Follow中,重复此过程直到Bn的Follow被处理完毕 c. 如果B1是终结符,则无需处理 4. 对于文法G中的每个产生式A -> B1B2...Bn,按照以下规则求出B2、B3、...Bn的Follow: a. 如果Bi是非终结符,则将Bi+1的First中除空串之外的所有元素加入到Bi的Follow中 b. 如果Bi可以推出空串,则将A的Follow中的所有元素加入到Bi的Follow中,重复此过程直到Bn的Follow被处理完毕 c. 如果Bi是终结符,则无需处理 5. 返回所有非终结符的Follow

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值