001: package antlr.debug;
002:
003: import java.util.Vector;
004: import java.util.Hashtable;
005: import java.util.Enumeration;
006: import antlr.collections.impl.BitSet;
007: import antlr.RecognitionException;
008:
009: /** A class to assist in firing parser events
010: * NOTE: I intentionally _did_not_ synchronize the event firing and
011: * add/remove listener methods. This is because the add/remove should
012: * _only_ be called by the parser at its start/end, and the _same_thread_
013: * should be performing the parsing. This should help performance a tad...
014: */
015: public class ParserEventSupport {
016: private Object source;
017: private Hashtable doneListeners;
018: private Vector matchListeners;
019: private Vector messageListeners;
020: private Vector tokenListeners;
021: private Vector traceListeners;
022: private Vector semPredListeners;
023: private Vector synPredListeners;
024: private Vector newLineListeners;
025: private ParserMatchEvent matchEvent;
026: private MessageEvent messageEvent;
027: private ParserTokenEvent tokenEvent;
028: private SemanticPredicateEvent semPredEvent;
029: private SyntacticPredicateEvent synPredEvent;
030: private TraceEvent traceEvent;
031: private NewLineEvent newLineEvent;
032: private ParserController controller;
033: protected static final int CONSUME = 0;
034: protected static final int ENTER_RULE = 1;
035: protected static final int EXIT_RULE = 2;
036: protected static final int LA = 3;
037: protected static final int MATCH = 4;
038: protected static final int MATCH_NOT = 5;
039: protected static final int MISMATCH = 6;
040: protected static final int MISMATCH_NOT = 7;
041: protected static final int REPORT_ERROR = 8;
042: protected static final int REPORT_WARNING = 9;
043: protected static final int SEMPRED = 10;
044: protected static final int SYNPRED_FAILED = 11;
045: protected static final int SYNPRED_STARTED = 12;
046: protected static final int SYNPRED_SUCCEEDED = 13;
047: protected static final int NEW_LINE = 14;
048: protected static final int DONE_PARSING = 15;
049: private int ruleDepth = 0;
050:
051: public ParserEventSupport(Object source) {
052: matchEvent = new ParserMatchEvent(source);
053: messageEvent = new MessageEvent(source);
054: tokenEvent = new ParserTokenEvent(source);
055: traceEvent = new TraceEvent(source);
056: semPredEvent = new SemanticPredicateEvent(source);
057: synPredEvent = new SyntacticPredicateEvent(source);
058: newLineEvent = new NewLineEvent(source);
059: this .source = source;
060: }
061:
062: public void addDoneListener(ListenerBase l) {
063: if (doneListeners == null)
064: doneListeners = new Hashtable();
065: Integer i = (Integer) doneListeners.get(l);
066: int val;
067: if (i != null)
068: val = i.intValue() + 1;
069: else
070: val = 1;
071: doneListeners.put(l, new Integer(val));
072: }
073:
074: public void addMessageListener(MessageListener l) {
075: if (messageListeners == null)
076: messageListeners = new Vector();
077: messageListeners.addElement(l);
078: addDoneListener(l);
079: }
080:
081: public void addNewLineListener(NewLineListener l) {
082: if (newLineListeners == null)
083: newLineListeners = new Vector();
084: newLineListeners.addElement(l);
085: addDoneListener(l);
086: }
087:
088: public void addParserListener(ParserListener l) {
089: if (l instanceof ParserController) {
090: ((ParserController) l).setParserEventSupport(this );
091: controller = (ParserController) l;
092: }
093: addParserMatchListener(l);
094: addParserTokenListener(l);
095:
096: addMessageListener(l);
097: addTraceListener(l);
098: addSemanticPredicateListener(l);
099: addSyntacticPredicateListener(l);
100: }
101:
102: public void addParserMatchListener(ParserMatchListener l) {
103: if (matchListeners == null)
104: matchListeners = new Vector();
105: matchListeners.addElement(l);
106: addDoneListener(l);
107: }
108:
109: public void addParserTokenListener(ParserTokenListener l) {
110: if (tokenListeners == null)
111: tokenListeners = new Vector();
112: tokenListeners.addElement(l);
113: addDoneListener(l);
114: }
115:
116: public void addSemanticPredicateListener(SemanticPredicateListener l) {
117: if (semPredListeners == null)
118: semPredListeners = new Vector();
119: semPredListeners.addElement(l);
120: addDoneListener(l);
121: }
122:
123: public void addSyntacticPredicateListener(
124: SyntacticPredicateListener l) {
125: if (synPredListeners == null)
126: synPredListeners = new Vector();
127: synPredListeners.addElement(l);
128: addDoneListener(l);
129: }
130:
131: public void addTraceListener(TraceListener l) {
132: if (traceListeners == null)
133: traceListeners = new Vector();
134: traceListeners.addElement(l);
135: addDoneListener(l);
136: }
137:
138: public void fireConsume(int value) {
139: tokenEvent.setValues(ParserTokenEvent.CONSUME, 1, value);
140: fireEvents(CONSUME, tokenListeners);
141: }
142:
143: public void fireDoneParsing() {
144: traceEvent.setValues(TraceEvent.DONE_PARSING, 0, 0, 0);
145:
146: Hashtable targets = null;
147: // Hashtable targets=doneListeners;
148: ListenerBase l = null;
149:
150: synchronized (this ) {
151: if (doneListeners == null)
152: return;
153: targets = (Hashtable) doneListeners.clone();
154: }
155:
156: if (targets != null) {
157: Enumeration e = targets.keys();
158: while (e.hasMoreElements()) {
159: l = (ListenerBase) e.nextElement();
160: fireEvent(DONE_PARSING, l);
161: }
162: }
163: if (controller != null)
164: controller.checkBreak();
165: }
166:
167: public void fireEnterRule(int ruleNum, int guessing, int data) {
168: ruleDepth++;
169: traceEvent.setValues(TraceEvent.ENTER, ruleNum, guessing, data);
170: fireEvents(ENTER_RULE, traceListeners);
171: }
172:
173: public void fireEvent(int type, ListenerBase l) {
174: switch (type) {
175: case CONSUME:
176: ((ParserTokenListener) l).parserConsume(tokenEvent);
177: break;
178: case LA:
179: ((ParserTokenListener) l).parserLA(tokenEvent);
180: break;
181:
182: case ENTER_RULE:
183: ((TraceListener) l).enterRule(traceEvent);
184: break;
185: case EXIT_RULE:
186: ((TraceListener) l).exitRule(traceEvent);
187: break;
188:
189: case MATCH:
190: ((ParserMatchListener) l).parserMatch(matchEvent);
191: break;
192: case MATCH_NOT:
193: ((ParserMatchListener) l).parserMatchNot(matchEvent);
194: break;
195: case MISMATCH:
196: ((ParserMatchListener) l).parserMismatch(matchEvent);
197: break;
198: case MISMATCH_NOT:
199: ((ParserMatchListener) l).parserMismatchNot(matchEvent);
200: break;
201:
202: case SEMPRED:
203: ((SemanticPredicateListener) l)
204: .semanticPredicateEvaluated(semPredEvent);
205: break;
206:
207: case SYNPRED_STARTED:
208: ((SyntacticPredicateListener) l)
209: .syntacticPredicateStarted(synPredEvent);
210: break;
211: case SYNPRED_FAILED:
212: ((SyntacticPredicateListener) l)
213: .syntacticPredicateFailed(synPredEvent);
214: break;
215: case SYNPRED_SUCCEEDED:
216: ((SyntacticPredicateListener) l)
217: .syntacticPredicateSucceeded(synPredEvent);
218: break;
219:
220: case REPORT_ERROR:
221: ((MessageListener) l).reportError(messageEvent);
222: break;
223: case REPORT_WARNING:
224: ((MessageListener) l).reportWarning(messageEvent);
225: break;
226:
227: case DONE_PARSING:
228: l.doneParsing(traceEvent);
229: break;
230: case NEW_LINE:
231: ((NewLineListener) l).hitNewLine(newLineEvent);
232: break;
233:
234: default:
235: throw new IllegalArgumentException("bad type " + type
236: + " for fireEvent()");
237: }
238: }
239:
240: public void fireEvents(int type, Vector listeners) {
241: ListenerBase l = null;
242:
243: if (listeners != null)
244: for (int i = 0; i < listeners.size(); i++) {
245: l = (ListenerBase) listeners.elementAt(i);
246: fireEvent(type, l);
247: }
248: if (controller != null)
249: controller.checkBreak();
250: }
251:
252: public void fireExitRule(int ruleNum, int guessing, int data) {
253: traceEvent.setValues(TraceEvent.EXIT, ruleNum, guessing, data);
254: fireEvents(EXIT_RULE, traceListeners);
255: ruleDepth--;
256: if (ruleDepth == 0)
257: fireDoneParsing();
258: }
259:
260: public void fireLA(int k, int la) {
261: tokenEvent.setValues(ParserTokenEvent.LA, k, la);
262: fireEvents(LA, tokenListeners);
263: }
264:
265: public void fireMatch(char c, int guessing) {
266: matchEvent.setValues(ParserMatchEvent.CHAR, c,
267: new Character(c), null, guessing, false, true);
268: fireEvents(MATCH, matchListeners);
269: }
270:
271: public void fireMatch(char value, BitSet b, int guessing) {
272: matchEvent.setValues(ParserMatchEvent.CHAR_BITSET, value, b,
273: null, guessing, false, true);
274: fireEvents(MATCH, matchListeners);
275: }
276:
277: public void fireMatch(char value, String target, int guessing) {
278: matchEvent.setValues(ParserMatchEvent.CHAR_RANGE, value,
279: target, null, guessing, false, true);
280: fireEvents(MATCH, matchListeners);
281: }
282:
283: public void fireMatch(int value, BitSet b, String text, int guessing) {
284: matchEvent.setValues(ParserMatchEvent.BITSET, value, b, text,
285: guessing, false, true);
286: fireEvents(MATCH, matchListeners);
287: }
288:
289: public void fireMatch(int n, String text, int guessing) {
290: matchEvent.setValues(ParserMatchEvent.TOKEN, n, new Integer(n),
291: text, guessing, false, true);
292: fireEvents(MATCH, matchListeners);
293: }
294:
295: public void fireMatch(String s, int guessing) {
296: matchEvent.setValues(ParserMatchEvent.STRING, 0, s, null,
297: guessing, false, true);
298: fireEvents(MATCH, matchListeners);
299: }
300:
301: public void fireMatchNot(char value, char n, int guessing) {
302: matchEvent.setValues(ParserMatchEvent.CHAR, value,
303: new Character(n), null, guessing, true, true);
304: fireEvents(MATCH_NOT, matchListeners);
305: }
306:
307: public void fireMatchNot(int value, int n, String text, int guessing) {
308: matchEvent.setValues(ParserMatchEvent.TOKEN, value,
309: new Integer(n), text, guessing, true, true);
310: fireEvents(MATCH_NOT, matchListeners);
311: }
312:
313: public void fireMismatch(char value, char n, int guessing) {
314: matchEvent.setValues(ParserMatchEvent.CHAR, value,
315: new Character(n), null, guessing, false, false);
316: fireEvents(MISMATCH, matchListeners);
317: }
318:
319: public void fireMismatch(char value, BitSet b, int guessing) {
320: matchEvent.setValues(ParserMatchEvent.CHAR_BITSET, value, b,
321: null, guessing, false, true);
322: fireEvents(MISMATCH, matchListeners);
323: }
324:
325: public void fireMismatch(char value, String target, int guessing) {
326: matchEvent.setValues(ParserMatchEvent.CHAR_RANGE, value,
327: target, null, guessing, false, true);
328: fireEvents(MISMATCH, matchListeners);
329: }
330:
331: public void fireMismatch(int value, int n, String text, int guessing) {
332: matchEvent.setValues(ParserMatchEvent.TOKEN, value,
333: new Integer(n), text, guessing, false, false);
334: fireEvents(MISMATCH, matchListeners);
335: }
336:
337: public void fireMismatch(int value, BitSet b, String text,
338: int guessing) {
339: matchEvent.setValues(ParserMatchEvent.BITSET, value, b, text,
340: guessing, false, true);
341: fireEvents(MISMATCH, matchListeners);
342: }
343:
344: public void fireMismatch(String value, String text, int guessing) {
345: matchEvent.setValues(ParserMatchEvent.STRING, 0, text, value,
346: guessing, false, true);
347: fireEvents(MISMATCH, matchListeners);
348: }
349:
350: public void fireMismatchNot(char value, char c, int guessing) {
351: matchEvent.setValues(ParserMatchEvent.CHAR, value,
352: new Character(c), null, guessing, true, true);
353: fireEvents(MISMATCH_NOT, matchListeners);
354: }
355:
356: public void fireMismatchNot(int value, int n, String text,
357: int guessing) {
358: matchEvent.setValues(ParserMatchEvent.TOKEN, value,
359: new Integer(n), text, guessing, true, true);
360: fireEvents(MISMATCH_NOT, matchListeners);
361: }
362:
363: public void fireNewLine(int line) {
364: newLineEvent.setValues(line);
365: fireEvents(NEW_LINE, newLineListeners);
366: }
367:
368: public void fireReportError(Exception e) {
369: messageEvent.setValues(MessageEvent.ERROR, e.toString());
370: fireEvents(REPORT_ERROR, messageListeners);
371: }
372:
373: public void fireReportError(String s) {
374: messageEvent.setValues(MessageEvent.ERROR, s);
375: fireEvents(REPORT_ERROR, messageListeners);
376: }
377:
378: public void fireReportWarning(String s) {
379: messageEvent.setValues(MessageEvent.WARNING, s);
380: fireEvents(REPORT_WARNING, messageListeners);
381: }
382:
383: public boolean fireSemanticPredicateEvaluated(int type,
384: int condition, boolean result, int guessing) {
385: semPredEvent.setValues(type, condition, result, guessing);
386: fireEvents(SEMPRED, semPredListeners);
387: return result;
388: }
389:
390: public void fireSyntacticPredicateFailed(int guessing) {
391: synPredEvent.setValues(0, guessing);
392: fireEvents(SYNPRED_FAILED, synPredListeners);
393: }
394:
395: public void fireSyntacticPredicateStarted(int guessing) {
396: synPredEvent.setValues(0, guessing);
397: fireEvents(SYNPRED_STARTED, synPredListeners);
398: }
399:
400: public void fireSyntacticPredicateSucceeded(int guessing) {
401: synPredEvent.setValues(0, guessing);
402: fireEvents(SYNPRED_SUCCEEDED, synPredListeners);
403: }
404:
405: protected void refresh(Vector listeners) {
406: Vector v;
407: synchronized (listeners) {
408: v = (Vector) listeners.clone();
409: }
410: if (v != null)
411: for (int i = 0; i < v.size(); i++)
412: ((ListenerBase) v.elementAt(i)).refresh();
413: }
414:
415: public void refreshListeners() {
416: refresh(matchListeners);
417: refresh(messageListeners);
418: refresh(tokenListeners);
419: refresh(traceListeners);
420: refresh(semPredListeners);
421: refresh(synPredListeners);
422: }
423:
424: public void removeDoneListener(ListenerBase l) {
425: if (doneListeners == null)
426: return;
427: Integer i = (Integer) doneListeners.get(l);
428: int val = 0;
429: if (i != null)
430: val = i.intValue() - 1;
431:
432: if (val == 0)
433: doneListeners.remove(l);
434: else
435: doneListeners.put(l, new Integer(val));
436: }
437:
438: public void removeMessageListener(MessageListener l) {
439: if (messageListeners != null)
440: messageListeners.removeElement(l);
441: removeDoneListener(l);
442: }
443:
444: public void removeNewLineListener(NewLineListener l) {
445: if (newLineListeners != null)
446: newLineListeners.removeElement(l);
447: removeDoneListener(l);
448: }
449:
450: public void removeParserListener(ParserListener l) {
451: removeParserMatchListener(l);
452: removeMessageListener(l);
453: removeParserTokenListener(l);
454: removeTraceListener(l);
455: removeSemanticPredicateListener(l);
456: removeSyntacticPredicateListener(l);
457: }
458:
459: public void removeParserMatchListener(ParserMatchListener l) {
460: if (matchListeners != null)
461: matchListeners.removeElement(l);
462: removeDoneListener(l);
463: }
464:
465: public void removeParserTokenListener(ParserTokenListener l) {
466: if (tokenListeners != null)
467: tokenListeners.removeElement(l);
468: removeDoneListener(l);
469: }
470:
471: public void removeSemanticPredicateListener(
472: SemanticPredicateListener l) {
473: if (semPredListeners != null)
474: semPredListeners.removeElement(l);
475: removeDoneListener(l);
476: }
477:
478: public void removeSyntacticPredicateListener(
479: SyntacticPredicateListener l) {
480: if (synPredListeners != null)
481: synPredListeners.removeElement(l);
482: removeDoneListener(l);
483: }
484:
485: public void removeTraceListener(TraceListener l) {
486: if (traceListeners != null)
487: traceListeners.removeElement(l);
488: removeDoneListener(l);
489: }
490: }
|