Update corpus mapping rules
Change-Id: I445798472f4494ab29db796fa19ad2b09339b1ac
diff --git a/config/config.go b/config/config.go
index 73e5697..a4f9f77 100644
--- a/config/config.go
+++ b/config/config.go
@@ -32,6 +32,8 @@
LayerA string `yaml:"layerA,omitempty"`
FoundryB string `yaml:"foundryB,omitempty"`
LayerB string `yaml:"layerB,omitempty"`
+ FieldA string `yaml:"fieldA,omitempty"`
+ FieldB string `yaml:"fieldB,omitempty"`
Mappings []MappingRule `yaml:"mappings"`
}
@@ -41,8 +43,12 @@
}
// ParseCorpusMappings parses all mapping rules as corpus rules.
+// Bare values (without key=) are always allowed and receive the default
+// field name from the mapping list header (FieldA/FieldB) when set.
func (list *MappingList) ParseCorpusMappings() ([]*parser.CorpusMappingResult, error) {
corpusParser := parser.NewCorpusParser()
+ corpusParser.AllowBareValues = true
+
results := make([]*parser.CorpusMappingResult, len(list.Mappings))
for i, rule := range list.Mappings {
if rule == "" {
@@ -52,11 +58,33 @@
if err != nil {
return nil, fmt.Errorf("failed to parse corpus mapping rule %d in list '%s': %w", i, list.ID, err)
}
+
+ if list.FieldA != "" {
+ applyDefaultCorpusKey(result.Upper, list.FieldA)
+ }
+ if list.FieldB != "" {
+ applyDefaultCorpusKey(result.Lower, list.FieldB)
+ }
+
results[i] = result
}
return results, nil
}
+// applyDefaultCorpusKey recursively fills in empty keys on CorpusField nodes.
+func applyDefaultCorpusKey(node parser.CorpusNode, defaultKey string) {
+ switch n := node.(type) {
+ case *parser.CorpusField:
+ if n.Key == "" {
+ n.Key = defaultKey
+ }
+ case *parser.CorpusGroup:
+ for _, op := range n.Operands {
+ applyDefaultCorpusKey(op, defaultKey)
+ }
+ }
+}
+
// MappingConfig represents the root configuration containing multiple mapping lists
type MappingConfig struct {
SDK string `yaml:"sdk,omitempty"`
diff --git a/config/config_test.go b/config/config_test.go
index 3a7ad32..4ba8913 100644
--- a/config/config_test.go
+++ b/config/config_test.go
@@ -6,6 +6,7 @@
"testing"
"github.com/KorAP/Koral-Mapper/ast"
+ "github.com/KorAP/Koral-Mapper/parser"
"github.com/rs/zerolog/log"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@@ -949,3 +950,33 @@
assert.Error(t, err)
assert.Contains(t, err.Error(), "failed to parse corpus mapping rule")
}
+
+func TestParseCorpusMappingsWithFieldAFieldB(t *testing.T) {
+ list := &MappingList{
+ ID: "test-keyed",
+ Type: "corpus",
+ FieldA: "wikiCat",
+ FieldB: "textClass",
+ Mappings: []MappingRule{
+ "Entertainment <> ((kultur & musik) | (kultur & film))",
+ },
+ }
+
+ results, err := list.ParseCorpusMappings()
+ require.NoError(t, err)
+ require.Len(t, results, 1)
+
+ upper := results[0].Upper.(*parser.CorpusField)
+ assert.Equal(t, "wikiCat", upper.Key)
+ assert.Equal(t, "Entertainment", upper.Value)
+
+ group := results[0].Lower.(*parser.CorpusGroup)
+ assert.Equal(t, "or", group.Operation)
+ require.Len(t, group.Operands, 2)
+
+ and1 := group.Operands[0].(*parser.CorpusGroup)
+ assert.Equal(t, "textClass", and1.Operands[0].(*parser.CorpusField).Key)
+ assert.Equal(t, "kultur", and1.Operands[0].(*parser.CorpusField).Value)
+ assert.Equal(t, "textClass", and1.Operands[1].(*parser.CorpusField).Key)
+ assert.Equal(t, "musik", and1.Operands[1].(*parser.CorpusField).Value)
+}