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.RecognitionException;
32 
33 import java.util.List;
34 import java.util.ArrayList;
35 
36 /** Broadcast debug events to multiple listeners.  Lets you debug and still
37  *  use the event mechanism to build parse trees etc...  Not thread-safe.
38  *  Don't add events in one thread while parser fires events in another.
39  *
40  *  @see also DebugEventRepeater
41  */
42 public class DebugEventHub implements DebugEventListener {
43 	protected List listeners = new ArrayList();
44 
DebugEventHub(DebugEventListener listener)45 	public DebugEventHub(DebugEventListener listener) {
46 		listeners.add(listener);
47 	}
48 
DebugEventHub(DebugEventListener a, DebugEventListener b)49 	public DebugEventHub(DebugEventListener a, DebugEventListener b) {
50 		listeners.add(a);
51 		listeners.add(b);
52 	}
53 
54 	/** Add another listener to broadcast events too.  Not thread-safe.
55 	 *  Don't add events in one thread while parser fires events in another.
56 	 */
addListener(DebugEventListener listener)57 	public void addListener(DebugEventListener listener) {
58 		listeners.add(listener);
59 	}
60 
61 	/* To avoid a mess like this:
62 		public void enterRule(final String ruleName) {
63 			broadcast(new Code(){
64 				public void exec(DebugEventListener listener) {listener.enterRule(ruleName);}}
65 				);
66 		}
67 		I am dup'ing the for-loop in each.  Where are Java closures!? blech!
68 	 */
69 
enterRule(String grammarFileName, String ruleName)70 	public void enterRule(String grammarFileName, String ruleName) {
71 		for (int i = 0; i < listeners.size(); i++) {
72 			DebugEventListener listener = (DebugEventListener)listeners.get(i);
73 			listener.enterRule(grammarFileName,ruleName);
74 		}
75 	}
76 
exitRule(String grammarFileName, String ruleName)77 	public void exitRule(String grammarFileName, String ruleName) {
78 		for (int i = 0; i < listeners.size(); i++) {
79 			DebugEventListener listener = (DebugEventListener)listeners.get(i);
80 			listener.exitRule(grammarFileName, ruleName);
81 		}
82 	}
83 
enterAlt(int alt)84 	public void enterAlt(int alt) {
85 		for (int i = 0; i < listeners.size(); i++) {
86 			DebugEventListener listener = (DebugEventListener)listeners.get(i);
87 			listener.enterAlt(alt);
88 		}
89 	}
90 
enterSubRule(int decisionNumber)91 	public void enterSubRule(int decisionNumber) {
92 		for (int i = 0; i < listeners.size(); i++) {
93 			DebugEventListener listener = (DebugEventListener)listeners.get(i);
94 			listener.enterSubRule(decisionNumber);
95 		}
96 	}
97 
exitSubRule(int decisionNumber)98 	public void exitSubRule(int decisionNumber) {
99 		for (int i = 0; i < listeners.size(); i++) {
100 			DebugEventListener listener = (DebugEventListener)listeners.get(i);
101 			listener.exitSubRule(decisionNumber);
102 		}
103 	}
104 
enterDecision(int decisionNumber, boolean couldBacktrack)105 	public void enterDecision(int decisionNumber, boolean couldBacktrack) {
106 		for (int i = 0; i < listeners.size(); i++) {
107 			DebugEventListener listener = (DebugEventListener)listeners.get(i);
108 			listener.enterDecision(decisionNumber, couldBacktrack);
109 		}
110 	}
111 
exitDecision(int decisionNumber)112 	public void exitDecision(int decisionNumber) {
113 		for (int i = 0; i < listeners.size(); i++) {
114 			DebugEventListener listener = (DebugEventListener)listeners.get(i);
115 			listener.exitDecision(decisionNumber);
116 		}
117 	}
118 
location(int line, int pos)119 	public void location(int line, int pos) {
120 		for (int i = 0; i < listeners.size(); i++) {
121 			DebugEventListener listener = (DebugEventListener)listeners.get(i);
122 			listener.location(line, pos);
123 		}
124 	}
125 
consumeToken(Token token)126 	public void consumeToken(Token token) {
127 		for (int i = 0; i < listeners.size(); i++) {
128 			DebugEventListener listener = (DebugEventListener)listeners.get(i);
129 			listener.consumeToken(token);
130 		}
131 	}
132 
consumeHiddenToken(Token token)133 	public void consumeHiddenToken(Token token) {
134 		for (int i = 0; i < listeners.size(); i++) {
135 			DebugEventListener listener = (DebugEventListener)listeners.get(i);
136 			listener.consumeHiddenToken(token);
137 		}
138 	}
139 
LT(int index, Token t)140 	public void LT(int index, Token t) {
141 		for (int i = 0; i < listeners.size(); i++) {
142 			DebugEventListener listener = (DebugEventListener)listeners.get(i);
143 			listener.LT(index, t);
144 		}
145 	}
146 
mark(int index)147 	public void mark(int index) {
148 		for (int i = 0; i < listeners.size(); i++) {
149 			DebugEventListener listener = (DebugEventListener)listeners.get(i);
150 			listener.mark(index);
151 		}
152 	}
153 
rewind(int index)154 	public void rewind(int index) {
155 		for (int i = 0; i < listeners.size(); i++) {
156 			DebugEventListener listener = (DebugEventListener)listeners.get(i);
157 			listener.rewind(index);
158 		}
159 	}
160 
rewind()161 	public void rewind() {
162 		for (int i = 0; i < listeners.size(); i++) {
163 			DebugEventListener listener = (DebugEventListener)listeners.get(i);
164 			listener.rewind();
165 		}
166 	}
167 
beginBacktrack(int level)168 	public void beginBacktrack(int level) {
169 		for (int i = 0; i < listeners.size(); i++) {
170 			DebugEventListener listener = (DebugEventListener)listeners.get(i);
171 			listener.beginBacktrack(level);
172 		}
173 	}
174 
endBacktrack(int level, boolean successful)175 	public void endBacktrack(int level, boolean successful) {
176 		for (int i = 0; i < listeners.size(); i++) {
177 			DebugEventListener listener = (DebugEventListener)listeners.get(i);
178 			listener.endBacktrack(level, successful);
179 		}
180 	}
181 
recognitionException(RecognitionException e)182 	public void recognitionException(RecognitionException e) {
183 		for (int i = 0; i < listeners.size(); i++) {
184 			DebugEventListener listener = (DebugEventListener)listeners.get(i);
185 			listener.recognitionException(e);
186 		}
187 	}
188 
beginResync()189 	public void beginResync() {
190 		for (int i = 0; i < listeners.size(); i++) {
191 			DebugEventListener listener = (DebugEventListener)listeners.get(i);
192 			listener.beginResync();
193 		}
194 	}
195 
endResync()196 	public void endResync() {
197 		for (int i = 0; i < listeners.size(); i++) {
198 			DebugEventListener listener = (DebugEventListener)listeners.get(i);
199 			listener.endResync();
200 		}
201 	}
202 
semanticPredicate(boolean result, String predicate)203 	public void semanticPredicate(boolean result, String predicate) {
204 		for (int i = 0; i < listeners.size(); i++) {
205 			DebugEventListener listener = (DebugEventListener)listeners.get(i);
206 			listener.semanticPredicate(result, predicate);
207 		}
208 	}
209 
commence()210 	public void commence() {
211 		for (int i = 0; i < listeners.size(); i++) {
212 			DebugEventListener listener = (DebugEventListener)listeners.get(i);
213 			listener.commence();
214 		}
215 	}
216 
terminate()217 	public void terminate() {
218 		for (int i = 0; i < listeners.size(); i++) {
219 			DebugEventListener listener = (DebugEventListener)listeners.get(i);
220 			listener.terminate();
221 		}
222 	}
223 
224 
225 	// Tree parsing stuff
226 
consumeNode(Object t)227 	public void consumeNode(Object t) {
228 		for (int i = 0; i < listeners.size(); i++) {
229 			DebugEventListener listener = (DebugEventListener)listeners.get(i);
230 			listener.consumeNode(t);
231 		}
232 	}
233 
LT(int index, Object t)234 	public void LT(int index, Object t) {
235 		for (int i = 0; i < listeners.size(); i++) {
236 			DebugEventListener listener = (DebugEventListener)listeners.get(i);
237 			listener.LT(index, t);
238 		}
239 	}
240 
241 
242 	// AST Stuff
243 
nilNode(Object t)244 	public void nilNode(Object t) {
245 		for (int i = 0; i < listeners.size(); i++) {
246 			DebugEventListener listener = (DebugEventListener)listeners.get(i);
247 			listener.nilNode(t);
248 		}
249 	}
250 
errorNode(Object t)251 	public void errorNode(Object t) {
252 		for (int i = 0; i < listeners.size(); i++) {
253 			DebugEventListener listener = (DebugEventListener)listeners.get(i);
254 			listener.errorNode(t);
255 		}
256 	}
257 
createNode(Object t)258 	public void createNode(Object t) {
259 		for (int i = 0; i < listeners.size(); i++) {
260 			DebugEventListener listener = (DebugEventListener)listeners.get(i);
261 			listener.createNode(t);
262 		}
263 	}
264 
createNode(Object node, Token token)265 	public void createNode(Object node, Token token) {
266 		for (int i = 0; i < listeners.size(); i++) {
267 			DebugEventListener listener = (DebugEventListener)listeners.get(i);
268 			listener.createNode(node, token);
269 		}
270 	}
271 
becomeRoot(Object newRoot, Object oldRoot)272 	public void becomeRoot(Object newRoot, Object oldRoot) {
273 		for (int i = 0; i < listeners.size(); i++) {
274 			DebugEventListener listener = (DebugEventListener)listeners.get(i);
275 			listener.becomeRoot(newRoot, oldRoot);
276 		}
277 	}
278 
addChild(Object root, Object child)279 	public void addChild(Object root, Object child) {
280 		for (int i = 0; i < listeners.size(); i++) {
281 			DebugEventListener listener = (DebugEventListener)listeners.get(i);
282 			listener.addChild(root, child);
283 		}
284 	}
285 
setTokenBoundaries(Object t, int tokenStartIndex, int tokenStopIndex)286 	public void setTokenBoundaries(Object t, int tokenStartIndex, int tokenStopIndex) {
287 		for (int i = 0; i < listeners.size(); i++) {
288 			DebugEventListener listener = (DebugEventListener)listeners.get(i);
289 			listener.setTokenBoundaries(t, tokenStartIndex, tokenStopIndex);
290 		}
291 	}
292 }
293