forked from jasder/antlr
got wildcard working properly with recursion now!!! new unit test.
This commit is contained in:
parent
4d8158c6f3
commit
c8a51ccfad
|
@ -5,15 +5,24 @@ import org.antlr.v4.runtime.misc.Nullable;
|
|||
|
||||
public class LexerATNConfig extends ATNConfig {
|
||||
/** Capture lexer action we traverse */
|
||||
public int lexerActionIndex = -1; // TOOD: move to subclass
|
||||
public int lexerActionIndex = -1;
|
||||
|
||||
public LexerATNConfig(@NotNull ATNState state,
|
||||
int alt,
|
||||
@Nullable PredictionContext context)
|
||||
int alt,
|
||||
@Nullable PredictionContext context)
|
||||
{
|
||||
super(state, alt, context, SemanticContext.NONE);
|
||||
}
|
||||
|
||||
public LexerATNConfig(@NotNull ATNState state,
|
||||
int alt,
|
||||
@Nullable PredictionContext context,
|
||||
int actionIndex)
|
||||
{
|
||||
super(state, alt, context, SemanticContext.NONE);
|
||||
this.lexerActionIndex = actionIndex;
|
||||
}
|
||||
|
||||
public LexerATNConfig(@NotNull LexerATNConfig c, @NotNull ATNState state) {
|
||||
super(c, state, c.context, c.semanticContext);
|
||||
this.lexerActionIndex = c.lexerActionIndex;
|
||||
|
|
|
@ -534,7 +534,7 @@ public class LexerATNSimulator extends ATNSimulator {
|
|||
* [..., (2,1,[$]), ..., (7,1,[[$, 6 $]])]
|
||||
*
|
||||
* That means wacking (7,1,[$]) but not (7,1,[6 $]). If incoming config
|
||||
* has multiple stacks, must look for each one in other configs. :(
|
||||
* has multiple stacks, must look for each one in other configs.
|
||||
*
|
||||
* Closure is unmodified; copy returned.
|
||||
*/
|
||||
|
@ -550,39 +550,40 @@ public class LexerATNSimulator extends ATNSimulator {
|
|||
// collect ctxs from incoming config; must wack all of those.
|
||||
Set<SingletonPredictionContext> contextsToKill =
|
||||
new HashSet<SingletonPredictionContext>();
|
||||
if ( config.context!=null && !config.context.isEmpty() ) {
|
||||
for (SingletonPredictionContext ctx : config.context) {
|
||||
contextsToKill.add(ctx);
|
||||
}
|
||||
for (SingletonPredictionContext ctx : config.context) {
|
||||
contextsToKill.add(ctx);
|
||||
}
|
||||
|
||||
ATNConfigSet dup = new ATNConfigSet(closure);
|
||||
ATNConfigSet dup = new ATNConfigSet(); // build up as we go thru loop
|
||||
for (int j=0; j<=ci; j++) dup.add(closure.get(j)); // add stuff up to ci
|
||||
int j=ci+1;
|
||||
while ( j < dup.size() ) {
|
||||
ATNConfig c = dup.get(j);
|
||||
while ( j < closure.size() ) {
|
||||
LexerATNConfig c = (LexerATNConfig)closure.get(j);
|
||||
boolean isWildcard = c.state.getClass() == ATNState.class && // plain state only, not rulestop etc..
|
||||
c.state.transition(0) instanceof WildcardTransition;
|
||||
boolean killed = false;
|
||||
c.state.transition(0) instanceof WildcardTransition;
|
||||
if ( c.alt == alt && isWildcard ) {
|
||||
// found config to kill but must check stack.
|
||||
// found config to kill but only if same stack.
|
||||
// find c stacks that are in contextsToKill
|
||||
if ( c.context!=null && !c.context.isEmpty() ) {
|
||||
for (SingletonPredictionContext ctx : c.context) {
|
||||
if ( !ctx.isEmpty() ) {
|
||||
if ( contextsToKill.contains(ctx) ) {
|
||||
// c.alt, c.ctx matches and j > ci => kill it
|
||||
if ( debug ) {
|
||||
System.out.format("delete config %s since alt %d and %d leads to wildcard\n",
|
||||
c, c.alt, c.state.stateNumber);
|
||||
}
|
||||
dup.remove(j);
|
||||
killed = true;
|
||||
}
|
||||
for (SingletonPredictionContext ctx : c.context) {
|
||||
if ( contextsToKill.contains(ctx) ) {
|
||||
// c.alt, c.ctx matches and j > ci => kill it
|
||||
if ( debug ) {
|
||||
System.out.format("delete config %s since alt %d and %d leads to wildcard\n",
|
||||
c, c.alt, c.state.stateNumber);
|
||||
}
|
||||
// don't add
|
||||
}
|
||||
else {
|
||||
LexerATNConfig splitConfig =
|
||||
new LexerATNConfig(c.state, c.alt, ctx, c.lexerActionIndex);
|
||||
dup.add(splitConfig);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( !killed ) j++;
|
||||
else {
|
||||
dup.add(c); // add entire config
|
||||
}
|
||||
j++;
|
||||
}
|
||||
return dup;
|
||||
}
|
||||
|
|
|
@ -189,7 +189,7 @@ public abstract class PredictionContext implements Iterable<SingletonPredictionC
|
|||
if ( a.parent == EMPTY ) singleParent = EMPTY; // $ + b = $
|
||||
if ( b.parent == EMPTY ) singleParent = EMPTY; // a + $ = $
|
||||
}
|
||||
if ( a==b || a.parent.equals(b.parent) ) { // ax + bx = [a,b]x
|
||||
if ( a==b || (a.parent!=null && a.parent.equals(b.parent)) ) { // ax + bx = [a,b]x
|
||||
singleParent = a.parent;
|
||||
}
|
||||
if ( singleParent!=null ) { // parents are same
|
||||
|
|
|
@ -148,6 +148,15 @@ public class TestATNLexerInterpreter extends BaseTest {
|
|||
checkLexerMatches(lg, "/* ick */\n/* /*nested*/ */", expecting);
|
||||
}
|
||||
|
||||
@Test public void testRecursiveLexerRuleRefWithWildcard() throws Exception {
|
||||
LexerGrammar lg = new LexerGrammar(
|
||||
"lexer grammar L;\n"+
|
||||
"CMT : '/*' (CMT | .)+ '*/' ;\n" +
|
||||
"WS : (' '|'\n')+ ;");
|
||||
String expecting = "CMT, WS, CMT, EOF";
|
||||
checkLexerMatches(lg, "/* ick */\n/* /*nested*/ */", expecting);
|
||||
}
|
||||
|
||||
@Test public void testLexerWildcardNonGreedyLoopByDefault() throws Exception {
|
||||
LexerGrammar lg = new LexerGrammar(
|
||||
"lexer grammar L;\n"+
|
||||
|
|
Loading…
Reference in New Issue