• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
DebugTreeAdaptor(DebugEventListener dbg, TreeAdaptor adaptor)51 	public DebugTreeAdaptor(DebugEventListener dbg, TreeAdaptor adaptor) {
52 		this.dbg = dbg;
53 		this.adaptor = adaptor;
54 	}
55 
56 	@Override
create(Token payload)57 	public Object create(Token payload) {
58 		if ( payload.getTokenIndex() < 0 ) {
59 			// could be token conjured up during error recovery
60 			return create(payload.getType(), payload.getText());
61 		}
62 		Object node = adaptor.create(payload);
63 		dbg.createNode(node, payload);
64 		return node;
65 	}
66 
67 	@Override
errorNode(TokenStream input, Token start, Token stop, RecognitionException e)68 	public Object errorNode(TokenStream input, Token start, Token stop,
69 							RecognitionException e)
70 	{
71 		Object node = adaptor.errorNode(input, start, stop, e);
72 		if ( node!=null ) {
73 			dbg.errorNode(node);
74 		}
75 		return node;
76 	}
77 
78 	@Override
dupTree(Object tree)79 	public Object dupTree(Object tree) {
80 		Object t = adaptor.dupTree(tree);
81 		// walk the tree and emit create and add child events
82 		// to simulate what dupTree has done. dupTree does not call this debug
83 		// adapter so I must simulate.
84 		simulateTreeConstruction(t);
85 		return t;
86 	}
87 
88 	/** ^(A B C): emit create A, create B, add child, ...*/
simulateTreeConstruction(Object t)89 	protected void simulateTreeConstruction(Object t) {
90 		dbg.createNode(t);
91 		int n = adaptor.getChildCount(t);
92 		for (int i=0; i<n; i++) {
93 			Object child = adaptor.getChild(t, i);
94 			simulateTreeConstruction(child);
95 			dbg.addChild(t, child);
96 		}
97 	}
98 
99 	@Override
dupNode(Object treeNode)100 	public Object dupNode(Object treeNode) {
101 		Object d = adaptor.dupNode(treeNode);
102 		dbg.createNode(d);
103 		return d;
104 	}
105 
106 	@Override
nil()107 	public Object nil() {
108 		Object node = adaptor.nil();
109 		dbg.nilNode(node);
110 		return node;
111 	}
112 
113 	@Override
isNil(Object tree)114 	public boolean isNil(Object tree) {
115 		return adaptor.isNil(tree);
116 	}
117 
118 	@Override
addChild(Object t, Object child)119 	public void addChild(Object t, Object child) {
120 		if ( t==null || child==null ) {
121 			return;
122 		}
123 		adaptor.addChild(t,child);
124 		dbg.addChild(t, child);
125 	}
126 
127 	@Override
becomeRoot(Object newRoot, Object oldRoot)128 	public Object becomeRoot(Object newRoot, Object oldRoot) {
129 		Object n = adaptor.becomeRoot(newRoot, oldRoot);
130 		dbg.becomeRoot(newRoot, oldRoot);
131 		return n;
132 	}
133 
134 	@Override
rulePostProcessing(Object root)135 	public Object rulePostProcessing(Object root) {
136 		return adaptor.rulePostProcessing(root);
137 	}
138 
addChild(Object t, Token child)139 	public void addChild(Object t, Token child) {
140 		Object n = this.create(child);
141 		this.addChild(t, n);
142 	}
143 
144 	@Override
becomeRoot(Token newRoot, Object oldRoot)145 	public Object becomeRoot(Token newRoot, Object oldRoot) {
146 		Object n = this.create(newRoot);
147 		adaptor.becomeRoot(n, oldRoot);
148 		dbg.becomeRoot(newRoot, oldRoot);
149 		return n;
150 	}
151 
152 	@Override
create(int tokenType, Token fromToken)153 	public Object create(int tokenType, Token fromToken) {
154 		Object node = adaptor.create(tokenType, fromToken);
155 		dbg.createNode(node);
156 		return node;
157 	}
158 
159 	@Override
create(int tokenType, Token fromToken, String text)160 	public Object create(int tokenType, Token fromToken, String text) {
161 		Object node = adaptor.create(tokenType, fromToken, text);
162 		dbg.createNode(node);
163 		return node;
164 	}
165 
166 	@Override
create(int tokenType, String text)167 	public Object create(int tokenType, String text) {
168 		Object node = adaptor.create(tokenType, text);
169 		dbg.createNode(node);
170 		return node;
171 	}
172 
173 	@Override
getType(Object t)174 	public int getType(Object t) {
175 		return adaptor.getType(t);
176 	}
177 
178 	@Override
setType(Object t, int type)179 	public void setType(Object t, int type) {
180 		adaptor.setType(t, type);
181 	}
182 
183 	@Override
getText(Object t)184 	public String getText(Object t) {
185 		return adaptor.getText(t);
186 	}
187 
188 	@Override
setText(Object t, String text)189 	public void setText(Object t, String text) {
190 		adaptor.setText(t, text);
191 	}
192 
193 	@Override
getToken(Object t)194 	public Token getToken(Object t) {
195 		return adaptor.getToken(t);
196 	}
197 
198 	@Override
setTokenBoundaries(Object t, Token startToken, Token stopToken)199 	public void setTokenBoundaries(Object t, Token startToken, Token stopToken) {
200 		adaptor.setTokenBoundaries(t, startToken, stopToken);
201 		if ( t!=null && startToken!=null && stopToken!=null ) {
202 			dbg.setTokenBoundaries(
203 				t, startToken.getTokenIndex(),
204 				stopToken.getTokenIndex());
205 		}
206 	}
207 
208 	@Override
getTokenStartIndex(Object t)209 	public int getTokenStartIndex(Object t) {
210 		return adaptor.getTokenStartIndex(t);
211 	}
212 
213 	@Override
getTokenStopIndex(Object t)214 	public int getTokenStopIndex(Object t) {
215 		return adaptor.getTokenStopIndex(t);
216 	}
217 
218 	@Override
getChild(Object t, int i)219 	public Object getChild(Object t, int i) {
220 		return adaptor.getChild(t, i);
221 	}
222 
223 	@Override
setChild(Object t, int i, Object child)224 	public void setChild(Object t, int i, Object child) {
225 		adaptor.setChild(t, i, child);
226 	}
227 
228 	@Override
deleteChild(Object t, int i)229 	public Object deleteChild(Object t, int i) {
230 		return adaptor.deleteChild(t, i);
231 	}
232 
233 	@Override
getChildCount(Object t)234 	public int getChildCount(Object t) {
235 		return adaptor.getChildCount(t);
236 	}
237 
238 	@Override
getUniqueID(Object node)239 	public int getUniqueID(Object node) {
240 		return adaptor.getUniqueID(node);
241 	}
242 
243 	@Override
getParent(Object t)244 	public Object getParent(Object t) {
245 		return adaptor.getParent(t);
246 	}
247 
248 	@Override
getChildIndex(Object t)249 	public int getChildIndex(Object t) {
250 		return adaptor.getChildIndex(t);
251 	}
252 
253 	@Override
setParent(Object t, Object parent)254 	public void setParent(Object t, Object parent) {
255 		adaptor.setParent(t, parent);
256 	}
257 
258 	@Override
setChildIndex(Object t, int index)259 	public void setChildIndex(Object t, int index) {
260 		adaptor.setChildIndex(t, index);
261 	}
262 
263 	@Override
replaceChildren(Object parent, int startChildIndex, int stopChildIndex, Object t)264 	public void replaceChildren(Object parent, int startChildIndex, int stopChildIndex, Object t) {
265 		adaptor.replaceChildren(parent, startChildIndex, stopChildIndex, t);
266 	}
267 
268 	// support
269 
getDebugListener()270 	public DebugEventListener getDebugListener() {
271 		return dbg;
272 	}
273 
setDebugListener(DebugEventListener dbg)274 	public void setDebugListener(DebugEventListener dbg) {
275 		this.dbg = dbg;
276 	}
277 
getTreeAdaptor()278 	public TreeAdaptor getTreeAdaptor() {
279 		return adaptor;
280 	}
281 }
282