00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 package org.antlr.runtime.tree;
00029
00030 import org.stringtemplate.v4.ST;
00031
00032 import java.util.HashMap;
00033
00053 public class DOTTreeGenerator {
00054
00055 public static ST _treeST =
00056 new ST(
00057 "digraph {\n\n" +
00058 "\tordering=out;\n" +
00059 "\tranksep=.4;\n" +
00060 "\tbgcolor=\"lightgrey\"; node [shape=box, fixedsize=false, fontsize=12, fontname=\"Helvetica-bold\", fontcolor=\"blue\"\n" +
00061 "\t\twidth=.25, height=.25, color=\"black\", fillcolor=\"white\", style=\"filled, solid, bold\"];\n" +
00062 "\tedge [arrowsize=.5, color=\"black\", style=\"bold\"]\n\n" +
00063 " <nodes>\n" +
00064 " <edges>\n" +
00065 "}\n");
00066
00067 public static ST _nodeST =
00068 new ST("<name> [label=\"<text>\"];\n");
00069
00070 public static ST _edgeST =
00071 new ST("<parent> -> <child> // \"<parentText>\" -> \"<childText>\"\n");
00072
00074 HashMap nodeToNumberMap = new HashMap();
00075
00077 int nodeNumber = 0;
00078
00079 public ST toDOT(Object tree,
00080 TreeAdaptor adaptor,
00081 ST _treeST,
00082 ST _edgeST)
00083 {
00084 ST treeST = new ST(_treeST);
00085 nodeNumber = 0;
00086 toDOTDefineNodes(tree, adaptor, treeST);
00087 nodeNumber = 0;
00088 toDOTDefineEdges(tree, adaptor, treeST);
00089 return treeST;
00090 }
00091
00092 public ST toDOT(Object tree,
00093 TreeAdaptor adaptor)
00094 {
00095 return toDOT(tree, adaptor, _treeST, _edgeST);
00096 }
00097
00115 public ST toDOT(Tree tree) {
00116 return toDOT(tree, new CommonTreeAdaptor());
00117 }
00118
00119 protected void toDOTDefineNodes(Object tree,
00120 TreeAdaptor adaptor,
00121 ST treeST)
00122 {
00123 if ( tree==null ) {
00124 return;
00125 }
00126 int n = adaptor.getChildCount(tree);
00127 if ( n==0 ) {
00128
00129
00130 return;
00131 }
00132
00133
00134 ST parentNodeST = getNodeST(adaptor, tree);
00135 treeST.add("nodes", parentNodeST);
00136
00137
00138 for (int i = 0; i < n; i++) {
00139 Object child = adaptor.getChild(tree, i);
00140 ST nodeST = getNodeST(adaptor, child);
00141 treeST.add("nodes", nodeST);
00142 toDOTDefineNodes(child, adaptor, treeST);
00143 }
00144 }
00145
00146 protected void toDOTDefineEdges(Object tree,
00147 TreeAdaptor adaptor,
00148 ST treeST)
00149 {
00150 if ( tree==null ) {
00151 return;
00152 }
00153 int n = adaptor.getChildCount(tree);
00154 if ( n==0 ) {
00155
00156
00157 return;
00158 }
00159
00160 String parentName = "n"+getNodeNumber(tree);
00161
00162
00163 String parentText = adaptor.getText(tree);
00164 for (int i = 0; i < n; i++) {
00165 Object child = adaptor.getChild(tree, i);
00166 String childText = adaptor.getText(child);
00167 String childName = "n"+getNodeNumber(child);
00168 ST edgeST = new ST(_edgeST);
00169 edgeST.add("parent", parentName);
00170 edgeST.add("child", childName);
00171 edgeST.add("parentText", fixString(parentText));
00172 edgeST.add("childText", fixString(childText));
00173 treeST.add("edges", edgeST);
00174 toDOTDefineEdges(child, adaptor, treeST);
00175 }
00176 }
00177
00178 protected ST getNodeST(TreeAdaptor adaptor, Object t) {
00179 String text = adaptor.getText(t);
00180 ST nodeST = new ST(_nodeST);
00181 String uniqueName = "n"+getNodeNumber(t);
00182 nodeST.add("name", uniqueName);
00183
00184 nodeST.add("text", fixString(text));
00185 return nodeST;
00186 }
00187
00188 protected int getNodeNumber(Object t) {
00189 Integer nI = (Integer)nodeToNumberMap.get(t);
00190 if ( nI!=null ) {
00191 return nI.intValue();
00192 }
00193 else {
00194 nodeToNumberMap.put(t, new Integer(nodeNumber));
00195 nodeNumber++;
00196 return nodeNumber-1;
00197 }
00198 }
00199
00200 protected String fixString(String in)
00201 {
00202 String text = in;
00203
00204 if (text!=null) {
00205
00206 text = text.replaceAll("\"", "\\\\\"");
00207 text = text.replaceAll("\\t", " ");
00208 text = text.replaceAll("\\n", "\\\\n");
00209 text = text.replaceAll("\\r", "\\\\r");
00210 if (text.length() > 20) {
00211 text = text.substring(0, 8) + "..." + text.substring(text.length()-8);
00212 }
00213
00214 }
00215
00216 return text;
00217 }
00218 }