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 {
|
public class LexerATNConfig extends ATNConfig {
|
||||||
/** Capture lexer action we traverse */
|
/** Capture lexer action we traverse */
|
||||||
public int lexerActionIndex = -1; // TOOD: move to subclass
|
public int lexerActionIndex = -1;
|
||||||
|
|
||||||
public LexerATNConfig(@NotNull ATNState state,
|
public LexerATNConfig(@NotNull ATNState state,
|
||||||
int alt,
|
int alt,
|
||||||
@Nullable PredictionContext context)
|
@Nullable PredictionContext context)
|
||||||
{
|
{
|
||||||
super(state, alt, context, SemanticContext.NONE);
|
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) {
|
public LexerATNConfig(@NotNull LexerATNConfig c, @NotNull ATNState state) {
|
||||||
super(c, state, c.context, c.semanticContext);
|
super(c, state, c.context, c.semanticContext);
|
||||||
this.lexerActionIndex = c.lexerActionIndex;
|
this.lexerActionIndex = c.lexerActionIndex;
|
||||||
|
|
|
@ -534,7 +534,7 @@ public class LexerATNSimulator extends ATNSimulator {
|
||||||
* [..., (2,1,[$]), ..., (7,1,[[$, 6 $]])]
|
* [..., (2,1,[$]), ..., (7,1,[[$, 6 $]])]
|
||||||
*
|
*
|
||||||
* That means wacking (7,1,[$]) but not (7,1,[6 $]). If incoming config
|
* 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.
|
* Closure is unmodified; copy returned.
|
||||||
*/
|
*/
|
||||||
|
@ -550,39 +550,40 @@ public class LexerATNSimulator extends ATNSimulator {
|
||||||
// collect ctxs from incoming config; must wack all of those.
|
// collect ctxs from incoming config; must wack all of those.
|
||||||
Set<SingletonPredictionContext> contextsToKill =
|
Set<SingletonPredictionContext> contextsToKill =
|
||||||
new HashSet<SingletonPredictionContext>();
|
new HashSet<SingletonPredictionContext>();
|
||||||
if ( config.context!=null && !config.context.isEmpty() ) {
|
for (SingletonPredictionContext ctx : config.context) {
|
||||||
for (SingletonPredictionContext ctx : config.context) {
|
contextsToKill.add(ctx);
|
||||||
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;
|
int j=ci+1;
|
||||||
while ( j < dup.size() ) {
|
while ( j < closure.size() ) {
|
||||||
ATNConfig c = dup.get(j);
|
LexerATNConfig c = (LexerATNConfig)closure.get(j);
|
||||||
boolean isWildcard = c.state.getClass() == ATNState.class && // plain state only, not rulestop etc..
|
boolean isWildcard = c.state.getClass() == ATNState.class && // plain state only, not rulestop etc..
|
||||||
c.state.transition(0) instanceof WildcardTransition;
|
c.state.transition(0) instanceof WildcardTransition;
|
||||||
boolean killed = false;
|
|
||||||
if ( c.alt == alt && isWildcard ) {
|
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
|
// find c stacks that are in contextsToKill
|
||||||
if ( c.context!=null && !c.context.isEmpty() ) {
|
for (SingletonPredictionContext ctx : c.context) {
|
||||||
for (SingletonPredictionContext ctx : c.context) {
|
if ( contextsToKill.contains(ctx) ) {
|
||||||
if ( !ctx.isEmpty() ) {
|
// c.alt, c.ctx matches and j > ci => kill it
|
||||||
if ( contextsToKill.contains(ctx) ) {
|
if ( debug ) {
|
||||||
// c.alt, c.ctx matches and j > ci => kill it
|
System.out.format("delete config %s since alt %d and %d leads to wildcard\n",
|
||||||
if ( debug ) {
|
c, c.alt, c.state.stateNumber);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
// 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;
|
return dup;
|
||||||
}
|
}
|
||||||
|
|
|
@ -189,7 +189,7 @@ public abstract class PredictionContext implements Iterable<SingletonPredictionC
|
||||||
if ( a.parent == EMPTY ) singleParent = EMPTY; // $ + b = $
|
if ( a.parent == EMPTY ) singleParent = EMPTY; // $ + b = $
|
||||||
if ( b.parent == EMPTY ) singleParent = EMPTY; // a + $ = $
|
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;
|
singleParent = a.parent;
|
||||||
}
|
}
|
||||||
if ( singleParent!=null ) { // parents are same
|
if ( singleParent!=null ) { // parents are same
|
||||||
|
|
|
@ -148,6 +148,15 @@ public class TestATNLexerInterpreter extends BaseTest {
|
||||||
checkLexerMatches(lg, "/* ick */\n/* /*nested*/ */", expecting);
|
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 {
|
@Test public void testLexerWildcardNonGreedyLoopByDefault() throws Exception {
|
||||||
LexerGrammar lg = new LexerGrammar(
|
LexerGrammar lg = new LexerGrammar(
|
||||||
"lexer grammar L;\n"+
|
"lexer grammar L;\n"+
|
||||||
|
|
Loading…
Reference in New Issue