aboutsummaryrefslogtreecommitdiff
path: root/runtime/Java/src/main/java/org/antlr/runtime/debug/DebugTreeAdaptor.java
diff options
context:
space:
mode:
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.java250
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;
+ }
+}