Update specificity rule matching for annotations
Change-Id: Ifa7ec5eef3583cb196f4aa1ca0cfcd65790de226
diff --git a/ast/ast.go b/ast/ast.go
index b944824..df21ba9 100644
--- a/ast/ast.go
+++ b/ast/ast.go
@@ -487,11 +487,11 @@
SetRewrites([]Rewrite)
}
-func (t *Term) GetRewrites() []Rewrite { return t.Rewrites }
-func (t *Term) SetRewrites(r []Rewrite) { t.Rewrites = r }
-func (tg *TermGroup) GetRewrites() []Rewrite { return tg.Rewrites }
+func (t *Term) GetRewrites() []Rewrite { return t.Rewrites }
+func (t *Term) SetRewrites(r []Rewrite) { t.Rewrites = r }
+func (tg *TermGroup) GetRewrites() []Rewrite { return tg.Rewrites }
func (tg *TermGroup) SetRewrites(r []Rewrite) { tg.Rewrites = r }
-func (t *Token) GetRewrites() []Rewrite { return t.Rewrites }
+func (t *Token) GetRewrites() []Rewrite { return t.Rewrites }
func (t *Token) SetRewrites(r []Rewrite) { t.Rewrites = r }
// AppendRewrite appends a rewrite to any Rewriteable node.
@@ -502,6 +502,36 @@
}
}
+// Specificity returns the specificity score of an AST node.
+// Specificity is the count of AND-connected leaf constraints:
+// - Term -> 1
+// - TermGroup(AND) -> sum of Specificity of all operands
+// - TermGroup(OR) -> 0 (alternatives, not additional constraints)
+// - Token -> Specificity(Wrap)
+// - CatchallNode / nil -> 0
+func Specificity(node Node) int {
+ if node == nil {
+ return 0
+ }
+ switch n := node.(type) {
+ case *Term:
+ return 1
+ case *TermGroup:
+ if n.Relation == AndRelation {
+ total := 0
+ for _, op := range n.Operands {
+ total += Specificity(op)
+ }
+ return total
+ }
+ return 0
+ case *Token:
+ return Specificity(n.Wrap)
+ default:
+ return 0
+ }
+}
+
// StripRewrites recursively removes all rewrites from an AST tree.
func StripRewrites(node Node) {
if node == nil {