编译原理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;
import java.util.TreeMap;
import java.util.TreeSet;

public class AnalysisTable {
    private final int noFinalCharacterCount = 100;
    private Map<String, Integer>stringToInt = new TreeMap<String, Integer>();//分析表行 列 字母映射到数字
    private Map<Integer, String>tableRow = new TreeMap<Integer, String>();//分析表 行列 数字 映射到字母
    private Map<Integer, String>tableCol = new TreeMap<Integer, String>();
    private String[][] table = new String[noFinalCharacterCount][];//分析表
    private Set<Character>terminalCharacters = new TreeSet<Character>();//终结符集合
    private Map<String, Set<Character>> first = null;
    private Map<String, Set<Character>> follow = null;
    private Map<String, String[]> mp = null;
    private int nodeCntRow = 0, nodeCntCol=0;

    public static final int treeNodeCnt = 200;//树最多节点的个数
    private int cntTreeNode = 0;
    private ArrayList<String> usedProduction = new ArrayList<String>();//预测分析中所用到的产生式
    private int fatherNode;//treeGraphic搜素是的开始节点
    private TreeNode[] treeGraphic = new TreeNode[treeNodeCnt];

    private String[] analysisStack = null;
    public String[] getAnalysisStack(){
        return analysisStack;
    }

    public Map<String, Integer> getStringToInt(){
        return stringToInt;
    }
    public Set<Character> getTerminalCharacters(){
        return terminalCharacters;
    }

    public int getFatherNode(){
        return fatherNode;
    }

    public TreeNode[] getTreeGraphic(){
        return treeGraphic;
    }

    public AnalysisTable(Map<String, Set<Character>> first,
            Map<String, Set<Character>> follow, Map<String, String[]> mp) {
        super();
        this.first = first;
        this.follow = follow;
        this.mp = mp;
        init();
    }

    private void init(){
        for(String leftNode : mp.keySet()){
            stringToInt.put(leftNode, ++nodeCntRow);
            tableRow.put(nodeCntRow, leftNode);
            String[] rightNodes = mp.get(leftNode);
            for(int i=0; i<rightNodes.length; ++i){//枚举每一个产生式
                for(int j=0; j<rightNodes[i].length(); ++j)
                    if(!mp.containsKey(""+rightNodes[i].charAt(j)) && rightNodes[i].charAt(j)!=‘\‘‘ && rightNodes[i].charAt(j)!=‘$‘){//每一个终结符
                        if(!stringToInt.containsKey(""+rightNodes[i].charAt(j))){
                            stringToInt.put(""+rightNodes[i].charAt(j), ++nodeCntCol);
                            terminalCharacters.add(rightNodes[i].charAt(j));
                            tableCol.put(nodeCntCol, ""+rightNodes[i].charAt(j));
                        }
                    }
            }
        }
        stringToInt.put("#", ++nodeCntCol);
        tableCol.put(nodeCntCol, "#");
        terminalCharacters.add(‘#‘);
    }

    public ArrayList<TableNode> analysisTableKernealCode(){
        for(String leftNode : mp.keySet()){
            String[] rightNodes = mp.get(leftNode);
            for(int i=0; i<rightNodes.length; ++i){//枚举每一个产生式
                for(Character terminal : terminalCharacters){//每一个终结符
                        char finalCharacter = terminal;
                        Set<Character> productionFirstSet = new TreeSet<Character>();//产生式对应first集
                        for(int k=0; k<rightNodes[i].length(); ++k){
                            String node = ""+rightNodes[i].charAt(k);
                            if(k+1 < rightNodes[i].length() && rightNodes[i].charAt(k+1)==‘\‘‘){
                                node += ‘\‘‘;
                                ++k;
                            }
                            if(mp.containsKey(node)){//非终结符
                                productionFirstSet.addAll(first.get(node));
                                if(!first.get(node).contains(‘$‘)) break;
                            } else {//终结符
                                productionFirstSet.add(node.charAt(0));
                                break;
                            }
                        }

                        if(productionFirstSet.contains(finalCharacter)){//A->@ 对于每一个终结符 a属于FIRST(@),加入M[A, a]
                            int col = stringToInt.get(""+finalCharacter);
                            int row = stringToInt.get(leftNode);
                            if(table[row]==null)
                                table[row] = new String[nodeCntCol+1];
                            table[row][col] = leftNode + "->" + rightNodes[i];
                        }

                        /***********************************************************************/
                        else if(productionFirstSet.contains(‘$‘)){//A->@ 对于$属于First(@),对任何b属于Follow(A)则把A->@加入
                            if(follow.get(leftNode).contains(finalCharacter)){
                                int col = stringToInt.get(""+finalCharacter);
                                int row = stringToInt.get(leftNode);
                                if(table[row]==null)
                                    table[row] = new String[nodeCntCol+1];
                                table[row][col] = leftNode + "->" + rightNodes[i];
                            }
                        }
                }
            }
        }
        return printTalbe();
    }

    public ArrayList<TableNode> printTalbe(){
        ArrayList<TableNode> tableNodeAl = new ArrayList<TableNode>();
        System.out.println("分析表如下:");
        for(int i=1; i<=nodeCntRow; ++i){
            for(int j=1; j<=nodeCntCol; ++j)
                if(table[i]!=null && table[i][j]!=null){
                    tableNodeAl.add(new TableNode(i, j, table[i][j]));
                    System.out.println(tableRow.get(i) + ":" + tableCol.get(j) + "   " + table[i][j]);
                }
        }
        return tableNodeAl;
    }

    public boolean predictiveAnalysis(String formula){
        ArrayList<String>stringStack = new ArrayList<String>();
        System.out.println("开始进行预测分析,分析栈如下:");
        Stack<String> stack = new Stack<String>();
        stack.push("#");
        stack.push(tableRow.get(1));
        int formulaIndex = 0;
        char a = formula.charAt(formulaIndex++);
        boolean flag = false;
        while(true){
            if(stack.size() == 0){
                //error
                break;
            }
            stringStack.add(stack.toString());
            System.out.println(stack);
            String x = stack.pop();
            if(!mp.containsKey(x)){//终结符
                if(x.charAt(0)==a){
                    if(a==‘#‘){
                        flag = true;
                        break;
                    }
                    a = formula.charAt(formulaIndex++);
                } else {
                    //error
                }
            } else {//非终结符
                if(table[stringToInt.get(x)] != null){
                    String production = table[stringToInt.get(x)][stringToInt.get(""+a)];
                    if(production != null){
                        usedProduction.add(production);
                        if(!production.contains("$")){//X->X1X2X3....Xk 中 Xk....X3X2X1压入栈中
                            for(int i=production.length()-1; i>=0; --i){
                                if(production.charAt(i)==‘>‘) break;
                                if(production.charAt(i)==‘\‘‘){
                                    stack.push(""+production.charAt(i-1)+production.charAt(i));
                                    --i;
                                } else{
                                    stack.push(""+production.charAt(i));
                                }
                            }
                        }
                    } else {
                        //error
                    }
                } else {
                    //error
                }
            }
        }
        analysisStack = stringStack.toArray(new String[stringStack.size()]);
        return flag;
    }

    private int produceAnalysisTree(int curRow, String preNode){
        String curProduction = usedProduction.get(curRow);
        String splits[] = curProduction.split("->");
        if(preNode != null && !preNode.equals(splits[0]))
            return produceAnalysisTree(curRow+1, preNode);
        TreeNode treeNode = new TreeNode();
        treeNode.content = splits[0];
        for(int i=0; i<splits[1].length(); ++i){//右部的产生式
            String node = "" + splits[1].charAt(i);
            if(i+1<splits[1].length() && splits[1].charAt(i+1)==‘\‘‘){
                node += ‘\‘‘;
                ++i;
            }
            if(!mp.containsKey(node)){//不是 非终结点
                TreeNode tmpTreeNode = new TreeNode();
                tmpTreeNode.content = node;
                treeNode.child.add(cntTreeNode);//加入孩子节点
                treeGraphic[cntTreeNode++] = tmpTreeNode;
            } else {//非终结点
                int childNodeCnt = produceAnalysisTree(curRow+1, node);//得到这个孩子的节点
                treeNode.child.add(childNodeCnt);
            }
        }
        treeGraphic[cntTreeNode] = treeNode;
        return cntTreeNode++;
    }

    private void printAnalysisTree(int curNode){
        System.out.print(" " + treeGraphic[curNode].content);
        for(int i=0; i<treeGraphic[curNode].child.size(); ++i)
            printAnalysisTree(treeGraphic[curNode].child.get(i));
    }

    public void AnalysisTree(){
        fatherNode = produceAnalysisTree(0, null);
        System.out.println("分析树的先序遍历如下:");
        printAnalysisTree(fatherNode);
    }

    public static void main(String[] args) {

//        String[] rightLinearGrammar ={
//                "S->iCtSA|a",
//                "A->$|eS",
//                "C->b"
//        };

        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();
            Follow follow = new Follow(mp, first.getFirstSet());
            follow.followKernealCode();
            AnalysisTable analysisTable = new AnalysisTable(first.getFirstSet(), follow.getFollowSet(), mp);
            analysisTable.analysisTableKernealCode();

            analysisTable.predictiveAnalysis("i+i#");
            analysisTable.AnalysisTree();
    }

}
时间: 2024-10-05 06:17:04

编译原理LL1文法分析表算法实现的相关文章

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

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

编译原理——算符优先分析文法(附源代码)

算符优先分析文法 一.写在前面 算符优先分析文法是一种工具,在编译的过程中,隶属于语法分析环节,却又与中间代码的生成息息相关,编译可以分为五个阶段:词法分析.语法分析.语义分析(中间代码的生成).代码优化.目标代码生成.语法分析是指:在词法分析基础上,将单词符号串转化为语法单位(语法范畴)(短语.子句.句子.程序段.程序),并确定整个输入串是否构成语法上正确的程序.也就是说语法分析是检验输入串的语法是否正确,注意这里的语法正确,只是简单地符合自己定义的规范,而不能检测出运行时错误,比如"X/0&

LL(1)文法分析表的构造和分析过程示例

在考完编译原理之后才弄懂,悲哀啊.不过懂了就好,知识吗,不能局限于考试. 文法: E→TE' E'→+TE'|ε T→FT ' T'→*FT'|ε F→id| (E) 一.首先判断是不是 LL(1)文法 -------------------------------------------------------------------------------------------------------- 文法G的任意两个具有相同左部的产生式 A --> α|β 满足下列条件: 1.如果α和

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

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

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

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

编译原理-递归下降分析法

题:对下列文法,用递归下降分析法对任意输入的符号串进行分析: (1)E->TG (2)G->+TG|—TG (3)G->ε, (4)T->FS (5)S->*FS|/FS (6)S->ε (7)F->(E) (8)F->i 答:文法太多,可先合并. (1)E->FSG (2)G->+TG|—TG|ε (3)S->*FS|/FS|ε (4)F->(E)|i 结合1,4 (1)E->ESG|iSG (2)G->+TG|—TG|

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

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