forked from jasder/antlr
Merge branch 'equalitycomparator' of github.com:sharwell/antlr4
This commit is contained in:
commit
d3edfd1c71
|
@ -30,6 +30,7 @@
|
||||||
|
|
||||||
package org.antlr.v4.runtime.atn;
|
package org.antlr.v4.runtime.atn;
|
||||||
|
|
||||||
|
import org.antlr.v4.runtime.misc.AbstractEqualityComparator;
|
||||||
import org.antlr.v4.runtime.misc.Array2DHashSet;
|
import org.antlr.v4.runtime.misc.Array2DHashSet;
|
||||||
import org.antlr.v4.runtime.misc.DoubleKeyMap;
|
import org.antlr.v4.runtime.misc.DoubleKeyMap;
|
||||||
|
|
||||||
|
@ -239,7 +240,14 @@ public class ATNConfigSet implements Set<ATNConfig> {
|
||||||
*/
|
*/
|
||||||
public static class ConfigHashSet extends Array2DHashSet<ATNConfig> {
|
public static class ConfigHashSet extends Array2DHashSet<ATNConfig> {
|
||||||
public ConfigHashSet() {
|
public ConfigHashSet() {
|
||||||
super(16,2);
|
super(ConfigEqualityComparator.INSTANCE,16,2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class ConfigEqualityComparator extends AbstractEqualityComparator<ATNConfig> {
|
||||||
|
public static final ConfigEqualityComparator INSTANCE = new ConfigEqualityComparator();
|
||||||
|
|
||||||
|
private ConfigEqualityComparator() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -273,7 +281,7 @@ public class ATNConfigSet implements Set<ATNConfig> {
|
||||||
/** All configs but hashed by (s, i, _, pi) not incl context. Wiped out
|
/** All configs but hashed by (s, i, _, pi) not incl context. Wiped out
|
||||||
* when we go readonly as this set becomes a DFA state.
|
* when we go readonly as this set becomes a DFA state.
|
||||||
*/
|
*/
|
||||||
public ConfigHashSet configLookup;
|
public Array2DHashSet<ATNConfig> 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) */
|
||||||
public final ArrayList<ATNConfig> configs = new ArrayList<ATNConfig>(7);
|
public final ArrayList<ATNConfig> configs = new ArrayList<ATNConfig>(7);
|
||||||
|
|
|
@ -30,6 +30,9 @@
|
||||||
|
|
||||||
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.ObjectEqualityComparator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Sam Harwell
|
* @author Sam Harwell
|
||||||
|
@ -40,18 +43,9 @@ public class OrderedATNConfigSet extends ATNConfigSet {
|
||||||
this.configLookup = new LexerConfigHashSet();
|
this.configLookup = new LexerConfigHashSet();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static class LexerConfigHashSet extends ConfigHashSet {
|
public static class LexerConfigHashSet extends Array2DHashSet<ATNConfig> {
|
||||||
|
public LexerConfigHashSet() {
|
||||||
@Override
|
super(ObjectEqualityComparator.INSTANCE, 16, 2);
|
||||||
public int hashCode(ATNConfig o) {
|
|
||||||
return o.hashCode();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(ATNConfig a, ATNConfig b) {
|
|
||||||
return a.equals(b);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package org.antlr.v4.runtime.atn;
|
package org.antlr.v4.runtime.atn;
|
||||||
|
|
||||||
|
import org.antlr.v4.runtime.misc.AbstractEqualityComparator;
|
||||||
import org.antlr.v4.runtime.misc.FlexibleHashMap;
|
import org.antlr.v4.runtime.misc.FlexibleHashMap;
|
||||||
import org.antlr.v4.runtime.misc.NotNull;
|
import org.antlr.v4.runtime.misc.NotNull;
|
||||||
|
|
||||||
|
@ -34,6 +35,17 @@ public enum PredictionMode {
|
||||||
|
|
||||||
/** A Map that uses just the state and the stack context as the key. */
|
/** A Map that uses just the state and the stack context as the key. */
|
||||||
static class AltAndContextMap extends FlexibleHashMap<ATNConfig,BitSet> {
|
static class AltAndContextMap extends FlexibleHashMap<ATNConfig,BitSet> {
|
||||||
|
public AltAndContextMap() {
|
||||||
|
super(AltAndContextConfigEqualityComparator.INSTANCE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class AltAndContextConfigEqualityComparator extends AbstractEqualityComparator<ATNConfig> {
|
||||||
|
public static final AltAndContextConfigEqualityComparator INSTANCE = new AltAndContextConfigEqualityComparator();
|
||||||
|
|
||||||
|
private AltAndContextConfigEqualityComparator() {
|
||||||
|
}
|
||||||
|
|
||||||
/** Code is function of (s, _, ctx, _) */
|
/** Code is function of (s, _, ctx, _) */
|
||||||
@Override
|
@Override
|
||||||
public int hashCode(ATNConfig o) {
|
public int hashCode(ATNConfig o) {
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
* [The "BSD license"]
|
||||||
|
* Copyright (c) 2012 Terence Parr
|
||||||
|
* Copyright (c) 2012 Sam Harwell
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. The name of the author may not be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
package org.antlr.v4.runtime.misc;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This abstract base class is provided so performance-critical applications can
|
||||||
|
* use virtual- instead of interface-dispatch when calling comparator methods.
|
||||||
|
*
|
||||||
|
* @author Sam Harwell
|
||||||
|
*/
|
||||||
|
public abstract class AbstractEqualityComparator<T> implements EqualityComparator<T> {
|
||||||
|
|
||||||
|
}
|
|
@ -6,11 +6,14 @@ import java.util.NoSuchElementException;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/** Set impl with closed hashing (open addressing). */
|
/** Set impl with closed hashing (open addressing). */
|
||||||
public class Array2DHashSet<T> implements EquivalenceSet<T> {
|
public class Array2DHashSet<T> implements Set<T> {
|
||||||
public static final int INITAL_CAPACITY = 16; // must be power of 2
|
public static final int INITAL_CAPACITY = 16; // must be power of 2
|
||||||
public static final int INITAL_BUCKET_CAPACITY = 8;
|
public static final int INITAL_BUCKET_CAPACITY = 8;
|
||||||
public static final double LOAD_FACTOR = 0.75;
|
public static final double LOAD_FACTOR = 0.75;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
protected final AbstractEqualityComparator<? super T> comparator;
|
||||||
|
|
||||||
protected T[][] buckets;
|
protected T[][] buckets;
|
||||||
|
|
||||||
/** How many elements in set */
|
/** How many elements in set */
|
||||||
|
@ -22,11 +25,20 @@ public class Array2DHashSet<T> implements EquivalenceSet<T> {
|
||||||
protected int initialBucketCapacity = INITAL_BUCKET_CAPACITY;
|
protected int initialBucketCapacity = INITAL_BUCKET_CAPACITY;
|
||||||
|
|
||||||
public Array2DHashSet() {
|
public Array2DHashSet() {
|
||||||
this(INITAL_CAPACITY, INITAL_BUCKET_CAPACITY);
|
this(null, INITAL_CAPACITY, INITAL_BUCKET_CAPACITY);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Array2DHashSet(int initialCapacity, int initialBucketCapacity) {
|
public Array2DHashSet(@Nullable AbstractEqualityComparator<? super T> comparator) {
|
||||||
buckets = (T[][])new Object[initialCapacity][];
|
this(comparator, INITAL_CAPACITY, INITAL_BUCKET_CAPACITY);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Array2DHashSet(@Nullable AbstractEqualityComparator<? super T> comparator, int initialCapacity, int initialBucketCapacity) {
|
||||||
|
if (comparator == null) {
|
||||||
|
comparator = ObjectEqualityComparator.INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.comparator = comparator;
|
||||||
|
this.buckets = (T[][])new Object[initialCapacity][];
|
||||||
this.initialBucketCapacity = initialBucketCapacity;
|
this.initialBucketCapacity = initialBucketCapacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,7 +68,7 @@ public class Array2DHashSet<T> implements EquivalenceSet<T> {
|
||||||
n++;
|
n++;
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
if ( equals(existing, o) ) return existing; // found existing, quit
|
if ( comparator.equals(existing, o) ) return existing; // found existing, quit
|
||||||
}
|
}
|
||||||
// FULL BUCKET, expand and add to end
|
// FULL BUCKET, expand and add to end
|
||||||
T[] old = bucket;
|
T[] old = bucket;
|
||||||
|
@ -75,13 +87,13 @@ public class Array2DHashSet<T> implements EquivalenceSet<T> {
|
||||||
if ( bucket==null ) return null; // no bucket
|
if ( bucket==null ) return null; // no bucket
|
||||||
for (T e : bucket) {
|
for (T e : bucket) {
|
||||||
if ( e==null ) return null; // empty slot; not there
|
if ( e==null ) return null; // empty slot; not there
|
||||||
if ( equals(e, o) ) return e;
|
if ( comparator.equals(e, o) ) return e;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected int getBucket(T o) {
|
protected int getBucket(T o) {
|
||||||
int hash = hashCode(o);
|
int hash = comparator.hashCode(o);
|
||||||
int b = hash & (buckets.length-1); // assumes len is power of 2
|
int b = hash & (buckets.length-1); // assumes len is power of 2
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
@ -93,7 +105,7 @@ public class Array2DHashSet<T> implements EquivalenceSet<T> {
|
||||||
if ( bucket==null ) continue;
|
if ( bucket==null ) continue;
|
||||||
for (T o : bucket) {
|
for (T o : bucket) {
|
||||||
if ( o==null ) break;
|
if ( o==null ) break;
|
||||||
h += hashCode(o);
|
h += comparator.hashCode(o);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return h;
|
return h;
|
||||||
|
@ -129,14 +141,6 @@ public class Array2DHashSet<T> implements EquivalenceSet<T> {
|
||||||
n = oldSize;
|
n = oldSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int hashCode(T o) {
|
|
||||||
return o.hashCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean equals(T a, T b) {
|
|
||||||
return a.equals(b);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean add(T t) {
|
public boolean add(T t) {
|
||||||
T existing = absorb(t);
|
T existing = absorb(t);
|
||||||
|
@ -229,7 +233,7 @@ public class Array2DHashSet<T> implements EquivalenceSet<T> {
|
||||||
for (int i=0; i<bucket.length; i++) {
|
for (int i=0; i<bucket.length; i++) {
|
||||||
T e = bucket[i];
|
T e = bucket[i];
|
||||||
if ( e==null ) return false; // empty slot; not there
|
if ( e==null ) return false; // empty slot; not there
|
||||||
if ( equals(e, (T) o) ) { // found it
|
if ( comparator.equals(e, (T) o) ) { // found it
|
||||||
// shift all elements to the right down one
|
// shift all elements to the right down one
|
||||||
// for (int j=i; j<bucket.length-1; j++) bucket[j] = bucket[j+1];
|
// for (int j=i; j<bucket.length-1; j++) bucket[j] = bucket[j+1];
|
||||||
System.arraycopy(bucket, i+1, bucket, i, bucket.length-i-1);
|
System.arraycopy(bucket, i+1, bucket, i, bucket.length-i-1);
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
/*
|
||||||
|
* [The "BSD license"]
|
||||||
|
* Copyright (c) 2012 Terence Parr
|
||||||
|
* Copyright (c) 2012 Sam Harwell
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. The name of the author may not be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
package org.antlr.v4.runtime.misc;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This interface provides an abstract concept of object equality independent of
|
||||||
|
* {@link Object#equals} (object equality) and the {@code ==} operator
|
||||||
|
* (reference equality). It can be used to provide algorithm-specific unordered
|
||||||
|
* comparisons without requiring changes to the object itself.
|
||||||
|
*
|
||||||
|
* @author Sam Harwell
|
||||||
|
*/
|
||||||
|
public interface EqualityComparator<T> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method returns a hash code for the specified object.
|
||||||
|
*
|
||||||
|
* @param obj The object.
|
||||||
|
* @return The hash code for {@code obj}.
|
||||||
|
*/
|
||||||
|
int hashCode(T obj);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method tests if two objects are equal.
|
||||||
|
*
|
||||||
|
* @param a The first object to compare.
|
||||||
|
* @param b The second object to compare.
|
||||||
|
* @return {@code true} if {@code a} equals {@code b}, otherwise {@code false}.
|
||||||
|
*/
|
||||||
|
boolean equals(T a, T b);
|
||||||
|
|
||||||
|
}
|
|
@ -1,6 +0,0 @@
|
||||||
package org.antlr.v4.runtime.misc;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public interface EquivalenceMap<K,V> extends Map<K,V>, EquivalenceRelation<K> {
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
package org.antlr.v4.runtime.misc;
|
|
||||||
|
|
||||||
/** What does it mean for two objects to be equivalent? */
|
|
||||||
public interface EquivalenceRelation<T> {
|
|
||||||
public int hashCode(T o);
|
|
||||||
public boolean equals(T a, T b);
|
|
||||||
}
|
|
|
@ -1,12 +0,0 @@
|
||||||
package org.antlr.v4.runtime.misc;
|
|
||||||
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/** A set that allows us to override equivalence. For a single set, we might
|
|
||||||
* want multiple subset perspectives as defined by different hash code
|
|
||||||
* and equivalence methods. HashSet does not allow us to subclass and
|
|
||||||
* override the equivalence operations, so we have to implement our own
|
|
||||||
* sets that are flexible in terms of equivalence.
|
|
||||||
*/
|
|
||||||
public interface EquivalenceSet<T> extends Set<T>, EquivalenceRelation<T> {
|
|
||||||
}
|
|
|
@ -10,7 +10,7 @@ import java.util.Set;
|
||||||
/** A limited map (many unsupported operations) that lets me use
|
/** A limited map (many unsupported operations) that lets me use
|
||||||
* varying hashCode/equals.
|
* varying hashCode/equals.
|
||||||
*/
|
*/
|
||||||
public class FlexibleHashMap<K,V> implements EquivalenceMap<K,V> {
|
public class FlexibleHashMap<K,V> implements Map<K, V> {
|
||||||
public static final int INITAL_CAPACITY = 16; // must be power of 2
|
public static final int INITAL_CAPACITY = 16; // must be power of 2
|
||||||
public static final int INITAL_BUCKET_CAPACITY = 8;
|
public static final int INITAL_BUCKET_CAPACITY = 8;
|
||||||
public static final double LOAD_FACTOR = 0.75;
|
public static final double LOAD_FACTOR = 0.75;
|
||||||
|
@ -27,6 +27,9 @@ public class FlexibleHashMap<K,V> implements EquivalenceMap<K,V> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
protected final AbstractEqualityComparator<? super K> comparator;
|
||||||
|
|
||||||
protected LinkedList<Entry<K, V>>[] buckets;
|
protected LinkedList<Entry<K, V>>[] buckets;
|
||||||
|
|
||||||
/** How many elements in set */
|
/** How many elements in set */
|
||||||
|
@ -38,11 +41,20 @@ public class FlexibleHashMap<K,V> implements EquivalenceMap<K,V> {
|
||||||
protected int initialBucketCapacity = INITAL_BUCKET_CAPACITY;
|
protected int initialBucketCapacity = INITAL_BUCKET_CAPACITY;
|
||||||
|
|
||||||
public FlexibleHashMap() {
|
public FlexibleHashMap() {
|
||||||
this(INITAL_CAPACITY, INITAL_BUCKET_CAPACITY);
|
this(null, INITAL_CAPACITY, INITAL_BUCKET_CAPACITY);
|
||||||
}
|
}
|
||||||
|
|
||||||
public FlexibleHashMap(int initialCapacity, int initialBucketCapacity) {
|
public FlexibleHashMap(@Nullable AbstractEqualityComparator<? super K> comparator) {
|
||||||
buckets = createEntryListArray(initialBucketCapacity);
|
this(comparator, INITAL_CAPACITY, INITAL_BUCKET_CAPACITY);
|
||||||
|
}
|
||||||
|
|
||||||
|
public FlexibleHashMap(@Nullable AbstractEqualityComparator<? super K> comparator, int initialCapacity, int initialBucketCapacity) {
|
||||||
|
if (comparator == null) {
|
||||||
|
comparator = ObjectEqualityComparator.INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.comparator = comparator;
|
||||||
|
this.buckets = createEntryListArray(initialBucketCapacity);
|
||||||
this.initialBucketCapacity = initialBucketCapacity;
|
this.initialBucketCapacity = initialBucketCapacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,18 +64,8 @@ public class FlexibleHashMap<K,V> implements EquivalenceMap<K,V> {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(K keyA, K keyB) {
|
|
||||||
return keyA.equals(keyB);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode(K o) {
|
|
||||||
return o.hashCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected int getBucket(K key) {
|
protected int getBucket(K key) {
|
||||||
int hash = hashCode(key);
|
int hash = comparator.hashCode(key);
|
||||||
int b = hash & (buckets.length-1); // assumes len is power of 2
|
int b = hash & (buckets.length-1); // assumes len is power of 2
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
@ -77,7 +79,9 @@ public class FlexibleHashMap<K,V> implements EquivalenceMap<K,V> {
|
||||||
LinkedList<Entry<K, V>> bucket = buckets[b];
|
LinkedList<Entry<K, V>> bucket = buckets[b];
|
||||||
if ( bucket==null ) return null; // no bucket
|
if ( bucket==null ) return null; // no bucket
|
||||||
for (Entry<K, V> e : bucket) {
|
for (Entry<K, V> e : bucket) {
|
||||||
if ( equals(e.key, typedKey) ) return e.value; // use special equals
|
if ( comparator.equals(e.key, typedKey) ) {
|
||||||
|
return e.value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -92,7 +96,7 @@ public class FlexibleHashMap<K,V> implements EquivalenceMap<K,V> {
|
||||||
bucket = buckets[b] = new LinkedList<Entry<K, V>>();
|
bucket = buckets[b] = new LinkedList<Entry<K, V>>();
|
||||||
}
|
}
|
||||||
for (Entry<K, V> e : bucket) {
|
for (Entry<K, V> e : bucket) {
|
||||||
if ( equals(e.key, key) ) {
|
if ( comparator.equals(e.key, key) ) {
|
||||||
V prev = e.value;
|
V prev = e.value;
|
||||||
e.value = value;
|
e.value = value;
|
||||||
n++;
|
n++;
|
||||||
|
@ -154,7 +158,7 @@ public class FlexibleHashMap<K,V> implements EquivalenceMap<K,V> {
|
||||||
if ( bucket==null ) continue;
|
if ( bucket==null ) continue;
|
||||||
for (Entry<K, V> e : bucket) {
|
for (Entry<K, V> e : bucket) {
|
||||||
if ( e==null ) break;
|
if ( e==null ) break;
|
||||||
h += hashCode(e.key);
|
h += comparator.hashCode(e.key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return h;
|
return h;
|
||||||
|
|
|
@ -0,0 +1,74 @@
|
||||||
|
/*
|
||||||
|
* [The "BSD license"]
|
||||||
|
* Copyright (c) 2012 Terence Parr
|
||||||
|
* Copyright (c) 2012 Sam Harwell
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. The name of the author may not be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
package org.antlr.v4.runtime.misc;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This default implementation of {@link EqualityComparator} uses object equality
|
||||||
|
* for comparisons by calling {@link Object#hashCode} and {@link Object#equals}.
|
||||||
|
*
|
||||||
|
* @author Sam Harwell
|
||||||
|
*/
|
||||||
|
public final class ObjectEqualityComparator extends AbstractEqualityComparator<Object> {
|
||||||
|
public static final ObjectEqualityComparator INSTANCE = new ObjectEqualityComparator();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
* <p/>
|
||||||
|
* This implementation returns
|
||||||
|
* {@code obj.}{@link Object#hashCode hashCode()}.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int hashCode(Object obj) {
|
||||||
|
if (obj == null) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return obj.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
* <p/>
|
||||||
|
* This implementation relies on object equality. If both objects are
|
||||||
|
* {@code null}, this method returns {@code true}. Otherwise if only
|
||||||
|
* {@code a} is {@code null}, this method returns {@code false}. Otherwise,
|
||||||
|
* this method returns the result of
|
||||||
|
* {@code a.}{@link Object#equals equals}{@code (b)}.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object a, Object b) {
|
||||||
|
if (a == null) {
|
||||||
|
return b == null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return a.equals(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue