编译原理LL1文法分析表算法实现
import hjzgg.first.First;
import hjzgg.follow.Follow;
import hjzgg.tablenode.TableNode;
import hjzgg.treenode.TreeNode; import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import java.util.Stack;
import java.util.TreeMap;
import java.util.TreeSet; public class AnalysisTable {
private final int noFinalCharacterCount = 100;
private Map<String, Integer>stringToInt = new TreeMap<String, Integer>();//分析表行 列 字母映射到数字
private Map<Integer, String>tableRow = new TreeMap<Integer, String>();//分析表 行列 数字 映射到字母
private Map<Integer, String>tableCol = new TreeMap<Integer, String>();
private String[][] table = new String[noFinalCharacterCount][];//分析表
private Set<Character>terminalCharacters = new TreeSet<Character>();//终结符集合
private Map<String, Set<Character>> first = null;
private Map<String, Set<Character>> follow = null;
private Map<String, String[]> mp = null;
private int nodeCntRow = 0, nodeCntCol=0; public static final int treeNodeCnt = 200;//树最多节点的个数
private int cntTreeNode = 0;
private ArrayList<String> usedProduction = new ArrayList<String>();//预测分析中所用到的产生式
private int fatherNode;//treeGraphic搜素是的开始节点
private TreeNode[] treeGraphic = new TreeNode[treeNodeCnt]; private String[] analysisStack = null;
public String[] getAnalysisStack(){
return analysisStack;
} public Map<String, Integer> getStringToInt(){
return stringToInt;
}
public Set<Character> getTerminalCharacters(){
return terminalCharacters;
} public int getFatherNode(){
return fatherNode;
} public TreeNode[] getTreeGraphic(){
return treeGraphic;
} public AnalysisTable(Map<String, Set<Character>> first,
Map<String, Set<Character>> follow, Map<String, String[]> mp) {
super();
this.first = first;
this.follow = follow;
this.mp = mp;
init();
} private void init(){
for(String leftNode : mp.keySet()){
stringToInt.put(leftNode, ++nodeCntRow);
tableRow.put(nodeCntRow, leftNode);
String[] rightNodes = mp.get(leftNode);
for(int i=0; i<rightNodes.length; ++i){//枚举每一个产生式
for(int j=0; j<rightNodes[i].length(); ++j)
if(!mp.containsKey(""+rightNodes[i].charAt(j)) && rightNodes[i].charAt(j)!='\'' && rightNodes[i].charAt(j)!='$'){//每一个终结符
if(!stringToInt.containsKey(""+rightNodes[i].charAt(j))){
stringToInt.put(""+rightNodes[i].charAt(j), ++nodeCntCol);
terminalCharacters.add(rightNodes[i].charAt(j));
tableCol.put(nodeCntCol, ""+rightNodes[i].charAt(j));
}
}
}
}
stringToInt.put("#", ++nodeCntCol);
tableCol.put(nodeCntCol, "#");
terminalCharacters.add('#');
} public ArrayList<TableNode> analysisTableKernealCode(){
for(String leftNode : mp.keySet()){
String[] rightNodes = mp.get(leftNode);
for(int i=0; i<rightNodes.length; ++i){//枚举每一个产生式
for(Character terminal : terminalCharacters){//每一个终结符
char finalCharacter = terminal;
Set<Character> productionFirstSet = new TreeSet<Character>();//产生式对应first集
for(int k=0; k<rightNodes[i].length(); ++k){
String node = ""+rightNodes[i].charAt(k);
if(k+1 < rightNodes[i].length() && rightNodes[i].charAt(k+1)=='\''){
node += '\'';
++k;
}
if(mp.containsKey(node)){//非终结符
productionFirstSet.addAll(first.get(node));
if(!first.get(node).contains('$')) break;
} else {//终结符
productionFirstSet.add(node.charAt(0));
break;
}
} if(productionFirstSet.contains(finalCharacter)){//A->@ 对于每一个终结符 a属于FIRST(@),加入M[A, a]
int col = stringToInt.get(""+finalCharacter);
int row = stringToInt.get(leftNode);
if(table[row]==null)
table[row] = new String[nodeCntCol+1];
table[row][col] = leftNode + "->" + rightNodes[i];
} /***********************************************************************/
else if(productionFirstSet.contains('$')){//A->@ 对于$属于First(@),对任何b属于Follow(A)则把A->@加入
if(follow.get(leftNode).contains(finalCharacter)){
int col = stringToInt.get(""+finalCharacter);
int row = stringToInt.get(leftNode);
if(table[row]==null)
table[row] = new String[nodeCntCol+1];
table[row][col] = leftNode + "->" + rightNodes[i];
}
}
}
}
}
return printTalbe();
} public ArrayList<TableNode> printTalbe(){
ArrayList<TableNode> tableNodeAl = new ArrayList<TableNode>();
System.out.println("分析表如下:");
for(int i=1; i<=nodeCntRow; ++i){
for(int j=1; j<=nodeCntCol; ++j)
if(table[i]!=null && table[i][j]!=null){
tableNodeAl.add(new TableNode(i, j, table[i][j]));
System.out.println(tableRow.get(i) + ":" + tableCol.get(j) + " " + table[i][j]);
}
}
return tableNodeAl;
} public boolean predictiveAnalysis(String formula){
ArrayList<String>stringStack = new ArrayList<String>();
System.out.println("开始进行预测分析,分析栈如下:");
Stack<String> stack = new Stack<String>();
stack.push("#");
stack.push(tableRow.get(1));
int formulaIndex = 0;
char a = formula.charAt(formulaIndex++);
boolean flag = false;
while(true){
if(stack.size() == 0){
//error
break;
}
stringStack.add(stack.toString());
System.out.println(stack);
String x = stack.pop();
if(!mp.containsKey(x)){//终结符
if(x.charAt(0)==a){
if(a=='#'){
flag = true;
break;
}
a = formula.charAt(formulaIndex++);
} else {
//error
}
} else {//非终结符
if(table[stringToInt.get(x)] != null){
String production = table[stringToInt.get(x)][stringToInt.get(""+a)];
if(production != null){
usedProduction.add(production);
if(!production.contains("$")){//X->X1X2X3....Xk 中 Xk....X3X2X1压入栈中
for(int i=production.length()-1; i>=0; --i){
if(production.charAt(i)=='>') break;
if(production.charAt(i)=='\''){
stack.push(""+production.charAt(i-1)+production.charAt(i));
--i;
} else{
stack.push(""+production.charAt(i));
}
}
}
} else {
//error
}
} else {
//error
}
}
}
analysisStack = stringStack.toArray(new String[stringStack.size()]);
return flag;
} private int produceAnalysisTree(int curRow, String preNode){
String curProduction = usedProduction.get(curRow);
String splits[] = curProduction.split("->");
if(preNode != null && !preNode.equals(splits[0]))
return produceAnalysisTree(curRow+1, preNode);
TreeNode treeNode = new TreeNode();
treeNode.content = splits[0];
for(int i=0; i<splits[1].length(); ++i){//右部的产生式
String node = "" + splits[1].charAt(i);
if(i+1<splits[1].length() && splits[1].charAt(i+1)=='\''){
node += '\'';
++i;
}
if(!mp.containsKey(node)){//不是 非终结点
TreeNode tmpTreeNode = new TreeNode();
tmpTreeNode.content = node;
treeNode.child.add(cntTreeNode);//加入孩子节点
treeGraphic[cntTreeNode++] = tmpTreeNode;
} else {//非终结点
int childNodeCnt = produceAnalysisTree(curRow+1, node);//得到这个孩子的节点
treeNode.child.add(childNodeCnt);
}
}
treeGraphic[cntTreeNode] = treeNode;
return cntTreeNode++;
} private void printAnalysisTree(int curNode){
System.out.print(" " + treeGraphic[curNode].content);
for(int i=0; i<treeGraphic[curNode].child.size(); ++i)
printAnalysisTree(treeGraphic[curNode].child.get(i));
} public void AnalysisTree(){
fatherNode = produceAnalysisTree(0, null);
System.out.println("分析树的先序遍历如下:");
printAnalysisTree(fatherNode);
} public static void main(String[] args) { // String[] rightLinearGrammar ={
// "S->iCtSA|a",
// "A->$|eS",
// "C->b"
// }; 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();
Follow follow = new Follow(mp, first.getFirstSet());
follow.followKernealCode();
AnalysisTable analysisTable = new AnalysisTable(first.getFirstSet(), follow.getFollowSet(), mp);
analysisTable.analysisTableKernealCode(); analysisTable.predictiveAnalysis("i+i#");
analysisTable.AnalysisTree();
} }
编译原理LL1文法分析表算法实现的更多相关文章
- 编译原理LL1文法分析树(绘图过程)算法实现
import hjzgg.analysistable.AnalysisTable; import hjzgg.first.First; import hjzgg.follow.Follow; impo ...
- 编译原理LL1文法Follow集算法实现
import hjzgg.first.First; import java.util.LinkedHashMap; import java.util.Map; import java.util.Set ...
- 编译原理 LL1文法First集算法实现
import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; import java.util.TreeMap ...
- 《编译原理》LR 分析法与构造 LR(1) 分析表的步骤 - 例题解析
<编译原理>LR 分析法与构造 LR(1) 分析表的步骤 - 例题解析 笔记 直接做题是有一些特定步骤,有技巧.但也必须先了解一些基本概念,本篇会通过例题形式解释概念,会容易理解和记忆,以 ...
- 【编译原理】自底向上分析方法——LR文法分析方法的总结
LR(0).SLR(1).LR(1).LALR(1) de 若干方面的区别 目录 推导过程 分析能力 本质区别 文法对比 可以适当利用物理意义对二义性文法进行冲突处理 推导过程 LR(0)的基础上才有 ...
- LL(1)文法分析表的构造和分析过程示例
在考完编译原理之后才弄懂,悲哀啊.不过懂了就好,知识吗,不能局限于考试. 文法: E→TE' E'→+TE'|ε T→FT ' T'→*FT'|ε F→id| (E) 一.首先判断是不是 LL(1)文 ...
- 编译原理-递归下降分析法 c程序部分的分析
实验三 语法分析程序实验 专业 商软2班 姓名 黄仲浩 学号 201506110166 一. 实验目的 编制一个部分文法分析程序. 二. 实验内容和要求 输入:源程序字符串 输出:正确 ...
- GCC编译器原理(三)------编译原理三:编译过程(2-2)---编译之语法分析
2.2 语法分析 语法分析器(Grammar Parser)将对由扫描器产生的记号进行语法分析,从而产生语法树(Syntax Tree).整个分析过程采用了上下文无关语法(Context-free G ...
- 编译原理 First集和Follow集的求法
转载地址 https://blog.csdn.net/Alexander_Frank/article/details/51280798 自上而下分析: FIRST集求法 First集合最终是对产生式右 ...
随机推荐
- BZOJ2683 简单题(CDQ分治)
传送门 之前听别人说CDQ分治不难学,今天才知道果真如此.之前一直为自己想不到CDQ的方法二很不爽,今天终于是想出来了一道了,太弱-- cdq分治主要就是把整段区间分成两半,然后用左区间的值去更新右区 ...
- css样式重置,不建议用通配符
由于各个浏览器对css样式的默认样式不一致,所以有必要进行样式重置.在网上看到很多建议使用 *{margin:0;padding:0} 重置margin和padding.建议不这样子使用,原因主要是性 ...
- WebRTC实现网页版多人视频聊天室
因为产品中要加入网页中网络会议的功能,这几天都在倒腾 WebRTC,现在分享下工作成果. 话说 WebRTC Real Time Communication 简称 RTC,是谷歌若干年前收购的一项技术 ...
- 《JAVA与模式》之抽象工厂模式
场景问题 举个生活中常见的例子——组装电脑,我们在组装电脑的时候,通常需要选择一系列的配件,比如CPU.硬盘.内存.主板.电源.机箱等.为讨论使用简单点,只考虑选择CPU和主板的问题. 事实上,在选择 ...
- 用JQ仿造百度书籍预售页面的单屏滚页效果
今天的项目需要做到一个介绍页面,我主动提出走单屏滚页的风格,毕竟交互性好,逼格也高,具体效果可以参照百度知道书籍预售页面. 其实现效果就大概是这样的: 还是老样子,所有步骤文件可以从我的Github上 ...
- phonegap 基础原理
phonegap是web app 下调用移动OS原生API的库.在整个压缩包结构中主要分三块: 1.cordova.js,前端的js库:功能是提供js的API接口,最终调用的是promp方法,如下: ...
- HTTP解析
前言 B/S网络架构的核心是HTTP,掌握HTTP对一个从事互联网工作的程序员来说非常重要.要理解HTTP,最重要的是要熟悉HTTP的HTTP Header,HTTP Header控制着互联网上成千上 ...
- Java多线程11:ReentrantLock的使用和Condition
ReentrantLock ReentrantLock,一个可重入的互斥锁,它具有与使用synchronized方法和语句所访问的隐式监视器锁相同的一些基本行为和语义,但功能更强大. Reentran ...
- java提高篇(十九)-----数组之二
前面一节主要介绍了数组的基本概念,对什么是数组稍微深入了一点点,在这篇博文中主要介绍数组的其他方面. 三.性能?请优先考虑数组 在java中有很多方式来存储一系列数据,而且在操作上面比数组方便的多?但 ...
- No resource found that matches the given name 'android:Widget.Material.A解决方案
1:首先新建空白工作区 2:先import appcompat_v7 appcompat_v7在一个类似这样的地方, C:\mywork\android\android-sdk-windows\ext ...