forked from jasder/antlr
replace ctor for single ctx and don't merge wildcards when payloads aren't the same. fixes a unit test.
This commit is contained in:
parent
55ad7bdb2c
commit
ebe633a2cc
|
@ -84,7 +84,7 @@ public class ArrayPredictionContext extends PredictionContext {
|
||||||
@Override
|
@Override
|
||||||
public SingletonPredictionContext next() {
|
public SingletonPredictionContext next() {
|
||||||
SingletonPredictionContext ctx =
|
SingletonPredictionContext ctx =
|
||||||
new SingletonPredictionContext(parents[i], invokingStates[i]);
|
SingletonPredictionContext.create(parents[i], invokingStates[i]);
|
||||||
i++;
|
i++;
|
||||||
return ctx;
|
return ctx;
|
||||||
}
|
}
|
||||||
|
@ -144,8 +144,8 @@ public class ArrayPredictionContext extends PredictionContext {
|
||||||
next = PredictionContext.EMPTY;
|
next = PredictionContext.EMPTY;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
next = new SingletonPredictionContext(this.parents[i],
|
next = SingletonPredictionContext.create(this.parents[i],
|
||||||
this.invokingStates[i]);
|
this.invokingStates[i]);
|
||||||
}
|
}
|
||||||
boolean rootIsWildcard = fullCtx;
|
boolean rootIsWildcard = fullCtx;
|
||||||
newCtx = merge(newCtx, next, rootIsWildcard, mergeCache);
|
newCtx = merge(newCtx, next, rootIsWildcard, mergeCache);
|
||||||
|
|
|
@ -124,7 +124,7 @@ public class LL1Analyzer {
|
||||||
Transition t = s.transition(i);
|
Transition t = s.transition(i);
|
||||||
if ( t.getClass() == RuleTransition.class ) {
|
if ( t.getClass() == RuleTransition.class ) {
|
||||||
PredictionContext newContext =
|
PredictionContext newContext =
|
||||||
new SingletonPredictionContext(ctx, s.stateNumber);
|
SingletonPredictionContext.create(ctx, s.stateNumber);
|
||||||
_LOOK(t.target, newContext, look, lookBusy, seeThruPreds);
|
_LOOK(t.target, newContext, look, lookBusy, seeThruPreds);
|
||||||
}
|
}
|
||||||
else if ( t instanceof PredicateTransition ) {
|
else if ( t instanceof PredicateTransition ) {
|
||||||
|
|
|
@ -667,7 +667,7 @@ public class LexerATNSimulator extends ATNSimulator {
|
||||||
switch (t.getSerializationType()) {
|
switch (t.getSerializationType()) {
|
||||||
case Transition.RULE:
|
case Transition.RULE:
|
||||||
PredictionContext newContext =
|
PredictionContext newContext =
|
||||||
new SingletonPredictionContext(config.context, p.stateNumber);
|
SingletonPredictionContext.create(config.context, p.stateNumber);
|
||||||
c = new LexerATNConfig(config, t.target, newContext);
|
c = new LexerATNConfig(config, t.target, newContext);
|
||||||
break;
|
break;
|
||||||
case Transition.PREDICATE:
|
case Transition.PREDICATE:
|
||||||
|
|
|
@ -1115,7 +1115,7 @@ public class ParserATNSimulator extends ATNSimulator {
|
||||||
config.state.getClass()==PlusLoopbackState.class )
|
config.state.getClass()==PlusLoopbackState.class )
|
||||||
{
|
{
|
||||||
config.context =
|
config.context =
|
||||||
new SingletonPredictionContext(config.context, config.state.stateNumber);
|
SingletonPredictionContext.create(config.context, config.state.stateNumber);
|
||||||
// alter config; it's ok, since all calls to closure pass in a fresh config for us to chase
|
// alter config; it's ok, since all calls to closure pass in a fresh config for us to chase
|
||||||
if ( debug ) System.out.println("Loop back; push "+config.state.stateNumber+", stack="+config.context);
|
if ( debug ) System.out.println("Loop back; push "+config.state.stateNumber+", stack="+config.context);
|
||||||
}
|
}
|
||||||
|
@ -1286,7 +1286,7 @@ public class ParserATNSimulator extends ATNSimulator {
|
||||||
", ctx="+config.context);
|
", ctx="+config.context);
|
||||||
}
|
}
|
||||||
PredictionContext newContext =
|
PredictionContext newContext =
|
||||||
new SingletonPredictionContext(config.context, config.state.stateNumber);
|
SingletonPredictionContext.create(config.context, config.state.stateNumber);
|
||||||
return new ATNConfig(config, t.target, newContext);
|
return new ATNConfig(config, t.target, newContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -53,7 +53,7 @@ public abstract class PredictionContext implements Iterable<SingletonPredictionC
|
||||||
parent = PredictionContext.fromRuleContext(outerContext.parent);
|
parent = PredictionContext.fromRuleContext(outerContext.parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new SingletonPredictionContext(parent, outerContext.invokingState);
|
return SingletonPredictionContext.create(parent, outerContext.invokingState);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -123,7 +123,8 @@ public abstract class PredictionContext implements Iterable<SingletonPredictionC
|
||||||
boolean rootIsWildcard,
|
boolean rootIsWildcard,
|
||||||
DoubleKeyMap<PredictionContext,PredictionContext,PredictionContext> mergeCache)
|
DoubleKeyMap<PredictionContext,PredictionContext,PredictionContext> mergeCache)
|
||||||
{
|
{
|
||||||
if ( (a==null&&b==null) || a==b || a.equals(b) ) return a; // share same graph if both same
|
// share same graph if both same
|
||||||
|
if ( (a==null&&b==null) || a==b || (a!=null&&a.equals(b)) ) return a;
|
||||||
|
|
||||||
if ( a instanceof SingletonPredictionContext && b instanceof SingletonPredictionContext) {
|
if ( a instanceof SingletonPredictionContext && b instanceof SingletonPredictionContext) {
|
||||||
return mergeSingletons((SingletonPredictionContext)a,
|
return mergeSingletons((SingletonPredictionContext)a,
|
||||||
|
@ -178,17 +179,13 @@ public abstract class PredictionContext implements Iterable<SingletonPredictionC
|
||||||
// merge parents x and y, giving array node with x,y then remainders
|
// merge parents x and y, giving array node with x,y then remainders
|
||||||
// of those graphs. dup a, a' points at merged array
|
// of those graphs. dup a, a' points at merged array
|
||||||
// new joined parent so create new singleton pointing to it, a'
|
// new joined parent so create new singleton pointing to it, a'
|
||||||
PredictionContext a_ = new SingletonPredictionContext(parent, a.invokingState);
|
PredictionContext a_ = SingletonPredictionContext.create(parent, a.invokingState);
|
||||||
if ( mergeCache!=null ) mergeCache.put(a, b, a_);
|
if ( mergeCache!=null ) mergeCache.put(a, b, a_);
|
||||||
return a_;
|
return a_;
|
||||||
}
|
}
|
||||||
else { // a != b payloads differ
|
else { // a != b payloads differ
|
||||||
// see if we can collapse parents due to $+x parents if local ctx
|
// see if we can collapse parents due to $+x parents if local ctx
|
||||||
PredictionContext singleParent = null;
|
PredictionContext singleParent = null;
|
||||||
if ( rootIsWildcard ) {
|
|
||||||
if ( a.parent == EMPTY ) singleParent = EMPTY; // $ + b = $
|
|
||||||
if ( b.parent == EMPTY ) singleParent = EMPTY; // a + $ = $
|
|
||||||
}
|
|
||||||
if ( a==b || (a.parent!=null && 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;
|
||||||
}
|
}
|
||||||
|
@ -338,8 +335,9 @@ public abstract class PredictionContext implements Iterable<SingletonPredictionC
|
||||||
if ( p < lastSlot ) {
|
if ( p < lastSlot ) {
|
||||||
int n = p+1; // how many slots we really used in merge
|
int n = p+1; // how many slots we really used in merge
|
||||||
if ( n == 1 ) { // for just one merged element, return singleton top
|
if ( n == 1 ) { // for just one merged element, return singleton top
|
||||||
PredictionContext a_ = new SingletonPredictionContext(mergedParents[0],
|
PredictionContext a_ =
|
||||||
mergedInvokingStates[0]);
|
SingletonPredictionContext.create(mergedParents[0],
|
||||||
|
mergedInvokingStates[0]);
|
||||||
if ( mergeCache!=null ) mergeCache.put(a,b,a_);
|
if ( mergeCache!=null ) mergeCache.put(a,b,a_);
|
||||||
return a_;
|
return a_;
|
||||||
}
|
}
|
||||||
|
@ -490,7 +488,7 @@ public abstract class PredictionContext implements Iterable<SingletonPredictionC
|
||||||
updated = EMPTY;
|
updated = EMPTY;
|
||||||
}
|
}
|
||||||
else if (parents.length == 1) {
|
else if (parents.length == 1) {
|
||||||
updated = new SingletonPredictionContext(parents[0], context.getInvokingState(0));
|
updated = SingletonPredictionContext.create(parents[0], context.getInvokingState(0));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ArrayPredictionContext arrayPredictionContext = (ArrayPredictionContext)context;
|
ArrayPredictionContext arrayPredictionContext = (ArrayPredictionContext)context;
|
||||||
|
|
|
@ -8,7 +8,7 @@ public class SingletonPredictionContext extends PredictionContext {
|
||||||
public final PredictionContext parent;
|
public final PredictionContext parent;
|
||||||
public final int invokingState;
|
public final int invokingState;
|
||||||
|
|
||||||
public SingletonPredictionContext(PredictionContext parent, int invokingState) {
|
SingletonPredictionContext(PredictionContext parent, int invokingState) {
|
||||||
super(calculateHashCode(parent!=null ? 31 ^ parent.hashCode() : 1,
|
super(calculateHashCode(parent!=null ? 31 ^ parent.hashCode() : 1,
|
||||||
31 ^ invokingState));
|
31 ^ invokingState));
|
||||||
assert invokingState!=EMPTY_FULL_CTX_INVOKING_STATE &&
|
assert invokingState!=EMPTY_FULL_CTX_INVOKING_STATE &&
|
||||||
|
@ -17,6 +17,14 @@ public class SingletonPredictionContext extends PredictionContext {
|
||||||
this.invokingState = invokingState;
|
this.invokingState = invokingState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static SingletonPredictionContext create(PredictionContext parent, int invokingState) {
|
||||||
|
if ( invokingState == EMPTY_FULL_CTX_INVOKING_STATE && parent == null ) {
|
||||||
|
// someone can pass in the bits of an array ctx that mean $
|
||||||
|
return EMPTY;
|
||||||
|
}
|
||||||
|
return new SingletonPredictionContext(parent, invokingState);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Iterator<SingletonPredictionContext> iterator() {
|
public Iterator<SingletonPredictionContext> iterator() {
|
||||||
final SingletonPredictionContext self = this;
|
final SingletonPredictionContext self = this;
|
||||||
|
|
|
@ -2,7 +2,6 @@ package org.antlr.v4.test;
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
import org.antlr.v4.runtime.atn.ArrayPredictionContext;
|
import org.antlr.v4.runtime.atn.ArrayPredictionContext;
|
||||||
import org.antlr.v4.runtime.atn.EmptyPredictionContext;
|
|
||||||
import org.antlr.v4.runtime.atn.PredictionContext;
|
import org.antlr.v4.runtime.atn.PredictionContext;
|
||||||
import org.antlr.v4.runtime.atn.PredictionContextCache;
|
import org.antlr.v4.runtime.atn.PredictionContextCache;
|
||||||
import org.antlr.v4.runtime.atn.SingletonPredictionContext;
|
import org.antlr.v4.runtime.atn.SingletonPredictionContext;
|
||||||
|
@ -763,7 +762,7 @@ public class TestGraphNodes extends TestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
public SingletonPredictionContext createSingleton(PredictionContext parent, int payload) {
|
public SingletonPredictionContext createSingleton(PredictionContext parent, int payload) {
|
||||||
SingletonPredictionContext a = new SingletonPredictionContext(parent, payload);
|
SingletonPredictionContext a = SingletonPredictionContext.create(parent, payload);
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -820,7 +819,7 @@ public class TestGraphNodes extends TestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < current.size(); i++) {
|
for (int i = 0; i < current.size(); i++) {
|
||||||
if (current.getInvokingState(i) == EmptyPredictionContext.EMPTY_INVOKING_STATE) {
|
if (current.getInvokingState(i) == PredictionContext.EMPTY_FULL_CTX_INVOKING_STATE) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue