/// <summary> /// Applies the rule to the specified word analysis. /// </summary> /// <param name="input">The input word synthesis.</param> /// <param name="output">The output word syntheses.</param> /// <returns> /// <c>true</c> if the rule was successfully applied, otherwise <c>false</c> /// </returns> public override bool Apply(WordSynthesis input, out ICollection<WordSynthesis> output) { output = null; // these should probably be moved to IsApplicable, but we will leave it here for // now so we don't have to call it again to set the features for the output word // synthesis record // check head features FeatureValues headHeadFeatures; if (!m_headRequiredHeadFeatures.UnifyDefaults(input.HeadFeatures, out headHeadFeatures)) return false; FeatureValues nonHeadHeadFeatures; if (!m_nonHeadRequiredHeadFeatures.UnifyDefaults(input.NonHead.HeadFeatures, out nonHeadHeadFeatures)) return false; // check foot features FeatureValues headFootFeatures; if (!m_headRequiredFootFeatures.UnifyDefaults(input.FootFeatures, out headFootFeatures)) return false; FeatureValues nonHeadFootFeatures; if (!m_nonHeadRequiredFootFeatures.UnifyDefaults(input.NonHead.FootFeatures, out nonHeadFootFeatures)) return false; MorphologicalRuleSynthesisTrace trace = null; if (TraceSynthesis) { // create morphological rule synthesis trace record trace = new MorphologicalRuleSynthesisTrace(this, input.Clone()); input.CurrentTrace.AddChild(trace); } output = new List<WordSynthesis>(); foreach (Subrule sr in m_subrules) { WordSynthesis ws; if (sr.Apply(input, out ws)) { if (m_outPOS != null) ws.POS = m_outPOS; if (m_outHeadFeatures != null) ws.HeadFeatures = m_outHeadFeatures.Clone(); ws.HeadFeatures.Add(headHeadFeatures); if (m_outFootFeatures != null) ws.FootFeatures = m_outFootFeatures.Clone(); ws.FootFeatures.Add(headFootFeatures); if (m_obligHeadFeatures != null) { foreach (Feature feature in m_obligHeadFeatures) ws.AddObligatoryHeadFeature(feature); } ws.MorphologicalRuleApplied(this); ws = CheckBlocking(ws); if (trace != null) { // set current trace record to the morphological rule trace record for each // output analysis ws.CurrentTrace = trace; // add output to morphological rule trace record trace.RuleAllomorph = sr; trace.Output = ws.Clone(); } output.Add(ws); // 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 if (sr.RequiredEnvironments == null && sr.ExcludedEnvironments == null) { break; } } } return output.Count > 0; }
/// <summary> /// Applies the rule to the specified word analysis. /// </summary> /// <param name="input">The input word synthesis.</param> /// <param name="output">The output word syntheses.</param> /// <returns> /// <c>true</c> if the rule was successfully applied, otherwise <c>false</c> /// </returns> public override bool Apply(WordSynthesis input, out ICollection <WordSynthesis> output) { output = null; // these should probably be moved to IsApplicable, but we will leave it here for // now so we don't have to call it again to set the features for the output word // synthesis record // check head features FeatureValues headHeadFeatures; if (!m_headRequiredHeadFeatures.UnifyDefaults(input.HeadFeatures, out headHeadFeatures)) { return(false); } FeatureValues nonHeadHeadFeatures; if (!m_nonHeadRequiredHeadFeatures.UnifyDefaults(input.NonHead.HeadFeatures, out nonHeadHeadFeatures)) { return(false); } // check foot features FeatureValues headFootFeatures; if (!m_headRequiredFootFeatures.UnifyDefaults(input.FootFeatures, out headFootFeatures)) { return(false); } FeatureValues nonHeadFootFeatures; if (!m_nonHeadRequiredFootFeatures.UnifyDefaults(input.NonHead.FootFeatures, out nonHeadFootFeatures)) { return(false); } MorphologicalRuleSynthesisTrace trace = null; if (TraceSynthesis) { // create morphological rule synthesis trace record trace = new MorphologicalRuleSynthesisTrace(this, input.Clone()); input.CurrentTrace.AddChild(trace); } output = new List <WordSynthesis>(); foreach (Subrule sr in m_subrules) { WordSynthesis ws; if (sr.Apply(input, out ws)) { if (m_outPOS != null) { ws.POS = m_outPOS; } if (m_outHeadFeatures != null) { ws.HeadFeatures = m_outHeadFeatures.Clone(); } ws.HeadFeatures.Add(headHeadFeatures); if (m_outFootFeatures != null) { ws.FootFeatures = m_outFootFeatures.Clone(); } ws.FootFeatures.Add(headFootFeatures); if (m_obligHeadFeatures != null) { foreach (Feature feature in m_obligHeadFeatures) { ws.AddObligatoryHeadFeature(feature); } } ws.MorphologicalRuleApplied(this); ws = CheckBlocking(ws); if (trace != null) { // set current trace record to the morphological rule trace record for each // output analysis ws.CurrentTrace = trace; // add output to morphological rule trace record trace.RuleAllomorph = sr; trace.Output = ws.Clone(); } output.Add(ws); // 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 if (sr.RequiredEnvironments == null && sr.ExcludedEnvironments == null) { break; } } } return(output.Count > 0); }
protected virtual void Write(Trace trace, bool printTraceInputs) { switch (trace.Type) { case Trace.TraceType.WORD_ANALYSIS: WordAnalysisTrace waTrace = trace as WordAnalysisTrace; m_xmlWriter.WriteStartElement(waTrace.GetType().Name); m_xmlWriter.WriteElementString("InputWord", waTrace.InputWord); break; case Trace.TraceType.STRATUM_ANALYSIS: StratumAnalysisTrace saTrace = trace as StratumAnalysisTrace; m_xmlWriter.WriteStartElement(saTrace.GetType().Name + (saTrace.IsInput ? "In" : "Out")); Write("Stratum", saTrace.Stratum); Write(saTrace.IsInput ? "Input" : "Output", saTrace.Analysis); break; case Trace.TraceType.STRATUM_SYNTHESIS: StratumSynthesisTrace ssTrace = trace as StratumSynthesisTrace; m_xmlWriter.WriteStartElement(ssTrace.GetType().Name + (ssTrace.IsInput ? "In" : "Out")); Write("Stratum", ssTrace.Stratum); Write(ssTrace.IsInput ? "Input" : "Output", ssTrace.Synthesis); break; case Trace.TraceType.LEX_LOOKUP: LexLookupTrace llTrace = trace as LexLookupTrace; m_xmlWriter.WriteStartElement(llTrace.GetType().Name); m_xmlWriter.WriteElementString("Stratum", llTrace.Stratum.Description); m_xmlWriter.WriteElementString("Shape", llTrace.Stratum.CharacterDefinitionTable.ToRegexString(llTrace.Shape, ModeType.ANALYSIS, true)); break; case Trace.TraceType.WORD_SYNTHESIS: WordSynthesisTrace wsTrace = trace as WordSynthesisTrace; m_xmlWriter.WriteStartElement(wsTrace.GetType().Name); Write("RootAllomorph", wsTrace.RootAllomorph); m_xmlWriter.WriteStartElement("MorphologicalRules"); foreach (MorphologicalRule rule in wsTrace.MorphologicalRules) { Write("MorphologicalRule", rule); } m_xmlWriter.WriteEndElement(); // MorphologicalRules m_xmlWriter.WriteElementString("RealizationalFeatures", wsTrace.RealizationalFeatures.ToString()); break; case Trace.TraceType.PHONOLOGICAL_RULE_ANALYSIS: PhonologicalRuleAnalysisTrace paTrace = trace as PhonologicalRuleAnalysisTrace; m_xmlWriter.WriteStartElement(paTrace.GetType().Name); Write("PhonologicalRule", paTrace.Rule); if (printTraceInputs) { Write("Input", paTrace.Input); } Write("Output", paTrace.Output); break; case Trace.TraceType.PHONOLOGICAL_RULE_SYNTHESIS: PhonologicalRuleSynthesisTrace psTrace = trace as PhonologicalRuleSynthesisTrace; m_xmlWriter.WriteStartElement(psTrace.GetType().Name); Write("PhonologicalRule", psTrace.Rule); if (printTraceInputs) { Write("Input", psTrace.Input); } Write("Output", psTrace.Output); break; case Trace.TraceType.PHONOLOGICAL_RULE_SYNTHESIS_REQUIREDPOS: PhonologicalRuleSynthesisRequiredPOSTrace psposTrace = trace as PhonologicalRuleSynthesisRequiredPOSTrace; m_xmlWriter.WriteStartElement(psposTrace.GetType().Name); Write("PhonologicalRuleStemPOS", psposTrace.PartOfSpeech); m_xmlWriter.WriteStartElement("PhonologicalRuleRequiredPOSes"); foreach (var partOfSpeech in psposTrace.RequiredPOSs) { Write("PhonologicalRuleRequiredPOS", partOfSpeech); } m_xmlWriter.WriteEndElement(); break; case Trace.TraceType.PHONOLOGICAL_RULE_SYNTHESIS_MPRFEATURES: PhonologicalRuleSynthesisMPRFeaturesTrace psmprTrace = trace as PhonologicalRuleSynthesisMPRFeaturesTrace; m_xmlWriter.WriteStartElement(psmprTrace.GetType().Name); string type = "required"; if (psmprTrace.MPRFeatureType == PhonologicalRuleSynthesisMPRFeaturesTrace.PhonologicalRuleSynthesisMPRFeaturesTraceType.EXCLUDED) { type = "excluded"; } m_xmlWriter.WriteAttributeString("type", type); m_xmlWriter.WriteStartElement("PhonologicalRuleMPRFeatures"); foreach (var mprFeature in psmprTrace.MPRFeatures) { Write("PhonologicalRuleMPRFeature", mprFeature); } m_xmlWriter.WriteEndElement(); m_xmlWriter.WriteStartElement("PhonologicalRuleConstrainingMPRFeatrues"); foreach (var mprFeature in psmprTrace.ConstrainingMPRFeatures) { Write("PhonologicalRuleMPRFeature", mprFeature); } m_xmlWriter.WriteEndElement(); break; case Trace.TraceType.TEMPLATE_ANALYSIS: TemplateAnalysisTrace taTrace = trace as TemplateAnalysisTrace; m_xmlWriter.WriteStartElement(taTrace.GetType().Name + (taTrace.IsInput ? "In" : "Out")); Write("AffixTemplate", taTrace.Template); Write(taTrace.IsInput ? "Input" : "Output", taTrace.Analysis); break; case Trace.TraceType.TEMPLATE_SYNTHESIS: TemplateSynthesisTrace tsTrace = trace as TemplateSynthesisTrace; m_xmlWriter.WriteStartElement(tsTrace.GetType().Name + (tsTrace.IsInput ? "In" : "Out")); Write("AffixTemplate", tsTrace.Template); Write(tsTrace.IsInput ? "Input" : "Output", tsTrace.Synthesis); break; case Trace.TraceType.MORPHOLOGICAL_RULE_ANALYSIS: MorphologicalRuleAnalysisTrace maTrace = trace as MorphologicalRuleAnalysisTrace; m_xmlWriter.WriteStartElement(maTrace.GetType().Name); Write("MorphologicalRule", maTrace.Rule); if (maTrace.RuleAllomorph != null) { Write("RuleAllomorph", maTrace.RuleAllomorph); } if (printTraceInputs) { Write("Input", maTrace.Input); } Write("Output", maTrace.Output); break; case Trace.TraceType.MORPHOLOGICAL_RULE_SYNTHESIS: MorphologicalRuleSynthesisTrace msTrace = trace as MorphologicalRuleSynthesisTrace; m_xmlWriter.WriteStartElement(msTrace.GetType().Name); Write("MorphologicalRule", msTrace.Rule); if (msTrace.RuleAllomorph != null) { Write("RuleAllomorph", msTrace.RuleAllomorph); } if (printTraceInputs) { Write("Input", msTrace.Input); } Write("Output", msTrace.Output); break; case Trace.TraceType.BLOCKING: BlockingTrace bTrace = trace as BlockingTrace; m_xmlWriter.WriteStartElement(bTrace.GetType().Name); Write("BlockingEntry", bTrace.BlockingEntry); break; case Trace.TraceType.REPORT_SUCCESS: ReportSuccessTrace rsTrace = trace as ReportSuccessTrace; m_xmlWriter.WriteStartElement(rsTrace.GetType().Name); Write("Result", rsTrace.Output); break; } foreach (Trace child in trace.Children) { Write(child, printTraceInputs); } m_xmlWriter.WriteEndElement(); }
public override void MorphologicalRuleApplied(MorphologicalRule rule, WordSynthesis input, WordSynthesis output, Allomorph allomorph) { if (IsSynthesisTracingEnabled(rule.ID)) { var trace = new MorphologicalRuleSynthesisTrace(rule, input.Clone()) {RuleAllomorph = allomorph, Output = output.Clone()}; ((Trace) output.CurrentTraceObject).AddChild(trace); // set current trace record to the morphological rule trace record for each // output analysis output.CurrentTraceObject = trace; } }
/// <summary> /// Applies the rule to the specified word synthesis. /// </summary> /// <param name="input">The input word synthesis.</param> /// <param name="output">The output word syntheses.</param> /// <returns> /// <c>true</c> if the rule was successfully applied, otherwise <c>false</c> /// </returns> public override bool Apply(WordSynthesis input, out ICollection <WordSynthesis> output) { output = null; // these should probably be moved to IsApplicable, but we will leave it here for // now so we don't have to call it again to set the features for the output word // synthesis record // check head features FeatureValues headFeatures; if (!m_requiredHeadFeatures.UnifyDefaults(input.HeadFeatures, out headFeatures)) { return(false); } // check foot features FeatureValues footFeatures; if (!m_requiredFootFeatures.UnifyDefaults(input.FootFeatures, out footFeatures)) { return(false); } output = new List <WordSynthesis>(); for (int i = 0; i < m_subrules.Count; i++) { WordSynthesis ws; if (m_subrules[i].Apply(input, out ws)) { if (m_outPOS != null) { ws.POS = m_outPOS; } if (m_outHeadFeatures != null) { ws.HeadFeatures = m_outHeadFeatures.Clone(); } ws.HeadFeatures.Add(headFeatures); if (m_outFootFeatures != null) { ws.FootFeatures = m_outFootFeatures.Clone(); } ws.FootFeatures.Add(footFeatures); if (m_obligHeadFeatures != null) { foreach (Feature feature in m_obligHeadFeatures) { ws.AddObligatoryHeadFeature(feature); } } ws.MorphologicalRuleApplied(this); ws = CheckBlocking(ws); if (TraceSynthesis) { MorphologicalRuleSynthesisTrace trace = new MorphologicalRuleSynthesisTrace(this, input.Clone()); // add output to morphological rule trace record trace.RuleAllomorph = m_subrules[i]; trace.Output = ws.Clone(); ws.CurrentTrace.AddChild(trace); // set current trace record to the morphological rule trace record for each // output analysis ws.CurrentTrace = trace; } output.Add(ws); // 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 != m_subrules.Count - 1 && !m_subrules[i].ConstraintsEqual(m_subrules[i + 1])) && m_subrules[i].RequiredEnvironments == null && m_subrules[i].ExcludedEnvironments == null) { break; } } } if (TraceSynthesis && output.Count == 0) { input.CurrentTrace.AddChild(new MorphologicalRuleSynthesisTrace(this, input.Clone())); } return(output.Count > 0); }