refactor to create DFAState target, fill it in, then add to DFA only after it's complete. Combine some helper methods. simpler.

This commit is contained in:
Terence Parr 2012-07-31 18:26:39 -07:00
parent fedb7c105b
commit b8f7acdeac
1 changed files with 63 additions and 62 deletions

View File

@ -250,7 +250,7 @@ public class ParserATNSimulator<Symbol extends Token> extends ATNSimulator {
ParserRuleContext.EMPTY,
greedy, loopsSimulateTailRecursion,
fullCtx);
dfa.s0 = addDFAState(dfa, s0_closure);
dfa.s0 = addDFAState(dfa, new DFAState(s0_closure));
int alt = 0;
int m = input.mark();
@ -477,7 +477,6 @@ public class ParserATNSimulator<Symbol extends Token> extends ATNSimulator {
ATNConfigSet previous = s0.configs;
DFAState previousD = s0;
DFAState D;
ATNConfigSet fullCtxSet;
if ( debug ) System.out.println("s0 = "+s0);
@ -506,23 +505,16 @@ public class ParserATNSimulator<Symbol extends Token> extends ATNSimulator {
// will get error no matter what.
throw noViableAlt(input, outerContext, previous, startIndex);
}
DFAState D2 = new DFAState(reach);
// if ( dfa.states.get(previousD)==null ) { always ok it seems; previousD always exists
// System.err.println("-----------------------------------------");
// }
D = addDFAEdge(dfa, previous, t, reach); // always adding edge even if to a conflict state
// create new target state; we'll add to DFA after it's complete
DFAState D = new DFAState(reach);
int predictedAlt = getUniqueAlt(reach);
if ( predictedAlt!=ATN.INVALID_ALT_NUMBER ) {
D.isAcceptState = true;
D.configs.uniqueAlt = predictedAlt;
D.prediction = predictedAlt;
D2.isAcceptState = true;
D2.configs.uniqueAlt = predictedAlt;
D2.prediction = predictedAlt;
}
else {
D.configs.conflictingAlts = getConflictingAlts(reach);
D2.configs.conflictingAlts = D.configs.conflictingAlts;
if ( D.configs.conflictingAlts!=null ) {
if ( greedy ) {
// int k = input.index() - startIndex + 1; // how much input we used
@ -536,9 +528,7 @@ public class ParserATNSimulator<Symbol extends Token> extends ATNSimulator {
D.configs.conflictingAlts, D.configs);
}
D.isAcceptState = true;
D2.isAcceptState = true;
D.prediction = D.configs.conflictingAlts.getMinElement();
D2.prediction = D2.configs.conflictingAlts.getMinElement();
if ( debug ) System.out.println("RESOLVED TO "+D.prediction+" for "+D);
predictedAlt = D.prediction;
}
@ -565,11 +555,7 @@ public class ParserATNSimulator<Symbol extends Token> extends ATNSimulator {
D.prediction = predictedAlt = fullCtxSet.uniqueAlt; // TODO: why set prediction?
D.prediction = ATN.INVALID_ALT_NUMBER;
D.contextToPredictedAlt.put(predictionCtx, predictedAlt);
D2.isCtxSensitive = true; // always force DFA to ATN simulate
D2.prediction = predictedAlt = fullCtxSet.uniqueAlt; // TODO: why set prediction?
D2.prediction = ATN.INVALID_ALT_NUMBER;
D2.contextToPredictedAlt.put(predictionCtx, predictedAlt);
//addDFAEdge(dfa, previous, t, reach);
addDFAEdge(dfa, previousD, t, D);
return predictedAlt; // all done with preds, etc...
}
}
@ -578,10 +564,9 @@ public class ParserATNSimulator<Symbol extends Token> extends ATNSimulator {
// this handles case where we find ambiguity that stops DFA construction
// before a config hits rule stop state. Was leaving prediction blank.
int exitAlt = 2;
D.isAcceptState = true; // when ambig or ctx sens or nongreedy or .* loop hitting rule stop
// when ambig or ctx sens or nongreedy or .* loop hitting rule stop
D.isAcceptState = true;
D.prediction = predictedAlt = exitAlt;
D2.isAcceptState = true; // when ambig or ctx sens or nongreedy or .* loop hitting rule stop
D2.prediction = predictedAlt = exitAlt;
}
}
}
@ -593,16 +578,12 @@ public class ParserATNSimulator<Symbol extends Token> extends ATNSimulator {
// reaches end via .* means nothing after.
D.isAcceptState = true;
D.prediction = predictedAlt = exitAlt;
D2.isAcceptState = true;
D2.prediction = predictedAlt = exitAlt;
}
else {// if we reached end of rule via exit branch and decision nongreedy, we matched
if ( configWithAltAtStopState(reach, exitAlt) ) {
if ( debug ) System.out.println("nongreedy at stop state for exit branch");
D.isAcceptState = true;
D.prediction = predictedAlt = exitAlt;
D2.isAcceptState = true;
D2.prediction = predictedAlt = exitAlt;
}
}
}
@ -615,14 +596,13 @@ public class ParserATNSimulator<Symbol extends Token> extends ATNSimulator {
List<DFAState.PredPrediction> predPredictions =
predicateDFAState(D, D.configs, outerContext, nalts);
// TODO: get rid of side-effects? sets predicted 2x
predicateDFAState(D2, D2.configs, outerContext, nalts); // alters D
predicateDFAState(D, D.configs, outerContext, nalts); // alters D
if ( predPredictions!=null ) {
int stopIndex = input.index();
input.seek(startIndex);
IntervalSet alts = evalSemanticContext(predPredictions, outerContext, true);
D.prediction = ATN.INVALID_ALT_NUMBER; // indicate we have preds
D2.prediction = ATN.INVALID_ALT_NUMBER;
//addDFAEdge(dfa, previous, t, reach);
addDFAEdge(dfa, previousD, t, D);
switch (alts.size()) {
case 0:
throw noViableAlt(input, outerContext, D.configs, startIndex);
@ -634,13 +614,12 @@ public class ParserATNSimulator<Symbol extends Token> extends ATNSimulator {
// report ambiguity after predicate evaluation to make sure the correct
// set of ambig alts is reported.
reportAmbiguity(dfa, D, startIndex, stopIndex, alts, D.configs);
return alts.getMinElement();
}
}
}
//addDFAEdge(dfa, previous, t, reach);
addDFAEdge(dfa, previousD, t, D);
if ( D.isAcceptState ) return predictedAlt;
previous = reach;
@ -1470,46 +1449,68 @@ public class ParserATNSimulator<Symbol extends Token> extends ATNSimulator {
return false;
}
@NotNull
protected DFAState addDFAEdge(@NotNull DFA dfa,
@NotNull ATNConfigSet p,
int t,
@NotNull ATNConfigSet q)
// @NotNull
// protected DFAState addDFAEdge(@NotNull DFA dfa,
// @NotNull DFAState from,
// @NotNull ATNConfigSet p,
// int t,
// @NotNull ATNConfigSet q,
// @NotNull DFAState to)
// {
// // TODO: how can from ever be new? oh, the first time into execATN;
// // wait: shouldn't that be s0
//// DFAState from = addDFAState(dfa, p);
//// DFAState to = addDFAState(dfa, q);
// if ( debug ) System.out.println("EDGE "+from+" -> "+to+" upon "+getTokenName(t));
//// addDFAEdge(from, t, to);
// if ( debug ) System.out.println("DFA=\n"+dfa.toString(parser!=null?parser.getTokenNames():null));
// return to;
// }
protected void addDFAEdge(@NotNull DFA dfa,
@Nullable DFAState from,
int t,
@Nullable DFAState to)
{
// TODO: how can from ever be new? oh, the first time into execATN;
// wait: shouldn't that be s0
DFAState from = addDFAState(dfa, p);
DFAState to = addDFAState(dfa, q);
if ( debug ) System.out.println("EDGE "+from+" -> "+to+" upon "+getTokenName(t));
addDFAEdge(from, t, to);
if ( from==null || t < -1 || to == null ) return;
to = addDFAState(dfa, to);
if ( from.edges==null ) {
from.edges = new DFAState[atn.maxTokenType+1+1]; // TODO: make adaptive
}
from.edges[t+1] = to; // connect
if ( debug ) System.out.println("DFA=\n"+dfa.toString(parser!=null?parser.getTokenNames():null));
return to;
}
protected void addDFAEdge(@Nullable DFAState p, int t, @Nullable DFAState q) {
if ( p==null || t < -1 || q == null ) return;
if ( p.edges==null ) {
p.edges = new DFAState[atn.maxTokenType+1+1]; // TODO: make adaptive
}
p.edges[t+1] = q; // connect
/** Add D if not there and return D. Return previous if already present. */
protected DFAState addDFAState(@NotNull DFA dfa, @NotNull DFAState D) {
DFAState existing = dfa.states.get(D);
if ( existing!=null ) return existing;
D.stateNumber = dfa.states.size();
D.configs.optimizeConfigs(this);
D.configs.setReadonly(true);
dfa.states.put(D, D);
if ( debug ) System.out.println("adding new DFA state: "+D);
return D;
}
/** See comment on LexerInterpreter.addDFAState. */
@NotNull
protected DFAState addDFAState(@NotNull DFA dfa, @NotNull ATNConfigSet configs) {
DFAState proposed = new DFAState(configs);
DFAState existing = dfa.states.get(proposed);
if ( existing!=null ) return existing;
DFAState newState = proposed;
newState.stateNumber = dfa.states.size();
configs.optimizeConfigs(this);
configs.setReadonly(true);
newState.configs = configs;
dfa.states.put(newState, newState);
if ( debug ) System.out.println("adding new DFA state: "+newState);
return newState;
}
// @NotNull
// protected DFAState addDFAState(@NotNull DFA dfa, @NotNull ATNConfigSet configs) {
// DFAState proposed = new DFAState(configs);
// DFAState existing = dfa.states.get(proposed);
// if ( existing!=null ) return existing;
//
// DFAState newState = proposed;
// newState.stateNumber = dfa.states.size();
// configs.optimizeConfigs(this);
// configs.setReadonly(true);
// newState.configs = configs;
// dfa.states.put(newState, newState);
// if ( debug ) System.out.println("adding new DFA state: "+newState);
// return newState;
// }
public void reportAttemptingFullContext(DFA dfa, ATNConfigSet configs, int startIndex, int stopIndex) {
if ( debug || retry_debug ) {