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()));
            }
        }
Beispiel #2
0
        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();
 }
Beispiel #4
0
        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);
        }