编译原理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-11-05 14:12:50

编译原理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

编译原理——正规式转DFA算法概述

一.概念概述 给定一个单词,判断该单词是否满足我们给定的单词描述规则,需要用到编译原理中词法分析的相关知识,其中涉及到的两个很重要的概念就是正规式(Regular Expression)和有穷自动机(Finite Automata).正规式是描述单词规则的工具,首先要明确的一点是所有单词组成的是一个无穷的集合,而正规式正是描述这种无穷集合的一个工具:有穷自动机则是识别正规式的一个有效的工具,它分为确定的有穷自动机(Deterministic Finite Automata,DFA)和不确定的有穷

编译原理之文法和语言总结与梳理

前言 一个程序设计语言是一个记号系统,如同自然语言一样,它的完整定义应包括语法和语义两个方面.所谓一个语言的语法是指一组规则,用它可以形成和产生一个合适的程序.目前广泛使用的手段是上下文无关文法,即用上下文无关文法作为程序设计语言语法的描述工具.语法只是定义什么样的符号序列是合法的,与这此符导的含义落无关系,比如对于个Pascal程序来说,一个上下文无关文法可以定义符号串A:一B+C是一个合乎语法的默值语句,而A:=B+就不是.但是,如果B是实型的,而C是布尔理的,或者B.C中任何一个变量没有事

编译原理FRIST和FOLLOW

First集合的求法: First集合最终是对产生式右部的字符串而言的,但其关键是求出非终结符的First集合,由于终结符的First集合就是它自己,所以求出非终结符的First集合后,就可很直观地得到每个字符串的First集合. 1.  直接收取:对形如U-a-的产生式(其中a是终结符),把a收入到First(U)中 2.  反复传送:对形入U-P-的产生式(其中P是非终结符),应把First(P)中的全部内容传送到First(U)中. Follow集合的求法: Follow集合是针对非终结符

编译原理:文法和语言总结与梳理

1. 梳理第二章的内容,写一篇理解与总结. 一. 对程序设计语言的描述从语法.语义和语用三个因素考虑: 语法:对语言结构的定义: 语义:语言的含义: 语用:从使用的角度描述语言. 形式语言理论是编译的理论基础. 二. 字母表:元素的非空有穷集合: 符号/字符:字母表中的元素: 符号串:符号的有穷序列. 三. 符号串运算: 符号串的连接:εx=xε=x: 集合的乘积:AB={xy|x∈A,y∈B}:{ε}A=A{ε}=A: 符号串的幂运算:x=abc,x^2=abcabc; 集合的幂运算 正闭包A

编译原理的文法与语言

理解符号串与集合运算. L={A,B, … ,Z,a,b, … ,z} D={0,1, … ,9} 说明下表示的含义: LUD :全部字母和数字的结合的一个集合 LD :由一个字母后跟一个数字组成的所有符号串的集合 L4:由4个字母组成的所有符号串的集合 L*:由字母组成的所有符号串包括空符号串ξ的集合 D+:由一个或到九个数字全组成的符号串的集合 L(LUD)*:以字母开头,后跟字母或数字组成的所有符号串的集合 文法G(Z):Z->aZb|ab定义的是什么样的语言? Z->aZb|ab Z-

0909对编译原理的初了解

1.编译原理学什么? "编译原理":研究设计和构造编译程序原理和方法以及主要实现技术.其中蕴含着计算机科学中解决问题的思路.形式化问题和解决问题的方法.通过本课程的学习,使学生掌握编译理论和方法方面的基本知识,同时也获得设计.实现.分析和移植编译程序方面的初步能力. 编译原理(第3版)共10章,内容包括语言及文法的基本知识.词法分析.语法分析.语义分析及中间代码生成.符号表组织.运行时的存储组织与分配.代码优化及目标代码生成等.此外编译原理是一门实践性较强的课程,要联系实际,多看实验参