2023-08-17 05:15:28 +00:00
|
|
|
// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved.
|
2023-05-29 21:03:29 +00:00
|
|
|
// 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.
|
|
|
|
|
|
|
|
package antlr
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"strconv"
|
|
|
|
)
|
|
|
|
|
2024-08-19 08:01:33 +00:00
|
|
|
// SemanticContext is a tree structure used to record the semantic context in which
|
2023-05-29 21:03:29 +00:00
|
|
|
//
|
2024-08-19 08:01:33 +00:00
|
|
|
// an ATN configuration is valid. It's either a single predicate,
|
|
|
|
// a conjunction p1 && p2, or a sum of products p1 || p2.
|
2023-05-29 21:03:29 +00:00
|
|
|
//
|
2024-08-19 08:01:33 +00:00
|
|
|
// I have scoped the AND, OR, and Predicate subclasses of
|
|
|
|
// [SemanticContext] within the scope of this outer ``class''
|
2023-05-29 21:03:29 +00:00
|
|
|
type SemanticContext interface {
|
2023-08-17 05:15:28 +00:00
|
|
|
Equals(other Collectable[SemanticContext]) bool
|
|
|
|
Hash() int
|
2023-05-29 21:03:29 +00:00
|
|
|
|
|
|
|
evaluate(parser Recognizer, outerContext RuleContext) bool
|
|
|
|
evalPrecedence(parser Recognizer, outerContext RuleContext) SemanticContext
|
|
|
|
|
|
|
|
String() string
|
|
|
|
}
|
|
|
|
|
|
|
|
func SemanticContextandContext(a, b SemanticContext) SemanticContext {
|
|
|
|
if a == nil || a == SemanticContextNone {
|
|
|
|
return b
|
|
|
|
}
|
|
|
|
if b == nil || b == SemanticContextNone {
|
|
|
|
return a
|
|
|
|
}
|
|
|
|
result := NewAND(a, b)
|
|
|
|
if len(result.opnds) == 1 {
|
|
|
|
return result.opnds[0]
|
|
|
|
}
|
|
|
|
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
|
|
|
func SemanticContextorContext(a, b SemanticContext) SemanticContext {
|
|
|
|
if a == nil {
|
|
|
|
return b
|
|
|
|
}
|
|
|
|
if b == nil {
|
|
|
|
return a
|
|
|
|
}
|
|
|
|
if a == SemanticContextNone || b == SemanticContextNone {
|
|
|
|
return SemanticContextNone
|
|
|
|
}
|
|
|
|
result := NewOR(a, b)
|
|
|
|
if len(result.opnds) == 1 {
|
|
|
|
return result.opnds[0]
|
|
|
|
}
|
|
|
|
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
|
|
|
type Predicate struct {
|
|
|
|
ruleIndex int
|
|
|
|
predIndex int
|
|
|
|
isCtxDependent bool
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewPredicate(ruleIndex, predIndex int, isCtxDependent bool) *Predicate {
|
|
|
|
p := new(Predicate)
|
|
|
|
|
|
|
|
p.ruleIndex = ruleIndex
|
|
|
|
p.predIndex = predIndex
|
|
|
|
p.isCtxDependent = isCtxDependent // e.g., $i ref in pred
|
|
|
|
return p
|
|
|
|
}
|
|
|
|
|
|
|
|
//The default {@link SemanticContext}, which is semantically equivalent to
|
|
|
|
//a predicate of the form {@code {true}?}.
|
|
|
|
|
2023-08-17 05:15:28 +00:00
|
|
|
var SemanticContextNone = NewPredicate(-1, -1, false)
|
2023-05-29 21:03:29 +00:00
|
|
|
|
2024-08-19 08:01:33 +00:00
|
|
|
func (p *Predicate) evalPrecedence(_ Recognizer, _ RuleContext) SemanticContext {
|
2023-05-29 21:03:29 +00:00
|
|
|
return p
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *Predicate) evaluate(parser Recognizer, outerContext RuleContext) bool {
|
|
|
|
|
|
|
|
var localctx RuleContext
|
|
|
|
|
|
|
|
if p.isCtxDependent {
|
|
|
|
localctx = outerContext
|
|
|
|
}
|
|
|
|
|
|
|
|
return parser.Sempred(localctx, p.ruleIndex, p.predIndex)
|
|
|
|
}
|
|
|
|
|
2023-08-17 05:15:28 +00:00
|
|
|
func (p *Predicate) Equals(other Collectable[SemanticContext]) bool {
|
2023-05-29 21:03:29 +00:00
|
|
|
if p == other {
|
|
|
|
return true
|
|
|
|
} else if _, ok := other.(*Predicate); !ok {
|
|
|
|
return false
|
|
|
|
} else {
|
|
|
|
return p.ruleIndex == other.(*Predicate).ruleIndex &&
|
|
|
|
p.predIndex == other.(*Predicate).predIndex &&
|
|
|
|
p.isCtxDependent == other.(*Predicate).isCtxDependent
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-17 05:15:28 +00:00
|
|
|
func (p *Predicate) Hash() int {
|
2023-05-29 21:03:29 +00:00
|
|
|
h := murmurInit(0)
|
|
|
|
h = murmurUpdate(h, p.ruleIndex)
|
|
|
|
h = murmurUpdate(h, p.predIndex)
|
|
|
|
if p.isCtxDependent {
|
|
|
|
h = murmurUpdate(h, 1)
|
|
|
|
} else {
|
|
|
|
h = murmurUpdate(h, 0)
|
|
|
|
}
|
|
|
|
return murmurFinish(h, 3)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *Predicate) String() string {
|
|
|
|
return "{" + strconv.Itoa(p.ruleIndex) + ":" + strconv.Itoa(p.predIndex) + "}?"
|
|
|
|
}
|
|
|
|
|
|
|
|
type PrecedencePredicate struct {
|
|
|
|
precedence int
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewPrecedencePredicate(precedence int) *PrecedencePredicate {
|
|
|
|
|
|
|
|
p := new(PrecedencePredicate)
|
|
|
|
p.precedence = precedence
|
|
|
|
|
|
|
|
return p
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *PrecedencePredicate) evaluate(parser Recognizer, outerContext RuleContext) bool {
|
|
|
|
return parser.Precpred(outerContext, p.precedence)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *PrecedencePredicate) evalPrecedence(parser Recognizer, outerContext RuleContext) SemanticContext {
|
|
|
|
if parser.Precpred(outerContext, p.precedence) {
|
|
|
|
return SemanticContextNone
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *PrecedencePredicate) compareTo(other *PrecedencePredicate) int {
|
|
|
|
return p.precedence - other.precedence
|
|
|
|
}
|
|
|
|
|
2023-08-17 05:15:28 +00:00
|
|
|
func (p *PrecedencePredicate) Equals(other Collectable[SemanticContext]) bool {
|
|
|
|
|
|
|
|
var op *PrecedencePredicate
|
|
|
|
var ok bool
|
|
|
|
if op, ok = other.(*PrecedencePredicate); !ok {
|
2023-05-29 21:03:29 +00:00
|
|
|
return false
|
|
|
|
}
|
2023-08-17 05:15:28 +00:00
|
|
|
|
|
|
|
if p == op {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
return p.precedence == other.(*PrecedencePredicate).precedence
|
2023-05-29 21:03:29 +00:00
|
|
|
}
|
|
|
|
|
2023-08-17 05:15:28 +00:00
|
|
|
func (p *PrecedencePredicate) Hash() int {
|
2023-05-29 21:03:29 +00:00
|
|
|
h := uint32(1)
|
|
|
|
h = 31*h + uint32(p.precedence)
|
|
|
|
return int(h)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *PrecedencePredicate) String() string {
|
|
|
|
return "{" + strconv.Itoa(p.precedence) + ">=prec}?"
|
|
|
|
}
|
|
|
|
|
2023-08-17 05:15:28 +00:00
|
|
|
func PrecedencePredicatefilterPrecedencePredicates(set *JStore[SemanticContext, Comparator[SemanticContext]]) []*PrecedencePredicate {
|
2023-05-29 21:03:29 +00:00
|
|
|
result := make([]*PrecedencePredicate, 0)
|
|
|
|
|
2023-08-17 05:15:28 +00:00
|
|
|
set.Each(func(v SemanticContext) bool {
|
2023-05-29 21:03:29 +00:00
|
|
|
if c2, ok := v.(*PrecedencePredicate); ok {
|
|
|
|
result = append(result, c2)
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
})
|
|
|
|
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
|
|
|
// A semantic context which is true whenever none of the contained contexts
|
|
|
|
// is false.`
|
|
|
|
|
|
|
|
type AND struct {
|
|
|
|
opnds []SemanticContext
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewAND(a, b SemanticContext) *AND {
|
|
|
|
|
2024-08-19 08:01:33 +00:00
|
|
|
operands := NewJStore[SemanticContext, Comparator[SemanticContext]](semctxEqInst, SemanticContextCollection, "NewAND() operands")
|
2023-05-29 21:03:29 +00:00
|
|
|
if aa, ok := a.(*AND); ok {
|
|
|
|
for _, o := range aa.opnds {
|
2023-08-17 05:15:28 +00:00
|
|
|
operands.Put(o)
|
2023-05-29 21:03:29 +00:00
|
|
|
}
|
|
|
|
} else {
|
2023-08-17 05:15:28 +00:00
|
|
|
operands.Put(a)
|
2023-05-29 21:03:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if ba, ok := b.(*AND); ok {
|
|
|
|
for _, o := range ba.opnds {
|
2023-08-17 05:15:28 +00:00
|
|
|
operands.Put(o)
|
2023-05-29 21:03:29 +00:00
|
|
|
}
|
|
|
|
} else {
|
2023-08-17 05:15:28 +00:00
|
|
|
operands.Put(b)
|
2023-05-29 21:03:29 +00:00
|
|
|
}
|
|
|
|
precedencePredicates := PrecedencePredicatefilterPrecedencePredicates(operands)
|
|
|
|
if len(precedencePredicates) > 0 {
|
|
|
|
// interested in the transition with the lowest precedence
|
|
|
|
var reduced *PrecedencePredicate
|
|
|
|
|
|
|
|
for _, p := range precedencePredicates {
|
|
|
|
if reduced == nil || p.precedence < reduced.precedence {
|
|
|
|
reduced = p
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-17 05:15:28 +00:00
|
|
|
operands.Put(reduced)
|
2023-05-29 21:03:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
vs := operands.Values()
|
|
|
|
opnds := make([]SemanticContext, len(vs))
|
2024-08-19 08:01:33 +00:00
|
|
|
copy(opnds, vs)
|
2023-05-29 21:03:29 +00:00
|
|
|
|
|
|
|
and := new(AND)
|
|
|
|
and.opnds = opnds
|
|
|
|
|
|
|
|
return and
|
|
|
|
}
|
|
|
|
|
2023-08-17 05:15:28 +00:00
|
|
|
func (a *AND) Equals(other Collectable[SemanticContext]) bool {
|
2023-05-29 21:03:29 +00:00
|
|
|
if a == other {
|
|
|
|
return true
|
2023-08-17 05:15:28 +00:00
|
|
|
}
|
|
|
|
if _, ok := other.(*AND); !ok {
|
2023-05-29 21:03:29 +00:00
|
|
|
return false
|
|
|
|
} else {
|
|
|
|
for i, v := range other.(*AND).opnds {
|
2023-08-17 05:15:28 +00:00
|
|
|
if !a.opnds[i].Equals(v) {
|
2023-05-29 21:03:29 +00:00
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// {@inheritDoc}
|
|
|
|
//
|
|
|
|
// <p>
|
|
|
|
// The evaluation of predicates by a context is short-circuiting, but
|
|
|
|
// unordered.</p>
|
|
|
|
func (a *AND) evaluate(parser Recognizer, outerContext RuleContext) bool {
|
|
|
|
for i := 0; i < len(a.opnds); i++ {
|
|
|
|
if !a.opnds[i].evaluate(parser, outerContext) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
func (a *AND) evalPrecedence(parser Recognizer, outerContext RuleContext) SemanticContext {
|
|
|
|
differs := false
|
|
|
|
operands := make([]SemanticContext, 0)
|
|
|
|
|
|
|
|
for i := 0; i < len(a.opnds); i++ {
|
|
|
|
context := a.opnds[i]
|
|
|
|
evaluated := context.evalPrecedence(parser, outerContext)
|
|
|
|
differs = differs || (evaluated != context)
|
|
|
|
if evaluated == nil {
|
|
|
|
// The AND context is false if any element is false
|
|
|
|
return nil
|
|
|
|
} else if evaluated != SemanticContextNone {
|
|
|
|
// Reduce the result by Skipping true elements
|
|
|
|
operands = append(operands, evaluated)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if !differs {
|
|
|
|
return a
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(operands) == 0 {
|
|
|
|
// all elements were true, so the AND context is true
|
|
|
|
return SemanticContextNone
|
|
|
|
}
|
|
|
|
|
|
|
|
var result SemanticContext
|
|
|
|
|
|
|
|
for _, o := range operands {
|
|
|
|
if result == nil {
|
|
|
|
result = o
|
|
|
|
} else {
|
|
|
|
result = SemanticContextandContext(result, o)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
2023-08-17 05:15:28 +00:00
|
|
|
func (a *AND) Hash() int {
|
2023-05-29 21:03:29 +00:00
|
|
|
h := murmurInit(37) // Init with a value different from OR
|
|
|
|
for _, op := range a.opnds {
|
2023-08-17 05:15:28 +00:00
|
|
|
h = murmurUpdate(h, op.Hash())
|
2023-05-29 21:03:29 +00:00
|
|
|
}
|
|
|
|
return murmurFinish(h, len(a.opnds))
|
|
|
|
}
|
|
|
|
|
2024-08-19 08:01:33 +00:00
|
|
|
func (o *OR) Hash() int {
|
|
|
|
h := murmurInit(41) // Init with o value different from AND
|
|
|
|
for _, op := range o.opnds {
|
2023-08-17 05:15:28 +00:00
|
|
|
h = murmurUpdate(h, op.Hash())
|
2023-05-29 21:03:29 +00:00
|
|
|
}
|
2024-08-19 08:01:33 +00:00
|
|
|
return murmurFinish(h, len(o.opnds))
|
2023-05-29 21:03:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (a *AND) String() string {
|
|
|
|
s := ""
|
|
|
|
|
|
|
|
for _, o := range a.opnds {
|
|
|
|
s += "&& " + fmt.Sprint(o)
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(s) > 3 {
|
|
|
|
return s[0:3]
|
|
|
|
}
|
|
|
|
|
|
|
|
return s
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// A semantic context which is true whenever at least one of the contained
|
|
|
|
// contexts is true.
|
|
|
|
//
|
|
|
|
|
|
|
|
type OR struct {
|
|
|
|
opnds []SemanticContext
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewOR(a, b SemanticContext) *OR {
|
|
|
|
|
2024-08-19 08:01:33 +00:00
|
|
|
operands := NewJStore[SemanticContext, Comparator[SemanticContext]](semctxEqInst, SemanticContextCollection, "NewOR() operands")
|
2023-05-29 21:03:29 +00:00
|
|
|
if aa, ok := a.(*OR); ok {
|
|
|
|
for _, o := range aa.opnds {
|
2023-08-17 05:15:28 +00:00
|
|
|
operands.Put(o)
|
2023-05-29 21:03:29 +00:00
|
|
|
}
|
|
|
|
} else {
|
2023-08-17 05:15:28 +00:00
|
|
|
operands.Put(a)
|
2023-05-29 21:03:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if ba, ok := b.(*OR); ok {
|
|
|
|
for _, o := range ba.opnds {
|
2023-08-17 05:15:28 +00:00
|
|
|
operands.Put(o)
|
2023-05-29 21:03:29 +00:00
|
|
|
}
|
|
|
|
} else {
|
2023-08-17 05:15:28 +00:00
|
|
|
operands.Put(b)
|
2023-05-29 21:03:29 +00:00
|
|
|
}
|
|
|
|
precedencePredicates := PrecedencePredicatefilterPrecedencePredicates(operands)
|
|
|
|
if len(precedencePredicates) > 0 {
|
|
|
|
// interested in the transition with the lowest precedence
|
|
|
|
var reduced *PrecedencePredicate
|
|
|
|
|
|
|
|
for _, p := range precedencePredicates {
|
|
|
|
if reduced == nil || p.precedence > reduced.precedence {
|
|
|
|
reduced = p
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-17 05:15:28 +00:00
|
|
|
operands.Put(reduced)
|
2023-05-29 21:03:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
vs := operands.Values()
|
|
|
|
|
|
|
|
opnds := make([]SemanticContext, len(vs))
|
2024-08-19 08:01:33 +00:00
|
|
|
copy(opnds, vs)
|
2023-05-29 21:03:29 +00:00
|
|
|
|
|
|
|
o := new(OR)
|
|
|
|
o.opnds = opnds
|
|
|
|
|
|
|
|
return o
|
|
|
|
}
|
|
|
|
|
2023-08-17 05:15:28 +00:00
|
|
|
func (o *OR) Equals(other Collectable[SemanticContext]) bool {
|
2023-05-29 21:03:29 +00:00
|
|
|
if o == other {
|
|
|
|
return true
|
|
|
|
} else if _, ok := other.(*OR); !ok {
|
|
|
|
return false
|
|
|
|
} else {
|
|
|
|
for i, v := range other.(*OR).opnds {
|
2023-08-17 05:15:28 +00:00
|
|
|
if !o.opnds[i].Equals(v) {
|
2023-05-29 21:03:29 +00:00
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// <p>
|
|
|
|
// The evaluation of predicates by o context is short-circuiting, but
|
|
|
|
// unordered.</p>
|
|
|
|
func (o *OR) evaluate(parser Recognizer, outerContext RuleContext) bool {
|
|
|
|
for i := 0; i < len(o.opnds); i++ {
|
|
|
|
if o.opnds[i].evaluate(parser, outerContext) {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
func (o *OR) evalPrecedence(parser Recognizer, outerContext RuleContext) SemanticContext {
|
|
|
|
differs := false
|
|
|
|
operands := make([]SemanticContext, 0)
|
|
|
|
for i := 0; i < len(o.opnds); i++ {
|
|
|
|
context := o.opnds[i]
|
|
|
|
evaluated := context.evalPrecedence(parser, outerContext)
|
|
|
|
differs = differs || (evaluated != context)
|
|
|
|
if evaluated == SemanticContextNone {
|
|
|
|
// The OR context is true if any element is true
|
|
|
|
return SemanticContextNone
|
|
|
|
} else if evaluated != nil {
|
|
|
|
// Reduce the result by Skipping false elements
|
|
|
|
operands = append(operands, evaluated)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if !differs {
|
|
|
|
return o
|
|
|
|
}
|
|
|
|
if len(operands) == 0 {
|
|
|
|
// all elements were false, so the OR context is false
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
var result SemanticContext
|
|
|
|
|
|
|
|
for _, o := range operands {
|
|
|
|
if result == nil {
|
|
|
|
result = o
|
|
|
|
} else {
|
|
|
|
result = SemanticContextorContext(result, o)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
|
|
|
func (o *OR) String() string {
|
|
|
|
s := ""
|
|
|
|
|
|
|
|
for _, o := range o.opnds {
|
|
|
|
s += "|| " + fmt.Sprint(o)
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(s) > 3 {
|
|
|
|
return s[0:3]
|
|
|
|
}
|
|
|
|
|
|
|
|
return s
|
|
|
|
}
|