| /* |
| [The "BSD license"] |
| Copyright (c) 2005-2009 Terence Parr |
| All rights reserved. |
| |
| Redistribution and use in source and binary forms, with or without |
| modification, are permitted provided that the following conditions |
| are met: |
| 1. Redistributions of source code must retain the above copyright |
| notice, this list of conditions and the following disclaimer. |
| 2. Redistributions in binary form must reproduce the above copyright |
| notice, this list of conditions and the following disclaimer in the |
| documentation and/or other materials provided with the distribution. |
| 3. The name of the author may not be used to endorse or promote products |
| derived from this software without specific prior written permission. |
| |
| THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
| IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
| OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
| IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
| INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
| NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
| THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| package org.antlr.runtime.debug; |
| |
| import org.antlr.runtime.Token; |
| import org.antlr.runtime.RecognitionException; |
| |
| import java.util.List; |
| import java.util.ArrayList; |
| |
| /** Broadcast debug events to multiple listeners. Lets you debug and still |
| * use the event mechanism to build parse trees etc... Not thread-safe. |
| * Don't add events in one thread while parser fires events in another. |
| * |
| * @see also DebugEventRepeater |
| */ |
| public class DebugEventHub implements DebugEventListener { |
| protected List listeners = new ArrayList(); |
| |
| public DebugEventHub(DebugEventListener listener) { |
| listeners.add(listener); |
| } |
| |
| public DebugEventHub(DebugEventListener a, DebugEventListener b) { |
| listeners.add(a); |
| listeners.add(b); |
| } |
| |
| /** Add another listener to broadcast events too. Not thread-safe. |
| * Don't add events in one thread while parser fires events in another. |
| */ |
| public void addListener(DebugEventListener listener) { |
| listeners.add(listener); |
| } |
| |
| /* To avoid a mess like this: |
| public void enterRule(final String ruleName) { |
| broadcast(new Code(){ |
| public void exec(DebugEventListener listener) {listener.enterRule(ruleName);}} |
| ); |
| } |
| I am dup'ing the for-loop in each. Where are Java closures!? blech! |
| */ |
| |
| public void enterRule(String grammarFileName, String ruleName) { |
| for (int i = 0; i < listeners.size(); i++) { |
| DebugEventListener listener = (DebugEventListener)listeners.get(i); |
| listener.enterRule(grammarFileName,ruleName); |
| } |
| } |
| |
| public void exitRule(String grammarFileName, String ruleName) { |
| for (int i = 0; i < listeners.size(); i++) { |
| DebugEventListener listener = (DebugEventListener)listeners.get(i); |
| listener.exitRule(grammarFileName, ruleName); |
| } |
| } |
| |
| public void enterAlt(int alt) { |
| for (int i = 0; i < listeners.size(); i++) { |
| DebugEventListener listener = (DebugEventListener)listeners.get(i); |
| listener.enterAlt(alt); |
| } |
| } |
| |
| public void enterSubRule(int decisionNumber) { |
| for (int i = 0; i < listeners.size(); i++) { |
| DebugEventListener listener = (DebugEventListener)listeners.get(i); |
| listener.enterSubRule(decisionNumber); |
| } |
| } |
| |
| public void exitSubRule(int decisionNumber) { |
| for (int i = 0; i < listeners.size(); i++) { |
| DebugEventListener listener = (DebugEventListener)listeners.get(i); |
| listener.exitSubRule(decisionNumber); |
| } |
| } |
| |
| public void enterDecision(int decisionNumber, boolean couldBacktrack) { |
| for (int i = 0; i < listeners.size(); i++) { |
| DebugEventListener listener = (DebugEventListener)listeners.get(i); |
| listener.enterDecision(decisionNumber, couldBacktrack); |
| } |
| } |
| |
| public void exitDecision(int decisionNumber) { |
| for (int i = 0; i < listeners.size(); i++) { |
| DebugEventListener listener = (DebugEventListener)listeners.get(i); |
| listener.exitDecision(decisionNumber); |
| } |
| } |
| |
| public void location(int line, int pos) { |
| for (int i = 0; i < listeners.size(); i++) { |
| DebugEventListener listener = (DebugEventListener)listeners.get(i); |
| listener.location(line, pos); |
| } |
| } |
| |
| public void consumeToken(Token token) { |
| for (int i = 0; i < listeners.size(); i++) { |
| DebugEventListener listener = (DebugEventListener)listeners.get(i); |
| listener.consumeToken(token); |
| } |
| } |
| |
| public void consumeHiddenToken(Token token) { |
| for (int i = 0; i < listeners.size(); i++) { |
| DebugEventListener listener = (DebugEventListener)listeners.get(i); |
| listener.consumeHiddenToken(token); |
| } |
| } |
| |
| public void LT(int index, Token t) { |
| for (int i = 0; i < listeners.size(); i++) { |
| DebugEventListener listener = (DebugEventListener)listeners.get(i); |
| listener.LT(index, t); |
| } |
| } |
| |
| public void mark(int index) { |
| for (int i = 0; i < listeners.size(); i++) { |
| DebugEventListener listener = (DebugEventListener)listeners.get(i); |
| listener.mark(index); |
| } |
| } |
| |
| public void rewind(int index) { |
| for (int i = 0; i < listeners.size(); i++) { |
| DebugEventListener listener = (DebugEventListener)listeners.get(i); |
| listener.rewind(index); |
| } |
| } |
| |
| public void rewind() { |
| for (int i = 0; i < listeners.size(); i++) { |
| DebugEventListener listener = (DebugEventListener)listeners.get(i); |
| listener.rewind(); |
| } |
| } |
| |
| public void beginBacktrack(int level) { |
| for (int i = 0; i < listeners.size(); i++) { |
| DebugEventListener listener = (DebugEventListener)listeners.get(i); |
| listener.beginBacktrack(level); |
| } |
| } |
| |
| public void endBacktrack(int level, boolean successful) { |
| for (int i = 0; i < listeners.size(); i++) { |
| DebugEventListener listener = (DebugEventListener)listeners.get(i); |
| listener.endBacktrack(level, successful); |
| } |
| } |
| |
| public void recognitionException(RecognitionException e) { |
| for (int i = 0; i < listeners.size(); i++) { |
| DebugEventListener listener = (DebugEventListener)listeners.get(i); |
| listener.recognitionException(e); |
| } |
| } |
| |
| public void beginResync() { |
| for (int i = 0; i < listeners.size(); i++) { |
| DebugEventListener listener = (DebugEventListener)listeners.get(i); |
| listener.beginResync(); |
| } |
| } |
| |
| public void endResync() { |
| for (int i = 0; i < listeners.size(); i++) { |
| DebugEventListener listener = (DebugEventListener)listeners.get(i); |
| listener.endResync(); |
| } |
| } |
| |
| public void semanticPredicate(boolean result, String predicate) { |
| for (int i = 0; i < listeners.size(); i++) { |
| DebugEventListener listener = (DebugEventListener)listeners.get(i); |
| listener.semanticPredicate(result, predicate); |
| } |
| } |
| |
| public void commence() { |
| for (int i = 0; i < listeners.size(); i++) { |
| DebugEventListener listener = (DebugEventListener)listeners.get(i); |
| listener.commence(); |
| } |
| } |
| |
| public void terminate() { |
| for (int i = 0; i < listeners.size(); i++) { |
| DebugEventListener listener = (DebugEventListener)listeners.get(i); |
| listener.terminate(); |
| } |
| } |
| |
| |
| // Tree parsing stuff |
| |
| public void consumeNode(Object t) { |
| for (int i = 0; i < listeners.size(); i++) { |
| DebugEventListener listener = (DebugEventListener)listeners.get(i); |
| listener.consumeNode(t); |
| } |
| } |
| |
| public void LT(int index, Object t) { |
| for (int i = 0; i < listeners.size(); i++) { |
| DebugEventListener listener = (DebugEventListener)listeners.get(i); |
| listener.LT(index, t); |
| } |
| } |
| |
| |
| // AST Stuff |
| |
| public void nilNode(Object t) { |
| for (int i = 0; i < listeners.size(); i++) { |
| DebugEventListener listener = (DebugEventListener)listeners.get(i); |
| listener.nilNode(t); |
| } |
| } |
| |
| public void errorNode(Object t) { |
| for (int i = 0; i < listeners.size(); i++) { |
| DebugEventListener listener = (DebugEventListener)listeners.get(i); |
| listener.errorNode(t); |
| } |
| } |
| |
| public void createNode(Object t) { |
| for (int i = 0; i < listeners.size(); i++) { |
| DebugEventListener listener = (DebugEventListener)listeners.get(i); |
| listener.createNode(t); |
| } |
| } |
| |
| public void createNode(Object node, Token token) { |
| for (int i = 0; i < listeners.size(); i++) { |
| DebugEventListener listener = (DebugEventListener)listeners.get(i); |
| listener.createNode(node, token); |
| } |
| } |
| |
| public void becomeRoot(Object newRoot, Object oldRoot) { |
| for (int i = 0; i < listeners.size(); i++) { |
| DebugEventListener listener = (DebugEventListener)listeners.get(i); |
| listener.becomeRoot(newRoot, oldRoot); |
| } |
| } |
| |
| public void addChild(Object root, Object child) { |
| for (int i = 0; i < listeners.size(); i++) { |
| DebugEventListener listener = (DebugEventListener)listeners.get(i); |
| listener.addChild(root, child); |
| } |
| } |
| |
| public void setTokenBoundaries(Object t, int tokenStartIndex, int tokenStopIndex) { |
| for (int i = 0; i < listeners.size(); i++) { |
| DebugEventListener listener = (DebugEventListener)listeners.get(i); |
| listener.setTokenBoundaries(t, tokenStartIndex, tokenStopIndex); |
| } |
| } |
| } |