编译原理LL1文法分析树(绘图过程)算法实现

简介:
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("语法分析树");
    }
}









本文转自 小眼儿 博客园博客,原文链接:http://www.cnblogs.com/hujunzheng/p/4454777.html,如需转载请自行联系原作者
目录
相关文章
|
11月前
|
数据采集 机器学习/深度学习 算法
别急着上算法,咱先把数据整明白:大数据分析的5个基本步骤,你都搞对了吗?
别急着上算法,咱先把数据整明白:大数据分析的5个基本步骤,你都搞对了吗?
715 4
|
9月前
|
机器学习/深度学习 边缘计算 算法
NOMA和OFDMA优化算法分析
NOMA和OFDMA优化算法分析
437 127
|
5月前
|
存储 机器学习/深度学习 监控
网络管理监控软件的 C# 区间树性能阈值查询算法
针对网络管理监控软件的高效区间查询需求,本文提出基于区间树的优化方案。传统线性遍历效率低,10万条数据查询超800ms,难以满足实时性要求。区间树以平衡二叉搜索树结构,结合节点最大值剪枝策略,将查询复杂度从O(N)降至O(logN+K),显著提升性能。通过C#实现,支持按指标类型分组建树、增量插入与多维度联合查询,在10万记录下查询耗时仅约2.8ms,内存占用降低35%。测试表明,该方案有效解决高负载场景下的响应延迟问题,助力管理员快速定位异常设备,提升运维效率与系统稳定性。
281 4
|
6月前
|
运维 监控 JavaScript
基于 Node.js 图结构的局域网设备拓扑分析算法在局域网内监控软件中的应用研究
本文探讨图结构在局域网监控系统中的应用,通过Node.js实现设备拓扑建模、路径分析与故障定位,提升网络可视化、可追溯性与运维效率,结合模拟实验验证其高效性与准确性。
353 3
|
6月前
|
存储 边缘计算 算法
【太阳能学报EI复现】基于粒子群优化算法的风-水电联合优化运行分析(Matlab代码实现)
【太阳能学报EI复现】基于粒子群优化算法的风-水电联合优化运行分析(Matlab代码实现)
117 0
|
8月前
|
编解码 算法 5G
MIMO雷达空间谱估计中Capon算法与MUSIC算法的对比分析及实现
MIMO雷达空间谱估计中Capon算法与MUSIC算法的对比分析及实现
700 2
|
7月前
|
机器学习/深度学习 算法 5G
【MUSIC、最大似然与克拉美-罗下界】MUSIC与ESPRIT 算法来估计到达角(AoA),并尝试推导克拉美-罗下界(CRLB)以分析其性能研究(Matlab代码实现)
【MUSIC、最大似然与克拉美-罗下界】MUSIC与ESPRIT 算法来估计到达角(AoA),并尝试推导克拉美-罗下界(CRLB)以分析其性能研究(Matlab代码实现)
357 0
|
8月前
|
人工智能 自然语言处理 算法
2025 年 7 月境内深度合成服务算法备案情况分析报告
2025年7月,中央网信办发布第十二批深度合成算法备案信息,全国389款产品通过备案,服务提供者占比超七成。截至7月14日,全国累计备案达3834款,覆盖文本、图像、音视频等多模态场景,广泛应用于生活服务、医疗、金融等领域。广东以135款居首,数字人、AI客服等C端应用主导,民营企业成主力,国企聚焦公共服务。随着AI政策推动,备案已成为AI产品合规上线关键环节。
|
10月前
|
存储 机器学习/深度学习 算法
KMP、Trie树 、AC自动机‌ ,三大算法实现 优雅 过滤 netty 敏感词
KMP、Trie树 、AC自动机‌ ,三大算法实现 优雅 过滤 netty 敏感词
KMP、Trie树 、AC自动机‌ ,三大算法实现 优雅 过滤 netty  敏感词
|
8月前
|
监控 算法 安全
基于 C# 基数树算法的网络屏幕监控敏感词检测技术研究
随着数字化办公和网络交互迅猛发展,网络屏幕监控成为信息安全的关键。基数树(Trie Tree)凭借高效的字符串处理能力,在敏感词检测中表现出色。结合C#语言,可构建高时效、高准确率的敏感词识别模块,提升网络安全防护能力。
202 2

热门文章

最新文章