消除文法中一切左递归算法
第一次写博客。。。编译原理课的一个实验。
感觉自己花了挺长的时间,所以作为博客保留下来,挺有纪念意义的 (因为我是菜鸟)
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;} }
转载于:https://www.cnblogs.com/snoopylovefiona/p/4593726.html
消除文法中一切左递归算法相关推荐
- 第四章:文法中的递归以及消除方法
在介绍递归文法之前,首先介绍一下递归下降分析器及其原理,然后分析右递归是如何处理的,再来分析左递归和间接左递归. 递归下降分析器 自顶向下语法分析的目的是为输入串寻找最左推导,或者说,从根节点(文法开 ...
- 如何消除摄影中的运动模糊?
点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 本文转自|计算机视觉life 如果你试过去拍摄一些运动场景,例如拍 ...
- LL(1)文法中FIRST集和FOLLOW集的计算方法
文章目录 深入理解 FIRST集的定义 FIRST集的实际意义 FIRST集的计算方法 FOLLOW集的定义 FOLLOW集的实际意义 FOLLOW集的计算方法 预测分析表的实质 LL(1)文法的判断 ...
- 《电脑音乐制作实战指南:伴奏、录歌、MTV全攻略》——2.7 消除歌曲中某个合音或乐器...
本节书摘来自异步社区<电脑音乐制作实战指南:伴奏.录歌.MTV全攻略>一书中的第2章,第2.7节,作者 健逗,更多章节内容可以访问云栖社区"异步社区"公众号查看. 2. ...
- 如何正确的使用Java8中的Optional类来消除代码中的null检查
点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 作者:一书生VOID lw900925.github.io/jav ...
- R语言ggplot2可视化移除数据中的NA值再可视化实战:消除图形中非常突出的NA柱状图、使用subset函数、使用drop_na函数
R语言ggplot2可视化移除数据中的NA值再可视化实战:消除图形中非常突出的NA柱状图.使用subset函数.使用drop_na函数 目录
- 消除 Xcode7 中 directory not found for option 'xxxx' 警告
消除 Xcode7 中 directory not found for option 'xxxx' 警告 升级Xcode7之后,你会遇到一些警告信息,诸如以下一条: ld: warning: dire ...
- LeakCanary——消除Android中的内存泄露
2019独角兽企业重金招聘Python工程师标准>>> ##LeakCanary ####简介 LeakCanary是Square公司最近公布的开源项目,旨在消除Android中的内 ...
- c++中的左值与右值
转载自 http://www.cnblogs.com/catch/p/3500678.html 左值 (lvalue)和右值 (rvalue) 是 c/c++ 中一个比较晦涩基础的概念,有的人可能甚至 ...
最新文章
- 默的各种写法图片_SEO标题写法?
- python游戏编程入门电子书-请问自学 Python 有必要买课程吗?
- 概率论 第二章 随机变量及其分布
- 【code】Splay 模板
- pat 甲级 1034. Head of a Gang (30)
- sql docker容器_了解SQL Server Docker容器中的备份和还原操作
- Firewalld防火墙转换成Iptables
- 计算机日常英语,计算机英语的常用句子
- android7.1获取存储权限,Android外部存储
- ARM指令集和X86指令集对比
- mysql unicode转换为中文_中文转换成Unicode编码 和 Unicode编码转换为中文
- android 修改机型,教你一个无需Root就能修改手机型号的简单方法
- ESP32使用百度语音合成 实现文字转语音播放
- 专精特新是什么,为什么要申报“专精特新”中小企业
- #先进先出#每批次采购价格不同,计算期末库存成本
- 怎么清楚计算机硬盘搜索记录,win7系统怎么清除搜索记录_windows7删除计算机搜索记录的方法...
- 分享一个特别好用的站长在线工具箱
- linux脚本编写图形,shell图形化界面脚本实现
- 本地——云服务器文件传输
- 极简汉字史 第一章 文象列而结绳移 鸟迹明而书契作