public SynthesisAffixProcessAllomorphRuleSpec(AffixProcessAllomorph allomorph) { _allomorph = allomorph; IList <Pattern <Word, ShapeNode> > lhs = _allomorph.Lhs; IList <MorphologicalOutputAction> rhs = _allomorph.Rhs; _nonAllomorphActions = new HashSet <MorphologicalOutputAction>(); var redupParts = new List <List <MorphologicalOutputAction> >(); foreach (List <MorphologicalOutputAction> partActions in rhs.Where(action => !string.IsNullOrEmpty(action.PartName)) .GroupBy(action => action.PartName).Select(g => g.ToList())) { if (partActions.Count == 1) { if (partActions[0] is CopyFromInput) { _nonAllomorphActions.Add(partActions[0]); } } else { redupParts.Add(partActions); } } if (redupParts.Count > 0) { int start = -1; switch (_allomorph.ReduplicationHint) { case ReduplicationHint.Prefix: int prefixPartIndex = lhs.Count - 1; for (int i = rhs.Count - 1; i >= 0; i--) { MorphologicalOutputAction action = rhs[i]; if (action.PartName == lhs[prefixPartIndex].Name || action.PartName == lhs[lhs.Count - 1].Name) { if (action.PartName == lhs[0].Name) { start = i; break; } if (action.PartName != lhs[prefixPartIndex].Name) { prefixPartIndex = lhs.Count - 1; } prefixPartIndex--; } else { prefixPartIndex = lhs.Count - 1; } } break; case ReduplicationHint.Suffix: case ReduplicationHint.Implicit: int suffixPartIndex = 0; for (int i = 0; i < rhs.Count; i++) { MorphologicalOutputAction action = rhs[i]; if (action.PartName == lhs[suffixPartIndex].Name || action.PartName == lhs[0].Name) { if (action.PartName == lhs[lhs.Count - 1].Name) { start = i - (lhs.Count - 1); break; } if (action.PartName != lhs[suffixPartIndex].Name) { suffixPartIndex = 0; } suffixPartIndex++; } else { suffixPartIndex = 0; } } break; } foreach (List <MorphologicalOutputAction> partActions in redupParts) { for (int j = 0; j < partActions.Count; j++) { int index = rhs.IndexOf(partActions[j]); if ((start == -1 && j == (_allomorph.ReduplicationHint == ReduplicationHint.Prefix ? partActions.Count - 1 : 0)) || (start != -1 && index >= start && index < start + lhs.Count)) { _nonAllomorphActions.Add(partActions[j]); } } } } _pattern = new Pattern <Word, ShapeNode>(); foreach (Pattern <Word, ShapeNode> part in lhs) { _pattern.Children.Add(new Group <Word, ShapeNode>(part.Name, part.Children.CloneItems())); } }
public IEnumerable <Word> Apply(Word input) { if (!input.IsMorphologicalRuleApplicable(_rule)) { return(Enumerable.Empty <Word>()); } if (input.GetApplicationCount(_rule) >= _rule.MaxApplicationCount) { if (_morpher.TraceManager.IsTracing) { _morpher.TraceManager.MorphologicalRuleNotApplied(_rule, -1, input, FailureReason.MaxApplicationCount, _rule.MaxApplicationCount); } return(Enumerable.Empty <Word>()); } // if a final template was last applied, // do not allow a non-partial rule to apply unless the input is partial if (!_rule.IsTemplateRule && (input.IsLastAppliedRuleFinal ?? false) && !input.IsPartial && !_rule.IsPartial) { if (_morpher.TraceManager.IsTracing) { _morpher.TraceManager.MorphologicalRuleNotApplied(_rule, -1, input, FailureReason.NonPartialRuleProhibitedAfterFinalTemplate, null); } return(Enumerable.Empty <Word>()); } // if a non-final template was last applied, // only allow a non-partial rule to apply unless the input is partial if (!_rule.IsTemplateRule && input.IsLastAppliedRuleFinal.HasValue && !input.IsLastAppliedRuleFinal.Value && !input.IsPartial && _rule.IsPartial) { if (_morpher.TraceManager.IsTracing) { _morpher.TraceManager.MorphologicalRuleNotApplied(_rule, -1, input, FailureReason.NonPartialRuleRequiredAfterNonFinalTemplate, null); } return(Enumerable.Empty <Word>()); } if (_rule.RequiredStemName != null && _rule.RequiredStemName != input.RootAllomorph.StemName) { if (_morpher.TraceManager.IsTracing) { _morpher.TraceManager.MorphologicalRuleNotApplied(_rule, -1, input, FailureReason.RequiredStemName, _rule.RequiredStemName); } return(Enumerable.Empty <Word>()); } FeatureStruct syntacticFS; if (!_rule.RequiredSyntacticFeatureStruct.Unify(input.SyntacticFeatureStruct, true, out syntacticFS)) { if (_morpher.TraceManager.IsTracing) { _morpher.TraceManager.MorphologicalRuleNotApplied(_rule, -1, input, FailureReason.RequiredSyntacticFeatureStruct, _rule.RequiredSyntacticFeatureStruct); } return(Enumerable.Empty <Word>()); } var output = new List <Word>(); for (int i = 0; i < _rules.Count; i++) { AffixProcessAllomorph allo = _rule.Allomorphs[i]; MprFeatureGroup group; if (allo.RequiredMprFeatures.Count > 0 && !allo.RequiredMprFeatures.IsMatchRequired(input.MprFeatures, out group)) { if (_morpher.TraceManager.IsTracing) { _morpher.TraceManager.MorphologicalRuleNotApplied(_rule, i, input, FailureReason.RequiredMprFeatures, group); } continue; } if (allo.ExcludedMprFeatures.Count > 0 && !allo.ExcludedMprFeatures.IsMatchExcluded(input.MprFeatures, out group)) { if (_morpher.TraceManager.IsTracing) { _morpher.TraceManager.MorphologicalRuleNotApplied(_rule, i, input, FailureReason.ExcludedMprFeatures, group); } continue; } Word outWord = _rules[i].Apply(input).SingleOrDefault(); if (outWord != null) { outWord.SyntacticFeatureStruct = syntacticFS; outWord.SyntacticFeatureStruct.PriorityUnion(_rule.OutSyntacticFeatureStruct); foreach (Feature obligFeature in _rule.ObligatorySyntacticFeatures) { outWord.ObligatorySyntacticFeatures.Add(obligFeature); } if (!_rule.IsTemplateRule) { if (_rule.IsPartial) { outWord.IsPartial = true; } else { outWord.IsLastAppliedRuleFinal = null; } } outWord.MorphologicalRuleApplied(_rule); Word newWord; if (_rule.Blockable && outWord.CheckBlocking(out newWord)) { if (_morpher.TraceManager.IsTracing) { _morpher.TraceManager.Blocked(_rule, newWord); } outWord = newWord; } else { outWord.Freeze(); } if (_morpher.TraceManager.IsTracing) { _morpher.TraceManager.MorphologicalRuleApplied(_rule, i, input, outWord); } output.Add(outWord); // return all word syntheses that match subrules that are constrained by environments, // HC violates the disjunctive property of allomorphs here because it cannot check the // environmental constraints until it has a surface form, we will enforce the disjunctive // property of allomorphs at that time // HC also checks for free fluctuation, if the next subrule has the same constraints, we // do not treat them as disjunctive if ((i != _rule.Allomorphs.Count - 1 && !allo.FreeFluctuatesWith(_rule.Allomorphs[i + 1])) && allo.Environments.Count == 0 && allo.RequiredSyntacticFeatureStruct.IsEmpty) { break; } } else if (_morpher.TraceManager.IsTracing) { _morpher.TraceManager.MorphologicalRuleNotApplied(_rule, i, input, FailureReason.Pattern, null); } } return(output); }
public AnalysisAffixProcessAllomorphRuleSpec(AffixProcessAllomorph allomorph) : base(allomorph.Lhs, allomorph.Rhs) { _allomorph = allomorph; Pattern.Freeze(); }
public IEnumerable <Word> Apply(Word input) { if (!_morpher.RuleSelector(_rule)) { return(Enumerable.Empty <Word>()); } if (!_rule.RealizationalFeatureStruct.Subsumes(input.RealizationalFeatureStruct)) { return(Enumerable.Empty <Word>()); } if (!_rule.RealizationalFeatureStruct.IsEmpty && IsBlocked(_rule.RealizationalFeatureStruct, input.SyntacticFeatureStruct, new HashSet <Tuple <FeatureStruct, FeatureStruct> >())) { return(Enumerable.Empty <Word>()); } FeatureStruct syntacticFS; if (!_rule.RequiredSyntacticFeatureStruct.Unify(input.SyntacticFeatureStruct, true, out syntacticFS)) { if (_morpher.TraceManager.IsTracing) { _morpher.TraceManager.MorphologicalRuleNotApplied(_rule, -1, input, FailureReason.RequiredSyntacticFeatureStruct, _rule.RequiredSyntacticFeatureStruct); } return(Enumerable.Empty <Word>()); } var output = new List <Word>(); for (int i = 0; i < _rules.Count; i++) { AffixProcessAllomorph allo = _rule.Allomorphs[i]; MprFeatureGroup group; if (allo.RequiredMprFeatures.Count > 0 && !allo.RequiredMprFeatures.IsMatchRequired(input.MprFeatures, out group)) { if (_morpher.TraceManager.IsTracing) { _morpher.TraceManager.MorphologicalRuleNotApplied(_rule, i, input, FailureReason.RequiredMprFeatures, group); } continue; } if (allo.ExcludedMprFeatures.Count > 0 && !allo.ExcludedMprFeatures.IsMatchExcluded(input.MprFeatures, out group)) { if (_morpher.TraceManager.IsTracing) { _morpher.TraceManager.MorphologicalRuleNotApplied(_rule, i, input, FailureReason.ExcludedMprFeatures, group); } continue; } Word outWord = _rules[i].Apply(input).SingleOrDefault(); if (outWord != null) { outWord.SyntacticFeatureStruct = syntacticFS; outWord.SyntacticFeatureStruct.PriorityUnion(_rule.RealizationalFeatureStruct); outWord.MorphologicalRuleApplied(_rule); Word newWord; if (_rule.Blockable && outWord.CheckBlocking(out newWord)) { if (_morpher.TraceManager.IsTracing) { _morpher.TraceManager.Blocked(_rule, newWord); } outWord = newWord; } else { outWord.Freeze(); } if (_morpher.TraceManager.IsTracing) { _morpher.TraceManager.MorphologicalRuleApplied(_rule, i, input, outWord); } output.Add(outWord); // return all word syntheses that match subrules that are constrained by environments, // HC violates the disjunctive property of allomorphs here because it cannot check the // environmental constraints until it has a surface form, we will enforce the disjunctive // property of allomorphs at that time // HC also checks for free fluctuation, if the next subrule has the same constraints, we // do not treat them as disjunctive if ((i != _rule.Allomorphs.Count - 1 && !allo.FreeFluctuatesWith(_rule.Allomorphs[i + 1])) && allo.Environments.Count == 0 && allo.RequiredSyntacticFeatureStruct.IsEmpty) { break; } } else if (_morpher.TraceManager.IsTracing) { _morpher.TraceManager.MorphologicalRuleNotApplied(_rule, i, input, FailureReason.Pattern, null); } } return(output); }