• 消除文法中一切左递归算法


      第一次写博客。。。编译原理课的一个实验。

      感觉自己花了挺长的时间,所以作为博客保留下来,挺有纪念意义的  (因为我是菜鸟)

    package com.insist.entity;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Scanner;
    
    /**
     * 
     * @author SNOOPY 消除一切左递归
     */
    public class EliminateLeftRecursion {
    
        private static int n;// 实际输入产生式个数
    
        public static void main(String[] args) {
            Scanner scan = new Scanner(System.in);
            System.out.println("请输入产生式个数:");
            n = scan.nextInt();
            // 创建产生式数组存放输入的产生式
            List<Regular> regulars = new ArrayList<Regular>();
            for (int i = 0; i < n; i++) {
                Regular reg = new Regular();
                System.out.println("请输入产生式左部:");
                String left = scan.next();
                reg.setLeft(left);
                System.out.println("请输入产生式的右部:");
                String right = scan.next();
                reg.setRight(right);
                regulars.add(reg);
            }
            /*
             * 测试输出------->成功 for (Regular reg: regulars) { System.out.println(reg.getLeft()+"---->"+reg.getRight()); }
             */
    
            // 构造一个字符型的数组用来存放排序好的非终结符
            String[] Vn = new String[50];
            // 对所有的产生式按照一定的顺序存放
            Vn[0] = regulars.get(0).getLeft();// 把产生式第一个非终结符放到集合中
            int flag = 0;
            int count = 0;
            for (int i = 1; i < n; i++) {// 对非终结符排序并存取 1、遍历产生式数组
                for (int j = 0; j < i; j++) {
                    // 如果产生式左部等于在它前面的产生式的左部
                    if (regulars.get(i).getLeft().equals(regulars.get(j).getLeft())) {// 说明有重复的
                        flag++;
                    }
                }
                if (flag == 0) {// 说明没有重复,则加入非终结符数组中
                    count++;
                    Vn[count] = regulars.get(i).getLeft();
                }
                flag = 0;
            }
            /*
             * 测试非终结符数组------------>成功 for (int i = 0; i < Vn.length; i++) { if(Vn[i]!=null){ System.out.println(Vn[i]); } }
             */
            for (Regular reg : regulars) {
                if (reg != null) {
                    System.out.println(reg.getLeft() + "---->" + reg.getRight());
                }
            }
            regulars = subFunction(regulars, Vn, count);
            for (Regular reg : regulars) {
                if (reg != null) {
                    System.out.println(reg.getLeft() + "---->" + reg.getRight());
                }
            }
        }
    
        public static List<Regular> subFunction(List<Regular> regulars, String[] Vn, int count) {
            int flag = 0;
            // 判断是否存在间接左递归并转化为直接左递归
            for (int i = 0; i <= count; i++) {// 对每一个非终结符 迭代
                for (int j = 0; j < i; j++) {// 对每一个小于i的非终结符遍历
                    for (int k = 0; k < regulars.size(); k++) // 对每一个产生式
                        if (Vn[i].equals(regulars.get(k).getLeft())) {// i非终结符与第k产生式左边第一个字母相等-->锁定非终结符集合中的一个非终结符的产生式
                            if (regulars.get(k).getRight().substring(0, 1).equals(Vn[j])) { // g产生式右边产生式第一个符号与第j个非终结符相等-->说明存在间接左递归
                                for (int h = 0; h < regulars.size(); h++) {
                                    if (regulars.get(h).getLeft().equals(Vn[j])) {// 进行替换
                                        String str;
                                        str = regulars.get(k).getRight().substring(1);// 截取右边第一个以后的字符
                                        Regular reg = new Regular();
                                        reg.setLeft(regulars.get(k).getLeft());
                                        reg.setRight(regulars.get(h).getRight() + str);
                                        regulars.add(reg);
                                    }
                                }
                                regulars.remove(k);
                            }
                        }
                }
            }
            // 消除所有直接左递归
            for (int i = 0; i <= count; i++) {
                flag = 0;
                for (int j = 0; j < regulars.size(); j++) {// 判断是否存在直接左递归
                    if (regulars.get(j).getLeft().equals(Vn[i])) {
                        System.out.println(regulars.get(j).getLeft() + " ======= " + Vn[i]);
                        if (regulars.get(j).getLeft().equals(regulars.get(j).getRight().substring(0, 1))) {
                            System.out.println("消除间接左递归后存在直接左递归");
                            flag++;
                        }
                    }
                }
                if (flag != 0) {// 存在直接左递归
                    for (int j = 0; j < regulars.size(); j++) {
                        if (regulars.get(j).getLeft().equals(Vn[i])) {// 寻找与存在直接左递归的非终结符左部相同的的产生式
                            if (regulars.get(j).getLeft().equals(regulars.get(j).getRight().substring(0, 1))) {
                                // 直接左递归的产生式
                                String str = regulars.get(j).getRight().substring(1);
                                String temp = regulars.get(j).getLeft();
                                String temp1 = "'";
                                regulars.get(j).setLeft(temp + temp1);
                                regulars.get(j).setRight(str + regulars.get(j).getLeft());
                                Regular reg = new Regular();
                                reg.setLeft(regulars.get(j).getLeft());
                                reg.setRight("ε");
                                regulars.add(reg);
    
                            } else {
                                String temp = regulars.get(j).getLeft();
                                String temp1 = "'";
                                temp = temp + temp1;
                                regulars.get(j).setRight(regulars.get(j).getRight() + temp);
                            }
                        }
                    }
                }
            }
            return regulars;
        }
    }
    package com.insist.entity;
    
    import java.io.Serializable;
    
    /**
     * 
     * @author SNOOPY
     *
     */
    public class Regular implements Serializable {
    
        private static final long serialVersionUID = 1L;
    
        private String right;// 定义产生式右部
    
        private String left;// 定义产生式左部
    
        public String getRight() {
            return right;
        }
    
        public void setRight(String right) {
            this.right = right;
        }
    
        public String getLeft() {
            return left;
        }
    
        public void setLeft(String left) {
            this.left = left;
        }
    }
  • 相关阅读:
    MyBatis Generator去掉生成的注解
    IDEA git修改远程仓库地址
    Spring Boot 集成druid
    解决 SpringBoot 没有主清单属性
    Intellij IDEA 安装lombok及使用详解
    SET FOREIGN_KEY_CHECKS=0;在Mysql中取消外键约束
    @SpringBootApplication
    IDEA 创建git 分支 拉取分支
    Intellij Idea 将java项目打包成jar
    Spring Could Stream 基本用法
  • 原文地址:https://www.cnblogs.com/snoopylovefiona/p/4593726.html
Copyright © 2020-2023  润新知