diff --git a/src/SIL.Machine.Morphology.HermitCrab/AnalysisLanguageRule.cs b/src/SIL.Machine.Morphology.HermitCrab/AnalysisLanguageRule.cs index b4673ca5..8c700a09 100644 --- a/src/SIL.Machine.Morphology.HermitCrab/AnalysisLanguageRule.cs +++ b/src/SIL.Machine.Morphology.HermitCrab/AnalysisLanguageRule.cs @@ -31,6 +31,8 @@ public IEnumerable Apply(Word input) HashSet outputSet = tempSet; outputSet.Clear(); + AnalysisStratumRule stratumRule = _rules[i] as AnalysisStratumRule; + stratumRule?.InitializeDuplicationDetection(); foreach (Word inData in inputSet) { @@ -41,9 +43,10 @@ public IEnumerable Apply(Word input) } } + stratumRule?.ClearDuplicationDetection(); tempSet = inputSet; inputSet = outputSet; - } + } return results; } diff --git a/src/SIL.Machine.Morphology.HermitCrab/AnalysisStratumRule.cs b/src/SIL.Machine.Morphology.HermitCrab/AnalysisStratumRule.cs index 97c31c2e..00972d41 100644 --- a/src/SIL.Machine.Morphology.HermitCrab/AnalysisStratumRule.cs +++ b/src/SIL.Machine.Morphology.HermitCrab/AnalysisStratumRule.cs @@ -14,6 +14,7 @@ internal class AnalysisStratumRule : IRule private readonly IRule _templatesRule; private readonly Stratum _stratum; private readonly Morpher _morpher; + private HashSet _shapeSet; public AnalysisStratumRule(Morpher morpher, Stratum stratum) { @@ -58,6 +59,16 @@ public AnalysisStratumRule(Morpher morpher, Stratum stratum) } } + public void InitializeDuplicationDetection() + { + _shapeSet = new HashSet(FreezableEqualityComparer.Default); + } + + public void ClearDuplicationDetection() + { + _shapeSet = null; + } + public IEnumerable Apply(Word input) { if (_morpher.TraceManager.IsTracing) @@ -117,6 +128,18 @@ private IEnumerable ApplyMorphologicalRules(Word input) private IEnumerable ApplyTemplates(Word input) { + if (_shapeSet != null) + { + // Ignore shapes that we have already tried at this level of the stratum. + // ApplyTemplates is called at the very beginning of applying the analysis stratum. + // It is also called recursively by ApplyMorphologicalRules if the rules are unordered. + // In this case, we can still use the same shapeSet since the templates and morphological + // rules continue to be applied until there are no more changes, and so + // trying this shape again won't change the results. + if (_shapeSet.Contains(input.Shape)) + yield break; + _shapeSet.Add(input.Shape); + } foreach (Word tempOutWord in _templatesRule.Apply(input).Distinct(FreezableEqualityComparer.Default)) { switch (_stratum.MorphologicalRuleOrder) diff --git a/tests/SIL.Machine.Morphology.HermitCrab.Tests/XmlLanguageSerializationTests.cs b/tests/SIL.Machine.Morphology.HermitCrab.Tests/XmlLanguageSerializationTests.cs index 390c67c0..0ace2578 100644 --- a/tests/SIL.Machine.Morphology.HermitCrab.Tests/XmlLanguageSerializationTests.cs +++ b/tests/SIL.Machine.Morphology.HermitCrab.Tests/XmlLanguageSerializationTests.cs @@ -1,4 +1,5 @@ using NUnit.Framework; +using System.Diagnostics; namespace SIL.Machine.Morphology.HermitCrab; @@ -27,4 +28,14 @@ public void RoundTripXml() File.Delete(TempXmlFileName); } } + + [Test] + public void TestParseWord() + { + Language language = XmlLanguageLoader.Load("C:\\Users\\PC\\AppData\\Local\\Temp\\Mbugwe LizzieHC practice.xml"); + Morpher morpher = new Morpher(new TraceManager(), language); + var output = morpher.ParseWord("wa", out _); + Debug.WriteLine(output); + } + }