diff options
Diffstat (limited to 'runtime/Java/src/main/java/org/antlr/runtime/debug/DebugTreeAdaptor.java')
-rw-r--r-- | runtime/Java/src/main/java/org/antlr/runtime/debug/DebugTreeAdaptor.java | 250 |
1 files changed, 250 insertions, 0 deletions
diff --git a/runtime/Java/src/main/java/org/antlr/runtime/debug/DebugTreeAdaptor.java b/runtime/Java/src/main/java/org/antlr/runtime/debug/DebugTreeAdaptor.java new file mode 100644 index 0000000..1884bd6 --- /dev/null +++ b/runtime/Java/src/main/java/org/antlr/runtime/debug/DebugTreeAdaptor.java @@ -0,0 +1,250 @@ +/* + [The "BSD license"] + Copyright (c) 2005-2009 Terence Parr + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.antlr.runtime.debug; + +import org.antlr.runtime.Token; +import org.antlr.runtime.TokenStream; +import org.antlr.runtime.RecognitionException; +import org.antlr.runtime.tree.TreeAdaptor; + +/** A TreeAdaptor proxy that fires debugging events to a DebugEventListener + * delegate and uses the TreeAdaptor delegate to do the actual work. All + * AST events are triggered by this adaptor; no code gen changes are needed + * in generated rules. Debugging events are triggered *after* invoking + * tree adaptor routines. + * + * Trees created with actions in rewrite actions like "-> ^(ADD {foo} {bar})" + * cannot be tracked as they might not use the adaptor to create foo, bar. + * The debug listener has to deal with tree node IDs for which it did + * not see a createNode event. A single <unknown> node is sufficient even + * if it represents a whole tree. + */ +public class DebugTreeAdaptor implements TreeAdaptor { + protected DebugEventListener dbg; + protected TreeAdaptor adaptor; + + public DebugTreeAdaptor(DebugEventListener dbg, TreeAdaptor adaptor) { + this.dbg = dbg; + this.adaptor = adaptor; + } + + public Object create(Token payload) { + if ( payload.getTokenIndex() < 0 ) { + // could be token conjured up during error recovery + return create(payload.getType(), payload.getText()); + } + Object node = adaptor.create(payload); + dbg.createNode(node, payload); + return node; + } + + public Object errorNode(TokenStream input, Token start, Token stop, + RecognitionException e) + { + Object node = adaptor.errorNode(input, start, stop, e); + if ( node!=null ) { + dbg.errorNode(node); + } + return node; + } + + public Object dupTree(Object tree) { + Object t = adaptor.dupTree(tree); + // walk the tree and emit create and add child events + // to simulate what dupTree has done. dupTree does not call this debug + // adapter so I must simulate. + simulateTreeConstruction(t); + return t; + } + + /** ^(A B C): emit create A, create B, add child, ...*/ + protected void simulateTreeConstruction(Object t) { + dbg.createNode(t); + int n = adaptor.getChildCount(t); + for (int i=0; i<n; i++) { + Object child = adaptor.getChild(t, i); + simulateTreeConstruction(child); + dbg.addChild(t, child); + } + } + + public Object dupNode(Object treeNode) { + Object d = adaptor.dupNode(treeNode); + dbg.createNode(d); + return d; + } + + public Object nil() { + Object node = adaptor.nil(); + dbg.nilNode(node); + return node; + } + + public boolean isNil(Object tree) { + return adaptor.isNil(tree); + } + + public void addChild(Object t, Object child) { + if ( t==null || child==null ) { + return; + } + adaptor.addChild(t,child); + dbg.addChild(t, child); + } + + public Object becomeRoot(Object newRoot, Object oldRoot) { + Object n = adaptor.becomeRoot(newRoot, oldRoot); + dbg.becomeRoot(newRoot, oldRoot); + return n; + } + + public Object rulePostProcessing(Object root) { + return adaptor.rulePostProcessing(root); + } + + public void addChild(Object t, Token child) { + Object n = this.create(child); + this.addChild(t, n); + } + + public Object becomeRoot(Token newRoot, Object oldRoot) { + Object n = this.create(newRoot); + adaptor.becomeRoot(n, oldRoot); + dbg.becomeRoot(newRoot, oldRoot); + return n; + } + + public Object create(int tokenType, Token fromToken) { + Object node = adaptor.create(tokenType, fromToken); + dbg.createNode(node); + return node; + } + + public Object create(int tokenType, Token fromToken, String text) { + Object node = adaptor.create(tokenType, fromToken, text); + dbg.createNode(node); + return node; + } + + public Object create(int tokenType, String text) { + Object node = adaptor.create(tokenType, text); + dbg.createNode(node); + return node; + } + + public int getType(Object t) { + return adaptor.getType(t); + } + + public void setType(Object t, int type) { + adaptor.setType(t, type); + } + + public String getText(Object t) { + return adaptor.getText(t); + } + + public void setText(Object t, String text) { + adaptor.setText(t, text); + } + + public Token getToken(Object t) { + return adaptor.getToken(t); + } + + public void setTokenBoundaries(Object t, Token startToken, Token stopToken) { + adaptor.setTokenBoundaries(t, startToken, stopToken); + if ( t!=null && startToken!=null && stopToken!=null ) { + dbg.setTokenBoundaries( + t, startToken.getTokenIndex(), + stopToken.getTokenIndex()); + } + } + + public int getTokenStartIndex(Object t) { + return adaptor.getTokenStartIndex(t); + } + + public int getTokenStopIndex(Object t) { + return adaptor.getTokenStopIndex(t); + } + + public Object getChild(Object t, int i) { + return adaptor.getChild(t, i); + } + + public void setChild(Object t, int i, Object child) { + adaptor.setChild(t, i, child); + } + + public Object deleteChild(Object t, int i) { + return adaptor.deleteChild(t, i); + } + + public int getChildCount(Object t) { + return adaptor.getChildCount(t); + } + + public int getUniqueID(Object node) { + return adaptor.getUniqueID(node); + } + + public Object getParent(Object t) { + return adaptor.getParent(t); + } + + public int getChildIndex(Object t) { + return adaptor.getChildIndex(t); + } + + public void setParent(Object t, Object parent) { + adaptor.setParent(t, parent); + } + + public void setChildIndex(Object t, int index) { + adaptor.setChildIndex(t, index); + } + + public void replaceChildren(Object parent, int startChildIndex, int stopChildIndex, Object t) { + adaptor.replaceChildren(parent, startChildIndex, stopChildIndex, t); + } + + // support + + public DebugEventListener getDebugListener() { + return dbg; + } + + public void setDebugListener(DebugEventListener dbg) { + this.dbg = dbg; + } + + public TreeAdaptor getTreeAdaptor() { + return adaptor; + } +} |