Fix layer precedence and document precedences
Change-Id: I7fdc9f9122d7e723f98674a9f9e3010c38118ba9
diff --git a/ast/ast.go b/ast/ast.go
index 2da55b8..0f1c858 100644
--- a/ast/ast.go
+++ b/ast/ast.go
@@ -309,6 +309,42 @@
}
}
+// ApplyFoundryAndLayerOverridesWithPrecedence applies foundry and layer overrides while respecting precedence:
+// 1. Mapping rule foundry/layer (highest priority - don't override if already set)
+// 2. Passed overwrite foundry/layer (from MappingOptions)
+// 3. Mapping list foundry/layer (lowest priority - defaults)
+func ApplyFoundryAndLayerOverridesWithPrecedence(node Node, foundry, layer string) {
+ if node == nil {
+ return
+ }
+
+ switch n := node.(type) {
+ case *Term:
+ // Only override if the term doesn't already have explicit values (respecting precedence)
+ if foundry != "" && n.Foundry == "" {
+ n.Foundry = foundry
+ }
+ if layer != "" && n.Layer == "" {
+ n.Layer = layer
+ }
+ case *TermGroup:
+ for _, op := range n.Operands {
+ ApplyFoundryAndLayerOverridesWithPrecedence(op, foundry, layer)
+ }
+ case *Token:
+ if n.Wrap != nil {
+ ApplyFoundryAndLayerOverridesWithPrecedence(n.Wrap, foundry, layer)
+ }
+ case *CatchallNode:
+ if n.Wrap != nil {
+ ApplyFoundryAndLayerOverridesWithPrecedence(n.Wrap, foundry, layer)
+ }
+ for _, op := range n.Operands {
+ ApplyFoundryAndLayerOverridesWithPrecedence(op, foundry, layer)
+ }
+ }
+}
+
// RestrictToObligatory takes a replacement node from a mapping rule and reduces the boolean structure
// to only obligatory operations by removing optional OR-relations and keeping required AND-relations.
// It also applies foundry and layer overrides like ApplyFoundryAndLayerOverrides().
@@ -336,6 +372,25 @@
return restricted
}
+// RestrictToObligatoryWithPrecedence is like RestrictToObligatory but respects precedence rules
+// when applying foundry and layer overrides
+func RestrictToObligatoryWithPrecedence(node Node, foundry, layer string) Node {
+ if node == nil {
+ return nil
+ }
+
+ // First, clone and restrict to obligatory operations
+ cloned := node.Clone()
+ restricted := restrictToObligatoryRecursive(cloned)
+
+ // Then apply foundry and layer overrides with precedence to the smaller, restricted tree
+ if restricted != nil {
+ ApplyFoundryAndLayerOverridesWithPrecedence(restricted, foundry, layer)
+ }
+
+ return restricted
+}
+
// restrictToObligatoryRecursive performs the actual restriction logic
func restrictToObligatoryRecursive(node Node) Node {
if node == nil {