博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
消除文法中一切左递归算法
阅读量:4439 次
发布时间:2019-06-07

本文共 6000 字,大约阅读时间需要 20 分钟。

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

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

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
regulars = new ArrayList
(); 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
subFunction(List
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;    }}

 

转载于:https://www.cnblogs.com/snoopylovefiona/p/4593726.html

你可能感兴趣的文章
几种垃圾回收GC概述
查看>>
netty 配置 jsp
查看>>
类加载器-双亲委托
查看>>
【算法导论】第6章堆排序及利用堆建立最小优先级队列
查看>>
Log4Net配置方法
查看>>
ASP.NET禁用一部分验证控件,ValidationGroup的设置与使用
查看>>
JavaScript DOM高级程序设计 5动态修改样式和层叠样式表2--我要坚持到底!
查看>>
[.NET源码学习]实例化Font,遭遇字体不存在的情况。
查看>>
手机如何设置静态IP
查看>>
JS操作文件
查看>>
解放创意——自由人的自由联合
查看>>
Django框架之路由
查看>>
GitHub & GitHub Package Registry
查看>>
HTML5 & how to download SVG in js
查看>>
Machine Learning & ML
查看>>
常用会计科目通俗解释
查看>>
给网卡配置10个临时ip地址,但是不配置192.168.17.15这个ip
查看>>
html滑动
查看>>
个人作品:EasyPicker(轻取)简洁而又实用的文件收取Web应用
查看>>
Android代码中动态设置图片的大小(自动缩放),位置
查看>>