improve combine common parents, return a or b in merge array of merged is a or b; new unit test.

This commit is contained in:
Terence Parr 2012-07-22 20:07:46 -07:00
parent e18b9132d9
commit d8a9207041
2 changed files with 48 additions and 14 deletions

View File

@ -8,6 +8,7 @@ import java.util.ArrayDeque;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Deque; import java.util.Deque;
import java.util.HashMap;
import java.util.IdentityHashMap; import java.util.IdentityHashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
@ -203,7 +204,7 @@ public abstract class PredictionContext implements Iterable<SingletonPredictionC
public static PredictionContext merge(PredictionContext a, PredictionContext b, public static PredictionContext merge(PredictionContext a, PredictionContext b,
boolean rootIsWildcard) boolean rootIsWildcard)
{ {
if ( a.equals(b) ) return a; // share same graph if both same if ( (a==null&&b==null) || a.equals(b) ) return a; // share same graph if both same
if ( a instanceof SingletonPredictionContext && b instanceof SingletonPredictionContext) { if ( a instanceof SingletonPredictionContext && b instanceof SingletonPredictionContext) {
return mergeSingletons((SingletonPredictionContext)a, return mergeSingletons((SingletonPredictionContext)a,
@ -401,7 +402,10 @@ public abstract class PredictionContext implements Iterable<SingletonPredictionC
ArrayPredictionContext M = ArrayPredictionContext M =
new ArrayPredictionContext(mergedParents, mergedInvokingStates); new ArrayPredictionContext(mergedParents, mergedInvokingStates);
// TODO: if we created same array as a or b, return that instead // 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;
combineCommonParents(mergedParents); combineCommonParents(mergedParents);
@ -410,14 +414,19 @@ public abstract class PredictionContext implements Iterable<SingletonPredictionC
/** make pass over all M parents; merge any equals() ones */ /** make pass over all M parents; merge any equals() ones */
protected static void combineCommonParents(PredictionContext[] parents) { protected static void combineCommonParents(PredictionContext[] parents) {
// compare pairwise Map<PredictionContext, PredictionContext> uniqueParents =
for (int i = 0; i < parents.length; i++) { new HashMap<PredictionContext, PredictionContext>();
for (int j = i+1; j < parents.length; j++) {
if ( parents[i].equals(parents[j]) ) { for (int p = 0; p < parents.length; p++) {
parents[j] = parents[i]; // use left one if same PredictionContext parent = parents[p];
} if ( !uniqueParents.containsKey(parent) ) { // don't replace
uniqueParents.put(parent, parent);
} }
} }
for (int p = 0; p < parents.length; p++) {
parents[p] = uniqueParents.get(parents[p]);
}
} }
public static String toDotString(PredictionContext context) { public static String toDotString(PredictionContext context) {

View File

@ -491,10 +491,10 @@ public class TestGraphNodes extends TestCase {
String expecting = String expecting =
"digraph G {\n" + "digraph G {\n" +
"rankdir=LR;\n" + "rankdir=LR;\n" +
" s6 [shape=box, label=\"[1, 2]\"];\n" + " s3 [shape=box, label=\"[1, 2]\"];\n" +
" s0 [label=\"$\"];\n" + " s0 [label=\"$\"];\n" +
" s6->s0 [label=\"parent[0]\"];\n" + " s3->s0 [label=\"parent[0]\"];\n" +
" s6->s0 [label=\"parent[1]\"];\n" + " s3->s0 [label=\"parent[1]\"];\n" +
"}\n"; "}\n";
assertEquals(expecting, PredictionContext.toDotString(r)); assertEquals(expecting, PredictionContext.toDotString(r));
} }
@ -507,10 +507,10 @@ public class TestGraphNodes extends TestCase {
String expecting = String expecting =
"digraph G {\n" + "digraph G {\n" +
"rankdir=LR;\n" + "rankdir=LR;\n" +
" s6 [shape=box, label=\"[1, 2]\"];\n" + " s3 [shape=box, label=\"[1, 2]\"];\n" +
" s0 [label=\"$\"];\n" + " s0 [label=\"$\"];\n" +
" s6->s0 [label=\"parent[0]\"];\n" + " s3->s0 [label=\"parent[0]\"];\n" +
" s6->s0 [label=\"parent[1]\"];\n" + " s3->s0 [label=\"parent[1]\"];\n" +
"}\n"; "}\n";
assertEquals(expecting, PredictionContext.toDotString(r)); assertEquals(expecting, PredictionContext.toDotString(r));
} }
@ -689,6 +689,31 @@ public class TestGraphNodes extends TestCase {
assertEquals(expecting, PredictionContext.toDotString(r)); assertEquals(expecting, PredictionContext.toDotString(r));
} }
@Test public void test_Aaubu_Acudu() { // au,bu + cu,du -> [a,b,c,d]->[u,u,u,u]
SingletonPredictionContext a = createSingleton(u(), 1);
SingletonPredictionContext b = createSingleton(u(), 2);
SingletonPredictionContext c = createSingleton(u(), 3);
SingletonPredictionContext d = createSingleton(u(), 4);
ArrayPredictionContext A1 = array(a, b);
ArrayPredictionContext A2 = array(c, d);
PredictionContext r = PredictionContext.merge(A1, A2, rootIsWildcard());
System.out.println(PredictionContext.toDotString(r));
String expecting =
"digraph G {\n" +
"rankdir=LR;\n" +
" s11 [shape=box, label=\"[1, 2, 3, 4]\"];\n" +
" s1 [label=\"6\"];\n" +
" s0 [label=\"$\"];\n" +
" s11->s1 [label=\"parent[0]\"];\n" +
" s11->s1 [label=\"parent[1]\"];\n" +
" s11->s1 [label=\"parent[2]\"];\n" +
" s11->s1 [label=\"parent[3]\"];\n" +
" s1->s0;\n" +
"}\n";
assertEquals(expecting, PredictionContext.toDotString(r));
}
// ------------ SUPPORT ------------------------- // ------------ SUPPORT -------------------------
protected SingletonPredictionContext a() { protected SingletonPredictionContext a() {