added mergeArray cache, which didnt help java much but made massive diff to Go grammar. a file, nat.go, went from 2min to 3s in speed. Fixed bug where SLL had preds but they ORd to NONE. made it resolve to min alt. DoubleKeyMap moved to runtime.

This commit is contained in:
Terence Parr 2012-08-03 20:23:54 -07:00
parent 8a0af228d8
commit 88dedbd1e0
9 changed files with 151 additions and 86 deletions

View File

@ -30,6 +30,7 @@
package org.antlr.v4.runtime.atn;
import org.antlr.v4.runtime.misc.Array2DHashSet;
import org.antlr.v4.runtime.misc.DoubleKeyMap;
import org.antlr.v4.runtime.misc.IntervalSet;
import java.util.ArrayList;
@ -297,7 +298,7 @@ public class ATNConfigSet implements Set<ATNConfig> {
}
public ATNConfigSet() { this(true); }
public ATNConfigSet(ATNConfigSet old, PredictionContextCache contextCache) {
public ATNConfigSet(ATNConfigSet old) {
this(old.fullCtx);
addAll(old);
this.uniqueAlt = old.uniqueAlt;
@ -306,12 +307,19 @@ public class ATNConfigSet implements Set<ATNConfig> {
this.dipsIntoOuterContext = old.dipsIntoOuterContext;
}
@Override
public boolean add(ATNConfig config) {
return add(config, null);
}
/** Adding a new config means merging contexts with existing configs for
* (s, i, pi, _)
* We use (s,i,pi) as key
*/
@Override
public boolean add(ATNConfig config) {
public boolean add(
ATNConfig config,
DoubleKeyMap<PredictionContext,PredictionContext,PredictionContext> mergeCache)
{
if ( readonly ) throw new IllegalStateException("This set is readonly");
if ( config.semanticContext!=SemanticContext.NONE ) {
hasSemanticContext = true;
@ -324,7 +332,7 @@ public class ATNConfigSet implements Set<ATNConfig> {
// a previous (s,i,pi,_), merge with it and save result
boolean rootIsWildcard = !fullCtx;
PredictionContext merged =
PredictionContext.merge(existing.context, config.context, rootIsWildcard);
PredictionContext.merge(existing.context, config.context, rootIsWildcard, mergeCache);
// no need to check for existing.context, config.context in cache
// since only way to create new graphs is "call rule" and here. We
// cache at both places.

View File

@ -1,5 +1,7 @@
package org.antlr.v4.runtime.atn;
import org.antlr.v4.runtime.misc.DoubleKeyMap;
import java.util.Arrays;
import java.util.Iterator;
@ -123,8 +125,10 @@ public class ArrayPredictionContext extends PredictionContext {
* elements from this context and merge into new context.
*/
@Override
public PredictionContext popAll(int invokingState,
boolean fullCtx)
public PredictionContext popAll(
int invokingState,
boolean fullCtx,
DoubleKeyMap<PredictionContext,PredictionContext,PredictionContext> mergeCache)
{
int index = Arrays.binarySearch(this.invokingStates, invokingState);
if ( index < 0 ) {
@ -132,7 +136,7 @@ public class ArrayPredictionContext extends PredictionContext {
}
PredictionContext newCtx =
this.parents[index].popAll(invokingState, fullCtx);
this.parents[index].popAll(invokingState, fullCtx, mergeCache);
for (int i = 0; i < this.invokingStates.length; i++) {
if (i == index) continue;
PredictionContext next;
@ -144,7 +148,7 @@ public class ArrayPredictionContext extends PredictionContext {
this.invokingStates[i]);
}
boolean rootIsWildcard = fullCtx;
newCtx = merge(newCtx, next, rootIsWildcard);
newCtx = merge(newCtx, next, rootIsWildcard, mergeCache);
}
return newCtx;

View File

@ -503,7 +503,7 @@ public class LexerATNSimulator extends ATNSimulator {
/** Delete configs for alt following ci. Closure is unmodified; copy returned. */
public ATNConfigSet deleteWildcardConfigsForAlt(@NotNull ATNConfigSet closure, int ci, int alt) {
ATNConfigSet dup = new ATNConfigSet(closure, null);
ATNConfigSet dup = new ATNConfigSet(closure);
int j=ci+1;
while ( j < dup.size() ) {
ATNConfig c = dup.get(j);

View File

@ -38,6 +38,7 @@ import org.antlr.v4.runtime.Token;
import org.antlr.v4.runtime.TokenStream;
import org.antlr.v4.runtime.dfa.DFA;
import org.antlr.v4.runtime.dfa.DFAState;
import org.antlr.v4.runtime.misc.DoubleKeyMap;
import org.antlr.v4.runtime.misc.Interval;
import org.antlr.v4.runtime.misc.IntervalSet;
import org.antlr.v4.runtime.misc.NotNull;
@ -236,7 +237,11 @@ public class ParserATNSimulator<Symbol extends Token> extends ATNSimulator {
public static boolean dfa_debug = false;
public static boolean retry_debug = false;
public static final boolean SLL_loopsSimulateTailRecursion = true;
/** Should we simulate tail recursion for loops in SLL mode? Costs
* about 10% in time to turn on so let's leave off. Full LL turns
* it on for sure.
*/
public static final boolean SLL_loopsSimulateTailRecursion = false;
public static int ATN_failover = 0;
public static int predict_calls = 0;
@ -254,6 +259,13 @@ public class ParserATNSimulator<Symbol extends Token> extends ATNSimulator {
/** Do only local context prediction (SLL(k) style). */
protected boolean SLL = false;
/** Each prediction operation uses a cache for merge of prediction contexts.
* Don't keep around as it wastes huge amounts of memory. DoubleKeyMap
* isn't synchronized but we're ok since two threads shouldn't reuse same
* parser/atnsim object because it can only handle one input at a time.
*/
protected DoubleKeyMap<PredictionContext,PredictionContext,PredictionContext> mergeCache;
// LAME globals to avoid parameters!!!!! I need these down deep in predTransition
protected TokenStream _input;
protected int _startIndex;
@ -290,6 +302,7 @@ public class ParserATNSimulator<Symbol extends Token> extends ATNSimulator {
" exec LA(1)=="+ getLookaheadName(input)+
" line "+input.LT(1).getLine()+":"+input.LT(1).getCharPositionInLine());
}
mergeCache = new DoubleKeyMap<PredictionContext,PredictionContext,PredictionContext>();
_input = input;
_startIndex = input.index();
_outerContext = outerContext;
@ -311,7 +324,12 @@ public class ParserATNSimulator<Symbol extends Token> extends ATNSimulator {
// But, do we still need an initial state?
if ( dfa.s0==null ) { // recheck
if ( dfa.s0==null ) { // recheck
return predictATN(dfa, input, outerContext);
try {
return predictATN(dfa, input, outerContext);
}
finally {
mergeCache = null; // wack cache after each prediction
}
}
// fall through; another thread set dfa.s0 while we waited for lock
}
@ -320,10 +338,10 @@ public class ParserATNSimulator<Symbol extends Token> extends ATNSimulator {
int m = input.mark();
int index = input.index();
try {
int alt = execDFA(dfa, dfa.s0, input, index, outerContext);
return alt;
return execDFA(dfa, dfa.s0, input, index, outerContext);
}
finally {
mergeCache = null; // wack cache after each prediction
input.seek(index);
input.release(m);
}
@ -624,6 +642,7 @@ public class ParserATNSimulator<Symbol extends Token> extends ATNSimulator {
D.prediction = D.configs.conflictingAlts.getMinElement();
if ( debug ) System.out.println("RESOLVED TO "+D.prediction+" for "+D);
predictedAlt = D.prediction;
// Falls through to check predicates below
}
else {
// SLL CONFLICT; RETRY WITH FULL LL CONTEXT
@ -688,8 +707,16 @@ public class ParserATNSimulator<Symbol extends Token> extends ATNSimulator {
// pairs if preds found for conflicting alts
IntervalSet altsToCollectPredsFrom = getConflictingAltsOrUniqueAlt(D.configs);
SemanticContext[] altToPred = getPredsForAmbigAlts(altsToCollectPredsFrom, D.configs, nalts);
D.predicates = getPredicatePredictions(altsToCollectPredsFrom, altToPred);
D.prediction = ATN.INVALID_ALT_NUMBER; // make sure we use preds
if ( altToPred!=null ) {
D.predicates = getPredicatePredictions(altsToCollectPredsFrom, altToPred);
D.prediction = ATN.INVALID_ALT_NUMBER; // make sure we use preds
}
else {
// There are preds in configs but they might go away
// when OR'd together like {p}? || NONE == NONE. If neither
// alt has preds, resolve to min alt
D.prediction = altsToCollectPredsFrom.getMinElement();
}
if ( D.predicates!=null ) {
int stopIndex = input.index();
@ -807,7 +834,7 @@ public class ParserATNSimulator<Symbol extends Token> extends ATNSimulator {
Transition trans = c.state.transition(ti);
ATNState target = getReachableTarget(trans, t);
if ( target!=null ) {
intermediate.add(new ATNConfig(c, target));
intermediate.add(new ATNConfig(c, target), mergeCache);
}
}
}
@ -818,12 +845,12 @@ public class ParserATNSimulator<Symbol extends Token> extends ATNSimulator {
// It can only have one alternative; just add to result
// Also don't pursue the closure if there is unique alternative
// among the configurations.
reach = new ATNConfigSet(intermediate, null);
reach = new ATNConfigSet(intermediate);
}
else if ( ParserATNSimulator.getUniqueAlt(intermediate)==1 ) {
// Also don't pursue the closure if there is unique alternative
// among the configurations.
reach = new ATNConfigSet(intermediate, null);
reach = new ATNConfigSet(intermediate);
}
else {
for (ATNConfig c : intermediate) {
@ -888,7 +915,6 @@ public class ParserATNSimulator<Symbol extends Token> extends ATNSimulator {
int nalts)
{
// REACH=[1|1|[]|0:0, 1|2|[]|0:1]
/* altToPred starts as an array of all null contexts. The entry at index i
* corresponds to alternative i. altToPred[i] may have one of three values:
* 1. null: no ATNConfig c is found such that c.alt==i
@ -900,8 +926,7 @@ public class ParserATNSimulator<Symbol extends Token> extends ATNSimulator {
*
* From this, it is clear that NONE||anything==NONE.
*/
SemanticContext[] altToPred = new SemanticContext[nalts +1];
int n = altToPred.length;
SemanticContext[] altToPred = new SemanticContext[nalts + 1];
for (ATNConfig c : configs) {
if ( ambigAlts.contains(c.alt) ) {
altToPred[c.alt] = SemanticContext.or(altToPred[c.alt], c.semanticContext);
@ -909,7 +934,7 @@ public class ParserATNSimulator<Symbol extends Token> extends ATNSimulator {
}
int nPredAlts = 0;
for (int i = 1; i < n; i++) {
for (int i = 1; i <= nalts; i++) {
if (altToPred[i] == null) {
altToPred[i] = SemanticContext.NONE;
}
@ -1033,7 +1058,7 @@ public class ParserATNSimulator<Symbol extends Token> extends ATNSimulator {
// don't see past end of a rule for any nongreedy decision
if ( debug ) System.out.println("NONGREEDY at stop state of "+
getRuleName(config.state.ruleIndex));
configs.add(config);
configs.add(config, mergeCache);
return;
}
// We hit rule end. If we have context info, use it
@ -1085,7 +1110,8 @@ public class ParserATNSimulator<Symbol extends Token> extends ATNSimulator {
LoopEndState end = (LoopEndState)config.state;
// pop all the way back until we don't see the loopback state anymore
config.context = config.context.popAll(end.loopBackStateNumber,
configs.fullCtx);
configs.fullCtx,
mergeCache);
if ( debug ) System.out.println(" becomes "+config.context);
}
}
@ -1107,7 +1133,7 @@ public class ParserATNSimulator<Symbol extends Token> extends ATNSimulator {
ATNState p = config.state;
// optimization
if ( !p.onlyHasEpsilonTransitions() ) {
configs.add(config);
configs.add(config, mergeCache);
if ( config.semanticContext!=null && config.semanticContext!= SemanticContext.NONE ) {
configs.hasSemanticContext = true;
}

View File

@ -2,6 +2,7 @@ package org.antlr.v4.runtime.atn;
import org.antlr.v4.runtime.Recognizer;
import org.antlr.v4.runtime.RuleContext;
import org.antlr.v4.runtime.misc.DoubleKeyMap;
import org.antlr.v4.runtime.misc.NotNull;
import org.antlr.v4.runtime.misc.Nullable;
@ -64,15 +65,15 @@ public abstract class PredictionContext implements Iterable<SingletonPredictionC
public abstract int getInvokingState(int index);
// public abstract int findInvokingState(int invokingState);
/** This means only the EMPTY context is in set */
public boolean isEmpty() {
return this == EMPTY;
}
public abstract PredictionContext popAll(int invokingState,
boolean fullCtx);
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
@ -117,15 +118,17 @@ public abstract class PredictionContext implements Iterable<SingletonPredictionC
// }
// dispatch
public static PredictionContext merge(PredictionContext a, PredictionContext b,
boolean rootIsWildcard)
public static PredictionContext merge(
PredictionContext a, PredictionContext b,
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
if ( a instanceof SingletonPredictionContext && b instanceof SingletonPredictionContext) {
return mergeSingletons((SingletonPredictionContext)a,
(SingletonPredictionContext)b,
rootIsWildcard);
rootIsWildcard, mergeCache);
}
// At least one of a or b is array
@ -143,19 +146,21 @@ public abstract class PredictionContext implements Iterable<SingletonPredictionC
b = new ArrayPredictionContext((SingletonPredictionContext)b);
}
return mergeArrays((ArrayPredictionContext) a, (ArrayPredictionContext) b,
rootIsWildcard);
rootIsWildcard, mergeCache);
}
// http://www.antlr.org/wiki/download/attachments/32014352/singleton-merge.png
public static PredictionContext mergeSingletons(SingletonPredictionContext a,
SingletonPredictionContext b,
boolean rootIsWildcard)
public static PredictionContext mergeSingletons(
SingletonPredictionContext a,
SingletonPredictionContext b,
boolean rootIsWildcard,
DoubleKeyMap<PredictionContext,PredictionContext,PredictionContext> mergeCache)
{
PredictionContext rootMerge = mergeRoot(a, b, rootIsWildcard);
if ( rootMerge!=null ) return rootMerge;
if ( a.invokingState==b.invokingState ) { // a == b
PredictionContext parent = merge(a.parent, b.parent, rootIsWildcard);
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
if ( parent == b.parent ) return b; // ax + bx = bx, if a=b
@ -234,10 +239,17 @@ public abstract class PredictionContext implements Iterable<SingletonPredictionC
}
// http://www.antlr.org/wiki/download/attachments/32014352/array-merge.png
public static PredictionContext mergeArrays(ArrayPredictionContext a,
ArrayPredictionContext b,
boolean rootIsWildcard)
public static PredictionContext mergeArrays(
ArrayPredictionContext a,
ArrayPredictionContext b,
boolean rootIsWildcard,
DoubleKeyMap<PredictionContext,PredictionContext,PredictionContext> mergeCache)
{
if ( mergeCache!=null ) {
PredictionContext previous = mergeCache.get(a,b);
if ( previous!=null ) return previous;
}
// merge sorted payloads a + b => M
int i = 0; // walks a
int j = 0; // walks b
@ -265,7 +277,7 @@ public abstract class PredictionContext implements Iterable<SingletonPredictionC
}
else { // ax+ay -> a'[x,y]
PredictionContext mergedParent =
merge(a_parent, b_parent, rootIsWildcard);
merge(a_parent, b_parent, rootIsWildcard, mergeCache);
mergedParents[k] = mergedParent;
mergedInvokingStates[k] = payload;
}
@ -313,6 +325,7 @@ public abstract class PredictionContext implements Iterable<SingletonPredictionC
if ( n == 1 ) { // for just one merged element, return singleton top
PredictionContext a_ = new SingletonPredictionContext(mergedParents[0],
mergedInvokingStates[0]);
if ( mergeCache!=null ) mergeCache.put(a,b,a_);
return a_;
}
mergedParents = Arrays.copyOf(mergedParents, n);
@ -325,11 +338,18 @@ public abstract class PredictionContext implements Iterable<SingletonPredictionC
// if we created same array as a or b, return that instead
// TODO: track whether this is possible above during merge sort for speed
if ( M.equals(a) ) return a;
if ( M.equals(b) ) return b;
if ( M.equals(a) ) {
if ( mergeCache!=null ) mergeCache.put(a,b,a);
return a;
}
if ( M.equals(b) ) {
if ( mergeCache!=null ) mergeCache.put(a,b,b);
return b;
}
combineCommonParents(mergedParents);
if ( mergeCache!=null ) mergeCache.put(a,b,M);
return M;
}

View File

@ -1,5 +1,7 @@
package org.antlr.v4.runtime.atn;
import org.antlr.v4.runtime.misc.DoubleKeyMap;
import java.util.Iterator;
public class SingletonPredictionContext extends PredictionContext {
@ -49,11 +51,13 @@ public class SingletonPredictionContext extends PredictionContext {
}
@Override
public PredictionContext popAll(int invokingState,
boolean fullCtx)
public PredictionContext popAll(
int invokingState,
boolean fullCtx,
DoubleKeyMap<PredictionContext,PredictionContext,PredictionContext> mergeCache)
{
if ( invokingState == this.invokingState ) {
return parent.popAll(invokingState, fullCtx);
return parent.popAll(invokingState, fullCtx, mergeCache);
}
return this;
}

View File

@ -27,9 +27,12 @@
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.antlr.v4.misc;
package org.antlr.v4.runtime.misc;
import java.util.*;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
/** Sometimes we need to map a key to a value but key is two pieces of data.
* This nested hash table saves creating a single key each time we access

View File

@ -34,10 +34,10 @@ import org.antlr.runtime.tree.Tree;
import org.antlr.runtime.tree.TreeVisitor;
import org.antlr.runtime.tree.TreeVisitorAction;
import org.antlr.v4.Tool;
import org.antlr.v4.misc.DoubleKeyMap;
import org.antlr.v4.parse.ANTLRParser;
import org.antlr.v4.parse.BlockSetTransformer;
import org.antlr.v4.parse.GrammarASTAdaptor;
import org.antlr.v4.runtime.misc.DoubleKeyMap;
import org.antlr.v4.runtime.misc.Pair;
import org.antlr.v4.tool.ast.AltAST;
import org.antlr.v4.tool.ast.BlockAST;

View File

@ -22,7 +22,7 @@ public class TestGraphNodes extends TestCase {
@Test public void test_$_$() {
PredictionContext r = PredictionContext.merge(PredictionContext.EMPTY,
PredictionContext.EMPTY,
rootIsWildcard());
rootIsWildcard(), null);
System.out.println(PredictionContext.toDOTString(r));
String expecting =
"digraph G {\n" +
@ -35,7 +35,7 @@ public class TestGraphNodes extends TestCase {
@Test public void test_$_$_fullctx() {
PredictionContext r = PredictionContext.merge(PredictionContext.EMPTY,
PredictionContext.EMPTY,
fullCtx());
fullCtx(), null);
System.out.println(PredictionContext.toDOTString(r));
String expecting =
"digraph G {\n" +
@ -46,7 +46,7 @@ public class TestGraphNodes extends TestCase {
}
@Test public void test_x_$() {
PredictionContext r = PredictionContext.merge(x(), PredictionContext.EMPTY, rootIsWildcard());
PredictionContext r = PredictionContext.merge(x(), PredictionContext.EMPTY, rootIsWildcard(), null);
System.out.println(PredictionContext.toDOTString(r));
String expecting =
"digraph G {\n" +
@ -57,7 +57,7 @@ public class TestGraphNodes extends TestCase {
}
@Test public void test_x_$_fullctx() {
PredictionContext r = PredictionContext.merge(x(), PredictionContext.EMPTY, fullCtx());
PredictionContext r = PredictionContext.merge(x(), PredictionContext.EMPTY, fullCtx(), null);
System.out.println(PredictionContext.toDOTString(r));
String expecting =
"digraph G {\n" +
@ -70,7 +70,7 @@ public class TestGraphNodes extends TestCase {
}
@Test public void test_$_x() {
PredictionContext r = PredictionContext.merge(PredictionContext.EMPTY, x(), rootIsWildcard());
PredictionContext r = PredictionContext.merge(PredictionContext.EMPTY, x(), rootIsWildcard(), null);
System.out.println(PredictionContext.toDOTString(r));
String expecting =
"digraph G {\n" +
@ -81,7 +81,7 @@ public class TestGraphNodes extends TestCase {
}
@Test public void test_$_x_fullctx() {
PredictionContext r = PredictionContext.merge(PredictionContext.EMPTY, x(), fullCtx());
PredictionContext r = PredictionContext.merge(PredictionContext.EMPTY, x(), fullCtx(), null);
System.out.println(PredictionContext.toDOTString(r));
String expecting =
"digraph G {\n" +
@ -94,7 +94,7 @@ public class TestGraphNodes extends TestCase {
}
@Test public void test_a_a() {
PredictionContext r = PredictionContext.merge(a(), a(), rootIsWildcard());
PredictionContext r = PredictionContext.merge(a(), a(), rootIsWildcard(), null);
System.out.println(PredictionContext.toDOTString(r));
String expecting =
"digraph G {\n" +
@ -110,7 +110,7 @@ public class TestGraphNodes extends TestCase {
PredictionContext a1 = a();
PredictionContext x = x();
PredictionContext a2 = createSingleton(x, 1);
PredictionContext r = PredictionContext.merge(a1, a2, rootIsWildcard());
PredictionContext r = PredictionContext.merge(a1, a2, rootIsWildcard(), null);
System.out.println(PredictionContext.toDOTString(r));
String expecting =
"digraph G {\n" +
@ -126,7 +126,7 @@ public class TestGraphNodes extends TestCase {
PredictionContext a1 = a();
PredictionContext x = x();
PredictionContext a2 = createSingleton(x, 1);
PredictionContext r = PredictionContext.merge(a1, a2, fullCtx());
PredictionContext r = PredictionContext.merge(a1, a2, fullCtx(), null);
System.out.println(PredictionContext.toDOTString(r));
String expecting =
"digraph G {\n" +
@ -144,7 +144,7 @@ public class TestGraphNodes extends TestCase {
PredictionContext x = x();
PredictionContext a1 = createSingleton(x, 1);
PredictionContext a2 = a();
PredictionContext r = PredictionContext.merge(a1, a2, rootIsWildcard());
PredictionContext r = PredictionContext.merge(a1, a2, rootIsWildcard(), null);
System.out.println(PredictionContext.toDOTString(r));
String expecting =
"digraph G {\n" +
@ -160,7 +160,7 @@ public class TestGraphNodes extends TestCase {
PredictionContext x = x();
PredictionContext a1 = createSingleton(x, 1);
PredictionContext a2 = a();
PredictionContext r = PredictionContext.merge(a1, a2, fullCtx());
PredictionContext r = PredictionContext.merge(a1, a2, fullCtx(), null);
System.out.println(PredictionContext.toDOTString(r));
String expecting =
"digraph G {\n" +
@ -175,7 +175,7 @@ public class TestGraphNodes extends TestCase {
}
@Test public void test_a_b() {
PredictionContext r = PredictionContext.merge(a(), b(), rootIsWildcard());
PredictionContext r = PredictionContext.merge(a(), b(), rootIsWildcard(), null);
System.out.println(PredictionContext.toDOTString(r));
String expecting =
"digraph G {\n" +
@ -192,7 +192,7 @@ public class TestGraphNodes extends TestCase {
PredictionContext x = x();
PredictionContext a1 = createSingleton(x, 1);
PredictionContext a2 = createSingleton(x, 1);
PredictionContext r = PredictionContext.merge(a1, a2, rootIsWildcard());
PredictionContext r = PredictionContext.merge(a1, a2, rootIsWildcard(), null);
System.out.println(PredictionContext.toDOTString(r));
String expecting =
"digraph G {\n" +
@ -211,7 +211,7 @@ public class TestGraphNodes extends TestCase {
PredictionContext x2 = x();
PredictionContext a1 = createSingleton(x1, 1);
PredictionContext a2 = createSingleton(x2, 1);
PredictionContext r = PredictionContext.merge(a1, a2, rootIsWildcard());
PredictionContext r = PredictionContext.merge(a1, a2, rootIsWildcard(), null);
System.out.println(PredictionContext.toDOTString(r));
String expecting =
"digraph G {\n" +
@ -232,7 +232,7 @@ public class TestGraphNodes extends TestCase {
PredictionContext b2 = createSingleton(x2, 2);
PredictionContext a1 = createSingleton(b1, 1);
PredictionContext a2 = createSingleton(b2, 1);
PredictionContext r = PredictionContext.merge(a1, a2, rootIsWildcard());
PredictionContext r = PredictionContext.merge(a1, a2, rootIsWildcard(), null);
System.out.println(PredictionContext.toDOTString(r));
String expecting =
"digraph G {\n" +
@ -255,7 +255,7 @@ public class TestGraphNodes extends TestCase {
PredictionContext c = createSingleton(x2, 3);
PredictionContext a1 = createSingleton(b, 1);
PredictionContext a2 = createSingleton(c, 1);
PredictionContext r = PredictionContext.merge(a1, a2, rootIsWildcard());
PredictionContext r = PredictionContext.merge(a1, a2, rootIsWildcard(), null);
System.out.println(PredictionContext.toDOTString(r));
String expecting =
"digraph G {\n" +
@ -276,7 +276,7 @@ public class TestGraphNodes extends TestCase {
PredictionContext x = x();
PredictionContext a = createSingleton(x, 1);
PredictionContext b = createSingleton(x, 2);
PredictionContext r = PredictionContext.merge(a, b, rootIsWildcard());
PredictionContext r = PredictionContext.merge(a, b, rootIsWildcard(), null);
System.out.println(PredictionContext.toDOTString(r));
String expecting =
"digraph G {\n" +
@ -296,7 +296,7 @@ public class TestGraphNodes extends TestCase {
PredictionContext x2 = x();
PredictionContext a = createSingleton(x1, 1);
PredictionContext b = createSingleton(x2, 2);
PredictionContext r = PredictionContext.merge(a, b, rootIsWildcard());
PredictionContext r = PredictionContext.merge(a, b, rootIsWildcard(), null);
System.out.println(PredictionContext.toDOTString(r));
String expecting =
"digraph G {\n" +
@ -314,7 +314,7 @@ public class TestGraphNodes extends TestCase {
@Test public void test_ax_by() {
PredictionContext a = createSingleton(x(), 1);
PredictionContext b = createSingleton(y(), 2);
PredictionContext r = PredictionContext.merge(a, b, rootIsWildcard());
PredictionContext r = PredictionContext.merge(a, b, rootIsWildcard(), null);
System.out.println(PredictionContext.toDOTString(r));
String expecting =
"digraph G {\n" +
@ -335,7 +335,7 @@ public class TestGraphNodes extends TestCase {
PredictionContext x2 = x();
PredictionContext a = a();
PredictionContext b = createSingleton(x2, 2);
PredictionContext r = PredictionContext.merge(a, b, rootIsWildcard());
PredictionContext r = PredictionContext.merge(a, b, rootIsWildcard(), null);
System.out.println(PredictionContext.toDOTString(r));
String expecting =
"digraph G {\n" +
@ -352,7 +352,7 @@ public class TestGraphNodes extends TestCase {
PredictionContext x2 = x();
PredictionContext a = a();
PredictionContext b = createSingleton(x2, 2);
PredictionContext r = PredictionContext.merge(a, b, fullCtx());
PredictionContext r = PredictionContext.merge(a, b, fullCtx(), null);
System.out.println(PredictionContext.toDOTString(r));
String expecting =
"digraph G {\n" +
@ -374,7 +374,7 @@ public class TestGraphNodes extends TestCase {
PredictionContext f = createSingleton(x2, 6);
PredictionContext a = createSingleton(e, 1);
PredictionContext b = createSingleton(f, 2);
PredictionContext r = PredictionContext.merge(a, b, rootIsWildcard());
PredictionContext r = PredictionContext.merge(a, b, rootIsWildcard(), null);
System.out.println(PredictionContext.toDOTString(r));
String expecting =
"digraph G {\n" +
@ -400,7 +400,7 @@ public class TestGraphNodes extends TestCase {
@Test public void test_A$_A$_fullctx() {
ArrayPredictionContext A1 = array(PredictionContext.EMPTY);
ArrayPredictionContext A2 = array(PredictionContext.EMPTY);
PredictionContext r = PredictionContext.merge(A1, A2, fullCtx());
PredictionContext r = PredictionContext.merge(A1, A2, fullCtx(), null);
System.out.println(PredictionContext.toDOTString(r));
String expecting =
"digraph G {\n" +
@ -416,7 +416,7 @@ public class TestGraphNodes extends TestCase {
SingletonPredictionContext c = c();
ArrayPredictionContext A1 = array(a, b);
ArrayPredictionContext A2 = array(c);
PredictionContext r = PredictionContext.merge(A1, A2, rootIsWildcard());
PredictionContext r = PredictionContext.merge(A1, A2, rootIsWildcard(), null);
System.out.println(PredictionContext.toDOTString(r));
String expecting =
"digraph G {\n" +
@ -435,7 +435,7 @@ public class TestGraphNodes extends TestCase {
SingletonPredictionContext a2 = a();
ArrayPredictionContext A1 = array(a1);
ArrayPredictionContext A2 = array(a2);
PredictionContext r = PredictionContext.merge(A1, A2, rootIsWildcard());
PredictionContext r = PredictionContext.merge(A1, A2, rootIsWildcard(), null);
System.out.println(PredictionContext.toDOTString(r));
String expecting =
"digraph G {\n" +
@ -453,7 +453,7 @@ public class TestGraphNodes extends TestCase {
SingletonPredictionContext c = c();
ArrayPredictionContext A1 = array(a);
ArrayPredictionContext A2 = array(b, c);
PredictionContext r = PredictionContext.merge(A1, A2, rootIsWildcard());
PredictionContext r = PredictionContext.merge(A1, A2, rootIsWildcard(), null);
System.out.println(PredictionContext.toDOTString(r));
String expecting =
"digraph G {\n" +
@ -473,7 +473,7 @@ public class TestGraphNodes extends TestCase {
SingletonPredictionContext c = c();
ArrayPredictionContext A1 = array(a, c);
ArrayPredictionContext A2 = array(b);
PredictionContext r = PredictionContext.merge(A1, A2, rootIsWildcard());
PredictionContext r = PredictionContext.merge(A1, A2, rootIsWildcard(), null);
System.out.println(PredictionContext.toDOTString(r));
String expecting =
"digraph G {\n" +
@ -490,7 +490,7 @@ public class TestGraphNodes extends TestCase {
@Test public void test_Aab_Aa() { // a,b + a
ArrayPredictionContext A1 = array(a(), b());
ArrayPredictionContext A2 = array(a());
PredictionContext r = PredictionContext.merge(A1, A2, rootIsWildcard());
PredictionContext r = PredictionContext.merge(A1, A2, rootIsWildcard(), null);
System.out.println(PredictionContext.toDOTString(r));
String expecting =
"digraph G {\n" +
@ -506,7 +506,7 @@ public class TestGraphNodes extends TestCase {
@Test public void test_Aab_Ab() { // a,b + b
ArrayPredictionContext A1 = array(a(), b());
ArrayPredictionContext A2 = array(b());
PredictionContext r = PredictionContext.merge(A1, A2, rootIsWildcard());
PredictionContext r = PredictionContext.merge(A1, A2, rootIsWildcard(), null);
System.out.println(PredictionContext.toDOTString(r));
String expecting =
"digraph G {\n" +
@ -524,7 +524,7 @@ public class TestGraphNodes extends TestCase {
SingletonPredictionContext b = createSingleton(y(), 2);
ArrayPredictionContext A1 = array(a);
ArrayPredictionContext A2 = array(b);
PredictionContext r = PredictionContext.merge(A1, A2, rootIsWildcard());
PredictionContext r = PredictionContext.merge(A1, A2, rootIsWildcard(), null);
System.out.println(PredictionContext.toDOTString(r));
String expecting =
"digraph G {\n" +
@ -546,7 +546,7 @@ public class TestGraphNodes extends TestCase {
SingletonPredictionContext a2 = createSingleton(y(), 1);
ArrayPredictionContext A1 = array(a1);
ArrayPredictionContext A2 = array(a2);
PredictionContext r = PredictionContext.merge(A1, A2, rootIsWildcard());
PredictionContext r = PredictionContext.merge(A1, A2, rootIsWildcard(), null);
System.out.println(PredictionContext.toDOTString(r));
String expecting =
"digraph G {\n" +
@ -566,7 +566,7 @@ public class TestGraphNodes extends TestCase {
SingletonPredictionContext a2 = createSingleton(y(), 1);
ArrayPredictionContext A1 = array(a1, c());
ArrayPredictionContext A2 = array(a2, d());
PredictionContext r = PredictionContext.merge(A1, A2, rootIsWildcard());
PredictionContext r = PredictionContext.merge(A1, A2, rootIsWildcard(), null);
System.out.println(PredictionContext.toDOTString(r));
String expecting =
"digraph G {\n" +
@ -590,7 +590,7 @@ public class TestGraphNodes extends TestCase {
SingletonPredictionContext d = createSingleton(x(), 4);
ArrayPredictionContext A1 = array(a, b);
ArrayPredictionContext A2 = array(c, d);
PredictionContext r = PredictionContext.merge(A1, A2, rootIsWildcard());
PredictionContext r = PredictionContext.merge(A1, A2, rootIsWildcard(), null);
System.out.println(PredictionContext.toDOTString(r));
String expecting =
"digraph G {\n" +
@ -620,7 +620,7 @@ public class TestGraphNodes extends TestCase {
SingletonPredictionContext d = createSingleton(x(), 4);
ArrayPredictionContext A1 = array(a, b1);
ArrayPredictionContext A2 = array(b2, d);
PredictionContext r = PredictionContext.merge(A1, A2, rootIsWildcard());
PredictionContext r = PredictionContext.merge(A1, A2, rootIsWildcard(), null);
System.out.println(PredictionContext.toDOTString(r));
String expecting =
"digraph G {\n" +
@ -647,7 +647,7 @@ public class TestGraphNodes extends TestCase {
SingletonPredictionContext d = createSingleton(x(), 4);
ArrayPredictionContext A1 = array(a, b1);
ArrayPredictionContext A2 = array(b2, d);
PredictionContext r = PredictionContext.merge(A1, A2, rootIsWildcard());
PredictionContext r = PredictionContext.merge(A1, A2, rootIsWildcard(), null);
System.out.println(PredictionContext.toDOTString(r));
String expecting =
"digraph G {\n" +
@ -675,7 +675,7 @@ public class TestGraphNodes extends TestCase {
SingletonPredictionContext d = createSingleton(u(), 4);
ArrayPredictionContext A1 = array(a, b1);
ArrayPredictionContext A2 = array(b2, d);
PredictionContext r = PredictionContext.merge(A1, A2, rootIsWildcard());
PredictionContext r = PredictionContext.merge(A1, A2, rootIsWildcard(), null);
System.out.println(PredictionContext.toDOTString(r));
String expecting =
"digraph G {\n" +
@ -700,7 +700,7 @@ public class TestGraphNodes extends TestCase {
SingletonPredictionContext d = createSingleton(u(), 4);
ArrayPredictionContext A1 = array(a, b);
ArrayPredictionContext A2 = array(c, d);
PredictionContext r = PredictionContext.merge(A1, A2, rootIsWildcard());
PredictionContext r = PredictionContext.merge(A1, A2, rootIsWildcard(), null);
System.out.println(PredictionContext.toDOTString(r));
String expecting =
"digraph G {\n" +