public void MorphosyntacticRules() { var any = FeatureStruct.New().Symbol(HCFeatureSystem.Segment).Value; var rule1 = new CompoundingRule { Name = "rule1", NonHeadRequiredSyntacticFeatureStruct = FeatureStruct.New(Language.SyntacticFeatureSystem).Symbol("V").Value }; 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 9"); AssertRootAllomorphsEquals(output, "5"); AssertSyntacticFeatureStructsEqual(output, FeatureStruct.New(Language.SyntacticFeatureSystem).Symbol("N").Value); Assert.That(morpher.ParseWord("pʰutbupu"), Is.Empty); rule1.OutSyntacticFeatureStruct = FeatureStruct.New(Language.SyntacticFeatureSystem).Symbol("V").Value; morpher = new Morpher(SpanFactory, TraceManager, Language); output = morpher.ParseWord("pʰutdat").ToList(); AssertMorphsEqual(output, "5 9"); AssertRootAllomorphsEquals(output, "5"); AssertSyntacticFeatureStructsEqual(output, FeatureStruct.New(Language.SyntacticFeatureSystem).Symbol("V").Value); Allophonic.MorphologicalRules.Clear(); Morphophonemic.MorphologicalRules.Add(rule1); rule1.HeadRequiredSyntacticFeatureStruct = FeatureStruct.New(Language.SyntacticFeatureSystem) .Symbol("V") .Feature(Head).EqualTo(head => head .Feature("pers").EqualTo("2")).Value; rule1.NonHeadRequiredSyntacticFeatureStruct = FeatureStruct.New().Value; morpher = new Morpher(SpanFactory, TraceManager, Language); output = morpher.ParseWord("ssagabba").ToList(); AssertMorphsEqual(output, "Perc0 39", "Perc0 40", "Perc3 39", "Perc3 40"); AssertRootAllomorphsEquals(output, "Perc0", "Perc3"); }
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 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"); }
private bool TryLoadCompoundingRule(XElement compRuleElem, CharacterDefinitionTable defaultTable, out IMorphologicalRule mrule) { var compRuleID = (string) compRuleElem.Attribute("id"); var compRule = new CompoundingRule { Name = (string) compRuleElem.Element("Name"), Blockable = (bool?) compRuleElem.Attribute("blockable") ?? true }; var multApp = (string) compRuleElem.Attribute("multipleApplication"); if (!string.IsNullOrEmpty(multApp)) compRule.MaxApplicationCount = int.Parse(multApp); var fs = new FeatureStruct(); var headRequiredPos = (string) compRuleElem.Attribute("headPartsOfSpeech"); if (!string.IsNullOrEmpty(headRequiredPos)) fs.AddValue(_posFeature, ParsePartsOfSpeech(headRequiredPos)); XElement headRequiredHeadFeatElem = compRuleElem.Element("HeadRequiredHeadFeatures"); if (headRequiredHeadFeatElem != null) fs.AddValue(_headFeature, LoadFeatureStruct(headRequiredHeadFeatElem, _language.SyntacticFeatureSystem)); XElement headRequiredFootFeatElem = compRuleElem.Element("HeadRequiredFootFeatures"); if (headRequiredFootFeatElem != null) fs.AddValue(_footFeature, LoadFeatureStruct(headRequiredFootFeatElem, _language.SyntacticFeatureSystem)); fs.Freeze(); compRule.HeadRequiredSyntacticFeatureStruct = fs; fs = new FeatureStruct(); var nonHeadRequiredPos = (string) compRuleElem.Attribute("nonHeadPartsOfSpeech"); if (!string.IsNullOrEmpty(nonHeadRequiredPos)) fs.AddValue(_posFeature, ParsePartsOfSpeech(nonHeadRequiredPos)); XElement nonHeadRequiredHeadFeatElem = compRuleElem.Element("NonHeadRequiredHeadFeatures"); if (nonHeadRequiredHeadFeatElem != null) fs.AddValue(_headFeature, LoadFeatureStruct(nonHeadRequiredHeadFeatElem, _language.SyntacticFeatureSystem)); XElement nonHeadRequiredFootFeatElem = compRuleElem.Element("NonHeadRequiredFootFeatures"); if (nonHeadRequiredFootFeatElem != null) fs.AddValue(_footFeature, LoadFeatureStruct(nonHeadRequiredFootFeatElem, _language.SyntacticFeatureSystem)); fs.Freeze(); compRule.NonHeadRequiredSyntacticFeatureStruct = fs; fs = new FeatureStruct(); var outPos = (string) compRuleElem.Attribute("outputPartOfSpeech"); if (!string.IsNullOrEmpty(outPos)) fs.AddValue(_posFeature, ParsePartsOfSpeech(outPos)); XElement outHeadFeatElem = compRuleElem.Element("OutputHeadFeatures"); if (outHeadFeatElem != null) fs.AddValue(_headFeature, LoadFeatureStruct(outHeadFeatElem, _language.SyntacticFeatureSystem)); XElement outFootFeatElem = compRuleElem.Element("OutputFootFeatures"); if (outFootFeatElem != null) fs.AddValue(_footFeature, LoadFeatureStruct(outFootFeatElem, _language.SyntacticFeatureSystem)); fs.Freeze(); compRule.OutSyntacticFeatureStruct = fs; var obligHeadIDsStr = (string) compRuleElem.Attribute("outputObligatoryFeatures"); if (!string.IsNullOrEmpty(obligHeadIDsStr)) { foreach (string obligHeadID in obligHeadIDsStr.Split(' ')) compRule.ObligatorySyntacticFeatures.Add(_language.SyntacticFeatureSystem.GetFeature(obligHeadID)); } foreach (XElement subruleElem in compRuleElem.Elements("CompoundingSubrules").Elements("CompoundingSubrule").Where(IsActive)) { try { compRule.Subrules.Add(LoadCompoundingSubrule(subruleElem, defaultTable)); } catch (Exception e) { if (_errorHandler != null) _errorHandler(e, compRuleID); else throw; } } if (compRule.Subrules.Count > 0) { mrule = compRule; return true; } mrule = null; return false; }