package antlr.debug;
import java.util.
Vector;
import java.util.
Hashtable;
import java.util.
Enumeration;
import antlr.collections.impl.
BitSet;
import antlr.
RecognitionException;
/** A class to assist in firing parser events
* NOTE: I intentionally _did_not_ synchronize the event firing and
* add/remove listener methods. This is because the add/remove should
* _only_ be called by the parser at its start/end, and the _same_thread_
* should be performing the parsing. This should help performance a tad...
*/
public class
ParserEventSupport {
private
Object source;
private
Hashtable doneListeners;
private
Vector matchListeners;
private
Vector messageListeners;
private
Vector tokenListeners;
private
Vector traceListeners;
private
Vector semPredListeners;
private
Vector synPredListeners;
private
Vector newLineListeners;
private
ParserMatchEvent matchEvent;
private
MessageEvent messageEvent;
private
ParserTokenEvent tokenEvent;
private
SemanticPredicateEvent semPredEvent;
private
SyntacticPredicateEvent synPredEvent;
private
TraceEvent traceEvent;
private
NewLineEvent newLineEvent;
private
ParserController controller;
protected static final int
CONSUME=0;
protected static final int
ENTER_RULE=1;
protected static final int
EXIT_RULE=2;
protected static final int
LA=3;
protected static final int
MATCH=4;
protected static final int
MATCH_NOT=5;
protected static final int
MISMATCH=6;
protected static final int
MISMATCH_NOT=7;
protected static final int
REPORT_ERROR=8;
protected static final int
REPORT_WARNING=9;
protected static final int
SEMPRED=10;
protected static final int
SYNPRED_FAILED=11;
protected static final int
SYNPRED_STARTED=12;
protected static final int
SYNPRED_SUCCEEDED=13;
protected static final int
NEW_LINE=14;
protected static final int
DONE_PARSING=15;
private int
ruleDepth = 0;
public
ParserEventSupport(
Object source) {
matchEvent = new
ParserMatchEvent(
source);
messageEvent = new
MessageEvent(
source);
tokenEvent = new
ParserTokenEvent(
source);
traceEvent = new
TraceEvent(
source);
semPredEvent = new
SemanticPredicateEvent(
source);
synPredEvent = new
SyntacticPredicateEvent(
source);
newLineEvent = new
NewLineEvent(
source);
this.
source =
source;
}
public void
addDoneListener(
ListenerBase l) {
if (
doneListeners == null)
doneListeners = new
Hashtable();
Integer i = (
Integer)
doneListeners.
get(
l);
int
val;
if (
i != null)
val =
i.
intValue() + 1;
else
val = 1;
doneListeners.
put(
l, new
Integer(
val));
}
public void
addMessageListener(
MessageListener l) {
if (
messageListeners == null)
messageListeners = new
Vector();
messageListeners.
addElement(
l);
addDoneListener(
l);
}
public void
addNewLineListener(
NewLineListener l) {
if (
newLineListeners == null)
newLineListeners = new
Vector();
newLineListeners.
addElement(
l);
addDoneListener(
l);
}
public void
addParserListener(
ParserListener l) {
if (
l instanceof
ParserController) {
((
ParserController)
l).
setParserEventSupport(this);
controller = (
ParserController)
l;
}
addParserMatchListener(
l);
addParserTokenListener(
l);
addMessageListener(
l);
addTraceListener(
l);
addSemanticPredicateListener(
l);
addSyntacticPredicateListener(
l);
}
public void
addParserMatchListener(
ParserMatchListener l) {
if (
matchListeners == null)
matchListeners = new
Vector();
matchListeners.
addElement(
l);
addDoneListener(
l);
}
public void
addParserTokenListener(
ParserTokenListener l) {
if (
tokenListeners == null)
tokenListeners = new
Vector();
tokenListeners.
addElement(
l);
addDoneListener(
l);
}
public void
addSemanticPredicateListener(
SemanticPredicateListener l) {
if (
semPredListeners == null)
semPredListeners = new
Vector();
semPredListeners.
addElement(
l);
addDoneListener(
l);
}
public void
addSyntacticPredicateListener(
SyntacticPredicateListener l) {
if (
synPredListeners == null)
synPredListeners = new
Vector();
synPredListeners.
addElement(
l);
addDoneListener(
l);
}
public void
addTraceListener(
TraceListener l) {
if (
traceListeners == null)
traceListeners = new
Vector();
traceListeners.
addElement(
l);
addDoneListener(
l);
}
public void
fireConsume(int
value) {
tokenEvent.
setValues(
ParserTokenEvent.
CONSUME, 1,
value);
fireEvents(
CONSUME,
tokenListeners);
}
public void
fireDoneParsing() {
traceEvent.
setValues(
TraceEvent.
DONE_PARSING, 0,0,0);
Hashtable targets=null;
// Hashtable targets=doneListeners;
ListenerBase l=null;
synchronized (this) {
if (
doneListeners == null) return;
targets = (
Hashtable)
doneListeners.
clone();
}
if (
targets != null) {
Enumeration e =
targets.
keys();
while(
e.
hasMoreElements()) {
l = (
ListenerBase)
e.
nextElement();
fireEvent(
DONE_PARSING,
l);
}
}
if (
controller != null)
controller.
checkBreak();
}
public void
fireEnterRule(int
ruleNum, int
guessing, int
data) {
ruleDepth++;
traceEvent.
setValues(
TraceEvent.
ENTER,
ruleNum,
guessing,
data);
fireEvents(
ENTER_RULE,
traceListeners);
}
public void
fireEvent(int
type,
ListenerBase l) {
switch(
type) {
case
CONSUME: ((
ParserTokenListener)
l).
parserConsume(
tokenEvent); break;
case
LA: ((
ParserTokenListener)
l).
parserLA(
tokenEvent); break;
case
ENTER_RULE: ((
TraceListener)
l).
enterRule(
traceEvent); break;
case
EXIT_RULE: ((
TraceListener)
l).
exitRule(
traceEvent); break;
case
MATCH: ((
ParserMatchListener)
l).
parserMatch(
matchEvent); break;
case
MATCH_NOT: ((
ParserMatchListener)
l).
parserMatchNot(
matchEvent); break;
case
MISMATCH: ((
ParserMatchListener)
l).
parserMismatch(
matchEvent); break;
case
MISMATCH_NOT: ((
ParserMatchListener)
l).
parserMismatchNot(
matchEvent); break;
case
SEMPRED: ((
SemanticPredicateListener)
l).
semanticPredicateEvaluated(
semPredEvent); break;
case
SYNPRED_STARTED: ((
SyntacticPredicateListener)
l).
syntacticPredicateStarted(
synPredEvent); break;
case
SYNPRED_FAILED: ((
SyntacticPredicateListener)
l).
syntacticPredicateFailed(
synPredEvent); break;
case
SYNPRED_SUCCEEDED: ((
SyntacticPredicateListener)
l).
syntacticPredicateSucceeded(
synPredEvent); break;
case
REPORT_ERROR: ((
MessageListener)
l).
reportError(
messageEvent); break;
case
REPORT_WARNING: ((
MessageListener)
l).
reportWarning(
messageEvent); break;
case
DONE_PARSING:
l.
doneParsing(
traceEvent); break;
case
NEW_LINE: ((
NewLineListener)
l).
hitNewLine(
newLineEvent); break;
default:
throw new
IllegalArgumentException("bad type "+
type+" for fireEvent()");
}
}
public void
fireEvents(int
type,
Vector listeners) {
ListenerBase l=null;
if (
listeners != null)
for (int
i = 0;
i <
listeners.
size();
i++) {
l = (
ListenerBase)
listeners.
elementAt(
i);
fireEvent(
type,
l);
}
if (
controller != null)
controller.
checkBreak();
}
public void
fireExitRule(int
ruleNum, int
guessing, int
data) {
traceEvent.
setValues(
TraceEvent.
EXIT,
ruleNum,
guessing,
data);
fireEvents(
EXIT_RULE,
traceListeners);
ruleDepth--;
if (
ruleDepth == 0)
fireDoneParsing();
}
public void
fireLA(int
k, int
la) {
tokenEvent.
setValues(
ParserTokenEvent.
LA,
k,
la);
fireEvents(
LA,
tokenListeners);
}
public void
fireMatch(char
c, int
guessing) {
matchEvent.
setValues(
ParserMatchEvent.
CHAR,
c, new
Character(
c), null,
guessing, false, true);
fireEvents(
MATCH,
matchListeners);
}
public void
fireMatch(char
value,
BitSet b, int
guessing) {
matchEvent.
setValues(
ParserMatchEvent.
CHAR_BITSET,
value,
b, null,
guessing, false, true);
fireEvents(
MATCH,
matchListeners);
}
public void
fireMatch(char
value,
String target, int
guessing) {
matchEvent.
setValues(
ParserMatchEvent.
CHAR_RANGE,
value,
target, null,
guessing, false, true);
fireEvents(
MATCH,
matchListeners);
}
public void
fireMatch(int
value,
BitSet b,
String text, int
guessing) {
matchEvent.
setValues(
ParserMatchEvent.
BITSET,
value,
b,
text,
guessing, false, true);
fireEvents(
MATCH,
matchListeners);
}
public void
fireMatch(int
n,
String text, int
guessing) {
matchEvent.
setValues(
ParserMatchEvent.
TOKEN,
n, new
Integer(
n),
text,
guessing, false, true);
fireEvents(
MATCH,
matchListeners);
}
public void
fireMatch(
String s, int
guessing) {
matchEvent.
setValues(
ParserMatchEvent.
STRING, 0,
s, null,
guessing, false, true);
fireEvents(
MATCH,
matchListeners);
}
public void
fireMatchNot(char
value, char
n, int
guessing) {
matchEvent.
setValues(
ParserMatchEvent.
CHAR,
value, new
Character(
n), null,
guessing, true, true);
fireEvents(
MATCH_NOT,
matchListeners);
}
public void
fireMatchNot(int
value, int
n,
String text, int
guessing) {
matchEvent.
setValues(
ParserMatchEvent.
TOKEN,
value, new
Integer(
n),
text,
guessing, true, true);
fireEvents(
MATCH_NOT,
matchListeners);
}
public void
fireMismatch(char
value, char
n, int
guessing) {
matchEvent.
setValues(
ParserMatchEvent.
CHAR,
value, new
Character(
n), null,
guessing, false, false);
fireEvents(
MISMATCH,
matchListeners);
}
public void
fireMismatch(char
value,
BitSet b, int
guessing) {
matchEvent.
setValues(
ParserMatchEvent.
CHAR_BITSET,
value,
b, null,
guessing, false, true);
fireEvents(
MISMATCH,
matchListeners);
}
public void
fireMismatch(char
value,
String target, int
guessing) {
matchEvent.
setValues(
ParserMatchEvent.
CHAR_RANGE,
value,
target, null,
guessing, false, true);
fireEvents(
MISMATCH,
matchListeners);
}
public void
fireMismatch(int
value, int
n,
String text, int
guessing) {
matchEvent.
setValues(
ParserMatchEvent.
TOKEN,
value, new
Integer(
n),
text,
guessing, false, false);
fireEvents(
MISMATCH,
matchListeners);
}
public void
fireMismatch(int
value,
BitSet b,
String text, int
guessing) {
matchEvent.
setValues(
ParserMatchEvent.
BITSET,
value,
b,
text,
guessing, false, true);
fireEvents(
MISMATCH,
matchListeners);
}
public void
fireMismatch(
String value,
String text, int
guessing) {
matchEvent.
setValues(
ParserMatchEvent.
STRING, 0,
text,
value,
guessing, false, true);
fireEvents(
MISMATCH,
matchListeners);
}
public void
fireMismatchNot(char
value, char
c, int
guessing) {
matchEvent.
setValues(
ParserMatchEvent.
CHAR,
value, new
Character(
c), null,
guessing, true, true);
fireEvents(
MISMATCH_NOT,
matchListeners);
}
public void
fireMismatchNot(int
value, int
n,
String text, int
guessing) {
matchEvent.
setValues(
ParserMatchEvent.
TOKEN,
value, new
Integer(
n),
text,
guessing, true, true);
fireEvents(
MISMATCH_NOT,
matchListeners);
}
public void
fireNewLine(int
line) {
newLineEvent.
setValues(
line);
fireEvents(
NEW_LINE,
newLineListeners);
}
public void
fireReportError(
Exception e) {
messageEvent.
setValues(
MessageEvent.
ERROR,
e.
toString());
fireEvents(
REPORT_ERROR,
messageListeners);
}
public void
fireReportError(
String s) {
messageEvent.
setValues(
MessageEvent.
ERROR,
s);
fireEvents(
REPORT_ERROR,
messageListeners);
}
public void
fireReportWarning(
String s) {
messageEvent.
setValues(
MessageEvent.
WARNING,
s);
fireEvents(
REPORT_WARNING,
messageListeners);
}
public boolean
fireSemanticPredicateEvaluated(int
type, int
condition, boolean
result, int
guessing) {
semPredEvent.
setValues(
type,
condition,
result,
guessing);
fireEvents(
SEMPRED,
semPredListeners);
return
result;
}
public void
fireSyntacticPredicateFailed(int
guessing) {
synPredEvent.
setValues(0,
guessing);
fireEvents(
SYNPRED_FAILED,
synPredListeners);
}
public void
fireSyntacticPredicateStarted(int
guessing) {
synPredEvent.
setValues(0,
guessing);
fireEvents(
SYNPRED_STARTED,
synPredListeners);
}
public void
fireSyntacticPredicateSucceeded(int
guessing) {
synPredEvent.
setValues(0,
guessing);
fireEvents(
SYNPRED_SUCCEEDED,
synPredListeners);
}
protected void
refresh(
Vector listeners) {
Vector v;
synchronized (
listeners) {
v = (
Vector)
listeners.
clone();
}
if (
v != null)
for (int
i = 0;
i <
v.
size();
i++)
((
ListenerBase)
v.
elementAt(
i)).
refresh();
}
public void
refreshListeners() {
refresh(
matchListeners);
refresh(
messageListeners);
refresh(
tokenListeners);
refresh(
traceListeners);
refresh(
semPredListeners);
refresh(
synPredListeners);
}
public void
removeDoneListener(
ListenerBase l) {
if (
doneListeners == null) return;
Integer i = (
Integer)
doneListeners.
get(
l);
int
val=0;
if (
i != null)
val =
i.
intValue() - 1;
if (
val == 0)
doneListeners.
remove(
l);
else
doneListeners.
put(
l, new
Integer(
val));
}
public void
removeMessageListener(
MessageListener l) {
if (
messageListeners != null)
messageListeners.
removeElement(
l);
removeDoneListener(
l);
}
public void
removeNewLineListener(
NewLineListener l) {
if (
newLineListeners != null)
newLineListeners.
removeElement(
l);
removeDoneListener(
l);
}
public void
removeParserListener(
ParserListener l) {
removeParserMatchListener(
l);
removeMessageListener(
l);
removeParserTokenListener(
l);
removeTraceListener(
l);
removeSemanticPredicateListener(
l);
removeSyntacticPredicateListener(
l);
}
public void
removeParserMatchListener(
ParserMatchListener l) {
if (
matchListeners != null)
matchListeners.
removeElement(
l);
removeDoneListener(
l);
}
public void
removeParserTokenListener(
ParserTokenListener l) {
if (
tokenListeners != null)
tokenListeners.
removeElement(
l);
removeDoneListener(
l);
}
public void
removeSemanticPredicateListener(
SemanticPredicateListener l) {
if (
semPredListeners != null)
semPredListeners.
removeElement(
l);
removeDoneListener(
l);
}
public void
removeSyntacticPredicateListener(
SyntacticPredicateListener l) {
if (
synPredListeners != null)
synPredListeners.
removeElement(
l);
removeDoneListener(
l);
}
public void
removeTraceListener(
TraceListener l) {
if (
traceListeners != null)
traceListeners.
removeElement(
l);
removeDoneListener(
l);
}
}