got wildcard working properly with recursion now!!! new unit test.

This commit is contained in:
Terence Parr 2012-09-27 12:22:16 -07:00
parent 4d8158c6f3
commit c8a51ccfad
4 changed files with 47 additions and 28 deletions

View File

@ -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;

View File

@ -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;
}

View File

@ -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

View File

@ -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"+