/* * Copyright (c) 2006 David Holroyd */ package uk.co.badgersinfoil.metaas.impl.antlr; import java.io.OutputStream; import java.io.PrintWriter; import java.io.Writer; import java.util.IdentityHashMap; import java.util.Map; import org.antlr.runtime.Token; import org.asdt.core.internal.antlr.AS3Parser; /** * A little hack to create a 'dot' file representing the structure of the * given LinkedListTree, suitable to visualisation using the graphviz.org * 'dot' tool. */ public class ASTDot { private PrintWriter out; private Map doneTokens = new IdentityHashMap(); public ASTDot(Writer writer) { out = new PrintWriter(writer); } public ASTDot(OutputStream stream) { out = new PrintWriter(stream); } public static void dump(LinkedListTree ast) { new ASTDot(System.err).dotify(ast); } public void dotify(LinkedListTree ast) { println("digraph ast_diagram {"); println(" node [fontsize=12];"); nodeSubGraph(ast); tokenSubGraph(ast); startStopTokenEdges(ast); println("}"); out.flush(); } private void nodeSubGraph(LinkedListTree ast) { println(" subgraph tree {"); treeNodes(ast); println(" }"); } private void treeNodes(LinkedListTree ast) { println(" "+nodeName(ast)+" [label="+label(ast)+",shape=invhouse];"); for (int i=0; i "+nodeName(child)+" [weight=10,style=bold];"); treeNodes(child); } } private String label(LinkedListTree ast) { return label(AS3Parser.tokenNames[ast.getType()]); } private String nodeName(LinkedListTree ast) { return "ast_0x"+Integer.toHexString(System.identityHashCode(ast)); } private void tokenSubGraph(LinkedListTree ast) { println(" subgraph cluster_tokens {"); println(" rankdir=LR;"); tokenNodes(ast); println(" }"); } private void tokenNodes(LinkedListTree ast) { for (LinkedListToken tok = ast.getStartToken(); tok!=null; tok=tok.getNext()) { tokenNode(tok); } for (int i=0; i "+label(tok)); doneTokens.put(tok, runId); if (tok.getNext() != null) { out.print("|"); } } out.println("\",shape=record];"); } private String label(LinkedListToken tok) { if (tok.getType() == Token.EOF) { return "EOF"; } if (tok.getType() == AS3Parser.VIRTUAL_PLACEHOLDER) { return "PLACEHOLD"; } String txt = tok.getText(); if (txt.length() > 10) { txt = txt.substring(0, 7) + "..."; } return "\\\""+txt.replaceAll("\\|", "\\\\|") .replaceAll("\"", "\\\\\"") .replaceAll("\\{", "\\\\{") .replaceAll("\\}", "\\\\}") .replaceAll("<", "\\\\<") .replaceAll(">", "\\\\>") .replaceAll("\n", "\\\\\\\\n") .replaceAll("\t", "\\\\\\\\t")+"\\\""; } private String nodeName(LinkedListToken tok) { return "tok_"+doneTokens.get(tok)+":"+fieldName(tok); } private String fieldName(LinkedListToken tok) { return "f"+Integer.toHexString(System.identityHashCode(tok)); } private void startStopTokenEdges(LinkedListTree ast) { if (ast.getStartToken() != null) { println(" "+nodeName(ast)+" -> "+nodeName(ast.getStartToken())+" [minlen=2,color=green,tailport=w];"); } if (ast.getStopToken() != null) { println(" "+nodeName(ast)+" -> "+nodeName(ast.getStopToken())+" [minlen=2,color=red,tailport=e];"); } for (int i=0; i 15) { str = str.substring(0, 15); } StringBuffer res = new StringBuffer("\""); for (int i=0; i