From 85dd4d7087907e64a55a7bdf3b4a674068ff14c6 Mon Sep 17 00:00:00 2001 From: John Maxwell Date: Mon, 17 Mar 2025 11:40:37 -0700 Subject: [PATCH 1/5] Fix LT-21867: Optional contexts don't work properly in Hermit Crab --- .../PhonologicalRules/RewriteRuleSpec.cs | 4 ++-- src/SIL.Machine/FiniteState/Fst.cs | 14 ++++++++++++++ src/SIL.Machine/Matching/Matcher.cs | 5 +++++ .../PhonologicalRules/RewriteRuleTests.cs | 2 ++ 4 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/SIL.Machine.Morphology.HermitCrab/PhonologicalRules/RewriteRuleSpec.cs b/src/SIL.Machine.Morphology.HermitCrab/PhonologicalRules/RewriteRuleSpec.cs index f91899d61..d02a86a28 100644 --- a/src/SIL.Machine.Morphology.HermitCrab/PhonologicalRules/RewriteRuleSpec.cs +++ b/src/SIL.Machine.Morphology.HermitCrab/PhonologicalRules/RewriteRuleSpec.cs @@ -85,7 +85,7 @@ out PhonologicalSubruleMatch subruleMatch leftNode, varBindings ); - if (leftEnvMatch == null || leftEnvMatch.Success) + if (leftEnvMatch == null || leftEnvMatch.Success || subruleSpec.LeftEnvironmentMatcher.AcceptsEmpty()) { if (leftEnvMatch != null && leftEnvMatch.VariableBindings != null) varBindings = leftEnvMatch.VariableBindings; @@ -95,7 +95,7 @@ out PhonologicalSubruleMatch subruleMatch rightNode, varBindings ); - if (rightEnvMatch == null || rightEnvMatch.Success) + if (rightEnvMatch == null || rightEnvMatch.Success || subruleSpec.RightEnvironmentMatcher.AcceptsEmpty()) { if (rightEnvMatch != null && rightEnvMatch.VariableBindings != null) varBindings = rightEnvMatch.VariableBindings; diff --git a/src/SIL.Machine/FiniteState/Fst.cs b/src/SIL.Machine/FiniteState/Fst.cs index f56d8f86d..02a9c0f78 100644 --- a/src/SIL.Machine/FiniteState/Fst.cs +++ b/src/SIL.Machine/FiniteState/Fst.cs @@ -2130,5 +2130,19 @@ public int GetFrozenHashCode() { return GetHashCode(); } + + internal bool IsAcceptingState(State state) + { + State curState = state; + while (!curState.IsAccepting) + { + Arc highestPriArc = curState.Arcs.MinBy(a => a.Priority); + if (!highestPriArc.Input.IsEpsilon) + break; + curState = highestPriArc.Target; + } + + return curState.IsAccepting; + } } } diff --git a/src/SIL.Machine/Matching/Matcher.cs b/src/SIL.Machine/Matching/Matcher.cs index 10089063e..54150f3c2 100644 --- a/src/SIL.Machine/Matching/Matcher.cs +++ b/src/SIL.Machine/Matching/Matcher.cs @@ -336,5 +336,10 @@ private Annotation GetStartAnnotation(TData input, TOffset start) startAnn = startAnn.GetNextDepthFirst(_settings.Direction, _settings.Filter); return startAnn; } + + public bool AcceptsEmpty() + { + return _fsa.IsAcceptingState(_fsa.StartState); + } } } diff --git a/tests/SIL.Machine.Morphology.HermitCrab.Tests/PhonologicalRules/RewriteRuleTests.cs b/tests/SIL.Machine.Morphology.HermitCrab.Tests/PhonologicalRules/RewriteRuleTests.cs index 92dd64f88..bbf9bba6e 100644 --- a/tests/SIL.Machine.Morphology.HermitCrab.Tests/PhonologicalRules/RewriteRuleTests.cs +++ b/tests/SIL.Machine.Morphology.HermitCrab.Tests/PhonologicalRules/RewriteRuleTests.cs @@ -47,6 +47,8 @@ public void SimpleRules() new RewriteSubrule { Rhs = Pattern.New().Annotation(asp).Value, + // the following should be a NOOP because it accepts the empty string. + LeftEnvironment = Pattern.New().Annotation(nonCons).Optional.Annotation(nonCons).Optional.Value, RightEnvironment = Pattern.New().Annotation(nonCons).Value } ); From e56372b6b082f3c41001f9887e65d65f92c375cb Mon Sep 17 00:00:00 2001 From: John Maxwell Date: Mon, 17 Mar 2025 11:51:24 -0700 Subject: [PATCH 2/5] Fix format --- .../PhonologicalRules/RewriteRuleSpec.cs | 8 ++++++-- src/SIL.Machine/FiniteState/Fst.cs | 2 +- .../PhonologicalRules/RewriteRuleTests.cs | 6 +++++- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/SIL.Machine.Morphology.HermitCrab/PhonologicalRules/RewriteRuleSpec.cs b/src/SIL.Machine.Morphology.HermitCrab/PhonologicalRules/RewriteRuleSpec.cs index d02a86a28..8a9125606 100644 --- a/src/SIL.Machine.Morphology.HermitCrab/PhonologicalRules/RewriteRuleSpec.cs +++ b/src/SIL.Machine.Morphology.HermitCrab/PhonologicalRules/RewriteRuleSpec.cs @@ -85,7 +85,9 @@ out PhonologicalSubruleMatch subruleMatch leftNode, varBindings ); - if (leftEnvMatch == null || leftEnvMatch.Success || subruleSpec.LeftEnvironmentMatcher.AcceptsEmpty()) + if (leftEnvMatch == null + || leftEnvMatch.Success + || subruleSpec.LeftEnvironmentMatcher.AcceptsEmpty()) { if (leftEnvMatch != null && leftEnvMatch.VariableBindings != null) varBindings = leftEnvMatch.VariableBindings; @@ -95,7 +97,9 @@ out PhonologicalSubruleMatch subruleMatch rightNode, varBindings ); - if (rightEnvMatch == null || rightEnvMatch.Success || subruleSpec.RightEnvironmentMatcher.AcceptsEmpty()) + if (rightEnvMatch == null + || rightEnvMatch.Success + || subruleSpec.RightEnvironmentMatcher.AcceptsEmpty()) { if (rightEnvMatch != null && rightEnvMatch.VariableBindings != null) varBindings = rightEnvMatch.VariableBindings; diff --git a/src/SIL.Machine/FiniteState/Fst.cs b/src/SIL.Machine/FiniteState/Fst.cs index 02a9c0f78..b90f9ac40 100644 --- a/src/SIL.Machine/FiniteState/Fst.cs +++ b/src/SIL.Machine/FiniteState/Fst.cs @@ -2143,6 +2143,6 @@ internal bool IsAcceptingState(State state) } return curState.IsAccepting; - } + } } } diff --git a/tests/SIL.Machine.Morphology.HermitCrab.Tests/PhonologicalRules/RewriteRuleTests.cs b/tests/SIL.Machine.Morphology.HermitCrab.Tests/PhonologicalRules/RewriteRuleTests.cs index bbf9bba6e..9050252b7 100644 --- a/tests/SIL.Machine.Morphology.HermitCrab.Tests/PhonologicalRules/RewriteRuleTests.cs +++ b/tests/SIL.Machine.Morphology.HermitCrab.Tests/PhonologicalRules/RewriteRuleTests.cs @@ -48,7 +48,11 @@ public void SimpleRules() { Rhs = Pattern.New().Annotation(asp).Value, // the following should be a NOOP because it accepts the empty string. - LeftEnvironment = Pattern.New().Annotation(nonCons).Optional.Annotation(nonCons).Optional.Value, + LeftEnvironment = Pattern + .New() + .Annotation(nonCons).Optional + .Annotation(nonCons).Optional + .Value, RightEnvironment = Pattern.New().Annotation(nonCons).Value } ); From 1d95604cfbf63a21aba0774bb5f9b1f7fb15a83e Mon Sep 17 00:00:00 2001 From: John Maxwell Date: Mon, 17 Mar 2025 12:01:03 -0700 Subject: [PATCH 3/5] Fix format --- .../PhonologicalRules/RewriteRuleSpec.cs | 4 +--- .../PhonologicalRules/RewriteRuleTests.cs | 6 +++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/SIL.Machine.Morphology.HermitCrab/PhonologicalRules/RewriteRuleSpec.cs b/src/SIL.Machine.Morphology.HermitCrab/PhonologicalRules/RewriteRuleSpec.cs index 8a9125606..cff18829a 100644 --- a/src/SIL.Machine.Morphology.HermitCrab/PhonologicalRules/RewriteRuleSpec.cs +++ b/src/SIL.Machine.Morphology.HermitCrab/PhonologicalRules/RewriteRuleSpec.cs @@ -85,9 +85,7 @@ out PhonologicalSubruleMatch subruleMatch leftNode, varBindings ); - if (leftEnvMatch == null - || leftEnvMatch.Success - || subruleSpec.LeftEnvironmentMatcher.AcceptsEmpty()) + if (leftEnvMatch == null || leftEnvMatch.Success || subruleSpec.LeftEnvironmentMatcher.AcceptsEmpty()) { if (leftEnvMatch != null && leftEnvMatch.VariableBindings != null) varBindings = leftEnvMatch.VariableBindings; diff --git a/tests/SIL.Machine.Morphology.HermitCrab.Tests/PhonologicalRules/RewriteRuleTests.cs b/tests/SIL.Machine.Morphology.HermitCrab.Tests/PhonologicalRules/RewriteRuleTests.cs index 9050252b7..f57de738a 100644 --- a/tests/SIL.Machine.Morphology.HermitCrab.Tests/PhonologicalRules/RewriteRuleTests.cs +++ b/tests/SIL.Machine.Morphology.HermitCrab.Tests/PhonologicalRules/RewriteRuleTests.cs @@ -50,9 +50,9 @@ public void SimpleRules() // the following should be a NOOP because it accepts the empty string. LeftEnvironment = Pattern .New() - .Annotation(nonCons).Optional - .Annotation(nonCons).Optional - .Value, + .Annotation(nonCons) + .Optional.Annotation(nonCons) + .Optional.Value, RightEnvironment = Pattern.New().Annotation(nonCons).Value } ); From 123aec9befebed2e53393f617e642bd0c2d9800e Mon Sep 17 00:00:00 2001 From: John Maxwell Date: Mon, 17 Mar 2025 12:09:49 -0700 Subject: [PATCH 4/5] Fix format --- .../PhonologicalRules/RewriteRuleSpec.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/SIL.Machine.Morphology.HermitCrab/PhonologicalRules/RewriteRuleSpec.cs b/src/SIL.Machine.Morphology.HermitCrab/PhonologicalRules/RewriteRuleSpec.cs index cff18829a..1d6a339cf 100644 --- a/src/SIL.Machine.Morphology.HermitCrab/PhonologicalRules/RewriteRuleSpec.cs +++ b/src/SIL.Machine.Morphology.HermitCrab/PhonologicalRules/RewriteRuleSpec.cs @@ -95,9 +95,11 @@ out PhonologicalSubruleMatch subruleMatch rightNode, varBindings ); - if (rightEnvMatch == null + if ( + rightEnvMatch == null || rightEnvMatch.Success - || subruleSpec.RightEnvironmentMatcher.AcceptsEmpty()) + || subruleSpec.RightEnvironmentMatcher.AcceptsEmpty() + ) { if (rightEnvMatch != null && rightEnvMatch.VariableBindings != null) varBindings = rightEnvMatch.VariableBindings; From 1c1e7f13911a98de1543ee21aac1d4a1cd3c06fe Mon Sep 17 00:00:00 2001 From: John Maxwell Date: Mon, 17 Mar 2025 12:17:58 -0700 Subject: [PATCH 5/5] Fix format --- .../PhonologicalRules/RewriteRuleSpec.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SIL.Machine.Morphology.HermitCrab/PhonologicalRules/RewriteRuleSpec.cs b/src/SIL.Machine.Morphology.HermitCrab/PhonologicalRules/RewriteRuleSpec.cs index 1d6a339cf..f17b7b4ba 100644 --- a/src/SIL.Machine.Morphology.HermitCrab/PhonologicalRules/RewriteRuleSpec.cs +++ b/src/SIL.Machine.Morphology.HermitCrab/PhonologicalRules/RewriteRuleSpec.cs @@ -99,7 +99,7 @@ out PhonologicalSubruleMatch subruleMatch rightEnvMatch == null || rightEnvMatch.Success || subruleSpec.RightEnvironmentMatcher.AcceptsEmpty() - ) + ) { if (rightEnvMatch != null && rightEnvMatch.VariableBindings != null) varBindings = rightEnvMatch.VariableBindings;