protected void toStringWork(Object p, Object stop, StringBuffer buf) { if (!adaptor.isNil(p)) { String text = adaptor.getText(p); if (text == null) { text = " " + String.valueOf(adaptor.getType(p)); } buf.append(text); // ask the node to go to string } if (p == stop) { return; } int n = adaptor.getChildCount(p); if (n > 0 && !adaptor.isNil(p)) { buf.append(" "); buf.append(Token.DOWN); } for (int c = 0; c < n; c++) { Object child = adaptor.getChild(p, c); toStringWork(child, stop, buf); } if (n > 0 && !adaptor.isNil(p)) { buf.append(" "); buf.append(Token.UP); } }
public boolean hasNext() { if (firstTime) return root != null; if (nodes != null && nodes.size() > 0) return true; if (tree == null) return false; if (adaptor.getChildCount(tree) > 0) return true; return adaptor.getParent(tree) != null; // back at root? }
/** * Return the next node found during a depth-first walk of root. Also, add these nodes and DOWN/UP * imaginary nodes into the lokoahead buffer as a side-effect. Normally side-effects are bad, but * because we can emit many tokens for every next() call, it's pretty hard to use a single return * value for that. We must add these tokens to the lookahead buffer. * * <p>This does *not* return the DOWN/UP nodes; those are only returned by the LT() method. * * <p>Ugh. This mechanism is much more complicated than a recursive solution, but it's the only * way to provide nodes on-demand instead of walking once completely through and buffering up the * nodes. :( */ public Object next() { // already walked entire tree; nothing to return if (currentNode == null) { addLookahead(eof); // this is infinite stream returning EOF at end forever // so don't throw NoSuchElementException return null; } // initial condition (first time method is called) if (currentChildIndex == -1) { return handleRootNode(); } // index is in the child list? if (currentChildIndex < adaptor.getChildCount(currentNode)) { return visitChild(currentChildIndex); } // hit end of child list, return to parent node or its parent ... walkBackToMostRecentNodeWithUnvisitedChildren(); if (currentNode != null) { return visitChild(currentChildIndex); } return null; }
protected void toDOTDefineEdges(Object tree, TreeAdaptor adaptor, StringTemplate treeST) { if (tree == null) { return; } int n = adaptor.getChildCount(tree); if (n == 0) { // must have already dumped as child from previous // invocation; do nothing return; } String parentName = "n" + getNodeNumber(tree); // for each child, do a parent -> child edge using unique node names String parentText = adaptor.getText(tree); for (int i = 0; i < n; i++) { Object child = adaptor.getChild(tree, i); String childText = adaptor.getText(child); String childName = "n" + getNodeNumber(child); StringTemplate edgeST = _edgeST.getInstanceOf(); edgeST.setAttribute("parent", parentName); edgeST.setAttribute("child", childName); edgeST.setAttribute("parentText", fixString(parentText)); edgeST.setAttribute("childText", fixString(childText)); treeST.setAttribute("edges", edgeST); toDOTDefineEdges(child, adaptor, treeST); } }
/** Walk upwards looking for a node with more children to walk. */ protected void walkBackToMostRecentNodeWithUnvisitedChildren() { while (currentNode != null && currentChildIndex >= adaptor.getChildCount(currentNode)) { currentNode = nodeStack.pop(); if (currentNode == null) { // hit the root? return; } currentChildIndex = ((Integer) indexStack.pop()).intValue(); currentChildIndex++; // move to next child if (currentChildIndex >= adaptor.getChildCount(currentNode)) { if (!adaptor.isNil(currentNode)) { addNavigationNode(Token.UP); } if (currentNode == root) { // we done yet? currentNode = null; } } } }
public Object next() { if (firstTime) { // initial condition firstTime = false; if (adaptor.getChildCount(tree) == 0) { // single node tree (special) nodes.add(eof); return tree; } return tree; } // if any queued up, use those first if (nodes != null && nodes.size() > 0) return nodes.remove(); // no nodes left? if (tree == null) return eof; // next node will be child 0 if any children if (adaptor.getChildCount(tree) > 0) { tree = adaptor.getChild(tree, 0); nodes.add(tree); // real node is next after DOWN return down; } // if no children, look for next sibling of tree or ancestor Object parent = adaptor.getParent(tree); // while we're out of siblings, keep popping back up towards root while (parent != null && adaptor.getChildIndex(tree) + 1 >= adaptor.getChildCount(parent)) { nodes.add(up); // we're moving back up tree = parent; parent = adaptor.getParent(tree); } // no nodes left? if (parent == null) { tree = null; // back at root? nothing left then nodes.add(eof); // add to queue, might have UP nodes in there return nodes.remove(); } // must have found a node with an unvisited sibling // move to it and return it int nextSiblingIndex = adaptor.getChildIndex(tree) + 1; tree = adaptor.getChild(parent, nextSiblingIndex); nodes.add(tree); // add to queue, might have UP nodes in there return nodes.remove(); }
protected Object handleRootNode() { Object node; node = currentNode; // point to first child in prep for subsequent next() currentChildIndex = 0; if (adaptor.isNil(node)) { // don't count this root nil node node = visitChild(currentChildIndex); } else { addLookahead(node); if (adaptor.getChildCount(currentNode) == 0) { // single node case currentNode = null; // say we're done } } return node; }
protected void toDOTDefineNodes(Object tree, TreeAdaptor adaptor, StringTemplate treeST) { if (tree == null) { return; } int n = adaptor.getChildCount(tree); if (n == 0) { // must have already dumped as child from previous // invocation; do nothing return; } // define parent node StringTemplate parentNodeST = getNodeST(adaptor, tree); treeST.setAttribute("nodes", parentNodeST); // for each child, do a "<unique-name> [label=text]" node def for (int i = 0; i < n; i++) { Object child = adaptor.getChild(tree, i); StringTemplate nodeST = getNodeST(adaptor, child); treeST.setAttribute("nodes", nodeST); toDOTDefineNodes(child, adaptor, treeST); } }