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:
Terence Parr 2012-10-08 15:26:56 -07:00
parent 55ad7bdb2c
commit ebe633a2cc
7 changed files with 26 additions and 21 deletions

View File

@ -84,7 +84,7 @@ public class ArrayPredictionContext extends PredictionContext {
@Override
public SingletonPredictionContext next() {
SingletonPredictionContext ctx =
new SingletonPredictionContext(parents[i], invokingStates[i]);
SingletonPredictionContext.create(parents[i], invokingStates[i]);
i++;
return ctx;
}
@ -144,8 +144,8 @@ public class ArrayPredictionContext extends PredictionContext {
next = PredictionContext.EMPTY;
}
else {
next = new SingletonPredictionContext(this.parents[i],
this.invokingStates[i]);
next = SingletonPredictionContext.create(this.parents[i],
this.invokingStates[i]);
}
boolean rootIsWildcard = fullCtx;
newCtx = merge(newCtx, next, rootIsWildcard, mergeCache);

View File

@ -124,7 +124,7 @@ public class LL1Analyzer {
Transition t = s.transition(i);
if ( t.getClass() == RuleTransition.class ) {
PredictionContext newContext =
new SingletonPredictionContext(ctx, s.stateNumber);
SingletonPredictionContext.create(ctx, s.stateNumber);
_LOOK(t.target, newContext, look, lookBusy, seeThruPreds);
}
else if ( t instanceof PredicateTransition ) {

View File

@ -667,7 +667,7 @@ public class LexerATNSimulator extends ATNSimulator {
switch (t.getSerializationType()) {
case Transition.RULE:
PredictionContext newContext =
new SingletonPredictionContext(config.context, p.stateNumber);
SingletonPredictionContext.create(config.context, p.stateNumber);
c = new LexerATNConfig(config, t.target, newContext);
break;
case Transition.PREDICATE:

View File

@ -1115,7 +1115,7 @@ public class ParserATNSimulator extends ATNSimulator {
config.state.getClass()==PlusLoopbackState.class )
{
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
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);
}
PredictionContext newContext =
new SingletonPredictionContext(config.context, config.state.stateNumber);
SingletonPredictionContext.create(config.context, config.state.stateNumber);
return new ATNConfig(config, t.target, newContext);
}

View File

@ -53,7 +53,7 @@ public abstract class PredictionContext implements Iterable<SingletonPredictionC
parent = PredictionContext.fromRuleContext(outerContext.parent);
}
return new SingletonPredictionContext(parent, outerContext.invokingState);
return SingletonPredictionContext.create(parent, outerContext.invokingState);
}
@Override
@ -123,7 +123,8 @@ public abstract class PredictionContext implements Iterable<SingletonPredictionC
boolean rootIsWildcard,
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) {
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
// of those graphs. dup a, a' points at merged array
// 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_);
return a_;
}
else { // a != b payloads differ
// see if we can collapse parents due to $+x parents if local ctx
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
singleParent = a.parent;
}
@ -338,8 +335,9 @@ public abstract class PredictionContext implements Iterable<SingletonPredictionC
if ( p < lastSlot ) {
int n = p+1; // how many slots we really used in merge
if ( n == 1 ) { // for just one merged element, return singleton top
PredictionContext a_ = new SingletonPredictionContext(mergedParents[0],
mergedInvokingStates[0]);
PredictionContext a_ =
SingletonPredictionContext.create(mergedParents[0],
mergedInvokingStates[0]);
if ( mergeCache!=null ) mergeCache.put(a,b,a_);
return a_;
}
@ -490,7 +488,7 @@ public abstract class PredictionContext implements Iterable<SingletonPredictionC
updated = EMPTY;
}
else if (parents.length == 1) {
updated = new SingletonPredictionContext(parents[0], context.getInvokingState(0));
updated = SingletonPredictionContext.create(parents[0], context.getInvokingState(0));
}
else {
ArrayPredictionContext arrayPredictionContext = (ArrayPredictionContext)context;

View File

@ -8,7 +8,7 @@ public class SingletonPredictionContext extends PredictionContext {
public final PredictionContext parent;
public final int invokingState;
public SingletonPredictionContext(PredictionContext parent, int invokingState) {
SingletonPredictionContext(PredictionContext parent, int invokingState) {
super(calculateHashCode(parent!=null ? 31 ^ parent.hashCode() : 1,
31 ^ invokingState));
assert invokingState!=EMPTY_FULL_CTX_INVOKING_STATE &&
@ -17,6 +17,14 @@ public class SingletonPredictionContext extends PredictionContext {
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
public Iterator<SingletonPredictionContext> iterator() {
final SingletonPredictionContext self = this;

View File

@ -2,7 +2,6 @@ package org.antlr.v4.test;
import junit.framework.TestCase;
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.PredictionContextCache;
import org.antlr.v4.runtime.atn.SingletonPredictionContext;
@ -763,7 +762,7 @@ public class TestGraphNodes extends TestCase {
}
public SingletonPredictionContext createSingleton(PredictionContext parent, int payload) {
SingletonPredictionContext a = new SingletonPredictionContext(parent, payload);
SingletonPredictionContext a = SingletonPredictionContext.create(parent, payload);
return a;
}
@ -820,7 +819,7 @@ public class TestGraphNodes extends TestCase {
}
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;
}