public void SimpleRuleNotUnapplied() { var any = FeatureStruct.New().Symbol(HCFeatureSystem.Segment).Value; var prule = new MetathesisRule { Name = "rule1", Pattern = Pattern <Word, ShapeNode> .New() .Group("1", group => group.Annotation(Char(Table3, "i"))) .Group("2", group => group.Annotation(Char(Table3, "u"))).Value, LeftSwitchName = "2", RightSwitchName = "1" }; Morphophonemic.PhonologicalRules.Add(prule); var iSuffix = new AffixProcessRule { Name = "i_suffix", Gloss = "3SG" }; Morphophonemic.MorphologicalRules.Add(iSuffix); iSuffix.Allomorphs.Add( new AffixProcessAllomorph { Lhs = { Pattern <Word, ShapeNode> .New("1").Annotation(any).OneOrMore.Value }, Rhs = { new CopyFromInput("1"), new InsertSegments(Table3, "i") } }); var morpher = new Morpher(TraceManager, Language); AssertMorphsEqual(morpher.ParseWord("pui"), "52 3SG"); }
public void AnalyzeWord_CanAnalyze_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 <Word, ShapeNode> .New("1").Annotation(any).OneOrMore.Value }, Rhs = { new CopyFromInput("1"), new InsertSegments(Table3, "+d") } }); Morphophonemic.MorphologicalRules.Add(edSuffix); var morpher = new Morpher(TraceManager, Language); Assert.That(morpher.AnalyzeWord("sagd"), Is.EquivalentTo(new[] { new WordAnalysis(new IMorpheme[] { Entries["32"], edSuffix }, 0, "V") })); }
public void DisjunctiveAllomorphs() { var any = FeatureStruct.New().Symbol(HCFeatureSystem.Segment).Value; var edSuffix = new AffixProcessRule { 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 morpher = new Morpher(TraceManager, Language); AssertMorphsEqual(morpher.ParseWord("bazɯd"), "disj PAST"); Assert.That(morpher.ParseWord("batɯd"), Is.Empty); Assert.That(morpher.ParseWord("badɯd"), Is.Empty); Assert.That(morpher.ParseWord("basɯd"), Is.Empty); AssertMorphsEqual(morpher.ParseWord("bas"), "disj"); }
public void ComplexRule() { var any = FeatureStruct.New().Symbol(HCFeatureSystem.Segment).Value; var rule1 = new MetathesisRule { Name = "rule1", Pattern = Pattern <Word, ShapeNode> .New() .Group("1", group => group.Annotation(Char(Table3, "i"))) .Group("middle", group => group.Annotation(Char(Table3, "+"))) .Group("2", group => group.Annotation(Char(Table3, "u"))) .Group("rightEnv", group => group.Annotation(HCFeatureSystem.RightSideAnchor)).Value, LeftSwitchName = "2", RightSwitchName = "1" }; Morphophonemic.PhonologicalRules.Add(rule1); var uSuffix = new AffixProcessRule { Name = "u_suffix", Gloss = "3SG" }; Morphophonemic.MorphologicalRules.Add(uSuffix); uSuffix.Allomorphs.Add(new AffixProcessAllomorph { Lhs = { Pattern <Word, ShapeNode> .New("1").Annotation(any).OneOrMore.Value }, Rhs = { new CopyFromInput("1"), new InsertSegments(Table3, "+u") } }); var morpher = new Morpher(SpanFactory, TraceManager, Language); AssertMorphsEqual(morpher.ParseWord("mui"), "53 3SG"); }
public void SameRuleUsedInMultipleTemplates() { var any = FeatureStruct.New().Symbol(HCFeatureSystem.Segment).Value; var edSuffix = new AffixProcessRule { Name = "ed_suffix", Gloss = "PAST", RequiredSyntacticFeatureStruct = FeatureStruct.New(Language.SyntacticFeatureSystem) .Symbol("V", "IV", "TV").Value, }; edSuffix.Allomorphs.Add(new AffixProcessAllomorph { Lhs = { Pattern <Word, ShapeNode> .New("1").Annotation(any).OneOrMore.Value }, Rhs = { new CopyFromInput("1"), new InsertSegments(Table3, "d") } }); var transitiveVerbTemplate = new AffixTemplate { Name = "Transitive Verb", RequiredSyntacticFeatureStruct = FeatureStruct.New(Language.SyntacticFeatureSystem).Symbol("TV").Value }; transitiveVerbTemplate.Slots.Add(new AffixTemplateSlot(edSuffix)); Morphophonemic.AffixTemplates.Add(transitiveVerbTemplate); var intransitiveVerbTemplate = new AffixTemplate { Name = "Intransitive Verb", RequiredSyntacticFeatureStruct = FeatureStruct.New(Language.SyntacticFeatureSystem).Symbol("IV").Value }; intransitiveVerbTemplate.Slots.Add(new AffixTemplateSlot(edSuffix)); Morphophonemic.AffixTemplates.Add(intransitiveVerbTemplate); var nominalizer = new AffixProcessRule { Name = "intransitive verbalizer", Gloss = "IVERB", RequiredSyntacticFeatureStruct = FeatureStruct.New(Language.SyntacticFeatureSystem).Symbol("N").Value, OutSyntacticFeatureStruct = FeatureStruct.New(Language.SyntacticFeatureSystem).Symbol("IV").Value }; nominalizer.Allomorphs.Add(new AffixProcessAllomorph { Lhs = { Pattern <Word, ShapeNode> .New("1").Annotation(any).OneOrMore.Value }, Rhs = { new CopyFromInput("1"), new InsertSegments(Table3, "v") } }); Morphophonemic.MorphologicalRules.Add(nominalizer); var morpher = new Morpher(TraceManager, Language); AssertMorphsEqual(morpher.ParseWord("mivd"), "53 IVERB PAST"); }
public void PartialEntry() { var any = FeatureStruct.New().Symbol(HCFeatureSystem.Segment).Value; var nominalizer = new AffixProcessRule { Name = "nominalizer", Gloss = "NOM", RequiredSyntacticFeatureStruct = FeatureStruct.New(Language.SyntacticFeatureSystem).Symbol("V").Value, OutSyntacticFeatureStruct = FeatureStruct.New(Language.SyntacticFeatureSystem).Symbol("N").Value }; nominalizer.Allomorphs.Add(new AffixProcessAllomorph { Lhs = { Pattern <Word, ShapeNode> .New("1").Annotation(any).OneOrMore.Value }, Rhs = { new CopyFromInput("1"), new InsertSegments(Table3, "v") } }); Morphophonemic.MorphologicalRules.Add(nominalizer); var morpher = new Morpher(TraceManager, Language); AssertMorphsEqual(morpher.ParseWord("pi"), "54"); AssertMorphsEqual(morpher.ParseWord("piv"), "54 NOM"); Morphophonemic.MorphologicalRules.Clear(); var sSuffix = new AffixProcessRule { Name = "s_suffix", Gloss = "PAST", RequiredSyntacticFeatureStruct = FeatureStruct.New(Language.SyntacticFeatureSystem).Symbol("V").Value, }; sSuffix.Allomorphs.Add(new AffixProcessAllomorph { Lhs = { Pattern <Word, ShapeNode> .New("1").Annotation(any).OneOrMore.Value }, Rhs = { new CopyFromInput("1"), new InsertSegments(Table3, "s") } }); var verbTemplate = new AffixTemplate { Name = "verb", RequiredSyntacticFeatureStruct = FeatureStruct.New(Language.SyntacticFeatureSystem).Symbol("V").Value }; verbTemplate.Slots.Add(new AffixTemplateSlot(sSuffix) { Optional = true }); Morphophonemic.AffixTemplates.Add(verbTemplate); morpher = new Morpher(TraceManager, Language); AssertMorphsEqual(morpher.ParseWord("pi"), "54"); AssertMorphsEqual(morpher.ParseWord("pis")); }
public void AffixTemplateAppliedAfterMorphologicalRule() { var any = FeatureStruct.New().Symbol(HCFeatureSystem.Segment).Value; var nominalizer = new AffixProcessRule { Name = "nominalizer", Gloss = "NOM", RequiredSyntacticFeatureStruct = FeatureStruct.New(Language.SyntacticFeatureSystem).Symbol("V").Value, OutSyntacticFeatureStruct = FeatureStruct.New(Language.SyntacticFeatureSystem).Symbol("N").Value }; nominalizer.Allomorphs.Add(new AffixProcessAllomorph { Lhs = { Pattern <Word, ShapeNode> .New("1").Annotation(any).OneOrMore.Value }, Rhs = { new CopyFromInput("1"), new InsertSegments(Table3, "v") } }); Morphophonemic.MorphologicalRules.Add(nominalizer); var sSuffix = new AffixProcessRule { Name = "s_suffix", Gloss = "PL", RequiredSyntacticFeatureStruct = FeatureStruct.New(Language.SyntacticFeatureSystem).Symbol("N").Value, }; sSuffix.Allomorphs.Add(new AffixProcessAllomorph { Lhs = { Pattern <Word, ShapeNode> .New("1").Annotation(any).OneOrMore.Value }, Rhs = { new CopyFromInput("1"), new InsertSegments(Table3, "s") } }); var nounTemplate = new AffixTemplate { Name = "noun", RequiredSyntacticFeatureStruct = FeatureStruct.New(Language.SyntacticFeatureSystem).Symbol("N").Value }; nounTemplate.Slots.Add(new AffixTemplateSlot(sSuffix) { Optional = true }); Morphophonemic.AffixTemplates.Add(nounTemplate); var morpher = new Morpher(SpanFactory, TraceManager, Language); AssertMorphsEqual(morpher.ParseWord("sagv"), "32 NOM"); AssertMorphsEqual(morpher.ParseWord("sagvs"), "32 NOM PL"); }
public void GenerateWords_CanGenerate_ReturnsCorrectWord() { var any = FeatureStruct.New().Symbol(HCFeatureSystem.Segment).Value; var siPrefix = new AffixProcessRule { Id = "3SG", Name = "si_prefix", Gloss = "3SG", RequiredSyntacticFeatureStruct = FeatureStruct.New(Language.SyntacticFeatureSystem).Symbol("V").Value }; siPrefix.Allomorphs.Add(new AffixProcessAllomorph { Lhs = { Pattern <Word, ShapeNode> .New("1").Annotation(any).OneOrMore.Value }, Rhs = { new InsertSegments(Table3, "si+"), new CopyFromInput("1") } }); Morphophonemic.MorphologicalRules.Add(siPrefix); 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 morpher = new Morpher(TraceManager, Language); var analysis = new WordAnalysis(new IMorpheme[] { siPrefix, Entries["33"], edSuffix }, 1, "V"); string[] words = morpher.GenerateWords(analysis).ToArray(); Assert.That(words, Is.EquivalentTo(new[] { "sisasɯd" })); }
public void FreeFluctuation() { var any = FeatureStruct.New().Symbol(HCFeatureSystem.Segment).Value; var d = FeatureStruct.New(Language.PhonologicalFeatureSystem) .Symbol(HCFeatureSystem.Segment) .Symbol("cons+") .Symbol("strident-") .Symbol("del_rel-") .Symbol("alveolar") .Symbol("nasal-") .Symbol("vd+").Value; var edSuffix = new AffixProcessRule { 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, "+t") } }); edSuffix.Allomorphs.Add(new AffixProcessAllomorph { Lhs = { Pattern <Word, ShapeNode> .New("1").Annotation(any).OneOrMore.Value }, Rhs = { new CopyFromInput("1"), new InsertSegments(Table3, "+"), new InsertSimpleContext(d) } }); Morphophonemic.MorphologicalRules.Add(edSuffix); var morpher = new Morpher(TraceManager, Language); AssertMorphsEqual(morpher.ParseWord("tazd"), "free PAST"); AssertMorphsEqual(morpher.ParseWord("tast"), "free PAST"); AssertMorphsEqual(morpher.ParseWord("tazt"), "free PAST"); AssertMorphsEqual(morpher.ParseWord("tasd"), "free PAST"); }
public void SimpleRules() { var any = FeatureStruct.New().Symbol(HCFeatureSystem.Segment).Value; var rule1 = new CompoundingRule { Name = "rule1" }; Allophonic.MorphologicalRules.Add(rule1); rule1.Subrules.Add(new CompoundingSubrule { HeadLhs = { Pattern <Word, ShapeNode> .New("head").Annotation(any).OneOrMore.Value }, NonHeadLhs = { Pattern <Word, ShapeNode> .New("nonHead").Annotation(any).OneOrMore.Value }, Rhs = { new CopyFromInput("head"), new InsertSegments(Table3, "+"), new CopyFromInput("nonHead") } }); var morpher = new Morpher(SpanFactory, TraceManager, Language); List <Word> output = morpher.ParseWord("pʰutdat").ToList(); AssertMorphsEqual(output, "5 8", "5 9"); AssertRootAllomorphsEquals(output, "5"); Assert.That(morpher.ParseWord("pʰutdas"), Is.Empty); Assert.That(morpher.ParseWord("pʰusdat"), Is.Empty); rule1.Subrules.Clear(); rule1.Subrules.Add(new CompoundingSubrule { HeadLhs = { Pattern <Word, ShapeNode> .New("head").Annotation(any).OneOrMore.Value }, NonHeadLhs = { Pattern <Word, ShapeNode> .New("nonHead").Annotation(any).OneOrMore.Value }, Rhs = { new CopyFromInput("nonHead"), new InsertSegments(Table3, "+"), new CopyFromInput("head") } }); morpher = new Morpher(SpanFactory, TraceManager, Language); output = morpher.ParseWord("pʰutdat").ToList(); AssertMorphsEqual(output, "5 8", "5 9"); AssertRootAllomorphsEquals(output, "8", "9"); Assert.That(morpher.ParseWord("pʰutdas"), Is.Empty); Assert.That(morpher.ParseWord("pʰusdat"), Is.Empty); var prefix = new AffixProcessRule { Name = "prefix", Gloss = "PAST", RequiredSyntacticFeatureStruct = FeatureStruct.New(Language.SyntacticFeatureSystem).Symbol("V").Value, OutSyntacticFeatureStruct = FeatureStruct.New(Language.SyntacticFeatureSystem) .Feature(Head).EqualTo(head => head .Feature("tense").EqualTo("past")).Value }; Allophonic.MorphologicalRules.Insert(0, prefix); prefix.Allomorphs.Add(new AffixProcessAllomorph { Lhs = { Pattern <Word, ShapeNode> .New("1").Annotation(any).OneOrMore.Value }, Rhs = { new InsertSegments(Table3, "di+"), new CopyFromInput("1") } }); morpher = new Morpher(SpanFactory, TraceManager, Language); output = morpher.ParseWord("pʰutdidat").ToList(); AssertMorphsEqual(output, "5 PAST 9"); AssertRootAllomorphsEquals(output, "9"); Allophonic.MorphologicalRules.RemoveAt(0); rule1.MaxApplicationCount = 2; rule1.Subrules.Clear(); rule1.Subrules.Add(new CompoundingSubrule { HeadLhs = { Pattern <Word, ShapeNode> .New("head").Annotation(any).OneOrMore.Value }, NonHeadLhs = { Pattern <Word, ShapeNode> .New("nonHead").Annotation(any).OneOrMore.Value }, Rhs = { new CopyFromInput("head"), new InsertSegments(Table3, "+"), new CopyFromInput("nonHead") } }); morpher = new Morpher(SpanFactory, TraceManager, Language) { MaxStemCount = 3 }; output = morpher.ParseWord("pʰutdatpip").ToList(); AssertMorphsEqual(output, "5 8 41", "5 9 41"); AssertRootAllomorphsEquals(output, "5"); rule1.MaxApplicationCount = 1; var rule2 = new CompoundingRule { Name = "rule2" }; Allophonic.MorphologicalRules.Add(rule2); rule2.Subrules.Add(new CompoundingSubrule { HeadLhs = { Pattern <Word, ShapeNode> .New("head").Annotation(any).OneOrMore.Value }, NonHeadLhs = { Pattern <Word, ShapeNode> .New("nonHead").Annotation(any).OneOrMore.Value }, Rhs = { new CopyFromInput("nonHead"), new InsertSegments(Table3, "+"), new CopyFromInput("head") } }); morpher = new Morpher(SpanFactory, TraceManager, Language) { MaxStemCount = 3 }; output = morpher.ParseWord("pʰutdatpip").ToList(); AssertMorphsEqual(output, "5 8 41", "5 9 41"); AssertRootAllomorphsEquals(output, "8", "9"); }
public void StemNames() { var any = FeatureStruct.New().Symbol(HCFeatureSystem.Segment).Value; var edSuffix = new AffixProcessRule { Name = "ed_suffix", Gloss = "1", RequiredSyntacticFeatureStruct = FeatureStruct.New(Language.SyntacticFeatureSystem).Symbol("V").Value, OutSyntacticFeatureStruct = FeatureStruct.New(Language.SyntacticFeatureSystem) .Feature(Head).EqualTo(head => head .Feature("pers").EqualTo("1")).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 tSuffix = new AffixProcessRule { Name = "t_suffix", Gloss = "2", RequiredSyntacticFeatureStruct = FeatureStruct.New(Language.SyntacticFeatureSystem).Symbol("V").Value, OutSyntacticFeatureStruct = FeatureStruct.New(Language.SyntacticFeatureSystem) .Feature(Head).EqualTo(head => head .Feature("pers").EqualTo("2")).Value }; tSuffix.Allomorphs.Add(new AffixProcessAllomorph { Lhs = { Pattern <Word, ShapeNode> .New("1").Annotation(any).OneOrMore.Value }, Rhs = { new CopyFromInput("1"), new InsertSegments(Table3, "+t") } }); Morphophonemic.MorphologicalRules.Add(tSuffix); var sSuffix = new AffixProcessRule { Name = "s_suffix", Gloss = "3", RequiredSyntacticFeatureStruct = FeatureStruct.New(Language.SyntacticFeatureSystem).Symbol("V").Value, OutSyntacticFeatureStruct = FeatureStruct.New(Language.SyntacticFeatureSystem) .Feature(Head).EqualTo(head => head .Feature("pers").EqualTo("3")).Value }; sSuffix.Allomorphs.Add(new AffixProcessAllomorph { Lhs = { Pattern <Word, ShapeNode> .New("1").Annotation(any).OneOrMore.Value }, Rhs = { new CopyFromInput("1"), new InsertSegments(Table3, "+s") } }); Morphophonemic.MorphologicalRules.Add(sSuffix); var morpher = new Morpher(TraceManager, Language); AssertMorphsEqual(morpher.ParseWord("sanɯd")); AssertMorphsEqual(morpher.ParseWord("sant")); AssertMorphsEqual(morpher.ParseWord("sans")); AssertMorphsEqual(morpher.ParseWord("san"), "stemname"); AssertMorphsEqual(morpher.ParseWord("sadɯd"), "stemname 1"); AssertMorphsEqual(morpher.ParseWord("sadt"), "stemname 2"); AssertMorphsEqual(morpher.ParseWord("sads")); AssertMorphsEqual(morpher.ParseWord("sad")); AssertMorphsEqual(morpher.ParseWord("sapɯd"), "stemname 1"); AssertMorphsEqual(morpher.ParseWord("sapt")); AssertMorphsEqual(morpher.ParseWord("saps"), "stemname 3"); AssertMorphsEqual(morpher.ParseWord("sap")); }
public void NonFinalTemplate() { var any = FeatureStruct.New().Symbol(HCFeatureSystem.Segment).Value; var alvStop = FeatureStruct.New(Language.PhonologicalFeatureSystem) .Symbol(HCFeatureSystem.Segment) .Symbol("cons+") .Symbol("strident-") .Symbol("del_rel-") .Symbol("alveolar").Value; var voicelessCons = FeatureStruct.New(Language.PhonologicalFeatureSystem) .Symbol(HCFeatureSystem.Segment) .Symbol("cons+") .Symbol("vd-").Value; var edSuffix = new AffixProcessRule { Name = "ed_suffix", Gloss = "PAST", }; edSuffix.Allomorphs.Add(new AffixProcessAllomorph { Lhs = { Pattern <Word, ShapeNode> .New("1").Annotation(any).OneOrMore.Value, Pattern <Word, ShapeNode> .New("2").Annotation(alvStop).Value }, Rhs = { new CopyFromInput("1"), new CopyFromInput("2"), new InsertSegments(Table3, "ɯd") } }); edSuffix.Allomorphs.Add(new AffixProcessAllomorph { Lhs = { Pattern <Word, ShapeNode> .New("1").Annotation(any).OneOrMore.Annotation(voicelessCons).Value }, Rhs = { new CopyFromInput("1"), new InsertSegments(Table3, "t") } }); edSuffix.Allomorphs.Add(new AffixProcessAllomorph { Lhs = { Pattern <Word, ShapeNode> .New("1").Annotation(any).OneOrMore.Value }, Rhs = { new CopyFromInput("1"), new InsertSegments(Table3, "d") } }); var verbTemplate = new AffixTemplate { Name = "verb", RequiredSyntacticFeatureStruct = FeatureStruct.New(Language.SyntacticFeatureSystem).Symbol("V").Value }; verbTemplate.Slots.Add(new AffixTemplateSlot(edSuffix)); Morphophonemic.AffixTemplates.Add(verbTemplate); var nominalizer = new AffixProcessRule { Name = "nominalizer", Gloss = "NOM", RequiredSyntacticFeatureStruct = FeatureStruct.New(Language.SyntacticFeatureSystem).Symbol("V").Value, OutSyntacticFeatureStruct = FeatureStruct.New(Language.SyntacticFeatureSystem).Symbol("N").Value }; nominalizer.Allomorphs.Add(new AffixProcessAllomorph { Lhs = { Pattern <Word, ShapeNode> .New("1").Annotation(any).OneOrMore.Value }, Rhs = { new CopyFromInput("1"), new InsertSegments(Table3, "v") } }); Morphophonemic.MorphologicalRules.Add(nominalizer); var crule = new CompoundingRule { Name = "rule1", HeadRequiredSyntacticFeatureStruct = FeatureStruct.New(Language.SyntacticFeatureSystem) .Symbol("V").Value, NonHeadRequiredSyntacticFeatureStruct = FeatureStruct.New(Language.SyntacticFeatureSystem) .Symbol("N").Value, OutSyntacticFeatureStruct = FeatureStruct.New(Language.SyntacticFeatureSystem).Symbol("N").Value }; crule.Subrules.Add(new CompoundingSubrule { HeadLhs = { Pattern <Word, ShapeNode> .New("head").Annotation(any).OneOrMore.Value }, NonHeadLhs = { Pattern <Word, ShapeNode> .New("nonHead").Annotation(any).OneOrMore.Value }, Rhs = { new CopyFromInput("head"), new InsertSegments(Table3, "+"), new CopyFromInput("nonHead") } }); Morphophonemic.MorphologicalRules.Add(crule); var sSuffix = new AffixProcessRule { Name = "s_suffix", Gloss = "PL", RequiredSyntacticFeatureStruct = FeatureStruct.New(Language.SyntacticFeatureSystem).Symbol("N").Value, }; sSuffix.Allomorphs.Add(new AffixProcessAllomorph { Lhs = { Pattern <Word, ShapeNode> .New("1").Annotation(any).OneOrMore.Value }, Rhs = { new CopyFromInput("1"), new InsertSegments(Table3, "s") } }); var nounTemplate = new AffixTemplate { Name = "noun", RequiredSyntacticFeatureStruct = FeatureStruct.New(Language.SyntacticFeatureSystem).Symbol("N").Value }; nounTemplate.Slots.Add(new AffixTemplateSlot(sSuffix) { Optional = true }); Morphophonemic.AffixTemplates.Add(nounTemplate); var morpher = new Morpher(TraceManager, Language); AssertMorphsEqual(morpher.ParseWord("sagd"), "32 PAST"); AssertMorphsEqual(morpher.ParseWord("sagdv")); AssertMorphsEqual(morpher.ParseWord("sagdvs")); AssertMorphsEqual(morpher.ParseWord("sagdmi")); AssertMorphsEqual(morpher.ParseWord("sagdmis")); verbTemplate.IsFinal = false; morpher = new Morpher(TraceManager, Language); AssertMorphsEqual(morpher.ParseWord("sagd")); AssertMorphsEqual(morpher.ParseWord("sagdv"), "32 PAST NOM"); AssertMorphsEqual(morpher.ParseWord("sagdvs"), "32 PAST NOM PL"); AssertMorphsEqual(morpher.ParseWord("sagdmi"), "32 PAST 53"); AssertMorphsEqual(morpher.ParseWord("sagdmis"), "32 PAST 53 PL"); }