only 14 unit tests fail.
This commit is contained in:
parent
b8f072e231
commit
14372f2515
|
@ -29,6 +29,7 @@
|
||||||
|
|
||||||
package org.antlr.v4.runtime.atn;
|
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.IntervalSet;
|
||||||
import org.antlr.v4.runtime.misc.Nullable;
|
import org.antlr.v4.runtime.misc.Nullable;
|
||||||
|
|
||||||
|
@ -36,7 +37,6 @@ import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
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
|
/** Indicates that the set of configurations is read-only. Do not
|
||||||
* allow any code to manipulate the set; DFA states will point at
|
* 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
|
* 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;
|
protected boolean readonly = false;
|
||||||
|
|
||||||
/** Track every config we add */
|
/** 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) */
|
/** Track the elements as they are added to the set; supports get(i) */
|
||||||
// too hard to keep in sync
|
// 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: 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?
|
// 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 final boolean fullCtx;
|
||||||
|
|
||||||
public ATNConfigSet(boolean fullCtx) {
|
public ATNConfigSet(boolean fullCtx) {
|
||||||
configToContext = new LinkedHashMap<Key, ATNConfig>();
|
configLookup = new ConfigHashSet();
|
||||||
this.fullCtx = fullCtx;
|
this.fullCtx = fullCtx;
|
||||||
}
|
}
|
||||||
public ATNConfigSet() { this(true); }
|
public ATNConfigSet() { this(true); }
|
||||||
|
|
||||||
public ATNConfigSet(ATNConfigSet old, PredictionContextCache contextCache) {
|
public ATNConfigSet(ATNConfigSet old, PredictionContextCache contextCache) {
|
||||||
configToContext = new LinkedHashMap<Key, ATNConfig>(old.configToContext);
|
this(old.fullCtx);
|
||||||
this.fullCtx = old.fullCtx;
|
addAll(old, contextCache);
|
||||||
this.uniqueAlt = old.uniqueAlt;
|
this.uniqueAlt = old.uniqueAlt;
|
||||||
this.conflictingAlts = old.conflictingAlts;
|
this.conflictingAlts = old.conflictingAlts;
|
||||||
this.hasSemanticContext = old.hasSemanticContext;
|
this.hasSemanticContext = old.hasSemanticContext;
|
||||||
|
@ -249,9 +265,10 @@ public class ATNConfigSet implements Set<ATNConfig> {
|
||||||
hasSemanticContext = true;
|
hasSemanticContext = true;
|
||||||
}
|
}
|
||||||
Key key = new Key(config);
|
Key key = new Key(config);
|
||||||
ATNConfig existing = configToContext.get(key);
|
ATNConfig existing = configLookup.get(config);
|
||||||
if ( existing==null ) { // nothing there yet; easy, just add
|
if ( existing==null ) { // nothing there yet; easy, just add
|
||||||
configToContext.put(key, config);
|
configLookup.add(config);
|
||||||
|
configs.add(config); // track order here
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// a previous (s,i,pi,_), merge with it and save result
|
// 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 */
|
/** Return a List holding list of configs */
|
||||||
public List<ATNConfig> elements() {
|
public List<ATNConfig> elements() { return configs; }
|
||||||
List<ATNConfig> configs = new ArrayList<ATNConfig>();
|
|
||||||
configs.addAll(configToContext.values());
|
|
||||||
return configs;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Set<ATNState> getStates() {
|
public Set<ATNState> getStates() {
|
||||||
Set<ATNState> states = new HashSet<ATNState>();
|
Set<ATNState> states = new HashSet<ATNState>();
|
||||||
for (Key key : this.configToContext.keySet()) {
|
for (ATNConfig c : configs) {
|
||||||
states.add(key.state);
|
states.add(c.state);
|
||||||
}
|
}
|
||||||
return states;
|
return states;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<SemanticContext> getPredicates() {
|
public List<SemanticContext> getPredicates() {
|
||||||
List<SemanticContext> preds = new ArrayList<SemanticContext>();
|
List<SemanticContext> preds = new ArrayList<SemanticContext>();
|
||||||
for (ATNConfig c : configToContext.values()) {
|
for (ATNConfig c : configs) {
|
||||||
if ( c.semanticContext!=SemanticContext.NONE ) {
|
if ( c.semanticContext!=SemanticContext.NONE ) {
|
||||||
preds.add(c.semanticContext);
|
preds.add(c.semanticContext);
|
||||||
}
|
}
|
||||||
|
@ -293,27 +306,21 @@ public class ATNConfigSet implements Set<ATNConfig> {
|
||||||
return preds;
|
return preds;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: very expensive, used in lexer to kill after wildcard config
|
public ATNConfig get(int i) { return configs.get(i); }
|
||||||
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());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// TODO: very expensive, used in lexer to kill after wildcard config
|
||||||
public void remove(int i) {
|
public void remove(int i) {
|
||||||
if ( readonly ) throw new IllegalStateException("This set is readonly");
|
if ( readonly ) throw new IllegalStateException("This set is readonly");
|
||||||
ATNConfig c = elements().get(i);
|
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) {
|
public void optimizeConfigs(ATNSimulator interpreter) {
|
||||||
if ( readonly ) throw new IllegalStateException("This set is readonly");
|
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();
|
// int before = PredictionContext.getAllContextNodes(config.context).size();
|
||||||
config.context = interpreter.getCachedContext(config.context);
|
config.context = interpreter.getCachedContext(config.context);
|
||||||
// int after = PredictionContext.getAllContextNodes(config.context).size();
|
// int after = PredictionContext.getAllContextNodes(config.context).size();
|
||||||
|
@ -339,8 +346,8 @@ public class ATNConfigSet implements Set<ATNConfig> {
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
// System.out.print("equals " + this + ", " + o+" = ");
|
// System.out.print("equals " + this + ", " + o+" = ");
|
||||||
ATNConfigSet other = (ATNConfigSet)o;
|
ATNConfigSet other = (ATNConfigSet)o;
|
||||||
boolean same = configToContext!=null &&
|
boolean same = configLookup!=null &&
|
||||||
configToContext.equals(other.configToContext) &&
|
configLookup.equals(other.configLookup) &&
|
||||||
this.fullCtx == other.fullCtx &&
|
this.fullCtx == other.fullCtx &&
|
||||||
this.uniqueAlt == other.uniqueAlt &&
|
this.uniqueAlt == other.uniqueAlt &&
|
||||||
this.conflictingAlts == other.conflictingAlts &&
|
this.conflictingAlts == other.conflictingAlts &&
|
||||||
|
@ -353,36 +360,36 @@ public class ATNConfigSet implements Set<ATNConfig> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return configToContext.hashCode();
|
return configLookup.hashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int size() {
|
public int size() {
|
||||||
return configToContext.size();
|
return configLookup.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isEmpty() {
|
public boolean isEmpty() {
|
||||||
return configToContext.isEmpty();
|
return configLookup.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean contains(Object o) {
|
public boolean contains(Object o) {
|
||||||
if ( o instanceof ATNConfig ) {
|
if ( o instanceof ATNConfig ) {
|
||||||
return configToContext.containsKey(new Key((ATNConfig)o));
|
return configLookup.contains(o);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Iterator<ATNConfig> iterator() {
|
public Iterator<ATNConfig> iterator() {
|
||||||
return configToContext.values().iterator();
|
return configs.iterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void clear() {
|
public void clear() {
|
||||||
if ( readonly ) throw new IllegalStateException("This set is readonly");
|
if ( readonly ) throw new IllegalStateException("This set is readonly");
|
||||||
configToContext.clear();
|
configLookup.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setReadonly(boolean readonly) {
|
public void setReadonly(boolean readonly) {
|
||||||
|
@ -405,16 +412,16 @@ public class ATNConfigSet implements Set<ATNConfig> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object[] toArray() {
|
public Object[] toArray() {
|
||||||
ATNConfig[] configs = new ATNConfig[configToContext.size()];
|
ATNConfig[] configs = new ATNConfig[configLookup.size()];
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (ATNConfig c : configToContext.values()) configs[i++] = c;
|
for (ATNConfig c : configLookup) configs[i++] = c;
|
||||||
return configs;
|
return configs;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> T[] toArray(T[] a) {
|
public <T> T[] toArray(T[] a) {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (ATNConfig c : configToContext.values()) a[i++] = (T)c;
|
for (ATNConfig c : configLookup) a[i++] = (T)c;
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ import java.util.Iterator;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/** Set impl with closed hashing (open addressing). */
|
/** 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_CAPACITY = 4;
|
||||||
public static final int INITAL_BUCKET_CAPACITY = 2;
|
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
|
protected int currentPrime = 1; // jump by 4 primes each expand or whatever
|
||||||
|
|
||||||
public FlexHashingSet() {
|
public Array2DHashSet() {
|
||||||
buckets = (T[][])new Object[INITAL_CAPACITY][];
|
buckets = (T[][])new Object[INITAL_CAPACITY][];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,8 +92,8 @@ public class FlexHashingSet<T> implements Set<T> {
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (o == this) return true;
|
if (o == this) return true;
|
||||||
if ( !(o instanceof FlexHashingSet) || o==null ) return false;
|
if ( !(o instanceof Array2DHashSet) || o==null ) return false;
|
||||||
FlexHashingSet<T> other = (FlexHashingSet<T>)o;
|
Array2DHashSet<T> other = (Array2DHashSet<T>)o;
|
||||||
if ( other.size() != size() ) return false;
|
if ( other.size() != size() ) return false;
|
||||||
return containsAll(other);
|
return containsAll(other);
|
||||||
}
|
}
|
||||||
|
@ -105,7 +105,7 @@ public class FlexHashingSet<T> implements Set<T> {
|
||||||
T[][] newTable = (T[][])new Object[newCapacity][];
|
T[][] newTable = (T[][])new Object[newCapacity][];
|
||||||
buckets = newTable;
|
buckets = newTable;
|
||||||
threshold = (int)(newCapacity * LOAD_FACTOR);
|
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
|
// rehash all existing entries
|
||||||
int oldSize = size();
|
int oldSize = size();
|
||||||
for (T[] bucket : old) {
|
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 true;
|
||||||
if ( a==null || b==null ) return false;
|
if ( a==null || b==null ) return false;
|
||||||
if ( a==b ) return true;
|
if ( a==b ) return true;
|
||||||
|
if ( hashCode(a) != hashCode(b) ) return false;
|
||||||
return a.equals(b);
|
return a.equals(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -220,15 +221,20 @@ public class FlexHashingSet<T> implements Set<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean containsAll(Collection<?> c) {
|
public boolean containsAll(Collection<?> collection) {
|
||||||
if ( c instanceof FlexHashingSet) {
|
if ( collection instanceof Array2DHashSet ) {
|
||||||
for (Object o : ((FlexHashingSet<?>)c).buckets) {
|
Array2DHashSet<T> s = (Array2DHashSet<T>)collection;
|
||||||
if ( o!=null && !contains(o) ) return false;
|
for (T[] bucket : s.buckets) {
|
||||||
|
if ( bucket==null ) continue;
|
||||||
|
for (T o : bucket) {
|
||||||
|
if ( o==null ) break;
|
||||||
|
if ( !this.contains(o) ) return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
for (Object o : c) {
|
for (Object o : collection) {
|
||||||
if ( !contains(o) ) return false;
|
if ( !this.contains(o) ) return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -300,7 +306,7 @@ public class FlexHashingSet<T> implements Set<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
FlexHashingSet<String> clset = new FlexHashingSet<String>();
|
Array2DHashSet<String> clset = new Array2DHashSet<String>();
|
||||||
Set<String> set = clset;
|
Set<String> set = clset;
|
||||||
set.add("hi");
|
set.add("hi");
|
||||||
set.add("mom");
|
set.add("mom");
|
Loading…
Reference in New Issue