1 package antlr.debug;
2 
3 import java.util.Vector;
4 import java.util.Hashtable;
5 import java.util.Enumeration;
6 import antlr.collections.impl.BitSet;
7 import antlr.RecognitionException;
8 
9 
10 /** A class to assist in firing parser events
11  *  NOTE: I intentionally _did_not_ synchronize the event firing and
12  *        add/remove listener methods.  This is because the add/remove should
13  *        _only_ be called by the parser at its start/end, and the _same_thread_
14  *        should be performing the parsing.  This should help performance a tad...
15  */
16 public class ParserEventSupport {
17 	private Object source;
18 	private Hashtable doneListeners;
19 	private Vector matchListeners;
20 	private Vector messageListeners;
21 	private Vector tokenListeners;
22 	private Vector traceListeners;
23 	private Vector semPredListeners;
24 	private Vector synPredListeners;
25 	private Vector newLineListeners;
26 	private ParserMatchEvent        matchEvent;
27 	private MessageEvent            messageEvent;
28 	private ParserTokenEvent        tokenEvent;
29 	private SemanticPredicateEvent  semPredEvent;
30 	private SyntacticPredicateEvent synPredEvent;
31 	private TraceEvent              traceEvent;
32 	private NewLineEvent            newLineEvent;
33 	private ParserController        controller;
34 	protected static final int CONSUME=0;
35 	protected static final int ENTER_RULE=1;
36 	protected static final int EXIT_RULE=2;
37 	protected static final int LA=3;
38 	protected static final int MATCH=4;
39 	protected static final int MATCH_NOT=5;
40 	protected static final int MISMATCH=6;
41 	protected static final int MISMATCH_NOT=7;
42 	protected static final int REPORT_ERROR=8;
43 	protected static final int REPORT_WARNING=9;
44 	protected static final int SEMPRED=10;
45 	protected static final int SYNPRED_FAILED=11;
46 	protected static final int SYNPRED_STARTED=12;
47 	protected static final int SYNPRED_SUCCEEDED=13;
48 	protected static final int NEW_LINE=14;
49 	protected static final int DONE_PARSING=15;
50 	private int ruleDepth = 0;
51 
52 
ParserEventSupport(Object source)53 	public ParserEventSupport(Object source) {
54 		matchEvent   = new ParserMatchEvent(source);
55 		messageEvent = new MessageEvent(source);
56 		tokenEvent   = new ParserTokenEvent(source);
57 		traceEvent   = new TraceEvent(source);
58 		semPredEvent = new SemanticPredicateEvent(source);
59 		synPredEvent = new SyntacticPredicateEvent(source);
60 		newLineEvent = new NewLineEvent(source);
61 		this.source = source;
62 	}
addDoneListener(ListenerBase l)63 	public void addDoneListener(ListenerBase l) {
64 		if (doneListeners == null) doneListeners = new Hashtable();
65 		Integer i = (Integer)doneListeners.get(l);
66 		int val;
67 		if (i != null)
68 			val = i.intValue() + 1;
69 		else
70 			val = 1;
71 		doneListeners.put(l, new Integer(val));
72 	}
addMessageListener(MessageListener l)73 	public void addMessageListener(MessageListener l) {
74 		if (messageListeners == null) messageListeners = new Vector();
75 		messageListeners.addElement(l);
76 		addDoneListener(l);
77 	}
addNewLineListener(NewLineListener l)78 	public void addNewLineListener(NewLineListener l) {
79 		if (newLineListeners == null) newLineListeners = new Vector();
80 		newLineListeners.addElement(l);
81 		addDoneListener(l);
82 	}
addParserListener(ParserListener l)83 	public void addParserListener(ParserListener l) {
84 		if (l instanceof ParserController) {
85 			((ParserController)l).setParserEventSupport(this);
86 			controller = (ParserController)l;
87 		}
88 		addParserMatchListener(l);
89 		addParserTokenListener(l);
90 
91 		addMessageListener(l);
92 		addTraceListener(l);
93 		addSemanticPredicateListener(l);
94 		addSyntacticPredicateListener(l);
95 	}
addParserMatchListener(ParserMatchListener l)96 	public void addParserMatchListener(ParserMatchListener l) {
97 		if (matchListeners == null) matchListeners = new Vector();
98 		matchListeners.addElement(l);
99 		addDoneListener(l);
100 	}
addParserTokenListener(ParserTokenListener l)101 	public void addParserTokenListener(ParserTokenListener l) {
102 		if (tokenListeners == null) tokenListeners = new Vector();
103 		tokenListeners.addElement(l);
104 		addDoneListener(l);
105 	}
addSemanticPredicateListener(SemanticPredicateListener l)106 	public void addSemanticPredicateListener(SemanticPredicateListener l) {
107 		if (semPredListeners == null) semPredListeners = new Vector();
108 		semPredListeners.addElement(l);
109 		addDoneListener(l);
110 	}
addSyntacticPredicateListener(SyntacticPredicateListener l)111 	public void addSyntacticPredicateListener(SyntacticPredicateListener l) {
112 		if (synPredListeners == null) synPredListeners = new Vector();
113 		synPredListeners.addElement(l);
114 		addDoneListener(l);
115 	}
addTraceListener(TraceListener l)116 	public void addTraceListener(TraceListener l) {
117 		if (traceListeners == null) traceListeners = new Vector();
118 		traceListeners.addElement(l);
119 		addDoneListener(l);
120 	}
fireConsume(int value)121 	public void fireConsume(int value) {
122 		tokenEvent.setValues(ParserTokenEvent.CONSUME, 1, value);
123 		fireEvents(CONSUME, tokenListeners);
124 	}
fireDoneParsing()125 	public void fireDoneParsing() {
126 		traceEvent.setValues(TraceEvent.DONE_PARSING, 0,0,0);
127 
128 		Hashtable targets=null;
129 //		Hashtable targets=doneListeners;
130 		ListenerBase l=null;
131 
132 		synchronized (this) {
133 			if (doneListeners == null) return;
134 			targets = (Hashtable)doneListeners.clone();
135 		}
136 
137 		if (targets != null) {
138 			Enumeration e = targets.keys();
139 			while(e.hasMoreElements()) {
140 				l = (ListenerBase)e.nextElement();
141 				fireEvent(DONE_PARSING, l);
142 			}
143 		}
144 		if (controller != null)
145 			controller.checkBreak();
146 	}
fireEnterRule(int ruleNum, int guessing, int data)147 	public void fireEnterRule(int ruleNum, int guessing, int data) {
148 		ruleDepth++;
149 		traceEvent.setValues(TraceEvent.ENTER, ruleNum, guessing, data);
150 		fireEvents(ENTER_RULE, traceListeners);
151 	}
fireEvent(int type, ListenerBase l)152 	public void fireEvent(int type, ListenerBase l) {
153 		switch(type) {
154 			case CONSUME:    ((ParserTokenListener)l).parserConsume(tokenEvent); break;
155 			case LA:         ((ParserTokenListener)l).parserLA(tokenEvent);      break;
156 
157 			case ENTER_RULE: ((TraceListener)l).enterRule(traceEvent);           break;
158 			case EXIT_RULE:  ((TraceListener)l).exitRule(traceEvent);            break;
159 
160 			case MATCH:        ((ParserMatchListener)l).parserMatch(matchEvent);       break;
161 			case MATCH_NOT:    ((ParserMatchListener)l).parserMatchNot(matchEvent);    break;
162 			case MISMATCH:     ((ParserMatchListener)l).parserMismatch(matchEvent);    break;
163 			case MISMATCH_NOT: ((ParserMatchListener)l).parserMismatchNot(matchEvent); break;
164 
165 			case SEMPRED:      ((SemanticPredicateListener)l).semanticPredicateEvaluated(semPredEvent); break;
166 
167 			case SYNPRED_STARTED:   ((SyntacticPredicateListener)l).syntacticPredicateStarted(synPredEvent);   break;
168 			case SYNPRED_FAILED:    ((SyntacticPredicateListener)l).syntacticPredicateFailed(synPredEvent);    break;
169 			case SYNPRED_SUCCEEDED: ((SyntacticPredicateListener)l).syntacticPredicateSucceeded(synPredEvent); break;
170 
171 			case REPORT_ERROR:   ((MessageListener)l).reportError(messageEvent);   break;
172 			case REPORT_WARNING: ((MessageListener)l).reportWarning(messageEvent); break;
173 
174 			case DONE_PARSING: l.doneParsing(traceEvent); break;
175 			case NEW_LINE:     ((NewLineListener)l).hitNewLine(newLineEvent); break;
176 
177 			default:
178 				throw new IllegalArgumentException("bad type "+type+" for fireEvent()");
179 		}
180 	}
fireEvents(int type, Vector listeners)181 	public void fireEvents(int type, Vector listeners) {
182 		ListenerBase l=null;
183 
184 		if (listeners != null)
185 			for (int i = 0; i < listeners.size(); i++) {
186 				l = (ListenerBase)listeners.elementAt(i);
187 				fireEvent(type, l);
188 			}
189 		if (controller != null)
190 			controller.checkBreak();
191 	}
fireExitRule(int ruleNum, int guessing, int data)192 	public void fireExitRule(int ruleNum, int guessing, int data) {
193 		traceEvent.setValues(TraceEvent.EXIT, ruleNum, guessing, data);
194 		fireEvents(EXIT_RULE, traceListeners);
195 		ruleDepth--;
196 		if (ruleDepth == 0)
197 			fireDoneParsing();
198 	}
fireLA(int k, int la)199 	public void fireLA(int k, int la) {
200 		tokenEvent.setValues(ParserTokenEvent.LA, k, la);
201 		fireEvents(LA, tokenListeners);
202 	}
fireMatch(char c, int guessing)203 	public void fireMatch(char c, int guessing) {
204 		matchEvent.setValues(ParserMatchEvent.CHAR, c, new Character(c), null, guessing, false, true);
205 		fireEvents(MATCH, matchListeners);
206 	}
fireMatch(char value, BitSet b, int guessing)207 	public void fireMatch(char value, BitSet b, int guessing) {
208 		matchEvent.setValues(ParserMatchEvent.CHAR_BITSET, value, b, null, guessing, false, true);
209 		fireEvents(MATCH, matchListeners);
210 	}
fireMatch(char value, String target, int guessing)211 	public void fireMatch(char value, String target, int guessing) {
212 		matchEvent.setValues(ParserMatchEvent.CHAR_RANGE, value, target, null, guessing, false, true);
213 		fireEvents(MATCH, matchListeners);
214 	}
fireMatch(int value, BitSet b, String text, int guessing)215 	public void fireMatch(int value, BitSet b, String text, int guessing) {
216 		matchEvent.setValues(ParserMatchEvent.BITSET, value, b, text, guessing, false, true);
217 		fireEvents(MATCH, matchListeners);
218 	}
fireMatch(int n, String text, int guessing)219 	public void fireMatch(int n, String text, int guessing) {
220 		matchEvent.setValues(ParserMatchEvent.TOKEN, n, new Integer(n), text, guessing, false, true);
221 		fireEvents(MATCH, matchListeners);
222 	}
fireMatch(String s, int guessing)223 	public void fireMatch(String s, int guessing) {
224 		matchEvent.setValues(ParserMatchEvent.STRING, 0, s, null, guessing, false, true);
225 		fireEvents(MATCH, matchListeners);
226 	}
fireMatchNot(char value, char n, int guessing)227 	public void fireMatchNot(char value, char n, int guessing) {
228 		matchEvent.setValues(ParserMatchEvent.CHAR, value, new Character(n), null, guessing, true, true);
229 		fireEvents(MATCH_NOT, matchListeners);
230 	}
fireMatchNot(int value, int n, String text, int guessing)231 	public void fireMatchNot(int value, int n, String text, int guessing) {
232 		matchEvent.setValues(ParserMatchEvent.TOKEN, value, new Integer(n), text, guessing, true, true);
233 		fireEvents(MATCH_NOT, matchListeners);
234 	}
fireMismatch(char value, char n, int guessing)235 	public void fireMismatch(char value, char n, int guessing) {
236 		matchEvent.setValues(ParserMatchEvent.CHAR, value, new Character(n), null, guessing, false, false);
237 		fireEvents(MISMATCH, matchListeners);
238 	}
fireMismatch(char value, BitSet b, int guessing)239 	public void fireMismatch(char value, BitSet b, int guessing) {
240 		matchEvent.setValues(ParserMatchEvent.CHAR_BITSET, value, b, null, guessing, false, true);
241 		fireEvents(MISMATCH, matchListeners);
242 	}
fireMismatch(char value, String target, int guessing)243 	public void fireMismatch(char value, String target, int guessing) {
244 		matchEvent.setValues(ParserMatchEvent.CHAR_RANGE, value, target, null, guessing, false, true);
245 		fireEvents(MISMATCH, matchListeners);
246 	}
fireMismatch(int value, int n, String text, int guessing)247 	public void fireMismatch(int value, int n, String text, int guessing) {
248 		matchEvent.setValues(ParserMatchEvent.TOKEN, value, new Integer(n), text, guessing, false, false);
249 		fireEvents(MISMATCH, matchListeners);
250 	}
fireMismatch(int value, BitSet b, String text, int guessing)251 	public void fireMismatch(int value, BitSet b, String text, int guessing) {
252 		matchEvent.setValues(ParserMatchEvent.BITSET, value, b, text, guessing, false, true);
253 		fireEvents(MISMATCH, matchListeners);
254 	}
fireMismatch(String value, String text, int guessing)255 	public void fireMismatch(String value, String text, int guessing) {
256 		matchEvent.setValues(ParserMatchEvent.STRING, 0, text, value, guessing, false, true);
257 		fireEvents(MISMATCH, matchListeners);
258 	}
fireMismatchNot(char value, char c, int guessing)259 	public void fireMismatchNot(char value, char c, int guessing) {
260 		matchEvent.setValues(ParserMatchEvent.CHAR, value, new Character(c), null, guessing, true, true);
261 		fireEvents(MISMATCH_NOT, matchListeners);
262 	}
fireMismatchNot(int value, int n, String text, int guessing)263 	public void fireMismatchNot(int value, int n, String text, int guessing) {
264 		matchEvent.setValues(ParserMatchEvent.TOKEN, value, new Integer(n), text, guessing, true, true);
265 		fireEvents(MISMATCH_NOT, matchListeners);
266 	}
fireNewLine(int line)267 	public void fireNewLine(int line) {
268 		newLineEvent.setValues(line);
269 		fireEvents(NEW_LINE, newLineListeners);
270 	}
fireReportError(Exception e)271 	public void fireReportError(Exception e) {
272 		messageEvent.setValues(MessageEvent.ERROR, e.toString());
273 		fireEvents(REPORT_ERROR, messageListeners);
274 	}
fireReportError(String s)275 	public void fireReportError(String s) {
276 		messageEvent.setValues(MessageEvent.ERROR, s);
277 		fireEvents(REPORT_ERROR, messageListeners);
278 	}
fireReportWarning(String s)279 	public void fireReportWarning(String s) {
280 		messageEvent.setValues(MessageEvent.WARNING, s);
281 		fireEvents(REPORT_WARNING, messageListeners);
282 	}
fireSemanticPredicateEvaluated(int type, int condition, boolean result, int guessing)283 	public boolean fireSemanticPredicateEvaluated(int type, int condition, boolean result, int guessing) {
284 		semPredEvent.setValues(type, condition, result, guessing);
285 		fireEvents(SEMPRED, semPredListeners);
286 		return result;
287 	}
fireSyntacticPredicateFailed(int guessing)288 	public void fireSyntacticPredicateFailed(int guessing) {
289 		synPredEvent.setValues(0, guessing);
290 		fireEvents(SYNPRED_FAILED, synPredListeners);
291 	}
fireSyntacticPredicateStarted(int guessing)292 	public void fireSyntacticPredicateStarted(int guessing) {
293 		synPredEvent.setValues(0, guessing);
294 		fireEvents(SYNPRED_STARTED, synPredListeners);
295 	}
fireSyntacticPredicateSucceeded(int guessing)296 	public void fireSyntacticPredicateSucceeded(int guessing) {
297 		synPredEvent.setValues(0, guessing);
298 		fireEvents(SYNPRED_SUCCEEDED, synPredListeners);
299 	}
refresh(Vector listeners)300 	protected void refresh(Vector listeners) {
301 		Vector v;
302 		synchronized (listeners) {
303 			v = (Vector)listeners.clone();
304 		}
305 		if (v != null)
306 			for (int i = 0; i < v.size(); i++)
307 				((ListenerBase)v.elementAt(i)).refresh();
308 	}
refreshListeners()309 	public void refreshListeners() {
310 		refresh(matchListeners);
311 		refresh(messageListeners);
312 		refresh(tokenListeners);
313 		refresh(traceListeners);
314 		refresh(semPredListeners);
315 		refresh(synPredListeners);
316 	}
removeDoneListener(ListenerBase l)317 	public void removeDoneListener(ListenerBase l) {
318 		if (doneListeners == null) return;
319 		Integer i = (Integer)doneListeners.get(l);
320 		int val=0;
321 		if (i != null)
322 			val = i.intValue() - 1;
323 
324 		if (val == 0)
325 			doneListeners.remove(l);
326 		else
327 			doneListeners.put(l, new Integer(val));
328 	}
removeMessageListener(MessageListener l)329 	public void removeMessageListener(MessageListener l) {
330 		if (messageListeners != null)
331 			messageListeners.removeElement(l);
332 		removeDoneListener(l);
333 	}
removeNewLineListener(NewLineListener l)334 	public void removeNewLineListener(NewLineListener l) {
335 		if (newLineListeners != null)
336 			newLineListeners.removeElement(l);
337 		removeDoneListener(l);
338 	}
removeParserListener(ParserListener l)339 	public void removeParserListener(ParserListener l) {
340 		removeParserMatchListener(l);
341 		removeMessageListener(l);
342 		removeParserTokenListener(l);
343 		removeTraceListener(l);
344 		removeSemanticPredicateListener(l);
345 		removeSyntacticPredicateListener(l);
346 	}
removeParserMatchListener(ParserMatchListener l)347 	public void removeParserMatchListener(ParserMatchListener l) {
348 		if (matchListeners != null)
349 			matchListeners.removeElement(l);
350 		removeDoneListener(l);
351 	}
removeParserTokenListener(ParserTokenListener l)352 	public void removeParserTokenListener(ParserTokenListener l) {
353 		if (tokenListeners != null)
354 			tokenListeners.removeElement(l);
355 		removeDoneListener(l);
356 	}
removeSemanticPredicateListener(SemanticPredicateListener l)357 	public void removeSemanticPredicateListener(SemanticPredicateListener l) {
358 		if (semPredListeners != null)
359 			semPredListeners.removeElement(l);
360 		removeDoneListener(l);
361 	}
removeSyntacticPredicateListener(SyntacticPredicateListener l)362 	public void removeSyntacticPredicateListener(SyntacticPredicateListener l) {
363 		if (synPredListeners != null)
364 			synPredListeners.removeElement(l);
365 		removeDoneListener(l);
366 	}
removeTraceListener(TraceListener l)367 	public void removeTraceListener(TraceListener l) {
368 		if (traceListeners != null)
369 			traceListeners.removeElement(l);
370 		removeDoneListener(l);
371 	}
372 }
373