2023-08-17 05:15:28 +00:00
|
|
|
package antlr
|
|
|
|
|
|
|
|
// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved.
|
|
|
|
// Use of this file is governed by the BSD 3-clause license that
|
|
|
|
// can be found in the LICENSE.txt file in the project root.
|
|
|
|
|
|
|
|
// This file contains all the implementations of custom comparators used for generic collections when the
|
|
|
|
// Hash() and Equals() funcs supplied by the struct objects themselves need to be overridden. Normally, we would
|
|
|
|
// put the comparators in the source file for the struct themselves, but given the organization of this code is
|
|
|
|
// sorta kinda based upon the Java code, I found it confusing trying to find out which comparator was where and used by
|
|
|
|
// which instantiation of a collection. For instance, an Array2DHashSet in the Java source, when used with ATNConfig
|
|
|
|
// collections requires three different comparators depending on what the collection is being used for. Collecting - pun intended -
|
|
|
|
// all the comparators here, makes it much easier to see which implementation of hash and equals is used by which collection.
|
|
|
|
// It also makes it easy to verify that the Hash() and Equals() functions marry up with the Java implementations.
|
|
|
|
|
|
|
|
// ObjEqComparator is the equivalent of the Java ObjectEqualityComparator, which is the default instance of
|
|
|
|
// Equality comparator. We do not have inheritance in Go, only interfaces, so we use generics to enforce some
|
|
|
|
// type safety and avoid having to implement this for every type that we want to perform comparison on.
|
|
|
|
//
|
|
|
|
// This comparator works by using the standard Hash() and Equals() methods of the type T that is being compared. Which
|
2024-08-19 08:01:33 +00:00
|
|
|
// allows us to use it in any collection instance that does not require a special hash or equals implementation.
|
2023-08-17 05:15:28 +00:00
|
|
|
type ObjEqComparator[T Collectable[T]] struct{}
|
|
|
|
|
|
|
|
var (
|
2024-08-19 08:01:33 +00:00
|
|
|
aStateEqInst = &ObjEqComparator[ATNState]{}
|
|
|
|
aConfEqInst = &ObjEqComparator[*ATNConfig]{}
|
|
|
|
|
|
|
|
// aConfCompInst is the comparator used for the ATNConfigSet for the configLookup cache
|
|
|
|
aConfCompInst = &ATNConfigComparator[*ATNConfig]{}
|
|
|
|
atnConfCompInst = &BaseATNConfigComparator[*ATNConfig]{}
|
2023-08-17 05:15:28 +00:00
|
|
|
dfaStateEqInst = &ObjEqComparator[*DFAState]{}
|
|
|
|
semctxEqInst = &ObjEqComparator[SemanticContext]{}
|
2024-08-19 08:01:33 +00:00
|
|
|
atnAltCfgEqInst = &ATNAltConfigComparator[*ATNConfig]{}
|
|
|
|
pContextEqInst = &ObjEqComparator[*PredictionContext]{}
|
2023-08-17 05:15:28 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// Equals2 delegates to the Equals() method of type T
|
|
|
|
func (c *ObjEqComparator[T]) Equals2(o1, o2 T) bool {
|
|
|
|
return o1.Equals(o2)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Hash1 delegates to the Hash() method of type T
|
|
|
|
func (c *ObjEqComparator[T]) Hash1(o T) int {
|
|
|
|
|
|
|
|
return o.Hash()
|
|
|
|
}
|
|
|
|
|
|
|
|
type SemCComparator[T Collectable[T]] struct{}
|
|
|
|
|
2024-08-19 08:01:33 +00:00
|
|
|
// ATNConfigComparator is used as the comparator for the configLookup field of an ATNConfigSet
|
2023-08-17 05:15:28 +00:00
|
|
|
// and has a custom Equals() and Hash() implementation, because equality is not based on the
|
|
|
|
// standard Hash() and Equals() methods of the ATNConfig type.
|
|
|
|
type ATNConfigComparator[T Collectable[T]] struct {
|
|
|
|
}
|
|
|
|
|
|
|
|
// Equals2 is a custom comparator for ATNConfigs specifically for configLookup
|
2024-08-19 08:01:33 +00:00
|
|
|
func (c *ATNConfigComparator[T]) Equals2(o1, o2 *ATNConfig) bool {
|
2023-08-17 05:15:28 +00:00
|
|
|
|
|
|
|
// Same pointer, must be equal, even if both nil
|
|
|
|
//
|
|
|
|
if o1 == o2 {
|
|
|
|
return true
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// If either are nil, but not both, then the result is false
|
|
|
|
//
|
|
|
|
if o1 == nil || o2 == nil {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
return o1.GetState().GetStateNumber() == o2.GetState().GetStateNumber() &&
|
|
|
|
o1.GetAlt() == o2.GetAlt() &&
|
|
|
|
o1.GetSemanticContext().Equals(o2.GetSemanticContext())
|
|
|
|
}
|
|
|
|
|
|
|
|
// Hash1 is custom hash implementation for ATNConfigs specifically for configLookup
|
2024-08-19 08:01:33 +00:00
|
|
|
func (c *ATNConfigComparator[T]) Hash1(o *ATNConfig) int {
|
|
|
|
|
2023-08-17 05:15:28 +00:00
|
|
|
hash := 7
|
|
|
|
hash = 31*hash + o.GetState().GetStateNumber()
|
|
|
|
hash = 31*hash + o.GetAlt()
|
|
|
|
hash = 31*hash + o.GetSemanticContext().Hash()
|
|
|
|
return hash
|
|
|
|
}
|
|
|
|
|
|
|
|
// ATNAltConfigComparator is used as the comparator for mapping configs to Alt Bitsets
|
|
|
|
type ATNAltConfigComparator[T Collectable[T]] struct {
|
|
|
|
}
|
|
|
|
|
|
|
|
// Equals2 is a custom comparator for ATNConfigs specifically for configLookup
|
2024-08-19 08:01:33 +00:00
|
|
|
func (c *ATNAltConfigComparator[T]) Equals2(o1, o2 *ATNConfig) bool {
|
2023-08-17 05:15:28 +00:00
|
|
|
|
|
|
|
// Same pointer, must be equal, even if both nil
|
|
|
|
//
|
|
|
|
if o1 == o2 {
|
|
|
|
return true
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// If either are nil, but not both, then the result is false
|
|
|
|
//
|
|
|
|
if o1 == nil || o2 == nil {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
return o1.GetState().GetStateNumber() == o2.GetState().GetStateNumber() &&
|
|
|
|
o1.GetContext().Equals(o2.GetContext())
|
|
|
|
}
|
|
|
|
|
|
|
|
// Hash1 is custom hash implementation for ATNConfigs specifically for configLookup
|
2024-08-19 08:01:33 +00:00
|
|
|
func (c *ATNAltConfigComparator[T]) Hash1(o *ATNConfig) int {
|
2023-08-17 05:15:28 +00:00
|
|
|
h := murmurInit(7)
|
|
|
|
h = murmurUpdate(h, o.GetState().GetStateNumber())
|
|
|
|
h = murmurUpdate(h, o.GetContext().Hash())
|
|
|
|
return murmurFinish(h, 2)
|
|
|
|
}
|
|
|
|
|
2024-08-19 08:01:33 +00:00
|
|
|
// BaseATNConfigComparator is used as the comparator for the configLookup field of a ATNConfigSet
|
2023-08-17 05:15:28 +00:00
|
|
|
// and has a custom Equals() and Hash() implementation, because equality is not based on the
|
|
|
|
// standard Hash() and Equals() methods of the ATNConfig type.
|
|
|
|
type BaseATNConfigComparator[T Collectable[T]] struct {
|
|
|
|
}
|
|
|
|
|
|
|
|
// Equals2 is a custom comparator for ATNConfigs specifically for baseATNConfigSet
|
2024-08-19 08:01:33 +00:00
|
|
|
func (c *BaseATNConfigComparator[T]) Equals2(o1, o2 *ATNConfig) bool {
|
2023-08-17 05:15:28 +00:00
|
|
|
|
|
|
|
// Same pointer, must be equal, even if both nil
|
|
|
|
//
|
|
|
|
if o1 == o2 {
|
|
|
|
return true
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// If either are nil, but not both, then the result is false
|
|
|
|
//
|
|
|
|
if o1 == nil || o2 == nil {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
return o1.GetState().GetStateNumber() == o2.GetState().GetStateNumber() &&
|
|
|
|
o1.GetAlt() == o2.GetAlt() &&
|
|
|
|
o1.GetSemanticContext().Equals(o2.GetSemanticContext())
|
|
|
|
}
|
|
|
|
|
|
|
|
// Hash1 is custom hash implementation for ATNConfigs specifically for configLookup, but in fact just
|
|
|
|
// delegates to the standard Hash() method of the ATNConfig type.
|
2024-08-19 08:01:33 +00:00
|
|
|
func (c *BaseATNConfigComparator[T]) Hash1(o *ATNConfig) int {
|
2023-08-17 05:15:28 +00:00
|
|
|
return o.Hash()
|
|
|
|
}
|