only 14 unit tests fail.

This commit is contained in:
Terence Parr 2012-07-27 17:38:02 -07:00
parent b8f072e231
commit 14372f2515
2 changed files with 64 additions and 51 deletions

View File

@ -29,6 +29,7 @@
package org.antlr.v4.runtime.atn;
import org.antlr.v4.runtime.misc.Array2DHashSet;
import org.antlr.v4.runtime.misc.IntervalSet;
import org.antlr.v4.runtime.misc.Nullable;
@ -36,7 +37,6 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Set;
@ -188,6 +188,20 @@ public class ATNConfigSet implements Set<ATNConfig> {
}
}
public static class ConfigHashSet extends Array2DHashSet<ATNConfig> {
public int hashCode(ATNConfig o) {
return o.hashCode();
}
public boolean equals(ATNConfig a, ATNConfig b) {
if ( a==null && b==null ) return true;
if ( a==null || b==null ) return false;
if ( a==b ) return true;
if ( hashCode(a) != hashCode(b) ) return false;
return a.equals(b);
}
}
/** Indicates that the set of configurations is read-only. Do not
* allow any code to manipulate the set; DFA states will point at
* the sets and they must not change. This does not protect the other
@ -197,11 +211,13 @@ public class ATNConfigSet implements Set<ATNConfig> {
protected boolean readonly = false;
/** Track every config we add */
public final LinkedHashMap<Key,ATNConfig> configToContext;
// public final LinkedHashMap<Key,ATNConfig> configToContext;
/** All configs but hashed by (s, i, _, pi) not incl context */
public final ConfigHashSet configLookup;
/** Track the elements as they are added to the set; supports get(i) */
// too hard to keep in sync
// public final ArrayList<ATNConfig> configs = new ArrayList<ATNConfig>();
public final ArrayList<ATNConfig> configs = new ArrayList<ATNConfig>();
// TODO: these fields make me pretty uncomfortable but nice to pack up info together, saves recomputation
// TODO: can we track conflicts as they are added to save scanning configs later?
@ -219,14 +235,14 @@ public class ATNConfigSet implements Set<ATNConfig> {
public final boolean fullCtx;
public ATNConfigSet(boolean fullCtx) {
configToContext = new LinkedHashMap<Key, ATNConfig>();
configLookup = new ConfigHashSet();
this.fullCtx = fullCtx;
}
public ATNConfigSet() { this(true); }
public ATNConfigSet(ATNConfigSet old, PredictionContextCache contextCache) {
configToContext = new LinkedHashMap<Key, ATNConfig>(old.configToContext);
this.fullCtx = old.fullCtx;
this(old.fullCtx);
addAll(old, contextCache);
this.uniqueAlt = old.uniqueAlt;
this.conflictingAlts = old.conflictingAlts;
this.hasSemanticContext = old.hasSemanticContext;
@ -249,9 +265,10 @@ public class ATNConfigSet implements Set<ATNConfig> {
hasSemanticContext = true;
}
Key key = new Key(config);
ATNConfig existing = configToContext.get(key);
ATNConfig existing = configLookup.get(config);
if ( existing==null ) { // nothing there yet; easy, just add
configToContext.put(key, config);
configLookup.add(config);
configs.add(config); // track order here
return true;
}
// a previous (s,i,pi,_), merge with it and save result
@ -269,23 +286,19 @@ public class ATNConfigSet implements Set<ATNConfig> {
}
/** Return a List holding list of configs */
public List<ATNConfig> elements() {
List<ATNConfig> configs = new ArrayList<ATNConfig>();
configs.addAll(configToContext.values());
return configs;
}
public List<ATNConfig> elements() { return configs; }
public Set<ATNState> getStates() {
Set<ATNState> states = new HashSet<ATNState>();
for (Key key : this.configToContext.keySet()) {
states.add(key.state);
for (ATNConfig c : configs) {
states.add(c.state);
}
return states;
}
public List<SemanticContext> getPredicates() {
List<SemanticContext> preds = new ArrayList<SemanticContext>();
for (ATNConfig c : configToContext.values()) {
for (ATNConfig c : configs) {
if ( c.semanticContext!=SemanticContext.NONE ) {
preds.add(c.semanticContext);
}
@ -293,27 +306,21 @@ public class ATNConfigSet implements Set<ATNConfig> {
return preds;
}
// TODO: very expensive, used in lexer to kill after wildcard config
public ATNConfig get(int i) {
int j = 0;
for (ATNConfig c : configToContext.values()) {
if ( j == i ) return c;
j++;
}
throw new IndexOutOfBoundsException("config set index "+i+" not in 0.."+size());
}
public ATNConfig get(int i) { return configs.get(i); }
// TODO: very expensive, used in lexer to kill after wildcard config
public void remove(int i) {
if ( readonly ) throw new IllegalStateException("This set is readonly");
ATNConfig c = elements().get(i);
configToContext.remove(new Key(c));
configLookup.remove(c);
configs.remove(c); // slow linear search. ugh but not worse than it was
}
public void optimizeConfigs(ATNSimulator interpreter) {
if ( readonly ) throw new IllegalStateException("This set is readonly");
if ( configToContext.isEmpty() ) return;
if ( configLookup.isEmpty() ) return;
for (ATNConfig config : configToContext.values()) {
for (ATNConfig config : configs) {
// int before = PredictionContext.getAllContextNodes(config.context).size();
config.context = interpreter.getCachedContext(config.context);
// int after = PredictionContext.getAllContextNodes(config.context).size();
@ -339,8 +346,8 @@ public class ATNConfigSet implements Set<ATNConfig> {
public boolean equals(Object o) {
// System.out.print("equals " + this + ", " + o+" = ");
ATNConfigSet other = (ATNConfigSet)o;
boolean same = configToContext!=null &&
configToContext.equals(other.configToContext) &&
boolean same = configLookup!=null &&
configLookup.equals(other.configLookup) &&
this.fullCtx == other.fullCtx &&
this.uniqueAlt == other.uniqueAlt &&
this.conflictingAlts == other.conflictingAlts &&
@ -353,36 +360,36 @@ public class ATNConfigSet implements Set<ATNConfig> {
@Override
public int hashCode() {
return configToContext.hashCode();
return configLookup.hashCode();
}
@Override
public int size() {
return configToContext.size();
return configLookup.size();
}
@Override
public boolean isEmpty() {
return configToContext.isEmpty();
return configLookup.isEmpty();
}
@Override
public boolean contains(Object o) {
if ( o instanceof ATNConfig ) {
return configToContext.containsKey(new Key((ATNConfig)o));
return configLookup.contains(o);
}
return false;
}
@Override
public Iterator<ATNConfig> iterator() {
return configToContext.values().iterator();
return configs.iterator();
}
@Override
public void clear() {
if ( readonly ) throw new IllegalStateException("This set is readonly");
configToContext.clear();
configLookup.clear();
}
public void setReadonly(boolean readonly) {
@ -405,16 +412,16 @@ public class ATNConfigSet implements Set<ATNConfig> {
@Override
public Object[] toArray() {
ATNConfig[] configs = new ATNConfig[configToContext.size()];
ATNConfig[] configs = new ATNConfig[configLookup.size()];
int i = 0;
for (ATNConfig c : configToContext.values()) configs[i++] = c;
for (ATNConfig c : configLookup) configs[i++] = c;
return configs;
}
@Override
public <T> T[] toArray(T[] a) {
int i = 0;
for (ATNConfig c : configToContext.values()) a[i++] = (T)c;
for (ATNConfig c : configLookup) a[i++] = (T)c;
return a;
}

View File

@ -5,7 +5,7 @@ import java.util.Iterator;
import java.util.Set;
/** Set impl with closed hashing (open addressing). */
public class FlexHashingSet<T> implements Set<T> {
public class Array2DHashSet<T> implements Set<T> {
public static final int INITAL_CAPACITY = 4;
public static final int INITAL_BUCKET_CAPACITY = 2;
@ -20,7 +20,7 @@ public class FlexHashingSet<T> implements Set<T> {
protected int currentPrime = 1; // jump by 4 primes each expand or whatever
public FlexHashingSet() {
public Array2DHashSet() {
buckets = (T[][])new Object[INITAL_CAPACITY][];
}
@ -92,8 +92,8 @@ public class FlexHashingSet<T> implements Set<T> {
@Override
public boolean equals(Object o) {
if (o == this) return true;
if ( !(o instanceof FlexHashingSet) || o==null ) return false;
FlexHashingSet<T> other = (FlexHashingSet<T>)o;
if ( !(o instanceof Array2DHashSet) || o==null ) return false;
Array2DHashSet<T> other = (Array2DHashSet<T>)o;
if ( other.size() != size() ) return false;
return containsAll(other);
}
@ -105,7 +105,7 @@ public class FlexHashingSet<T> implements Set<T> {
T[][] newTable = (T[][])new Object[newCapacity][];
buckets = newTable;
threshold = (int)(newCapacity * LOAD_FACTOR);
System.out.println("new size="+newCapacity+", thres="+threshold);
// System.out.println("new size="+newCapacity+", thres="+threshold);
// rehash all existing entries
int oldSize = size();
for (T[] bucket : old) {
@ -126,6 +126,7 @@ public class FlexHashingSet<T> implements Set<T> {
if ( a==null && b==null ) return true;
if ( a==null || b==null ) return false;
if ( a==b ) return true;
if ( hashCode(a) != hashCode(b) ) return false;
return a.equals(b);
}
@ -220,15 +221,20 @@ public class FlexHashingSet<T> implements Set<T> {
}
@Override
public boolean containsAll(Collection<?> c) {
if ( c instanceof FlexHashingSet) {
for (Object o : ((FlexHashingSet<?>)c).buckets) {
if ( o!=null && !contains(o) ) return false;
public boolean containsAll(Collection<?> collection) {
if ( collection instanceof Array2DHashSet ) {
Array2DHashSet<T> s = (Array2DHashSet<T>)collection;
for (T[] bucket : s.buckets) {
if ( bucket==null ) continue;
for (T o : bucket) {
if ( o==null ) break;
if ( !this.contains(o) ) return false;
}
}
}
else {
for (Object o : c) {
if ( !contains(o) ) return false;
for (Object o : collection) {
if ( !this.contains(o) ) return false;
}
}
return true;
@ -300,7 +306,7 @@ public class FlexHashingSet<T> implements Set<T> {
}
public static void main(String[] args) {
FlexHashingSet<String> clset = new FlexHashingSet<String>();
Array2DHashSet<String> clset = new Array2DHashSet<String>();
Set<String> set = clset;
set.add("hi");
set.add("mom");