diff --git a/runtime/Go/antlr/atn_config.go b/runtime/Go/antlr/atn_config.go index dd6fb5bd58..159823c229 100644 --- a/runtime/Go/antlr/atn_config.go +++ b/runtime/Go/antlr/atn_config.go @@ -22,6 +22,8 @@ type ATNConfig interface { Hasher Comparable + HashCode() int + GetState() ATNState GetAlt() int GetSemanticContext() SemanticContext @@ -184,6 +186,20 @@ func (b *BaseATNConfig) Hash() string { return strconv.Itoa(b.state.GetStateNumber()) + "/" + strconv.Itoa(b.alt) + "/" + c + "/" + b.semanticContext.String() } +func (b *BaseATNConfig) HashCode() int { + var c int + if b.context != nil { + c = b.context.HashCode() + } + + h := initHash(7) + h = update(h, b.state.GetStateNumber()) + h = update(h, b.alt) + h = update(h, c) + h = update(h, b.semanticContext.HashCode()) + return finish(h, 4) +} + func (b *BaseATNConfig) String() string { var s1, s2, s3 string diff --git a/runtime/Go/antlr/atn_config_set.go b/runtime/Go/antlr/atn_config_set.go index e5af47855a..5a9c632861 100644 --- a/runtime/Go/antlr/atn_config_set.go +++ b/runtime/Go/antlr/atn_config_set.go @@ -9,6 +9,7 @@ import "fmt" type ATNConfigSet interface { Hasher + HashCode() int Add(ATNConfig, *DoubleDict) bool AddAll([]ATNConfig) bool @@ -50,6 +51,7 @@ type ATNConfigSet interface { // graph-structured stack. type BaseATNConfigSet struct { cachedHashString string + cachedHash int // configLookup is used to determine whether two BaseATNConfigSets are equal. We // need all configurations with the same (s, i, _, semctx) to be equal. A key @@ -246,6 +248,32 @@ func (b *BaseATNConfigSet) hashConfigs() string { return s } +func (b *BaseATNConfigSet) HashCode() int { + if b.readOnly { + if b.cachedHash == -1 { + b.cachedHash = b.hashCodeConfigs() + } + + return b.cachedHash + } + + return b.hashCodeConfigs() +} + +func (b *BaseATNConfigSet) hashCodeConfigs() int { + h := 1 + + for _, c := range b.configs { + h += 31 * h + + if c != nil { + h += c.HashCode() + } + } + + return h +} + func (b *BaseATNConfigSet) Length() int { return len(b.configs) } diff --git a/runtime/Go/antlr/dfa_state.go b/runtime/Go/antlr/dfa_state.go index 6c5748273a..6c8e3c0798 100644 --- a/runtime/Go/antlr/dfa_state.go +++ b/runtime/Go/antlr/dfa_state.go @@ -149,3 +149,24 @@ func (d *DFAState) Hash() string { return fmt.Sprint(d.configs) + s } + +func (d *DFAState) HashCode() int { + h := initHash(11) + + c := 1 + if d.isAcceptState { + if d.predicates != nil { + for _, p := range d.predicates { + h = update(h, p.alt) + h = update(h, p.pred.HashCode()) + c += 2 + } + } else { + h = update(h, d.prediction) + c += 1 + } + } + + h = update(h, d.configs.HashCode()) + return finish(h, c) +} \ No newline at end of file diff --git a/runtime/Go/antlr/utils.go b/runtime/Go/antlr/utils.go index ec74c37bf3..0801088dc7 100644 --- a/runtime/Go/antlr/utils.go +++ b/runtime/Go/antlr/utils.go @@ -365,6 +365,7 @@ func PrintArrayJavaStyle(sa []string) string { return buffer.String() } + // murmur hash const ( c1_32 = 0xCC9E2D51