1 /* 2 [The "BSD license"] 3 Copyright (c) 2005-2009 Terence Parr 4 All rights reserved. 5 6 Redistribution and use in source and binary forms, with or without 7 modification, are permitted provided that the following conditions 8 are met: 9 1. Redistributions of source code must retain the above copyright 10 notice, this list of conditions and the following disclaimer. 11 2. Redistributions in binary form must reproduce the above copyright 12 notice, this list of conditions and the following disclaimer in the 13 documentation and/or other materials provided with the distribution. 14 3. The name of the author may not be used to endorse or promote products 15 derived from this software without specific prior written permission. 16 17 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 package org.antlr.runtime.debug; 29 30 import org.antlr.runtime.Token; 31 import org.antlr.runtime.TokenStream; 32 import org.antlr.runtime.RecognitionException; 33 import org.antlr.runtime.tree.TreeAdaptor; 34 35 /** A TreeAdaptor proxy that fires debugging events to a DebugEventListener 36 * delegate and uses the TreeAdaptor delegate to do the actual work. All 37 * AST events are triggered by this adaptor; no code gen changes are needed 38 * in generated rules. Debugging events are triggered *after* invoking 39 * tree adaptor routines. 40 * 41 * Trees created with actions in rewrite actions like "-> ^(ADD {foo} {bar})" 42 * cannot be tracked as they might not use the adaptor to create foo, bar. 43 * The debug listener has to deal with tree node IDs for which it did 44 * not see a createNode event. A single <unknown> node is sufficient even 45 * if it represents a whole tree. 46 */ 47 public class DebugTreeAdaptor implements TreeAdaptor { 48 protected DebugEventListener dbg; 49 protected TreeAdaptor adaptor; 50 51 public DebugTreeAdaptor(DebugEventListener dbg, TreeAdaptor adaptor) { 52 this.dbg = dbg; 53 this.adaptor = adaptor; 54 } 55 56 public Object create(Token payload) { 57 if ( payload.getTokenIndex() < 0 ) { 58 // could be token conjured up during error recovery 59 return create(payload.getType(), payload.getText()); 60 } 61 Object node = adaptor.create(payload); 62 dbg.createNode(node, payload); 63 return node; 64 } 65 66 public Object errorNode(TokenStream input, Token start, Token stop, 67 RecognitionException e) 68 { 69 Object node = adaptor.errorNode(input, start, stop, e); 70 if ( node!=null ) { 71 dbg.errorNode(node); 72 } 73 return node; 74 } 75 76 public Object dupTree(Object tree) { 77 Object t = adaptor.dupTree(tree); 78 // walk the tree and emit create and add child events 79 // to simulate what dupTree has done. dupTree does not call this debug 80 // adapter so I must simulate. 81 simulateTreeConstruction(t); 82 return t; 83 } 84 85 /** ^(A B C): emit create A, create B, add child, ...*/ 86 protected void simulateTreeConstruction(Object t) { 87 dbg.createNode(t); 88 int n = adaptor.getChildCount(t); 89 for (int i=0; i<n; i++) { 90 Object child = adaptor.getChild(t, i); 91 simulateTreeConstruction(child); 92 dbg.addChild(t, child); 93 } 94 } 95 96 public Object dupNode(Object treeNode) { 97 Object d = adaptor.dupNode(treeNode); 98 dbg.createNode(d); 99 return d; 100 } 101 102 public Object nil() { 103 Object node = adaptor.nil(); 104 dbg.nilNode(node); 105 return node; 106 } 107 108 public boolean isNil(Object tree) { 109 return adaptor.isNil(tree); 110 } 111 112 public void addChild(Object t, Object child) { 113 if ( t==null || child==null ) { 114 return; 115 } 116 adaptor.addChild(t,child); 117 dbg.addChild(t, child); 118 } 119 120 public Object becomeRoot(Object newRoot, Object oldRoot) { 121 Object n = adaptor.becomeRoot(newRoot, oldRoot); 122 dbg.becomeRoot(newRoot, oldRoot); 123 return n; 124 } 125 126 public Object rulePostProcessing(Object root) { 127 return adaptor.rulePostProcessing(root); 128 } 129 130 public void addChild(Object t, Token child) { 131 Object n = this.create(child); 132 this.addChild(t, n); 133 } 134 135 public Object becomeRoot(Token newRoot, Object oldRoot) { 136 Object n = this.create(newRoot); 137 adaptor.becomeRoot(n, oldRoot); 138 dbg.becomeRoot(newRoot, oldRoot); 139 return n; 140 } 141 142 public Object create(int tokenType, Token fromToken) { 143 Object node = adaptor.create(tokenType, fromToken); 144 dbg.createNode(node); 145 return node; 146 } 147 148 public Object create(int tokenType, Token fromToken, String text) { 149 Object node = adaptor.create(tokenType, fromToken, text); 150 dbg.createNode(node); 151 return node; 152 } 153 154 public Object create(int tokenType, String text) { 155 Object node = adaptor.create(tokenType, text); 156 dbg.createNode(node); 157 return node; 158 } 159 160 public int getType(Object t) { 161 return adaptor.getType(t); 162 } 163 164 public void setType(Object t, int type) { 165 adaptor.setType(t, type); 166 } 167 168 public String getText(Object t) { 169 return adaptor.getText(t); 170 } 171 172 public void setText(Object t, String text) { 173 adaptor.setText(t, text); 174 } 175 176 public Token getToken(Object t) { 177 return adaptor.getToken(t); 178 } 179 180 public void setTokenBoundaries(Object t, Token startToken, Token stopToken) { 181 adaptor.setTokenBoundaries(t, startToken, stopToken); 182 if ( t!=null && startToken!=null && stopToken!=null ) { 183 dbg.setTokenBoundaries( 184 t, startToken.getTokenIndex(), 185 stopToken.getTokenIndex()); 186 } 187 } 188 189 public int getTokenStartIndex(Object t) { 190 return adaptor.getTokenStartIndex(t); 191 } 192 193 public int getTokenStopIndex(Object t) { 194 return adaptor.getTokenStopIndex(t); 195 } 196 197 public Object getChild(Object t, int i) { 198 return adaptor.getChild(t, i); 199 } 200 201 public void setChild(Object t, int i, Object child) { 202 adaptor.setChild(t, i, child); 203 } 204 205 public Object deleteChild(Object t, int i) { 206 return deleteChild(t, i); 207 } 208 209 public int getChildCount(Object t) { 210 return adaptor.getChildCount(t); 211 } 212 213 public int getUniqueID(Object node) { 214 return adaptor.getUniqueID(node); 215 } 216 217 public Object getParent(Object t) { 218 return adaptor.getParent(t); 219 } 220 221 public int getChildIndex(Object t) { 222 return adaptor.getChildIndex(t); 223 } 224 225 public void setParent(Object t, Object parent) { 226 adaptor.setParent(t, parent); 227 } 228 229 public void setChildIndex(Object t, int index) { 230 adaptor.setChildIndex(t, index); 231 } 232 233 public void replaceChildren(Object parent, int startChildIndex, int stopChildIndex, Object t) { 234 adaptor.replaceChildren(parent, startChildIndex, stopChildIndex, t); 235 } 236 237 // support 238 239 public DebugEventListener getDebugListener() { 240 return dbg; 241 } 242 243 public void setDebugListener(DebugEventListener dbg) { 244 this.dbg = dbg; 245 } 246 247 public TreeAdaptor getTreeAdaptor() { 248 return adaptor; 249 } 250 } 251