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("語法分析樹"); } }