From e5bd3e1400d3908dcbe929fc29d1b20dc0890b13 Mon Sep 17 00:00:00 2001 From: John Maxwell Date: Mon, 13 Jan 2025 09:40:02 -0800 Subject: [PATCH] Fix another bug with MorphologicalRuleOrder.Linear --- .../AnalysisStratumRule.cs | 6 +- .../MorpherTests.cs | 57 +++++++++++++++++++ 2 files changed, 62 insertions(+), 1 deletion(-) diff --git a/src/SIL.Machine.Morphology.HermitCrab/AnalysisStratumRule.cs b/src/SIL.Machine.Morphology.HermitCrab/AnalysisStratumRule.cs index 0edc7f9b..74681bc2 100644 --- a/src/SIL.Machine.Morphology.HermitCrab/AnalysisStratumRule.cs +++ b/src/SIL.Machine.Morphology.HermitCrab/AnalysisStratumRule.cs @@ -34,7 +34,11 @@ public AnalysisStratumRule(Morpher morpher, Stratum stratum) switch (stratum.MorphologicalRuleOrder) { case MorphologicalRuleOrder.Linear: - _mrulesRule = new LinearRuleCascade( + // Use PermutationRuleCascade instead of LinearRuleCascade + // because morphological rules should be considered optional + // during unapplication (they are obligatory during application, + // but we don't know they have been applied during unapplication). + _mrulesRule = new PermutationRuleCascade( mrules, true, FreezableEqualityComparer.Default diff --git a/tests/SIL.Machine.Morphology.HermitCrab.Tests/MorpherTests.cs b/tests/SIL.Machine.Morphology.HermitCrab.Tests/MorpherTests.cs index e17f09f9..d122802c 100644 --- a/tests/SIL.Machine.Morphology.HermitCrab.Tests/MorpherTests.cs +++ b/tests/SIL.Machine.Morphology.HermitCrab.Tests/MorpherTests.cs @@ -3,6 +3,7 @@ using SIL.Machine.FeatureModel; using SIL.Machine.Matching; using SIL.Machine.Morphology.HermitCrab.MorphologicalRules; +using SIL.Machine.Morphology.HermitCrab.PhonologicalRules; namespace SIL.Machine.Morphology.HermitCrab; @@ -36,8 +37,64 @@ public void AnalyzeWord_CanAnalyze_ReturnsCorrectAnalysis() morpher.AnalyzeWord("sagd"), Is.EquivalentTo(new[] { new WordAnalysis(new IMorpheme[] { Entries["32"], edSuffix }, 0, "V") }) ); + } + + [Test] + public void AnalyzeWord_CanAnalyzeLinear_ReturnsCorrectAnalysis() + { + var any = FeatureStruct.New().Symbol(HCFeatureSystem.Segment).Value; + + var edSuffix = new AffixProcessRule + { + Id = "PAST", + Name = "ed_suffix", + Gloss = "PAST", + RequiredSyntacticFeatureStruct = FeatureStruct.New(Language.SyntacticFeatureSystem).Symbol("V").Value + }; + edSuffix.Allomorphs.Add( + new AffixProcessAllomorph + { + Lhs = { Pattern.New("1").Annotation(any).OneOrMore.Value }, + Rhs = { new CopyFromInput("1"), new InsertSegments(Table3, "+d") } + } + ); + Morphophonemic.MorphologicalRules.Add(edSuffix); + + // Adding rules shouldn't block sagd analysis when Linear. + var tSuffix = new AffixProcessRule + { + Id = "PLURAL", + Name = "t_suffix", + Gloss = "PLURAL", + RequiredSyntacticFeatureStruct = FeatureStruct.New(Language.SyntacticFeatureSystem).Symbol("N").Value + }; + tSuffix.Allomorphs.Add( + new AffixProcessAllomorph + { + Lhs = { Pattern.New("1").Annotation(any).OneOrMore.Value }, + Rhs = { new CopyFromInput("1"), new InsertSegments(Table3, "+t") } + } + ); + Morphophonemic.MorphologicalRules.Add(tSuffix); + + // Add a phonological rule so that "sagd" becomes "sag[dt]" during unapplication. + // This is to verify that unapplication works correctly. + var rule1 = new RewriteRule + { + Name = "rule1", + Lhs = Pattern.New().Annotation(Character(Table1, "t")).Value + }; + rule1.Subrules.Add( + new RewriteSubrule + { + Rhs = Pattern.New().Annotation(Character(Table1, "d")).Value, + } + ); + Morphophonemic.PhonologicalRules.Add(rule1); SetRuleOrder(MorphologicalRuleOrder.Linear); + var morpher = new Morpher(TraceManager, Language); + Assert.That( morpher.AnalyzeWord("sagd"), Is.EquivalentTo(new[] { new WordAnalysis(new IMorpheme[] { Entries["32"], edSuffix }, 0, "V") })