编译原理之LL(1)文法_java

编译原理之First集,Follow集.Select集.

编译原理之LL1文法

    • 原理讲解
    • 实例
    • 代码实现
    • 效果图
    • 没有积分的小伙伴可以去我的码云下载

原理讲解

  • LL(1)是自上而下的分析方法,第一个L表示从左向右扫描输入串,第二个L表示分析过程中将使用最左推导,最后一个1表示只需要向右看一个符号就可以决定用哪个产生式进行推导
  • 步骤
    • 求出First集,FoLLow集
    • 根据First集与Follow集求出Select集
  • 根据Select集构造预测分析表
  • 具体参见我的上一个博客.

实例

E->E+T|T
T->T*F|F
F->i|(E)

编译原理之LL(1)文法_java_第1张图片
编译原理之LL(1)文法_java_第2张图片
编译原理之LL(1)文法_java_第3张图片

代码实现

以下为主要的 代码部分

package LL1;

import java.util.*;

public class LL1 {

    // 预测分析表
    private Map<String,Map<String,String>> analysisTable = new TreeMap<>();
    // 分析栈
    private Stack<String> analysisStack = new Stack<>();
    // 输入符号栈
    private Stack<String> inputStack = new Stack<>();
    // 输入串

    private String inputString ;


    private Map<String , Set<String>> select;
    private G g;

    public LL1(Map<String, Set<String>> select, G g, String inputString) {
        this.select = select;
        this.g = g;
        this.inputString = inputString;
    }



    public void startLL1() {
        // 初始化
        initLL1();

        // 开始分析
        startAnalysis();

    }

    // 开始分析
    private void startAnalysis() {
        String start = g.getpList().get(0).getKey(); // 默认第一个为 文法开始符号

        // 将开始符号压入栈中
        analysisStack.push(start);

        // 输出
        System.out.println("分析栈" + "                       "  + "剩余输入串" + "                       " +    "所用的产生式或匹配");
        while (!(analysisStack.peek().equals("#")&&inputStack.peek().equals("#"))) {
            String inputSymbol = inputStack.peek(); // 获取 输入栈的栈顶符号
            String anlysisSymbol = analysisStack.peek(); // 获取分析栈的栈顶符号

            if (isVNorVT(anlysisSymbol, g.getVT())) { // 如果分析栈顶是终结符
                if (inputSymbol.equals(anlysisSymbol)) { // 两栈符号相同

                    System.out.println(analysisStack.toString() + "                       "  + inputStack.toString() + "                       " + anlysisSymbol+ "匹配");

                    inputStack.pop();
                    analysisStack.pop();
                } else { // 两栈符号不同
                    try {
                        throw new Exception("终结符不匹配,可能非LL1文法");
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    break;
                }
            }else {
                String needAddanaly = analysisTable.get(anlysisSymbol).get(inputSymbol);
                if (needAddanaly==null||needAddanaly.equals("")) { // 如果不存在,报错
                    try {
                        throw new Exception("非终结符的产生式获取的为空,可能非LL1文法");
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    break;
                } else if (needAddanaly.equals("ε")){ // 如果推导的为ε,需要弹出
                    System.out.println(analysisStack.toString() + "                       "  + inputStack.toString() + "                       " +  anlysisSymbol + "->" +needAddanaly);
                    analysisStack.pop();
                } else { //有其他的话 需要压入栈中

                    System.out.println(analysisStack.toString() + "                       "  + inputStack.toString() + "                       " +  anlysisSymbol + "->" +needAddanaly);
                    addToStack(analysisStack, needAddanaly);
                }
            }

        }
    }

    // 将符号压入 分析栈中
    private void addToStack(Stack<String> analysisStack, String symbols) {
        analysisStack.pop();
        for (int i= symbols.length()-1; i>=0; i--) {
            String symbol = symbols.charAt(i)+ "";
            if (i>=1&&symbols.charAt(i)=='\'') {
                symbol = symbols.charAt(i-1)+symbol;
                --i;
            }
            analysisStack.push(symbol);
        }
    }

    // 判断是终结符还是非终结符
    private boolean isVNorVT(String charac , String[] value) {
        boolean bool = false;

        for (String val:value) {
            if (charac.equals(val)) {
                bool = true;
            }
        }
        return bool;
    }

    // 初始化 LL1文法
    private void initLL1(){

        // 根据Select集构建预测分析表
        setAnalysisTable();

        // 构造 输入符号栈
        setInputStack();

        // 初始化 分析栈
        setAnalysisStack();


    }

    // 构造分析表
    private void setAnalysisTable() {
        for (Map.Entry<String,Set<String>> set : select.entrySet()) { // 遍历 select
            String key = set.getKey().split("->")[0];
            String value = set.getKey().split("->")[1];

            // 获取需要的终结符
            String[] VTsymbols = new String[g.getVT().length+1];

            VTsymbols[g.getVT().length] = "#";
            System.arraycopy(g.getVT(), 0, VTsymbols, 0, g.getVT().length);

            // 存储
            Map<String, String> nowSymbol = new TreeMap<>();

            for (String symbols: VTsymbols) {
                if (set.getValue().contains(symbols)) {
                    nowSymbol.put(symbols,value);
                } else { // 如果没有 , 则为空
                    nowSymbol.put(symbols, "");
                }
            }
            if (analysisTable.get(key)== null) {
                analysisTable.put(key,nowSymbol);
            } else {
                Map<String,String> lastSymbol = analysisTable.get(key); //之前存储过此类数据,需要合并

                for (Map.Entry<String,String> entry:lastSymbol.entrySet()) {
                    if (!entry.getValue().equals("")&&nowSymbol.get(entry.getKey()).equals("")){
                        nowSymbol.put(entry.getKey(),entry.getValue());
                    }
                }

                analysisTable.get(key).putAll(nowSymbol);

            }
        }
        System.out.println("预测分析表:");
        System.out.println(analysisTable.toString());

    }
    // 构造输入符号栈
    private void setInputStack() {
        inputStack.push("#");
        for (int i = inputString.length() -1; i>=0;i--) {
            String symbol = inputString.charAt(i)+"";
            inputStack.push(symbol);
        }
        System.out.println("输入符号栈:");
        System.out.println(inputStack.toString());
    }

    // 构造分析栈
    private void setAnalysisStack() {
        analysisStack.push("#");
    }

}

效果图

编译原理之LL(1)文法_java_第4张图片
编译原理之LL(1)文法_java_第5张图片

没有积分的小伙伴可以去我的码云下载

我的码云上下载.

你可能感兴趣的:(编译原理)