forked from jasder/antlr
Make sure to consider context for the SLL precedence filter (fixes #509)
This commit is contained in:
parent
cb0119e761
commit
10558a7bea
|
@ -51,8 +51,10 @@ import java.util.ArrayList;
|
|||
import java.util.Arrays;
|
||||
import java.util.BitSet;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
|
@ -987,7 +989,8 @@ public class ParserATNSimulator extends ATNSimulator {
|
|||
* {@link SemanticContext#evalPrecedence}.</li>
|
||||
* <li>Remove all configurations which predict an alternative greater than
|
||||
* 1, for which another configuration that predicts alternative 1 is in the
|
||||
* same ATN state. This transformation is valid for the following reasons:
|
||||
* same ATN state with the same prediction context. This transformation is
|
||||
* valid for the following reasons:
|
||||
* <ul>
|
||||
* <li>The closure block cannot contain any epsilon transitions which bypass
|
||||
* the body of the closure, so all states reachable via alternative 1 are
|
||||
|
@ -1002,6 +1005,28 @@ public class ParserATNSimulator extends ATNSimulator {
|
|||
* </li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>
|
||||
* The prediction context must be considered by this filter to address
|
||||
* situations like the following.
|
||||
* </p>
|
||||
* <code>
|
||||
* <pre>
|
||||
* grammar TA;
|
||||
* prog: statement* EOF;
|
||||
* statement: letterA | statement letterA 'b' ;
|
||||
* letterA: 'a';
|
||||
* </pre>
|
||||
* </code>
|
||||
* <p>
|
||||
* If the above grammar, the ATN state immediately before the token
|
||||
* reference {@code 'a'} in {@code letterA} is reachable from the left edge
|
||||
* of both the primary and closure blocks of the left-recursive rule
|
||||
* {@code statement}. The prediction context associated with each of these
|
||||
* configurations distinguishes between them, and prevents the alternative
|
||||
* which stepped out to {@code prog} (and then back in to {@code statement}
|
||||
* from being eliminated by the filter.
|
||||
* </p>
|
||||
*
|
||||
* @param configs The configuration set computed by
|
||||
* {@link #computeStartState} as the start state for the DFA.
|
||||
* @return The transformed configuration set representing the start state
|
||||
|
@ -1010,7 +1035,7 @@ public class ParserATNSimulator extends ATNSimulator {
|
|||
*/
|
||||
@NotNull
|
||||
protected ATNConfigSet applyPrecedenceFilter(@NotNull ATNConfigSet configs) {
|
||||
Set<Integer> statesFromAlt1 = new HashSet<Integer>();
|
||||
Map<Integer, PredictionContext> statesFromAlt1 = new HashMap<Integer, PredictionContext>();
|
||||
ATNConfigSet configSet = new ATNConfigSet(configs.fullCtx);
|
||||
for (ATNConfig config : configs) {
|
||||
// handle alt 1 first
|
||||
|
@ -1024,7 +1049,7 @@ public class ParserATNSimulator extends ATNSimulator {
|
|||
continue;
|
||||
}
|
||||
|
||||
statesFromAlt1.add(config.state.stateNumber);
|
||||
statesFromAlt1.put(config.state.stateNumber, config.context);
|
||||
if (updatedContext != config.semanticContext) {
|
||||
configSet.add(new ATNConfig(config, updatedContext), mergeCache);
|
||||
}
|
||||
|
@ -1039,7 +1064,8 @@ public class ParserATNSimulator extends ATNSimulator {
|
|||
continue;
|
||||
}
|
||||
|
||||
if (statesFromAlt1.contains(config.state.stateNumber)) {
|
||||
PredictionContext context = statesFromAlt1.get(config.state.stateNumber);
|
||||
if (context != null && context.equals(config.context)) {
|
||||
// eliminated
|
||||
continue;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue