预测分析法(语法分析)


import java.io.*;
import java.util.*;

public class YCFXF {


    BufferedReader reader = null;
    private List<String> wf = new ArrayList<String>();
    private List<String> N = new ArrayList<String>();
    private List<String> V = new ArrayList<String>();
    private Map<String,List<String>> first = new HashMap<String, List<String>>();
    private Map<String,List<String>> follow = new HashMap<String, List<String>>();
    private Map<String,String> waitAdd = new HashMap<String, String>();
    private Scanner scanner = null;

    public YCFXF() throws FileNotFoundException {
        scanner = new Scanner(System.in);
        reader = new BufferedReader(
                new InputStreamReader(new FileInputStream(new File("F:\\Workplace\\IDEA_Workplace\\SchoolProect\\软件构造实验4\\wf.txt")))
        );
    }

    public void getWf() throws IOException {
        System.out.println("所有的文法:");
        String temp;
        while (!(temp = reader.readLine()).equals("#")){
            wf.add(temp);
            System.out.println(temp);
        }
    }

    public void getN() throws IOException {
        System.out.println("所有的非终结符:");
        String temp;
        while (!(temp = reader.readLine()).equals("#")){
            N.add(temp);
            System.out.println(temp);
        }
    }

    public void getV() throws IOException {
        System.out.println("所有的终结符:");
        String temp;
        while (!(temp = reader.readLine()).equals("#")){
            V.add(temp);
            System.out.println(temp);
        }
    }


    public void getFirst(){
        String wfStr;
        Collections.reverse(wf);
        for (int i = 0; i < wf.size(); i++) {
            List<String> wfFirst = new ArrayList<String>();
            wfStr = wf.get(i);
            //前后分割
            String[] strings = wfStr.split("->");
            //文法产生的式子
            String[] split = strings[1].split("\\|");
            //计算first集合
            for (int j = 0; j < split.length; j++) {
                String firstChar = String.valueOf(split[j].charAt(0));
                if (N.contains(firstChar)){
                    wfFirst.addAll(first.get(firstChar));
                }else {
                    wfFirst.add(firstChar);
                }
            }
            first.put(strings[0],wfFirst);
        }
        Collections.reverse(wf);
    }

    //获取follow集和
    public void getFollow(){
        for (int i = 0; i < N.size(); i++) {
            String n = N.get(i);
            List<String> wfFollow = new ArrayList<String>();
            if (n.equals("E")){
                wfFollow.add("#");
            }
            List<String> hasGet = new ArrayList<String>();
            //每个文法都遍历
            for (int j = 0; j < wf.size(); j++) {
                String wfStr = wf.get(j);
                String[] split = wfStr.split("->");
                String[] strings = split[1].split("\\|");

                for (int k = 0; k < strings.length; k++) {
                    if (strings[k].contains(n)){
                        int indexOf = strings[k].indexOf(n);
                        //如果不为最后一位
                        if (indexOf != (strings[k].length()-1) ){
                            String followChar = String.valueOf(strings[k].charAt(indexOf + 1));
                            if (hasGet.contains(followChar)){
                                continue;
                            }
                            if (V.contains(followChar) && !followChar.equals("^")){
                                //如果后方接的是终结符
                                wfFollow.add(String.valueOf(strings[k].charAt(indexOf + 1)));
                            }
                            else if (N.contains(followChar)){
                                //如果接的是非终结符
                                wfFollow.addAll(first.get(followChar));
                                hasGet.add(followChar);
                                if (haveK(followChar)){
                                    try {
                                        wfFollow.addAll(follow.get(split[0]));
                                    }catch (NullPointerException e){
                                        waitAdd.put(n,split[0]);
                                    }
                                }
                            }
                        }else {
                            //如果是最后一位
                            if (!n.equals(split[0])){
                                try {
                                    wfFollow.addAll(follow.get(split[0]));
                                }catch (NullPointerException e){
                                    waitAdd.put(n,split[0]);
                                }
                            }
                        }
                    }
                }
            }
            follow.put(n,wfFollow);
        }
        //再将添加失败的添加进去
        Set<String> keySet = waitAdd.keySet();
        for (String s : keySet) {
            String s1 = waitAdd.get(s);
            List<String> stringList = follow.get(s);
            stringList.addAll(follow.get(s1));
            follow.remove(s);
            follow.put(s,stringList);
        }
    }

    //判断该文法是否有空
    private boolean haveK(String c) {
        boolean haveK = false;
        List<String> strings = first.get(c);
        if (strings.contains("^")){
            haveK = true;
        }
        return haveK;
    }

    //显示follow集
    public void showFirst(){
        System.out.println("First集合:");
        Set<String> strings = first.keySet();
        for (String key : strings) {
            System.out.println(key + ":" + first.get(key));
        }
    }

    //显示follow集
    public void showFollow(){
        System.out.println("Follow集合:");
        Set<String> strings = follow.keySet();
        for (String key : strings) {
            System.out.println(key + ":" + follow.get(key));
        }
    }


    //处理follow集,清除相同元素及空
    public void chandleMap(){
        Set<String> keySet = follow.keySet();
        for (String s : keySet) {
            List<String> stringList = follow.get(s);
            Set set = new HashSet(stringList);
            set.remove("^");
            stringList.clear();
            stringList.addAll(set);
        }
    }


    //构建预测分析表
    public String[][] buildTable(){
        String[][] table = new String[N.size()][V.size()+1];
        for (int i = 0; i < wf.size(); i++) {
            //当前的文法
            String wfStr = wf.get(i);
            String[] split = wfStr.split("->");
            //当前的非终结符
            String NStr = split[0];
            //当前的产生式
            String tuidaoStr = split[1];
            //分割多个产生式
            String[] tuidao = tuidaoStr.split("\\|");
            //如果是一个产生式,那么该产生式就是所有的first集的产生式
            if (tuidao.length == 1){
                List<String> Nfirst = first.get(NStr);
                for (String s : Nfirst) {
                    int charIndex = getCharIndex(s);
                    table[i][charIndex] = N.get(i) + "->" + tuidao[0];
                }
            }else {
                for (int j = 0; j < tuidao.length; j++) {
                    String s = tuidao[j];
                    String startChar = String.valueOf(s.charAt(0));
                    //如果是空的话
                    if (startChar.equals("^")){
                        List<String> nFollow = follow.get(NStr);
                        for (String follow : nFollow) {
                            table[i][getCharIndex(follow)] = N.get(i) + "->^";
                        }
                        continue;
                    }
                    int charIndex = getCharIndex(startChar);
                    table[i][charIndex] = N.get(i) + "->" + s;
                }
            }
        }

        System.out.println("预测分析表:");
        System.out.println("\t+\t\t\t-\t\t\t*\t\t\t/\t\t\t(\t\t\t)\t\t\ti\t\t\t#");
        for (int i = 0; i < N.size(); i++) {
            System.out.printf(N.get(i)+"\t");
            for (int j = 0; j < V.size()+1; j++) {
                System.out.print(table[i][j] + "\t\t");
            }
            System.out.println();
        }
        return table;
    }

    //获取终结符在预测表中的位置
    public int getCharIndex(String c){
        if (c.equals("#")){
            return V.size();
        }
        return V.indexOf(c);
    }


    public void fx(String[][] table, String s) {
        Stack<String> stack = new Stack<String>();
        List<String> stackStr = new ArrayList<String>();
        stack.push("#");
        stack.push("E");
        stackStr.add("#");
        stackStr.add("E");
        String sy = s;
        System.out.println("分析栈\t\t\t剩余串\t\t产生式");
        while (!sy.equals("")){
            String fxChar = String.valueOf(sy.charAt(0));
            String peek = stack.peek();
            System.out.printf("%-10s%10s\t\t",stackStr.toString(), sy);
            //如果和栈顶元素相等
            if (fxChar.equals(peek)){
                System.out.println(fxChar + "匹配");
                stack.pop();
                stackStr.remove(stackStr.size()-1);
                String[] split = sy.split("|");
                sy = "";
                for (int i = 1; i < split.length; i++) {
                    sy+=split[i];
                }
                continue;
            }

            //如果和栈顶元素不相等
            int i = N.indexOf(peek);
            int j = getCharIndex(fxChar);
            try {
                String s1 = table[i][j];
                System.out.println(s1);
                String[] split = s1.split("->");
                String[] strings = split[1].split("|");
                //先出栈,再替换
                stack.pop();
                stackStr.remove(stackStr.size()-1);
                for (int k = (strings.length-1); k >=0 ; k--) {
                    if (strings[k].equals("^")){
                        continue;
                    }
                    stack.push(strings[k]);
                    stackStr.add(strings[k]);
                }
            }catch (NullPointerException e){
                System.err.printf("分析错误!");
                System.exit(1);
            }

        }
        System.out.println("分析成功!");
    }


    public void useYcfxf(String s) throws IOException {
        getWf();
        getN();
        getV();
        getFirst();
        showFirst();
        getFollow();
        chandleMap();
        showFollow();
        String[][] table = buildTable();
        fx(table,s);
    }


}


posted @ 2020-11-02 21:30  Nevesettle  阅读(412)  评论(0编辑  收藏  举报