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.ParserException;
8
9
10 * 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
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 }
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 }
73 public void addMessageListener(MessageListener l) {
74 if (messageListeners == null) messageListeners = new Vector();
75 messageListeners.addElement(l);
76 addDoneListener(l);
77 }
78 public void addNewLineListener(NewLineListener l) {
79 if (newLineListeners == null) newLineListeners = new Vector();
80 newLineListeners.addElement(l);
81 addDoneListener(l);
82 }
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 }
96 public void addParserMatchListener(ParserMatchListener l) {
97 if (matchListeners == null) matchListeners = new Vector();
98 matchListeners.addElement(l);
99 addDoneListener(l);
100 }
101 public void addParserTokenListener(ParserTokenListener l) {
102 if (tokenListeners == null) tokenListeners = new Vector();
103 tokenListeners.addElement(l);
104 addDoneListener(l);
105 }
106 public void addSemanticPredicateListener(SemanticPredicateListener l) {
107 if (semPredListeners == null) semPredListeners = new Vector();
108 semPredListeners.addElement(l);
109 addDoneListener(l);
110 }
111 public void addSyntacticPredicateListener(SyntacticPredicateListener l) {
112 if (synPredListeners == null) synPredListeners = new Vector();
113 synPredListeners.addElement(l);
114 addDoneListener(l);
115 }
116 public void addTraceListener(TraceListener l) {
117 if (traceListeners == null) traceListeners = new Vector();
118 traceListeners.addElement(l);
119 addDoneListener(l);
120 }
121 public void fireConsume(int value) {
122 tokenEvent.setValues(ParserTokenEvent.CONSUME, 1, value);
123 fireEvents(CONSUME, tokenListeners);
124 }
125 public void fireDoneParsing() {
126 traceEvent.setValues(TraceEvent.DONE_PARSING, 0,0,0);
127
128 Hashtable targets=null;
129 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 }
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 }
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 }
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 }
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 }
199 public void fireLA(int k, int la) {
200 tokenEvent.setValues(ParserTokenEvent.LA, k, la);
201 fireEvents(LA, tokenListeners);
202 }
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 }
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 }
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 }
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 }
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 }
223 public void fireMatch(String s, int guessing) {
224 matchEvent.setValues(ParserMatchEvent.STRING, 0, s, null, guessing, false, true);
225 fireEvents(MATCH, matchListeners);
226 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
267 public void fireNewLine(int line) {
268 newLineEvent.setValues(line);
269 fireEvents(NEW_LINE, newLineListeners);
270 }
271 public void fireReportError(Exception e) {
272 messageEvent.setValues(MessageEvent.ERROR, e.toString());
273 fireEvents(REPORT_ERROR, messageListeners);
274 }
275 public void fireReportError(String s) {
276 messageEvent.setValues(MessageEvent.ERROR, s);
277 fireEvents(REPORT_ERROR, messageListeners);
278 }
279 public void fireReportWarning(String s) {
280 messageEvent.setValues(MessageEvent.WARNING, s);
281 fireEvents(REPORT_WARNING, messageListeners);
282 }
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 }
288 public void fireSyntacticPredicateFailed(int guessing) {
289 synPredEvent.setValues(0, guessing);
290 fireEvents(SYNPRED_FAILED, synPredListeners);
291 }
292 public void fireSyntacticPredicateStarted(int guessing) {
293 synPredEvent.setValues(0, guessing);
294 fireEvents(SYNPRED_STARTED, synPredListeners);
295 }
296 public void fireSyntacticPredicateSucceeded(int guessing) {
297 synPredEvent.setValues(0, guessing);
298 fireEvents(SYNPRED_SUCCEEDED, synPredListeners);
299 }
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 }
309 public void refreshListeners() {
310 refresh(matchListeners);
311 refresh(messageListeners);
312 refresh(tokenListeners);
313 refresh(traceListeners);
314 refresh(semPredListeners);
315 refresh(synPredListeners);
316 }
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 }
329 public void removeMessageListener(MessageListener l) {
330 if (messageListeners != null)
331 messageListeners.removeElement(l);
332 removeDoneListener(l);
333 }
334 public void removeNewLineListener(NewLineListener l) {
335 if (newLineListeners != null)
336 newLineListeners.removeElement(l);
337 removeDoneListener(l);
338 }
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 }
347 public void removeParserMatchListener(ParserMatchListener l) {
348 if (matchListeners != null)
349 matchListeners.removeElement(l);
350 removeDoneListener(l);
351 }
352 public void removeParserTokenListener(ParserTokenListener l) {
353 if (tokenListeners != null)
354 tokenListeners.removeElement(l);
355 removeDoneListener(l);
356 }
357 public void removeSemanticPredicateListener(SemanticPredicateListener l) {
358 if (semPredListeners != null)
359 semPredListeners.removeElement(l);
360 removeDoneListener(l);
361 }
362 public void removeSyntacticPredicateListener(SyntacticPredicateListener l) {
363 if (synPredListeners != null)
364 synPredListeners.removeElement(l);
365 removeDoneListener(l);
366 }
367 public void removeTraceListener(TraceListener l) {
368 if (traceListeners != null)
369 traceListeners.removeElement(l);
370 removeDoneListener(l);
371 }
372 }
373