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 */ 28package org.antlr.runtime.debug; 29 30import org.antlr.runtime.Token; 31import org.antlr.runtime.RecognitionException; 32 33import java.util.List; 34import 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 */ 42public class DebugEventHub implements DebugEventListener { 43 protected List listeners = new ArrayList(); 44 45 public DebugEventHub(DebugEventListener listener) { 46 listeners.add(listener); 47 } 48 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 */ 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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