Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 33 additions & 26 deletions src/SIL.Machine.Morphology.HermitCrab/Allomorph.cs
Original file line number Diff line number Diff line change
Expand Up @@ -157,40 +157,47 @@ internal bool IsWordValid(Morpher morpher, Word word)

protected virtual bool CheckAllomorphConstraints(Morpher morpher, Allomorph allomorph, Word word)
{
if (
AllomorphCoOccurrenceRules.Count > 0
&& !AllomorphCoOccurrenceRules.Any(r => r.IsWordValid(allomorph, word))
)
if (AllomorphCoOccurrenceRules.Count > 0)
{
if (morpher != null && morpher.TraceManager.IsTracing)
foreach (AllomorphCoOccurrenceRule rule in AllomorphCoOccurrenceRules)
{
morpher.TraceManager.Failed(
morpher.Language,
word,
FailureReason.AllomorphCoOccurrenceRules,
this,
AllomorphCoOccurrenceRules
);
if (!rule.IsWordValid(allomorph, word))
{
if (morpher != null && morpher.TraceManager.IsTracing)
{
morpher.TraceManager.Failed(
morpher.Language,
word,
FailureReason.AllomorphCoOccurrenceRules,
this,
rule
);
}
return false;
}
}
return false;
}

if (
Morpheme.MorphemeCoOccurrenceRules.Count > 0
&& !Morpheme.MorphemeCoOccurrenceRules.Any(r => r.IsWordValid(Morpheme, word))
)
if (Morpheme.MorphemeCoOccurrenceRules.Count > 0)
{
if (morpher != null && morpher.TraceManager.IsTracing)
foreach (MorphemeCoOccurrenceRule rule in Morpheme.MorphemeCoOccurrenceRules)
{
morpher.TraceManager.Failed(
morpher.Language,
word,
FailureReason.MorphemeCoOccurrenceRules,
this,
Morpheme.MorphemeCoOccurrenceRules
);
// We need to check each one in turn and report any failure
if (!rule.IsWordValid(Morpheme, word))
{
if (morpher != null && morpher.TraceManager.IsTracing)
{
morpher.TraceManager.Failed(
morpher.Language,
word,
FailureReason.MorphemeCoOccurrenceRules,
this,
rule
);
}
return false;
}
}
return false;
}

return true;
Expand Down
114 changes: 114 additions & 0 deletions tests/SIL.Machine.Morphology.HermitCrab.Tests/MorpherTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,120 @@ public void AnalyzeWord_CannotAnalyze_ReturnsEmptyEnumerable()
Assert.That(morpher.AnalyzeWord("sagt"), Is.Empty);
}

[Test]
public void AnalyzeWord_CannotAnalyzeDueToAllomorphCooccurenceFailure_ReturnsEmptyEnumerable()
{
var any = FeatureStruct.New().Symbol(HCFeatureSystem.Segment).Value;

// Create co-occurence rule blocking sag +d
// get sag root
var sag = Language.Strata[0].Entries.ElementAt(6);
// create +ed suffix
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<Word, ShapeNode>.New("1").Annotation(any).OneOrMore.Value },
Rhs = { new CopyFromInput("1"), new InsertSegments(Table3, "+d") }
}
);
Morphophonemic.MorphologicalRules.Add(edSuffix);

var edAllo = edSuffix.GetAllomorph(0);

// create co-occurence rule which blocks the analysis
var other1 = new List<Allomorph> { edAllo };
var rule1 = new AllomorphCoOccurrenceRule(ConstraintType.Exclude, other1, MorphCoOccurrenceAdjacency.Anywhere);
var sagAllo = sag.GetAllomorph(0);
sagAllo.AllomorphCoOccurrenceRules.Add(rule1);
var morpher = new Morpher(TraceManager, Language);

Assert.That(morpher.AnalyzeWord("sagd"), Is.Empty);

// In FLEx, clitics occur as both a stem and an affix.
// LT-22156 notes that they can be ignored when they occur in a co-occurrence rule
// FLEx produces two rules for the key morpheme, one with the "other" using an affix and one using a stem
// Now create co-occurence rule blocking sag =d
var syntacticFeatSys = new SyntacticFeatureSystem();
syntacticFeatSys.AddPartsOfSpeech(
new FeatureSymbol("N", "Noun"),
new FeatureSymbol("V", "Verb"),
new FeatureSymbol("TV", "Transitive Verb"),
new FeatureSymbol("IV", "Intransitive Verb"),
new FeatureSymbol("A", "Adjective")
);
syntacticFeatSys.Freeze();
AddEntry("dEnclitic", FeatureStruct.New(syntacticFeatSys).Symbol("V").Value, Morphophonemic, "d");
var edEnclitic = Language.Strata[0].Entries.ElementAt(42);
var edEncliticAllo = edEnclitic.GetAllomorph(0);
var other2 = new List<Allomorph> { edEncliticAllo };
var rule2 = new AllomorphCoOccurrenceRule(ConstraintType.Exclude, other2, MorphCoOccurrenceAdjacency.Anywhere);
sagAllo.AllomorphCoOccurrenceRules.Add(rule2);

Assert.That(morpher.AnalyzeWord("sagd"), Is.Empty);
}

[Test]
public void AnalyzeWord_CannotAnalyzeDueToMorphemeCooccurenceFailure_ReturnsEmptyEnumerable()
{
var any = FeatureStruct.New().Symbol(HCFeatureSystem.Segment).Value;

// Create co-occurence rule blocking sag +d
// get sag root
var sag = Language.Strata[0].Entries.ElementAt(6);
// create +ed suffix
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<Word, ShapeNode>.New("1").Annotation(any).OneOrMore.Value },
Rhs = { new CopyFromInput("1"), new InsertSegments(Table3, "+d") }
}
);
Morphophonemic.MorphologicalRules.Add(edSuffix);

// create co-occurence rule which blocks the analysis
var other1 = new List<Morpheme> { edSuffix };
var rule1 = new MorphemeCoOccurrenceRule(ConstraintType.Exclude, other1, MorphCoOccurrenceAdjacency.Anywhere);
sag.MorphemeCoOccurrenceRules.Add(rule1);
var morpher = new Morpher(TraceManager, Language);

Assert.That(morpher.AnalyzeWord("sagd"), Is.Empty);

// In FLEx, clitics occur as both a stem and an affix.
// LT-22156 notes that they can be ignored when they occur in a co-occurrence rule
// FLEx produces two rules for the key morpheme, one with the "other" using an affix and one using a stem
// Now create co-occurence rule blocking sag =d
var syntacticFeatSys = new SyntacticFeatureSystem();
syntacticFeatSys.AddPartsOfSpeech(
new FeatureSymbol("N", "Noun"),
new FeatureSymbol("V", "Verb"),
new FeatureSymbol("TV", "Transitive Verb"),
new FeatureSymbol("IV", "Intransitive Verb"),
new FeatureSymbol("A", "Adjective")
);
syntacticFeatSys.Freeze();
AddEntry("dEnclitic", FeatureStruct.New(syntacticFeatSys).Symbol("V").Value, Morphophonemic, "d");
var edEnclitic = Language.Strata[0].Entries.ElementAt(42);
var other2 = new List<Morpheme> { edEnclitic };
var rule2 = new MorphemeCoOccurrenceRule(ConstraintType.Exclude, other2, MorphCoOccurrenceAdjacency.Anywhere);
sag.MorphemeCoOccurrenceRules.Add(rule2);

Assert.That(morpher.AnalyzeWord("sagd"), Is.Empty);
}

[Test]
public void AnalyzeWord_CanGuess_ReturnsCorrectAnalysis()
{
Expand Down
Loading