上下文无关文法消除文法中的ε产生式、单产生式、以及无用符号(java)

设计上下文无关文法的变换算法实验目的 编程实现上下文无关文法的变换算法,用于消除文法中的ε产生式、单产生式、以及无用符号。

import java.util.*;

public class CFG {
    //以#为空
    class Transfer {
        String beg;
        List<String> to;

        Transfer(){
            beg =new String();
            to =new ArrayList<>();
        }
    }

    List<String> nonterminal=new ArrayList<>();//非终结符的集合
    List<String> terminal=new ArrayList<>();//终结符的集合
    List<String> allterminal=new ArrayList<>();
    List<String> conversion=new ArrayList<>();//有空转换的字符
    String Begin =new String();

    void AddS1(){
        Transfer transfer=cfg.get(Begin);
        Transfer trans=new Transfer();
        trans.beg="S1";
        for(String s1:transfer.to){
            trans.to.add(s1);
        }
        cfg.put("S1",trans);
        nonterminal.add("S1");
        allterminal.add("S1");
    }

    HashMap<String, Transfer> cfg=new HashMap<>();

    void InputProduction(){
        Scanner sc=new Scanner(System.in);
        System.out.println("请输入有多少个非终结符,第一个为起始符");
        int i,num=sc.nextInt();
        for (i = 0; i < num; i++) {
            System.out.println("请输入非终结符符号");
            String name= sc.next();
            nonterminal.add(name);
            if(!allterminal.contains(name)){
                allterminal.add(name);
            }
            Transfer transfer = new Transfer();
            transfer.beg =name;
            System.out.println("请输入生成式个数");
            int num1=sc.nextInt();
            System.out.println("请输入生成式,以#为空");
            for (int j = 0; j < num1; j++) {
                String get= sc.next();
                if(get.equals("#")){
                    conversion.add(name);
                }
                char[] gets=get.toCharArray();
                for (char c:gets){
                    String str=new String(new char[]{c});
                    if(!allterminal.contains(str)){
                        allterminal.add(str);
                    }
                }
                transfer.to.add(get);
            }
            cfg.put(name,transfer);
            if(i==0){
                Begin=name;
                if(transfer.to.contains("#")){
                    AddS1();
                }

            }
        }

        terminal.addAll(allterminal);
        terminal.removeAll(nonterminal);
//        System.out.println(terminal);
//        System.out.println(nonterminal);
//        System.out.println(allterminal);
    }


    void OutputProduction(){
        System.out.println("非终结符有:"+nonterminal);
        System.out.println("终结符有:"+terminal);
        for (Transfer t: cfg.values()) {
            for (String str:t.to) {
                System.out.println(t.beg +"->"+str);
            }
        }
    }

    void RemoveEpsilon(){
        boolean flag=true;
        while (flag){
            List<String> newconversion=new ArrayList<>();

            flag=false;

            for (int i = 0; i < conversion.size(); i++) {
                Transfer trans=cfg.get(conversion.get(i));
                if(trans.to.contains("#")){
                    trans.to.remove("#");//删去直接置空的符号


                    for(Transfer tra:cfg.values()){//在其他式子中删去置空的非终结符
                        List<String> toadd=new ArrayList<>();
                        if(!conversion.contains(tra.beg)&&tra.to.contains(trans.beg)&&!tra.to.contains("#")){

                            toadd.add("#");
                            if(!tra.beg.equals("S1")){
                                flag = true;
                                newconversion.add(tra.beg);
                            }

                        }


                        for (String str:tra.to){
                            if (str.contains(conversion.get(i))){
                                Recursion(conversion.get(i),str,0,toadd);
                            }
                        }

                        for (String add:toadd) {
                            if(!tra.to.contains(add)){
                                tra.to.add(add);
                            }
                        }
                    }
                }

                }
            conversion.addAll(newconversion);
        }

    }

    void Recursion(String target, String ori, int index, List<String> toadd) {
        if (index == -1) {
            return;
        }
        index = ori.indexOf(target, index);
        if (index != -1) {
            String nstr;
            if (index == 0) {
                nstr = ori.substring(1);
            } else {
                nstr = ori.substring(0, index) + ori.substring(index + 1);
            }
            Recursion(target, ori, index+1, toadd);
            if (!toadd.contains(nstr)&&!nstr.equals("")) {
                toadd.add(nstr);
            }
            Recursion(target, nstr, index, toadd);
        }
    }

    void EliminateUnitProduction(){
        boolean flag=true;
        while (flag){
            flag=false;
            for(Transfer tra:cfg.values()){//移除单生成式
                List<String> strs = new ArrayList<>();
                for (String str: tra.to) {
                    if(nonterminal.contains(str)){
                        flag=true;
                        strs.add(str);
                    }
                }
                for (String ss:strs) {
                    tra.to.remove(ss);
                    Transfer t=cfg.get(ss);
                    List<String> anewss=new ArrayList<>();
                    for (String gets:t.to) {
                        if(!tra.to.contains(gets)){
                            anewss.add(gets);
                        }
                    }

                    tra.to.addAll(anewss);
                }
            }
        }

    }

    void EliminateUselessSymbols(){
        List<String> toEnd=terminal;
        boolean keep=true;
        while (keep){
            keep=false;
            for(Transfer tra:cfg.values()){//找到可以终结的字符
                for (String str: tra.to){
                    char[] chars=str.toCharArray();
                    boolean flag=true;
                    for (char ch:chars) {
                        if(!toEnd.contains(String.valueOf(ch))){
                            flag=false;
                        }
                    }
                    if(flag&&!toEnd.contains(tra.beg)){
                        toEnd.add(tra.beg);
                        keep=true;
                        break;
                    }
                }
            }
        }

        //可以终结的非终结符
        List<String> nontoend=new ArrayList<>();
        for(String ss:nonterminal){
            if(toEnd.contains(ss)){
                nontoend.add(ss);
            }
        }
        //不可以终结的非终结符
        List<String> cannot=new ArrayList<>();
        cannot.addAll(nonterminal);
        cannot.addAll(toEnd);
        cannot.removeAll(toEnd);
        allterminal.removeAll(cannot);
        nonterminal=nontoend;
        terminal.removeAll(nonterminal);

        for (String s:cannot) {//删去不可终结的非终结符
            cfg.remove(s);
        }
        for (Transfer tr: cfg.values()) {
            List<String> todel=new ArrayList<>();
            for (String st: tr.to){
                for (String sj:cannot) {
                    if(st.contains(sj)){
                        todel.add(st);
                        break;
                    }
                }
            }
            tr.to.removeAll(todel);
        }
    }

    public static void main(String[] args) {
        CFG cfg=new CFG();

        cfg.InputProduction();
        cfg.RemoveEpsilon();
        cfg.EliminateUnitProduction();
        cfg.EliminateUselessSymbols();
        cfg.OutputProduction();
    }
}

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,我明白了您的问题。这个问题的解决方案需要分别解决 ε-产生产生无用符号的问题。下面是我推荐的算法: 1. 消除 ε-产生 对于文法的每个非终结符 A,找出能够推导出 ε 的所有规则,并将这些规则文法删除。然后,对于每个非终结符 A,找出所有可以到达 A 的符号集合,称为 FIRST(A)。使用这些符号替换文法所有 A 的出现,以便生成不包含 ε 产生的新文法。重复此过程,直到没有更多的 ε 产生可以消除。 对于这个文法,我们可以找到两个 ε-产生:A→ε 和 D→ε。因此,我们将这些规则文法删除。然后,我们替换文法所有 A 和 D 的出现,以便生成以下新文法: S→a|bA|B|ccD|cc A→abB|bB|aB|ab B→aA|a C→ddC D→ddd|dd 2. 消除产生 产生是指只有一个非终结符的产生。这些产生可以使用传递闭包算法来消除。对于每个非终结符 A,计算它可以到达的所有符号集合,称为 REACH(A)。然后,对于每个非终结符 A,将所有 REACH(A) 产生替换为 A 的出现。这将生成一个新的文法,其不存在产生。 对于这个文法,我们可以看到 B→a 和 C→ddC 都是产生。因此,我们使用传递闭包算法消除这些产生。计算 REACH(B) 和 REACH(C): - REACH(B) = {B, A, S} - REACH(C) = {C, S} 然后,我们将 B→a 和 C→ddC 替换为: - S→a|bA|B|ccD|cc - A→abB|bB|aB|ab - B→abB|bB|aB|ab|ccD|cc - C→ddd|dd 3. 消除无用符号 无用符号是指不会出现在任何句子的推导符号。可以使用以下步骤来消除无用符号: - 找到所有终结符,将它们标记为有用符号。 - 对于每个规则 A→α,如果 α 存在一个符号,该符号已被标记为有用符号,则将 A 标记为有用符号。 - 重复上述步骤,直到没有新的符号被标记为有用符号。 然后,从文法删除所有无用符号规则。 对于这个文法,我们可以看到 D 是一个无用符号。因此,我们将 D 和规则 D→ddd 从文法删除。得到最终的文法: S→a|bA|B|cc A→abB|bB|aB|ab B→abB|bB|aB|ab|cc

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值