编译原理LL1文法Follow集算法实现

import hjzgg.first.First;

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;

public class Follow {
    private Map<String, Set<Character>> first = null;
    private Map<String, Set<Character>> follow = new TreeMap<String, Set<Character>>();
    private Map<String, String[]> mp = null;
    public Follow(Map<String, String[]> mp, Map<String, Set<Character>> first) {
        super();
        this.first = first;
        this.mp = mp;
    }

    public Map<String, Set<Character>> getFollowSet(){
        return follow;
    }

    private void getFirstSet(Set<Character> st, String node, int k){
        if(k >= node.length()) return;
        if(node.charAt(k)=='\'') --k;
        String nextNode = "" + node.charAt(k);
        if(k+1<node.length() && node.charAt(k+1)=='\''){
            nextNode += '\'';
            ++k;
        }
        if(!mp.containsKey(nextNode)){//终结点
            st.add(nextNode.charAt(0));
        } else {
            st.addAll(first.get(nextNode));
            if(first.get(nextNode).contains('$'))
                getFirstSet(st, node, k+1);
        }
    }

    private void findFollow(String curNode){
        Set<Character> st = null;
        for(String leftNode : mp.keySet()){
            String rightNodes[] = mp.get(leftNode);
            for(int i=0; i<rightNodes.length; ++i){
                int index = rightNodes[i].indexOf(curNode, 0);
                while(index != -1){
                    int nextIndex = index + 1;
                    if(curNode.length()==1 && index+1<rightNodes[i].length() && rightNodes[i].charAt(index+1)=='\''){
                        index = rightNodes[i].indexOf(curNode, nextIndex);
                        continue;
                    }
                    index = index+curNode.length();
                    if(index == rightNodes[i].length()){//末尾的非终结点, A->@B
                        if(follow.get(leftNode) == null)
                            findFollow(leftNode);
                        if(follow.get(curNode) == null){
                            st = new TreeSet<Character>();
                            st.addAll(follow.get(leftNode));
                            follow.put(curNode, st);
                        }
                        else follow.get(curNode).addAll(follow.get(leftNode));
                    } else {
                        String nextNode = ""+rightNodes[i].charAt(index);
                        if(index+1 < rightNodes[i].length() && rightNodes[i].charAt(index+1)=='\''){
                            nextNode += '\'';
                            ++index;
                        }
                        if(mp.containsKey(nextNode)){//非终结符
                            if(first.get(nextNode).contains(new Character('$'))){//A->@B&, 而 &->$
                                if(follow.get(leftNode) == null)
                                    findFollow(leftNode);
                                if(follow.get(curNode) == null){
                                    st = new TreeSet<Character>();
                                    st.addAll(follow.get(leftNode));
                                    follow.put(curNode, st);
                                }
                                else follow.get(curNode).addAll(follow.get(leftNode));
                            } 

                            //好特殊的情况啊....
                            {//A->@B&, First(&)^$ 放入follow(B)
                                Set<Character> tmpSt = new TreeSet<Character>();
                                getFirstSet(tmpSt, rightNodes[i], index);
                                tmpSt.remove('$');
                                if(follow.get(curNode) == null){
                                    st = new TreeSet<Character>();
                                    st.addAll(tmpSt);
                                    follow.put(curNode, st);
                                }
                                else follow.get(curNode).addAll(tmpSt);
                            }
                        } else {//终结符
                            if(follow.get(curNode) == null){
                                st = new TreeSet<Character>();
                                st.add(nextNode.charAt(0));
                                follow.put(curNode, st);
                            }
                            else follow.get(curNode).add(nextNode.charAt(0));
                        }
                    }
                    index = rightNodes[i].indexOf(curNode, nextIndex);
                }
            }
        }
    }

    public String followKernealCode(){
         String content = "";
         boolean flag = true;
         for(String leftNode : mp.keySet()){
             if(flag){
                 Set<Character> st = new TreeSet<Character>();
                 st.add('#');
                 follow.put(leftNode, st);
                 flag = false;
             }
             findFollow(leftNode);
         }
         //打印first集合
         System.out.println("Follow 集合如下:");
         for(Map.Entry<String, Set<Character>> entry : follow.entrySet()){
             content += entry.getKey() + "  :  " + entry.getValue() + "\n";
             System.out.println(entry.getKey() + "  :  " + entry.getValue());
         }
         return content;
    }

    public static void main(String[] args) {
        String[] rightLinearGrammar = {
            "E->TE\'",
            "E\'->+TE\'|$",
            "T->FT\'",
            "T\'->*FT\'|$",
            "F->(E)|i"
        };

//        String[] rightLinearGrammar = {
//                "S->ABc",
//                "A->a|$",
//                "B->b|$"
//        };

        Map<String, String[]> mp = new LinkedHashMap<String, String[]>();
        try{
            for(int i=0; i<rightLinearGrammar.length; ++i){
                String split1[] = rightLinearGrammar[i].split("->");
                String split2[] = split1[1].split("\\|");
                mp.put(split1[0], split2);
            }

        } catch(Exception e){
            e.printStackTrace();
            System.out.println("右线性文法错误!");
        }
        First first = new First(mp);
        first.firstKernealCode();
        new Follow(mp, first.getFirstSet()).followKernealCode();
    }

}
时间: 2024-10-28 11:36:02

编译原理LL1文法Follow集算法实现的相关文章

编译原理 LL1文法First集算法实现

import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; import java.util.TreeMap; import java.util.TreeSet; public class First { private Map<String, Set<Character>> first = new TreeMap<String, Set<Character>>();

编译原理LL1文法分析表算法实现

import hjzgg.first.First; import hjzgg.follow.Follow; import hjzgg.tablenode.TableNode; import hjzgg.treenode.TreeNode; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; import java.util.Stack; im

编译原理LL1文法分析树(绘图过程)算法实现

import hjzgg.analysistable.AnalysisTable; import hjzgg.first.First; import hjzgg.follow.Follow; import hjzgg.treenode.TreeNode; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.Font; import java.awt.Grap

编译原理之文法

关于编译原理这块之前根本没有涉及过,这次要用到这里的知识就需要来接触一下这里的内容.编译原理顾名思义就是处理高级语言,使之称为计算机能够识别的语言(低级语言)的原理.而文法呢?就是用来描述程序设计语言的方法.类似佛法,用来描述佛家的诵经禅道的规则的.不用去纠结这个名字,知道这个含义,足以. 文法 概念 终结符和非终结符 如图:在p这个推导式的集合中,存在六个推导式.其中S.A.B为非终结符.a.b.c.d.q.p为终结符.终结符是原子不可分的. 分类 文法的分类也就这几种了,先看各自的定义,在定

【编译原理】语法分析LL(1)分析法的FIRST和FOLLOW集

近来复习编译原理,语法分析中的自上而下LL(1)分析法,需要构造求出一个文法的FIRST和FOLLOW集,然后构造分析表,利用分析表+一个栈来做自上而下的语法分析(递归下降/预测分析),可是这个FIRST集合FOLLOW集看得我头大... 教课书上的规则如下,用我理解的语言描述的: 任意符号α的FIRST集求法: 1. α为终结符,则把它自身加入FIRSRT(α) 2. α为非终结符,则: (1)若存在产生式α->a...,则把a加入FIRST(α),其中a可以为ε (2)若存在一串非终结符Y1

编译原理

编译原理 语法是指这样的一组规则,用它可以形成和产生一个合适的程序. 词法规则是指单词符号的形成规则. 语法规则是语法单位的形成规则,规定了如何从单词符号形成更大的结构(即语法单位或语法范畴). 一般程序语言的语法单位有:表达式.语句.分程序.函数.过程和程序等. 程序语言的基本功能是描述数据和对数据的运算.所谓程序,从本质上来说是描述一定数据的处理过程.   强制式语言也称过程式语言.其特点是命令驱动,面向语句.一个强制式语言程序由一系列的语句组成,每个语句的执行引起若干存储单元中的值的改变.

请教编译原理中的问题

问题描述 请教编译原理中的问题 考虑下列定义的文法族Gn:S->Aibi 1<=i<=nAi->ajAi|aj 1<=ij<=n且i!=j试证明:(1)Gn具有2n^2-n个产生式(2)Gn具有2^n+n^2+n个LR(0)项目集(3)Gn是SLR(0)吗?

深入剖析ASP.NET的编译原理之一:动态编译(Dynamical Compilation)

Microsoft 的Visual Studio为我们在应用开发中提供的强大功能,我们是有目共睹.借助该工具,是我们的开发 显得更加高效而轻松.从Microsoft把这个IDE的名字从VS.NET 该为VS(比如原来的Visual Studio.NET 2003,现在的版本叫VS2005),可以MS对该IDE的期望和野心:MS要把它改造成一个万能的IDE.不过任何都有其两面性,对于我们广大的开发者来说,VS是我们的各种行为简单化,傻瓜化:但是在另一方面,他也会蒙蔽我们的眼睛,使我们对它背后做的事

编译原理学习.

有时候感觉很无助,迷茫的时候,没有精神支柱的时候.[自暴自弃] 进入人生低谷的时候,找不到方向的时候, 总会出现一些让我兴奋和受到鼓舞的东西. 在一次次的脱变中,发现自己需要学习的东西还很多,很多... .. 我感觉不经历一些事情,就不会学会一些事情,不怕你做错事情,就怕你不肯改错. 我又接触词法分析的另一种词法分析算法[转换表],书中如此描述"理解了此算法思想,也就理解了词法分析器的核心". 仔细看了30分钟,反复琢磨,终于理解了此算法的真谛,让我狠高兴,很兴奋,在编程的学习道路又燃