Updated naming conventions since RuleContext stores invoking states but PredictionContext stores return states
This commit is contained in:
parent
c2722b127a
commit
3470978749
|
@ -8,49 +8,49 @@ import java.util.Iterator;
|
|||
public class ArrayPredictionContext extends PredictionContext {
|
||||
/** Parent can be null only if full ctx mode and we make an array
|
||||
* from EMPTY and non-empty. We merge EMPTY by using null parent and
|
||||
* invokingState == EMPTY_FULL_INVOKING_STATE
|
||||
* returnState == EMPTY_FULL_RETURN_STATE
|
||||
*/
|
||||
public final PredictionContext[] parents;
|
||||
|
||||
/** Sorted for merge, no duplicates; if present,
|
||||
* EMPTY_FULL_INVOKING_STATE is always first
|
||||
* EMPTY_FULL_RETURN_STATE is always first
|
||||
*/
|
||||
public final int[] invokingStates;
|
||||
public final int[] returnStates;
|
||||
|
||||
public ArrayPredictionContext(SingletonPredictionContext a) {
|
||||
this(new PredictionContext[] {a.parent}, new int[] {a.invokingState});
|
||||
this(new PredictionContext[] {a.parent}, new int[] {a.returnState});
|
||||
}
|
||||
|
||||
public ArrayPredictionContext(PredictionContext[] parents, int[] invokingStates) {
|
||||
super(calculateHashCode(parents, invokingStates));
|
||||
public ArrayPredictionContext(PredictionContext[] parents, int[] returnStates) {
|
||||
super(calculateHashCode(parents, returnStates));
|
||||
assert parents!=null && parents.length>0;
|
||||
assert invokingStates!=null && invokingStates.length>0;
|
||||
// System.err.println("CREATE ARRAY: "+Arrays.toString(parents)+", "+Arrays.toString(invokingStates));
|
||||
assert returnStates!=null && returnStates.length>0;
|
||||
// System.err.println("CREATE ARRAY: "+Arrays.toString(parents)+", "+Arrays.toString(returnStates));
|
||||
this.parents = parents;
|
||||
this.invokingStates = invokingStates;
|
||||
this.returnStates = returnStates;
|
||||
}
|
||||
|
||||
//ArrayPredictionContext(@NotNull PredictionContext[] parents, int[] invokingStates, int parentHashCode, int invokingStateHashCode) {
|
||||
// super(calculateHashCode(parentHashCode, invokingStateHashCode));
|
||||
// assert parents.length == invokingStates.length;
|
||||
// assert invokingStates.length > 1 || invokingStates[0] != EMPTY_FULL_STATE_KEY : "Should be using PredictionContext.EMPTY instead.";
|
||||
//ArrayPredictionContext(@NotNull PredictionContext[] parents, int[] returnStates, int parentHashCode, int returnStateHashCode) {
|
||||
// super(calculateHashCode(parentHashCode, returnStateHashCode));
|
||||
// assert parents.length == returnStates.length;
|
||||
// assert returnStates.length > 1 || returnStates[0] != EMPTY_FULL_STATE_KEY : "Should be using PredictionContext.EMPTY instead.";
|
||||
//
|
||||
// this.parents = parents;
|
||||
// this.invokingStates = invokingStates;
|
||||
// this.returnStates = returnStates;
|
||||
// }
|
||||
//
|
||||
//ArrayPredictionContext(@NotNull PredictionContext[] parents, int[] invokingStates, int hashCode) {
|
||||
//ArrayPredictionContext(@NotNull PredictionContext[] parents, int[] returnStates, int hashCode) {
|
||||
// super(hashCode);
|
||||
// assert parents.length == invokingStates.length;
|
||||
// assert invokingStates.length > 1 || invokingStates[0] != EMPTY_FULL_STATE_KEY : "Should be using PredictionContext.EMPTY instead.";
|
||||
// assert parents.length == returnStates.length;
|
||||
// assert returnStates.length > 1 || returnStates[0] != EMPTY_FULL_STATE_KEY : "Should be using PredictionContext.EMPTY instead.";
|
||||
//
|
||||
// this.parents = parents;
|
||||
// this.invokingStates = invokingStates;
|
||||
// this.returnStates = returnStates;
|
||||
// }
|
||||
|
||||
protected static int calculateHashCode(PredictionContext[] parents, int[] invokingStates) {
|
||||
protected static int calculateHashCode(PredictionContext[] parents, int[] returnStates) {
|
||||
return calculateHashCode(calculateParentHashCode(parents),
|
||||
calculateInvokingStatesHashCode(invokingStates));
|
||||
calculateReturnStatesHashCode(returnStates));
|
||||
}
|
||||
|
||||
protected static int calculateParentHashCode(PredictionContext[] parents) {
|
||||
|
@ -64,9 +64,9 @@ public class ArrayPredictionContext extends PredictionContext {
|
|||
return hashCode;
|
||||
}
|
||||
|
||||
protected static int calculateInvokingStatesHashCode(int[] invokingStates) {
|
||||
protected static int calculateReturnStatesHashCode(int[] returnStates) {
|
||||
int hashCode = 1;
|
||||
for (int state : invokingStates) {
|
||||
for (int state : returnStates) {
|
||||
hashCode = hashCode * 31 ^ state;
|
||||
}
|
||||
|
||||
|
@ -83,7 +83,7 @@ public class ArrayPredictionContext extends PredictionContext {
|
|||
@Override
|
||||
public SingletonPredictionContext next() {
|
||||
SingletonPredictionContext ctx =
|
||||
SingletonPredictionContext.create(parents[i], invokingStates[i]);
|
||||
SingletonPredictionContext.create(parents[i], returnStates[i]);
|
||||
i++;
|
||||
return ctx;
|
||||
}
|
||||
|
@ -96,12 +96,12 @@ public class ArrayPredictionContext extends PredictionContext {
|
|||
@Override
|
||||
public boolean isEmpty() {
|
||||
return size()==1 &&
|
||||
invokingStates[0]==EMPTY_INVOKING_STATE;
|
||||
returnStates[0]==EMPTY_RETURN_STATE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return invokingStates.length;
|
||||
return returnStates.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -110,49 +110,15 @@ public class ArrayPredictionContext extends PredictionContext {
|
|||
}
|
||||
|
||||
@Override
|
||||
public int getInvokingState(int index) {
|
||||
return invokingStates[index];
|
||||
public int getReturnState(int index) {
|
||||
return returnStates[index];
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public int findInvokingState(int invokingState) {
|
||||
// return Arrays.binarySearch(invokingStates, invokingState);
|
||||
// public int findReturnState(int returnState) {
|
||||
// return Arrays.binarySearch(returnStates, returnState);
|
||||
// }
|
||||
|
||||
/** Find invokingState parameter (call it x) in this.invokingStates,
|
||||
* if present. Call pop on all x's parent(s) and then pull other
|
||||
* elements from this context and merge into new context.
|
||||
*/
|
||||
@Override
|
||||
public PredictionContext popAll(
|
||||
int invokingState,
|
||||
boolean fullCtx,
|
||||
DoubleKeyMap<PredictionContext,PredictionContext,PredictionContext> mergeCache)
|
||||
{
|
||||
int index = Arrays.binarySearch(this.invokingStates, invokingState);
|
||||
if ( index < 0 ) {
|
||||
return this;
|
||||
}
|
||||
|
||||
PredictionContext newCtx =
|
||||
this.parents[index].popAll(invokingState, fullCtx, mergeCache);
|
||||
for (int i = 0; i < this.invokingStates.length; i++) {
|
||||
if (i == index) continue;
|
||||
PredictionContext next;
|
||||
if ( this.invokingStates[i] == EMPTY_INVOKING_STATE ) {
|
||||
next = PredictionContext.EMPTY;
|
||||
}
|
||||
else {
|
||||
next = SingletonPredictionContext.create(this.parents[i],
|
||||
this.invokingStates[i]);
|
||||
}
|
||||
boolean rootIsWildcard = fullCtx;
|
||||
newCtx = merge(newCtx, next, rootIsWildcard, mergeCache);
|
||||
}
|
||||
|
||||
return newCtx;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
|
@ -167,7 +133,7 @@ public class ArrayPredictionContext extends PredictionContext {
|
|||
}
|
||||
|
||||
ArrayPredictionContext a = (ArrayPredictionContext)o;
|
||||
return Arrays.equals(invokingStates, a.invokingStates) &&
|
||||
return Arrays.equals(returnStates, a.returnStates) &&
|
||||
Arrays.equals(parents, a.parents);
|
||||
}
|
||||
|
||||
|
@ -176,13 +142,13 @@ public class ArrayPredictionContext extends PredictionContext {
|
|||
if ( isEmpty() ) return "[]";
|
||||
StringBuilder buf = new StringBuilder();
|
||||
buf.append("[");
|
||||
for (int i=0; i<invokingStates.length; i++) {
|
||||
for (int i=0; i<returnStates.length; i++) {
|
||||
if ( i>0 ) buf.append(", ");
|
||||
if ( invokingStates[i]==EMPTY_INVOKING_STATE ) {
|
||||
if ( returnStates[i]==EMPTY_RETURN_STATE ) {
|
||||
buf.append("$");
|
||||
continue;
|
||||
}
|
||||
buf.append(invokingStates[i]);
|
||||
buf.append(returnStates[i]);
|
||||
if ( parents[i]!=null ) {
|
||||
buf.append(' ');
|
||||
buf.append(parents[i].toString());
|
||||
|
|
|
@ -2,7 +2,7 @@ package org.antlr.v4.runtime.atn;
|
|||
|
||||
public class EmptyPredictionContext extends SingletonPredictionContext {
|
||||
public EmptyPredictionContext() {
|
||||
super(null, EMPTY_INVOKING_STATE);
|
||||
super(null, EMPTY_RETURN_STATE);
|
||||
}
|
||||
|
||||
public boolean isEmpty() { return true; }
|
||||
|
@ -18,8 +18,8 @@ public class EmptyPredictionContext extends SingletonPredictionContext {
|
|||
}
|
||||
|
||||
@Override
|
||||
public int getInvokingState(int index) {
|
||||
return invokingState;
|
||||
public int getReturnState(int index) {
|
||||
return returnState;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -109,7 +109,7 @@ public class LL1Analyzer {
|
|||
if ( ctx != PredictionContext.EMPTY ) {
|
||||
// run thru all possible stack tops in ctx
|
||||
for (SingletonPredictionContext p : ctx) {
|
||||
ATNState returnState = atn.states.get(p.invokingState);
|
||||
ATNState returnState = atn.states.get(p.returnState);
|
||||
// System.out.println("popping back to "+retState);
|
||||
_LOOK(returnState, p.parent, look, lookBusy, seeThruPreds);
|
||||
}
|
||||
|
|
|
@ -407,8 +407,8 @@ public class LexerATNSimulator extends ATNSimulator {
|
|||
if ( config.context!=null && !config.context.isEmpty() ) {
|
||||
for (SingletonPredictionContext ctx : config.context) {
|
||||
if ( !ctx.isEmpty() ) {
|
||||
PredictionContext newContext = ctx.parent; // "pop" invoking state
|
||||
if ( ctx.invokingState==PredictionContext.EMPTY_INVOKING_STATE ) {
|
||||
PredictionContext newContext = ctx.parent; // "pop" return state
|
||||
if ( ctx.returnState==PredictionContext.EMPTY_RETURN_STATE ) {
|
||||
// we have no context info. Don't pursue but
|
||||
// record a config that indicates how we hit end
|
||||
LexerATNConfig c = new LexerATNConfig(config, config.state, ctx);
|
||||
|
@ -418,7 +418,7 @@ public class LexerATNSimulator extends ATNSimulator {
|
|||
configs.add(c);
|
||||
continue;
|
||||
}
|
||||
ATNState returnState = atn.states.get(ctx.invokingState);
|
||||
ATNState returnState = atn.states.get(ctx.returnState);
|
||||
LexerATNConfig c = new LexerATNConfig(returnState, config.alt, newContext);
|
||||
currentAltReachedAcceptState = closure(input, c, configs, currentAltReachedAcceptState, speculative);
|
||||
}
|
||||
|
|
|
@ -1071,7 +1071,7 @@ public class ParserATNSimulator extends ATNSimulator {
|
|||
// run thru all possible stack tops in ctx
|
||||
if ( config.context!=null && !config.context.isEmpty() ) {
|
||||
for (SingletonPredictionContext ctx : config.context) {
|
||||
if ( ctx.invokingState==PredictionContext.EMPTY_INVOKING_STATE ) {
|
||||
if ( ctx.returnState==PredictionContext.EMPTY_RETURN_STATE ) {
|
||||
// we have no context info, just chase follow links (if greedy)
|
||||
if ( debug ) System.out.println("FALLING off rule "+
|
||||
getRuleName(config.state.ruleIndex));
|
||||
|
@ -1079,8 +1079,8 @@ public class ParserATNSimulator extends ATNSimulator {
|
|||
fullCtx, depth);
|
||||
continue;
|
||||
}
|
||||
ATNState returnState = atn.states.get(ctx.invokingState);
|
||||
PredictionContext newContext = ctx.parent; // "pop" invoking state
|
||||
ATNState returnState = atn.states.get(ctx.returnState);
|
||||
PredictionContext newContext = ctx.parent; // "pop" return state
|
||||
ATNConfig c = new ATNConfig(returnState, config.alt, newContext,
|
||||
config.semanticContext);
|
||||
// While we have context to pop back from, we may have
|
||||
|
|
|
@ -22,9 +22,9 @@ public abstract class PredictionContext implements Iterable<SingletonPredictionC
|
|||
public static final EmptyPredictionContext EMPTY = new EmptyPredictionContext();
|
||||
|
||||
/** Represents $ in an array in full ctx mode, when $ doesn't mean wildcard:
|
||||
* $ + x = [$,x]. Here, $ = EMPTY_INVOKING_STATE.
|
||||
* $ + x = [$,x]. Here, $ = EMPTY_RETURN_STATE.
|
||||
*/
|
||||
public static final int EMPTY_INVOKING_STATE = Integer.MAX_VALUE;
|
||||
public static final int EMPTY_RETURN_STATE = Integer.MAX_VALUE;
|
||||
|
||||
public static int globalNodeCount = 0;
|
||||
public final int id = globalNodeCount++;
|
||||
|
@ -65,7 +65,7 @@ public abstract class PredictionContext implements Iterable<SingletonPredictionC
|
|||
|
||||
public abstract PredictionContext getParent(int index);
|
||||
|
||||
public abstract int getInvokingState(int index);
|
||||
public abstract int getReturnState(int index);
|
||||
|
||||
/** This means only the EMPTY context is in set */
|
||||
public boolean isEmpty() {
|
||||
|
@ -73,14 +73,9 @@ public abstract class PredictionContext implements Iterable<SingletonPredictionC
|
|||
}
|
||||
|
||||
public boolean hasEmptyPath() {
|
||||
return getInvokingState(size() - 1) == EMPTY_INVOKING_STATE;
|
||||
return getReturnState(size() - 1) == EMPTY_RETURN_STATE;
|
||||
}
|
||||
|
||||
public abstract PredictionContext popAll(
|
||||
int invokingState,
|
||||
boolean fullCtx,
|
||||
DoubleKeyMap<PredictionContext,PredictionContext,PredictionContext> mergeCache);
|
||||
|
||||
@Override
|
||||
public int compareTo(PredictionContext o) { // used for toDotString to print nodes in order
|
||||
return id - o.id;
|
||||
|
@ -91,8 +86,8 @@ public abstract class PredictionContext implements Iterable<SingletonPredictionC
|
|||
return cachedHashCode;
|
||||
}
|
||||
|
||||
protected static int calculateHashCode(int parentHashCode, int invokingStateHashCode) {
|
||||
return 5 * 5 * 7 + 5 * parentHashCode + invokingStateHashCode;
|
||||
protected static int calculateHashCode(int parentHashCode, int returnStateHashCode) {
|
||||
return 5 * 5 * 7 + 5 * parentHashCode + returnStateHashCode;
|
||||
}
|
||||
|
||||
/** Two contexts conflict() if they are equals() or one is a stack suffix
|
||||
|
@ -176,7 +171,7 @@ public abstract class PredictionContext implements Iterable<SingletonPredictionC
|
|||
return rootMerge;
|
||||
}
|
||||
|
||||
if ( a.invokingState==b.invokingState ) { // a == b
|
||||
if ( a.returnState==b.returnState ) { // a == b
|
||||
PredictionContext parent = merge(a.parent, b.parent, rootIsWildcard, mergeCache);
|
||||
// if parent is same as existing a or b parent or reduced to a parent, return it
|
||||
if ( parent == a.parent ) return a; // ax + bx = ax, if a=b
|
||||
|
@ -185,7 +180,7 @@ 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_ = SingletonPredictionContext.create(parent, a.invokingState);
|
||||
PredictionContext a_ = SingletonPredictionContext.create(parent, a.returnState);
|
||||
if ( mergeCache!=null ) mergeCache.put(a, b, a_);
|
||||
return a_;
|
||||
}
|
||||
|
@ -197,10 +192,10 @@ public abstract class PredictionContext implements Iterable<SingletonPredictionC
|
|||
}
|
||||
if ( singleParent!=null ) { // parents are same
|
||||
// sort payloads and use same parent
|
||||
int[] payloads = {a.invokingState, b.invokingState};
|
||||
if ( a.invokingState > b.invokingState ) {
|
||||
payloads[0] = b.invokingState;
|
||||
payloads[1] = a.invokingState;
|
||||
int[] payloads = {a.returnState, b.returnState};
|
||||
if ( a.returnState > b.returnState ) {
|
||||
payloads[0] = b.returnState;
|
||||
payloads[1] = a.returnState;
|
||||
}
|
||||
PredictionContext[] parents = {singleParent, singleParent};
|
||||
PredictionContext a_ = new ArrayPredictionContext(parents, payloads);
|
||||
|
@ -210,11 +205,11 @@ public abstract class PredictionContext implements Iterable<SingletonPredictionC
|
|||
// parents differ and can't merge them. Just pack together
|
||||
// into array; can't merge.
|
||||
// ax + by = [ax,by]
|
||||
int[] payloads = {a.invokingState, b.invokingState};
|
||||
int[] payloads = {a.returnState, b.returnState};
|
||||
PredictionContext[] parents = {a.parent, b.parent};
|
||||
if ( a.invokingState > b.invokingState ) { // sort by payload
|
||||
payloads[0] = b.invokingState;
|
||||
payloads[1] = a.invokingState;
|
||||
if ( a.returnState > b.returnState ) { // sort by payload
|
||||
payloads[0] = b.returnState;
|
||||
payloads[1] = a.returnState;
|
||||
parents = new PredictionContext[] {b.parent, a.parent};
|
||||
}
|
||||
PredictionContext a_ = new ArrayPredictionContext(parents, payloads);
|
||||
|
@ -237,14 +232,14 @@ public abstract class PredictionContext implements Iterable<SingletonPredictionC
|
|||
else {
|
||||
if ( a == EMPTY && b == EMPTY ) return EMPTY; // $ + $ = $
|
||||
if ( a == EMPTY ) { // $ + x = [$,x]
|
||||
int[] payloads = {b.invokingState, EMPTY_INVOKING_STATE};
|
||||
int[] payloads = {b.returnState, EMPTY_RETURN_STATE};
|
||||
PredictionContext[] parents = {b.parent, null};
|
||||
PredictionContext joined =
|
||||
new ArrayPredictionContext(parents, payloads);
|
||||
return joined;
|
||||
}
|
||||
if ( b == EMPTY ) { // x + $ = [$,x] ($ is always first if present)
|
||||
int[] payloads = {a.invokingState, EMPTY_INVOKING_STATE};
|
||||
int[] payloads = {a.returnState, EMPTY_RETURN_STATE};
|
||||
PredictionContext[] parents = {a.parent, null};
|
||||
PredictionContext joined =
|
||||
new ArrayPredictionContext(parents, payloads);
|
||||
|
@ -273,60 +268,60 @@ public abstract class PredictionContext implements Iterable<SingletonPredictionC
|
|||
int j = 0; // walks b
|
||||
int k = 0; // walks target M array
|
||||
|
||||
int[] mergedInvokingStates =
|
||||
new int[a.invokingStates.length + b.invokingStates.length];
|
||||
int[] mergedReturnStates =
|
||||
new int[a.returnStates.length + b.returnStates.length];
|
||||
PredictionContext[] mergedParents =
|
||||
new PredictionContext[a.invokingStates.length + b.invokingStates.length];
|
||||
// walk and merge to yield mergedParents, mergedInvokingStates
|
||||
while ( i<a.invokingStates.length && j<b.invokingStates.length ) {
|
||||
new PredictionContext[a.returnStates.length + b.returnStates.length];
|
||||
// walk and merge to yield mergedParents, mergedReturnStates
|
||||
while ( i<a.returnStates.length && j<b.returnStates.length ) {
|
||||
PredictionContext a_parent = a.parents[i];
|
||||
PredictionContext b_parent = b.parents[j];
|
||||
if ( a.invokingStates[i]==b.invokingStates[j] ) {
|
||||
if ( a.returnStates[i]==b.returnStates[j] ) {
|
||||
// same payload (stack tops are equal), must yield merged singleton
|
||||
int payload = a.invokingStates[i];
|
||||
int payload = a.returnStates[i];
|
||||
// $+$ = $
|
||||
boolean both$ = payload == EMPTY_INVOKING_STATE &&
|
||||
boolean both$ = payload == EMPTY_RETURN_STATE &&
|
||||
a_parent == null && b_parent == null;
|
||||
boolean ax_ax = (a_parent!=null && b_parent!=null) &&
|
||||
a_parent.equals(b_parent); // ax+ax -> ax
|
||||
if ( both$ || ax_ax ) {
|
||||
mergedParents[k] = a_parent; // choose left
|
||||
mergedInvokingStates[k] = payload;
|
||||
mergedReturnStates[k] = payload;
|
||||
}
|
||||
else { // ax+ay -> a'[x,y]
|
||||
PredictionContext mergedParent =
|
||||
merge(a_parent, b_parent, rootIsWildcard, mergeCache);
|
||||
mergedParents[k] = mergedParent;
|
||||
mergedInvokingStates[k] = payload;
|
||||
mergedReturnStates[k] = payload;
|
||||
}
|
||||
i++; // hop over left one as usual
|
||||
j++; // but also skip one in right side since we merge
|
||||
}
|
||||
else if ( a.invokingStates[i]<b.invokingStates[j] ) { // copy a[i] to M
|
||||
else if ( a.returnStates[i]<b.returnStates[j] ) { // copy a[i] to M
|
||||
mergedParents[k] = a_parent;
|
||||
mergedInvokingStates[k] = a.invokingStates[i];
|
||||
mergedReturnStates[k] = a.returnStates[i];
|
||||
i++;
|
||||
}
|
||||
else { // b > a, copy b[j] to M
|
||||
mergedParents[k] = b_parent;
|
||||
mergedInvokingStates[k] = b.invokingStates[j];
|
||||
mergedReturnStates[k] = b.returnStates[j];
|
||||
j++;
|
||||
}
|
||||
k++;
|
||||
}
|
||||
|
||||
// copy over any payloads remaining in either array
|
||||
if (i < a.invokingStates.length) {
|
||||
for (int p = i; p < a.invokingStates.length; p++) {
|
||||
if (i < a.returnStates.length) {
|
||||
for (int p = i; p < a.returnStates.length; p++) {
|
||||
mergedParents[k] = a.parents[p];
|
||||
mergedInvokingStates[k] = a.invokingStates[p];
|
||||
mergedReturnStates[k] = a.returnStates[p];
|
||||
k++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (int p = j; p < b.invokingStates.length; p++) {
|
||||
for (int p = j; p < b.returnStates.length; p++) {
|
||||
mergedParents[k] = b.parents[p];
|
||||
mergedInvokingStates[k] = b.invokingStates[p];
|
||||
mergedReturnStates[k] = b.returnStates[p];
|
||||
k++;
|
||||
}
|
||||
}
|
||||
|
@ -336,16 +331,16 @@ public abstract class PredictionContext implements Iterable<SingletonPredictionC
|
|||
if ( k == 1 ) { // for just one merged element, return singleton top
|
||||
PredictionContext a_ =
|
||||
SingletonPredictionContext.create(mergedParents[0],
|
||||
mergedInvokingStates[0]);
|
||||
mergedReturnStates[0]);
|
||||
if ( mergeCache!=null ) mergeCache.put(a,b,a_);
|
||||
return a_;
|
||||
}
|
||||
mergedParents = Arrays.copyOf(mergedParents, k);
|
||||
mergedInvokingStates = Arrays.copyOf(mergedInvokingStates, k);
|
||||
mergedReturnStates = Arrays.copyOf(mergedReturnStates, k);
|
||||
}
|
||||
|
||||
PredictionContext M =
|
||||
new ArrayPredictionContext(mergedParents, mergedInvokingStates);
|
||||
new ArrayPredictionContext(mergedParents, mergedReturnStates);
|
||||
|
||||
// if we created same array as a or b, return that instead
|
||||
// TODO: track whether this is possible above during merge sort for speed
|
||||
|
@ -394,9 +389,9 @@ public abstract class PredictionContext implements Iterable<SingletonPredictionC
|
|||
if ( current instanceof SingletonPredictionContext ) {
|
||||
String s = String.valueOf(current.id);
|
||||
buf.append(" s").append(s);
|
||||
String invokingState = String.valueOf(current.getInvokingState(0));
|
||||
if ( current instanceof EmptyPredictionContext ) invokingState = "$";
|
||||
buf.append(" [label=\"").append(invokingState).append("\"];\n");
|
||||
String returnState = String.valueOf(current.getReturnState(0));
|
||||
if ( current instanceof EmptyPredictionContext ) returnState = "$";
|
||||
buf.append(" [label=\"").append(returnState).append("\"];\n");
|
||||
continue;
|
||||
}
|
||||
ArrayPredictionContext arr = (ArrayPredictionContext)current;
|
||||
|
@ -404,9 +399,9 @@ public abstract class PredictionContext implements Iterable<SingletonPredictionC
|
|||
buf.append(" [shape=box, label=\"");
|
||||
buf.append("[");
|
||||
boolean first = true;
|
||||
for (int inv : arr.invokingStates) {
|
||||
for (int inv : arr.returnStates) {
|
||||
if ( !first ) buf.append(", ");
|
||||
if ( inv == EMPTY_INVOKING_STATE ) buf.append("$");
|
||||
if ( inv == EMPTY_RETURN_STATE ) buf.append("$");
|
||||
else buf.append(inv);
|
||||
first = false;
|
||||
}
|
||||
|
@ -486,11 +481,11 @@ public abstract class PredictionContext implements Iterable<SingletonPredictionC
|
|||
updated = EMPTY;
|
||||
}
|
||||
else if (parents.length == 1) {
|
||||
updated = SingletonPredictionContext.create(parents[0], context.getInvokingState(0));
|
||||
updated = SingletonPredictionContext.create(parents[0], context.getReturnState(0));
|
||||
}
|
||||
else {
|
||||
ArrayPredictionContext arrayPredictionContext = (ArrayPredictionContext)context;
|
||||
updated = new ArrayPredictionContext(parents, arrayPredictionContext.invokingStates);
|
||||
updated = new ArrayPredictionContext(parents, arrayPredictionContext.returnStates);
|
||||
}
|
||||
|
||||
synchronized (contextCache) {
|
||||
|
@ -556,7 +551,7 @@ public abstract class PredictionContext implements Iterable<SingletonPredictionC
|
|||
PredictionContext p = this;
|
||||
buf.append("[");
|
||||
// while ( p != null && p != stop ) {
|
||||
// if ( !p.isEmpty() ) buf.append(p.invokingState);
|
||||
// if ( !p.isEmpty() ) buf.append(p.returnState);
|
||||
// if ( p.parent != null && !p.parent.isEmpty() ) buf.append(" ");
|
||||
// p = p.parent;
|
||||
// }
|
||||
|
@ -608,17 +603,17 @@ public abstract class PredictionContext implements Iterable<SingletonPredictionC
|
|||
String ruleName = recognizer.getRuleNames()[s.ruleIndex];
|
||||
localBuffer.append(ruleName);
|
||||
}
|
||||
else if ( p.getInvokingState(index)!= EMPTY_INVOKING_STATE) {
|
||||
else if ( p.getReturnState(index)!= EMPTY_RETURN_STATE) {
|
||||
if ( !p.isEmpty() ) {
|
||||
if (localBuffer.length() > 1) {
|
||||
// first char is '[', if more than that this isn't the first rule
|
||||
localBuffer.append(' ');
|
||||
}
|
||||
|
||||
localBuffer.append(p.getInvokingState(index));
|
||||
localBuffer.append(p.getReturnState(index));
|
||||
}
|
||||
}
|
||||
stateNumber = p.getInvokingState(index);
|
||||
stateNumber = p.getReturnState(index);
|
||||
p = p.getParent(index);
|
||||
}
|
||||
localBuffer.append("]");
|
||||
|
|
|
@ -6,22 +6,22 @@ import java.util.Iterator;
|
|||
|
||||
public class SingletonPredictionContext extends PredictionContext {
|
||||
public final PredictionContext parent;
|
||||
public final int invokingState;
|
||||
public final int returnState;
|
||||
|
||||
SingletonPredictionContext(PredictionContext parent, int invokingState) {
|
||||
SingletonPredictionContext(PredictionContext parent, int returnState) {
|
||||
super(calculateHashCode(parent!=null ? 31 ^ parent.hashCode() : 1,
|
||||
31 ^ invokingState));
|
||||
assert invokingState!=ATNState.INVALID_STATE_NUMBER;
|
||||
31 ^ returnState));
|
||||
assert returnState!=ATNState.INVALID_STATE_NUMBER;
|
||||
this.parent = parent;
|
||||
this.invokingState = invokingState;
|
||||
this.returnState = returnState;
|
||||
}
|
||||
|
||||
public static SingletonPredictionContext create(PredictionContext parent, int invokingState) {
|
||||
if ( invokingState == EMPTY_INVOKING_STATE && parent == null ) {
|
||||
public static SingletonPredictionContext create(PredictionContext parent, int returnState) {
|
||||
if ( returnState == EMPTY_RETURN_STATE && parent == null ) {
|
||||
// someone can pass in the bits of an array ctx that mean $
|
||||
return EMPTY;
|
||||
}
|
||||
return new SingletonPredictionContext(parent, invokingState);
|
||||
return new SingletonPredictionContext(parent, returnState);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -52,21 +52,9 @@ public class SingletonPredictionContext extends PredictionContext {
|
|||
}
|
||||
|
||||
@Override
|
||||
public int getInvokingState(int index) {
|
||||
public int getReturnState(int index) {
|
||||
assert index == 0;
|
||||
return invokingState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PredictionContext popAll(
|
||||
int invokingState,
|
||||
boolean fullCtx,
|
||||
DoubleKeyMap<PredictionContext,PredictionContext,PredictionContext> mergeCache)
|
||||
{
|
||||
if ( invokingState == this.invokingState ) {
|
||||
return parent.popAll(invokingState, fullCtx, mergeCache);
|
||||
}
|
||||
return this;
|
||||
return returnState;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -83,7 +71,7 @@ public class SingletonPredictionContext extends PredictionContext {
|
|||
}
|
||||
|
||||
SingletonPredictionContext s = (SingletonPredictionContext)o;
|
||||
return invokingState == s.invokingState &&
|
||||
return returnState == s.returnState &&
|
||||
(parent!=null && parent.equals(s.parent));
|
||||
}
|
||||
|
||||
|
@ -91,11 +79,11 @@ public class SingletonPredictionContext extends PredictionContext {
|
|||
public String toString() {
|
||||
String up = parent!=null ? parent.toString() : "";
|
||||
if ( up.length()==0 ) {
|
||||
if ( invokingState == EMPTY_INVOKING_STATE ) {
|
||||
if ( returnState == EMPTY_RETURN_STATE ) {
|
||||
return "$";
|
||||
}
|
||||
return String.valueOf(invokingState);
|
||||
return String.valueOf(returnState);
|
||||
}
|
||||
return String.valueOf(invokingState)+" "+up;
|
||||
return String.valueOf(returnState)+" "+up;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -795,7 +795,7 @@ public class TestGraphNodes {
|
|||
int[] invokingStates = new int[nodes.length];
|
||||
for (int i=0; i<nodes.length; i++) {
|
||||
parents[i] = nodes[i].parent;
|
||||
invokingStates[i] = nodes[i].invokingState;
|
||||
invokingStates[i] = nodes[i].returnState;
|
||||
}
|
||||
return new ArrayPredictionContext(parents, invokingStates);
|
||||
}
|
||||
|
@ -828,7 +828,7 @@ public class TestGraphNodes {
|
|||
}
|
||||
|
||||
nodes.append("<p").append(i).append('>');
|
||||
if (current.getInvokingState(i) == PredictionContext.EMPTY_INVOKING_STATE) {
|
||||
if (current.getReturnState(i) == PredictionContext.EMPTY_RETURN_STATE) {
|
||||
nodes.append(rootIsWildcard ? '*' : '$');
|
||||
}
|
||||
}
|
||||
|
@ -843,7 +843,7 @@ public class TestGraphNodes {
|
|||
}
|
||||
|
||||
for (int i = 0; i < current.size(); i++) {
|
||||
if (current.getInvokingState(i) == PredictionContext.EMPTY_INVOKING_STATE) {
|
||||
if (current.getReturnState(i) == PredictionContext.EMPTY_RETURN_STATE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -859,7 +859,7 @@ public class TestGraphNodes {
|
|||
|
||||
edges.append("->");
|
||||
edges.append('s').append(contextIds.get(current.getParent(i)));
|
||||
edges.append("[label=\"").append(current.getInvokingState(i)).append("\"]");
|
||||
edges.append("[label=\"").append(current.getReturnState(i)).append("\"]");
|
||||
edges.append(";\n");
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue