import hjzgg.analysistable.AnalysisTable;
import hjzgg.first.First;
import hjzgg.follow.Follow;
import hjzgg.treenode.TreeNode; import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.HeadlessException;
import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.Map; import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane; public class TreeGraphic { private int fatherNode;//treeGraphic搜素是的开始节点
private TreeNode[] treeGraphic = null; private final int distNode = 50;//节点之间的距离
private final int heightNode = 50;//节点的高度
private final int widthNode = 50;//节点的宽度
private final int levelHeight = 100;//层与层之间的高度
private ArrayList<Rectangle> line = new ArrayList<Rectangle>();
private int curY = 0;
private int curX = 10; public TreeGraphic(int fatherNode, TreeNode[] treeGraphic) {
super();
this.fatherNode = fatherNode;
this.treeGraphic = treeGraphic;
prepareGraphic();
} public class TreeFrame extends JFrame{
private JPanel panel = new JPanel(){
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
for(Rectangle rect : line){
g.drawLine(rect.x, rect.y, rect.width, rect.height);
}
}
};
private JScrollPane scrollPane = new JScrollPane(panel);
public TreeFrame() throws HeadlessException {
super();
init();
} public TreeFrame(String title) throws HeadlessException {
super(title);
init();
} private void init(){
setLayout(new BorderLayout());
panel.setLayout(null);
drawTree(fatherNode);
add(scrollPane, BorderLayout.CENTER);
int width = curX + 50;
int height = curY + 50;
//这里要设置面板的PreferredSize,如果当前Frame大小不能显示PreferredSize那么才会出现滚动条
panel.setPreferredSize(new Dimension(width, height));
if(width > 600) width = 600;
if(height > 300) height = 500;
setBounds(400, 100, width, height);
setVisible(true);
} public void drawTree(int curNode){
JLabel label = new JLabel(treeGraphic[curNode].content, JLabel.CENTER);
label.setBounds(treeGraphic[curNode].getRect());
label.setFont(new Font("宋体",Font.BOLD, 32));
label.setOpaque(true);
label.setBackground(Color.RED);
panel.add(label);
if(treeGraphic[curNode].child.size()==0) return;
int x = treeGraphic[curNode].getRect().x;
int y = treeGraphic[curNode].getLevel()*levelHeight+heightNode;
int dist = widthNode / treeGraphic[curNode].child.size();//父节点到子节点连线的距离
for(int i=0; i<treeGraphic[curNode].child.size(); ++i){
drawTree(treeGraphic[curNode].child.get(i));
int xx = treeGraphic[treeGraphic[curNode].child.get(i)].getRect().x + widthNode/2;
int yy = y+levelHeight-heightNode;
line.add(new Rectangle(x, y, xx, yy));
x+=dist;
}
}
} private void prepareNodeLevel(int curNode, int level){//确定每一个节点的层次
treeGraphic[curNode].setLevel(level);
for(int i=0; i<treeGraphic[curNode].child.size(); ++i)
prepareNodeLevel(treeGraphic[curNode].child.get(i), level+1);
if(curY < (level+1)*levelHeight) curY = (level+1)*levelHeight;
} private void prepareNodeSize(int curNode){//确定节点的坐标位置
if(treeGraphic[curNode].child.size() == 0){//终结点
int x = curX; curX+=distNode+widthNode;
int y = treeGraphic[curNode].getLevel()*levelHeight;
treeGraphic[curNode].setRect(new Rectangle(x, y, widthNode, heightNode));
return;
} for(int i=0; i<treeGraphic[curNode].child.size(); ++i)
prepareNodeSize(treeGraphic[curNode].child.get(i));
int leftChildx=treeGraphic[treeGraphic[curNode].child.get(0)].getRect().x;
int rightChildx=treeGraphic[treeGraphic[curNode].child.get(treeGraphic[curNode].child.size()-1)].getRect().x;
//根据左右两边孩子的节点,确定父节点的坐标尺寸
int parentx = (leftChildx+rightChildx)/2;
int parenty = treeGraphic[curNode].getLevel()*levelHeight;
treeGraphic[curNode].setRect(new Rectangle(parentx, parenty, widthNode, heightNode));
} private void prepareGraphic(){
prepareNodeLevel(fatherNode, 0);
prepareNodeSize(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" "E->TE\'",
"E\'->ATE\'|$",
"T->FT\'",
"T\'->MFT\'|$",
"F->(E)|i",
"A->+|-",
"M->*|/"
}; // 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*(i/i)-i#");
     //通过分析表,在分析句子时产生的分析栈建立分析树,并将分析树返回,利用该程序绘制树
analysisTable.AnalysisTree();
TreeGraphic treeGraphic = new TreeGraphic(analysisTable.getFatherNode(), analysisTable.getTreeGraphic());
treeGraphic.new TreeFrame("语法分析树");
}
}

编译原理LL1文法分析树(绘图过程)算法实现的更多相关文章

  1. 编译原理LL1文法分析表算法实现

    import hjzgg.first.First; import hjzgg.follow.Follow; import hjzgg.tablenode.TableNode; import hjzgg ...

  2. 编译原理LL1文法Follow集算法实现

    import hjzgg.first.First; import java.util.LinkedHashMap; import java.util.Map; import java.util.Set ...

  3. 编译原理 LL1文法First集算法实现

    import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; import java.util.TreeMap ...

  4. 《编译原理》LR 分析法与构造 LR(1) 分析表的步骤 - 例题解析

    <编译原理>LR 分析法与构造 LR(1) 分析表的步骤 - 例题解析 笔记 直接做题是有一些特定步骤,有技巧.但也必须先了解一些基本概念,本篇会通过例题形式解释概念,会容易理解和记忆,以 ...

  5. 编译原理-递归下降分析法 c程序部分的分析

    实验三 语法分析程序实验 专业 商软2班   姓名 黄仲浩  学号 201506110166 一. 实验目的      编制一个部分文法分析程序. 二. 实验内容和要求 输入:源程序字符串 输出:正确 ...

  6. 【编译原理】自底向上分析方法——LR文法分析方法的总结

    LR(0).SLR(1).LR(1).LALR(1) de 若干方面的区别 目录 推导过程 分析能力 本质区别 文法对比 可以适当利用物理意义对二义性文法进行冲突处理 推导过程 LR(0)的基础上才有 ...

  7. 编译原理:正规式转变成DFA算法

    //将正规式转变成NFApackage hjzgg.formal_ceremony_to_dfa; import java.util.ArrayList; class Edge{ public int ...

  8. <编译原理 - 函数绘图语言解释器(2)语法分析器 - python>

    <编译原理 - 函数绘图语言解释器(2)语法分析器 - python> 背景 编译原理上机实现一个对函数绘图语言的解释器 - 用除C外的不同种语言实现 设计思路: 设计函数绘图语言的文法, ...

  9. <编译原理 - 函数绘图语言解释器(3)解释器 - python>

    <编译原理 - 函数绘图语言解释器(3)解释器 - python> <编译原理 - 函数绘图语言解释器(2)词法分析器 - python> <编译原理 - 函数绘图语言解 ...

随机推荐

  1. PHP程序员如何突破技术瓶颈

    身边有几个做PHP开发的朋友,也接触到不少的PHP工程师,他们常疑虑自己将来在技术上的成长与发展,我常给他们一些建议,希望他们能破突自己,有更好的发展. 先明确我所指的PHP工程题,是指毕业工作后,主 ...

  2. 自己做了一个json格式化工具,亲测可以使用

    随笔背景:在向后台请求数据之后,我们常常会拿到一串json格式.此时,为了方便查看key-value,程序猿们常常使用一些在线json格式化工具或者是类似于notepadd++这样的工具进行转换.今天 ...

  3. 拾遗——java多线程

    由于sleep()方法是Thread类的方法,因此它不能改变对象的机锁.所以当在一个Synchronized方法中调用sleep()时,线程虽然休眠了,但是对象的机锁没有被释放,其他线程仍然无法访问这 ...

  4. java jdb命令详解

    jdb - Java debugger 功能描述: 通过简单的命令行程序,对本地或远程jvm进程进行调试. 开启jdb会话: 有多种方式可以开启jdb会话. (1)常见的方式是采用Jdb命令打开一个新 ...

  5. 【原创】.NET之我见

    最近在准备面试,自己也顺带巩固了下基础,加上自己对码农的一些理解都写在这里了,水平不行,欢迎吐槽 //.NET基础 1.Class 和struct 区别 类是一种“引用类型”.创建类的对象时,对象赋值 ...

  6. 跨平台开源通讯组件elastic communication

    elastic communication是基于c#开发支持.net和mono的通讯组件(简称EC),EC的主要目的简化mono和.net下的通讯开发难度,通过EC可以非常快速地开发基于mono和.n ...

  7. Storm-源码分析- Storm中Zookeeper的使用

    在backtype.storm.cluster.clj中, 定义了storm对于Zookeeper的使用   ClusterState 首先定义操作Zookeeper集群的interface (def ...

  8. FB引擎系列-之CloudSand

    CloudSand,欲打破之前的集中版本制作的模式, http://code.taobao.org/p/cloudsand包含服务器端代码(php)和客户端代码(unity)   EasyDown的时 ...

  9. 如何将Icon转成Bitmap

    最近工作中有个需求是将Icon转成带Alpha通道的Bitmap, 虽然网上有不少这方面的文章,但很多都是错的, 这里记录下,或许对后来人有用. 要实现这个功能,我们首先需要理解Icon的格式,我们可 ...

  10. JavaScript字符转Unicode,顺便说句:GitHub的Oh no页面很亮

    遇到个输不出来的字符怎么办,因为输不出来的字符一般又是不常见大多数时候连名字也喊不出来的,所以想问百度谷歌大大也不大可能.如果是小白用户肯定会去把输入法软盘打开切换到其他键盘一个一个找.即使有搜狗输入 ...