Home | History | Annotate | Download | only in debug
      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