编译原理LL1文法Follow集算法实现
import hjzgg.first.First; import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet; public class Follow {
private Map<String, Set<Character>> first = null;
private Map<String, Set<Character>> follow = new TreeMap<String, Set<Character>>();
private Map<String, String[]> mp = null;
public Follow(Map<String, String[]> mp, Map<String, Set<Character>> first) {
super();
this.first = first;
this.mp = mp;
} public Map<String, Set<Character>> getFollowSet(){
return follow;
} private void getFirstSet(Set<Character> st, String node, int k){
if(k >= node.length()) return;
if(node.charAt(k)=='\'') --k;
String nextNode = "" + node.charAt(k);
if(k+1<node.length() && node.charAt(k+1)=='\''){
nextNode += '\'';
++k;
}
if(!mp.containsKey(nextNode)){//终结点
st.add(nextNode.charAt(0));
} else {
st.addAll(first.get(nextNode));
if(first.get(nextNode).contains('$'))
getFirstSet(st, node, k+1);
}
} private void findFollow(String curNode){
Set<Character> st = null;
for(String leftNode : mp.keySet()){
String rightNodes[] = mp.get(leftNode);
for(int i=0; i<rightNodes.length; ++i){
int index = rightNodes[i].indexOf(curNode, 0);
while(index != -1){
int nextIndex = index + 1;
if(curNode.length()==1 && index+1<rightNodes[i].length() && rightNodes[i].charAt(index+1)=='\''){
index = rightNodes[i].indexOf(curNode, nextIndex);
continue;
}
index = index+curNode.length();
if(index == rightNodes[i].length()){//末尾的非终结点, A->@B
if(follow.get(leftNode) == null)
findFollow(leftNode);
if(follow.get(curNode) == null){
st = new TreeSet<Character>();
st.addAll(follow.get(leftNode));
follow.put(curNode, st);
}
else follow.get(curNode).addAll(follow.get(leftNode));
} else {
String nextNode = ""+rightNodes[i].charAt(index);
if(index+1 < rightNodes[i].length() && rightNodes[i].charAt(index+1)=='\''){
nextNode += '\'';
++index;
}
if(mp.containsKey(nextNode)){//非终结符
if(first.get(nextNode).contains(new Character('$'))){//A->@B&, 而 &->$
if(follow.get(leftNode) == null)
findFollow(leftNode);
if(follow.get(curNode) == null){
st = new TreeSet<Character>();
st.addAll(follow.get(leftNode));
follow.put(curNode, st);
}
else follow.get(curNode).addAll(follow.get(leftNode));
} //好特殊的情况啊....
{//A->@B&, First(&)^$ 放入follow(B)
Set<Character> tmpSt = new TreeSet<Character>();
getFirstSet(tmpSt, rightNodes[i], index);
tmpSt.remove('$');
if(follow.get(curNode) == null){
st = new TreeSet<Character>();
st.addAll(tmpSt);
follow.put(curNode, st);
}
else follow.get(curNode).addAll(tmpSt);
}
} else {//终结符
if(follow.get(curNode) == null){
st = new TreeSet<Character>();
st.add(nextNode.charAt(0));
follow.put(curNode, st);
}
else follow.get(curNode).add(nextNode.charAt(0));
}
}
index = rightNodes[i].indexOf(curNode, nextIndex);
}
}
}
} public String followKernealCode(){
String content = "";
boolean flag = true;
for(String leftNode : mp.keySet()){
if(flag){
Set<Character> st = new TreeSet<Character>();
st.add('#');
follow.put(leftNode, st);
flag = false;
}
findFollow(leftNode);
}
//打印first集合
System.out.println("Follow 集合如下:");
for(Map.Entry<String, Set<Character>> entry : follow.entrySet()){
content += entry.getKey() + " : " + entry.getValue() + "\n";
System.out.println(entry.getKey() + " : " + entry.getValue());
}
return content;
} public static void main(String[] args) {
String[] rightLinearGrammar = {
"E->TE\'",
"E\'->+TE\'|$",
"T->FT\'",
"T\'->*FT\'|$",
"F->(E)|i"
}; // String[] rightLinearGrammar = {
// "S->ABc",
// "A->a|$",
// "B->b|$"
// }; Map<String, String[]> mp = new LinkedHashMap<String, String[]>();
try{
for(int i=0; i<rightLinearGrammar.length; ++i){
String split1[] = rightLinearGrammar[i].split("->");
String split2[] = split1[1].split("\\|");
mp.put(split1[0], split2);
} } catch(Exception e){
e.printStackTrace();
System.out.println("右线性文法错误!");
}
First first = new First(mp);
first.firstKernealCode();
new Follow(mp, first.getFirstSet()).followKernealCode();
} }
编译原理LL1文法Follow集算法实现的更多相关文章
- 编译原理 LL1文法First集算法实现
import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; import java.util.TreeMap ...
- 编译原理LL1文法分析表算法实现
import hjzgg.first.First; import hjzgg.follow.Follow; import hjzgg.tablenode.TableNode; import hjzgg ...
- 编译原理-First集和Follow集
刚学first集和follow集的时候,如果上课老师没有讲明白或者自己没听明白,自己看的时候还真是有点难理解,不过结合着具体的题目可以理解的更快. 先看一下两种集合的求法: First集合的求法: ...
- 编译原理 First集和Follow集的求法
转载地址 https://blog.csdn.net/Alexander_Frank/article/details/51280798 自上而下分析: FIRST集求法 First集合最终是对产生式右 ...
- 编译原理LL1文法分析树(绘图过程)算法实现
import hjzgg.analysistable.AnalysisTable; import hjzgg.first.First; import hjzgg.follow.Follow; impo ...
- 编译原理LR(0)项目集规范族的构造详解
转载于https://blog.csdn.net/johan_joe_king/article/details/79051993#comments 学编译原理的时候,感觉什么LL(1).LR(0).S ...
- 编译原理: FIRST(x) FOLLOW(x) SELECT(x)的计算
目录 First计算 Follow计算 Select计算 已知文法G[S]: S→MH|a H→LSo|ε K→dML|ε L→eHf M→K|bLM 判断G是否是LL(1)文法. First计算 F ...
- 编译原理 First,Follow,select集求法
参考:https://blog.csdn.net/CooperNiu/article/details/78524688
- 《编译原理》-用例题理解-自顶向下语法分析及 FIRST,FOLLOW,SELECT集,LL(1)文法
<编译原理>-用例题理解-自顶向下语法分析及 FIRST,FOLLOW,SELECT集,LL(1)文法 此编译原理确定某高级程序设计语言编译原理,理论基础,学习笔记 本笔记是对教材< ...
随机推荐
- easyui的datagrid行的某一列添加链接
通过formatter方法给easyui 的datagrid 每行增加操作链接. 效果图 jsp代码: <th field="url" width="100&quo ...
- TreeMap源码分析
MapClassDiagram
- 正则表达式统计java代码空白行,有效代码
import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; import jav ...
- testng+reportng,运行xml
在看了http://seleniumcn.cn/read.php?tid=7960视频的Reportng后自己实验了下, 1.下载reportng-1.1.4.zip,解压后如下,把reportng- ...
- PHP——使用header()函数下载文件
思路:先指明内容的MIME类型,内容描述,内容长度(也即文件大小). 一.下载txt文件的程序: <?phpheader('Content-Type:text/plain');header('C ...
- 3.使用CXF开发webService
CXF 简介 关于 Apache CXF Apache CXF = Celtix + XFire,Apache CXF 的前身叫 Apache CeltiXfire,现在已经正式更名为 Apache ...
- Redis主从复制深入剖析
Redis是一个开源的,遵守BSD许可协议的key/value缓存系统,并由其高效的响应速度以及丰富的数据结构而闻名.Redis在京东的使用也是非常普遍的,包括很多关键业务上的 使用,由于Redis官 ...
- 你以为的ASP.NET文件上传大小限制是你以为的吗
我们以为的文件大小限制 我们大家都知道ASP.NET为我们提供了文件上传服务器控件FileUpload,默认情况下可上传的最大文件为4M,如果要改变可上传文件大小限制,那么我们可以在web.confi ...
- java提高篇(一)-----理解java的三大特性之封装
从大二接触java开始,到现在也差不多三个年头了.从最基础的HTML.CSS到最后的SSH自己都是一步一个脚印走出来的,其中开心过.失落过.寂寞过.虽然是半道出家但是经过自己的努力也算是完成了“学业” ...
- 面向对象架构模式之:领域模型(Domain Model)
一:面向对象设计中最简单的部分与最难的部分 如果说事务脚本是 面向过程 的,那么领域模型就是 面向对象 的.面向对象的一个很重要的点就是:“把事情交给最适合的类去做”,即:“你得在一个个领域类之间跳转 ...