package de.skuzzle.polly.core.parser.util; import java.io.PrintStream; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import de.skuzzle.polly.tools.collections.LinkedStack; import de.skuzzle.polly.tools.collections.Stack; import de.skuzzle.polly.tools.iterators.ArrayIterator; public class PreOrderDotBuilder { private class Edge { Object source; Object target; public Edge(Object source, Object target) { super(); this.source = source; this.target = target; } } private int preorderNum; private final Stack<Integer> preorderStack; private final List<Edge> edgeList; private final Map<Object, Integer> preorderMap; private final Set<Object> mustPop; private final PrintStream out; private final boolean directed; public PreOrderDotBuilder(PrintStream out, boolean directed) { this.out = out; this.directed = directed; this.preorderStack = new LinkedStack<Integer>(); this.preorderMap = new HashMap<Object, Integer>(); this.edgeList = new ArrayList<Edge>(); this.mustPop = new HashSet<Object>(); if (this.directed) { this.out.println("digraph \"\""); } else { this.out.println("graph \"\""); } this.out.println("{"); this.out.println("node [shape=box]"); this.out.println("graph[bgcolor=white, ordering=out]"); } public void finish() { for (final Edge edge : this.edgeList) { Integer source = this.preorderMap.get(edge.source); Integer target = this.preorderMap.get(edge.target); if (source != null && target != null) { this.emitEdge(source, target); } } this.out.println("}"); } public void printNodeWithEdgeTo(Object newNode, Object parent, String...attributes) { this.printLabel(newNode, false, attributes); this.edgeList.add(new Edge(newNode, parent)); } private void printLabel(Object node, boolean edge, String...attributes) { int orderNum; boolean fromMap = false; if (this.preorderMap.get(node) != null) { orderNum = this.preorderMap.get(node); fromMap = true; } else { ++this.preorderNum; this.preorderMap.put(node, this.preorderNum); orderNum = this.preorderNum; this.mustPop.add(node); } this.out.print("n"); this.out.print(orderNum); this.out.print("[shape=Mrecord, fontname=\"Monospace\", label=\"{"); final Iterator<String> it = ArrayIterator.get(attributes); while(it.hasNext()) { this.out.print(this.simpleEscape(it.next())); if (it.hasNext()) { this.out.print("|"); } } this.out.println("}\"]"); if (edge && !this.preorderStack.isEmpty()) { this.emitEdge(this.preorderStack.peek(), orderNum); } if (!fromMap) { this.preorderStack.push(this.preorderNum); } } private String simpleEscape(String s) { s = s.replaceAll("<", "<"); s = s.replaceAll(">", ">"); return s; } public void printNode(Object node, String...attributes) { this.printLabel(node, true, attributes); } private void emitEdge(int source, int target) { this.out.print("n"); this.out.print(source); if (this.directed) { this.out.print(" -> "); } else { this.out.print(" -- "); } this.out.print("n"); this.out.println(target); } public void pop(Object node) { if (this.mustPop.contains(node)) { this.preorderStack.pop(); this.mustPop.remove(node); } } }