zoukankan      html  css  js  c++  java
  • 预测分析法(语法分析)

    
    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("	+			-			*			/			(			)			i			#");
            for (int i = 0; i < N.size(); i++) {
                System.out.printf(N.get(i)+"	");
                for (int j = 0; j < V.size()+1; j++) {
                    System.out.print(table[i][j] + "		");
                }
                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("分析栈			剩余串		产生式");
            while (!sy.equals("")){
                String fxChar = String.valueOf(sy.charAt(0));
                String peek = stack.peek();
                System.out.printf("%-10s%10s		",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);
        }
    
    
    }
    
    
    
  • 相关阅读:
    最短母串
    noip模拟测试7
    linux下的对拍程序
    noip模拟测试6
    QWidget 前后位置设定
    C++编程规范_第5~13条 设计风格
    random /timer/sort 示例代码
    资料准备
    【转】三维动态数组 分配与释放
    批量修改文件名
  • 原文地址:https://www.cnblogs.com/wuren-best/p/13916628.html
Copyright © 2011-2022 走看看