コード例 #1
0
        private static XElement CreateMorphologicalRuleElement(IMorphologicalRule rule)
        {
            XElement elem = CreateHCRuleElement("MorphologicalRule", rule);

            elem.Add(new XAttribute("type", rule is AffixProcessRule ? "affix" : "compound"));
            return(elem);
        }
コード例 #2
0
ファイル: TraceManager.cs プロジェクト: papeh/hermitcrab
 public void MorphologicalRuleNotApplied(IMorphologicalRule rule, int subruleIndex, Word input, FailureReason reason, object failureObj)
 {
     ((Trace)input.CurrentTrace).Children.Add(new Trace(TraceType.MorphologicalRuleSynthesis, rule)
     {
         SubruleIndex = subruleIndex, Input = input, FailureReason = reason
     });
 }
コード例 #3
0
ファイル: Word.cs プロジェクト: papeh/hermitcrab
        internal void CurrentMorphologicalRuleApplied()
        {
            CheckFrozen();
            IMorphologicalRule mrule = _mrules.Pop();

            MorphologicalRuleApplied(mrule);
        }
コード例 #4
0
ファイル: TraceManager.cs プロジェクト: papeh/hermitcrab
 public void MorphologicalRuleNotUnapplied(IMorphologicalRule rule, int subruleIndex, Word input)
 {
     ((Trace)input.CurrentTrace).Children.Add(new Trace(TraceType.MorphologicalRuleAnalysis, rule)
     {
         SubruleIndex = subruleIndex, Input = input
     });
 }
コード例 #5
0
ファイル: Word.cs プロジェクト: papeh/hermitcrab
 /// <summary>
 /// Notifies this analysis that the specified morphological rule was unapplied.
 /// </summary>
 /// <param name="mrule">The morphological rule.</param>
 /// <param name="realizational"> </param>
 internal void MorphologicalRuleUnapplied(IMorphologicalRule mrule, bool realizational)
 {
     CheckFrozen();
     _mrulesUnapplied.UpdateValue(mrule, () => 0, count => count + 1);
     if (!realizational)
     {
         _mrules.Push(mrule);
     }
 }
コード例 #6
0
ファイル: TraceManager.cs プロジェクト: papeh/hermitcrab
        public void MorphologicalRuleUnapplied(IMorphologicalRule rule, int subruleIndex, Word input, Word output)
        {
            var trace = new Trace(TraceType.MorphologicalRuleAnalysis, rule)
            {
                SubruleIndex = subruleIndex, Input = input, Output = output
            };

            ((Trace)output.CurrentTrace).Children.Add(trace);
            output.CurrentTrace = trace;
        }
コード例 #7
0
ファイル: Word.cs プロジェクト: papeh/hermitcrab
        /// <summary>
        /// Gets the number of times the specified morphological rule has been applied.
        /// </summary>
        /// <param name="mrule">The morphological rule.</param>
        /// <returns>The number of applications.</returns>
        internal int GetApplicationCount(IMorphologicalRule mrule)
        {
            int numApplies;

            if (!_mrulesApplied.TryGetValue(mrule, out numApplies))
            {
                numApplies = 0;
            }
            return(numApplies);
        }
コード例 #8
0
		public void MorphologicalRuleUnapplied(IMorphologicalRule rule, int subruleIndex, Word input, Word output)
		{
			var trace = new XElement("MorphologicalRuleAnalysisTrace",
				CreateMorphologicalRuleElement(rule));
			var aprule = rule as AffixProcessRule;
			if (aprule != null)
				trace.Add(CreateAllomorphElement(aprule.Allomorphs[subruleIndex]));
			trace.Add(CreateWordElement("Output", output, true));
			((XElement) output.CurrentTrace).Add(trace);
			output.CurrentTrace = trace;
		}
コード例 #9
0
        internal bool IsMorphologicalRuleApplicable(IMorphologicalRule rule)
        {
            if (_mruleAppIndex < 0)
            {
                return(false);
            }

            IMorphologicalRule curRule = _mruleApps[_mruleAppIndex];

            return(curRule == rule || (curRule == null && rule is CompoundingRule));
        }
コード例 #10
0
 /// <summary>
 /// Notifies this word that the specified morphological rule was unapplied. Null
 /// indicates that an unknown compounding rule was unapplied. This is used when
 /// generating a compound word, because the compounding rule is usually not known just
 /// the non-head allomorph.
 /// </summary>
 internal void MorphologicalRuleUnapplied(IMorphologicalRule mrule)
 {
     CheckFrozen();
     if (mrule != null)
     {
         _mrulesUnapplied.UpdateValue(mrule, () => 0, count => count + 1);
     }
     if (!(mrule is RealizationalAffixProcessRule))
     {
         _mruleApps.Add(mrule);
         _mruleAppIndex++;
     }
 }
コード例 #11
0
        public void MorphologicalRuleUnapplied(IMorphologicalRule rule, int subruleIndex, Word input, Word output)
        {
            var trace = new XElement("MorphologicalRuleAnalysisTrace",
                                     CreateMorphologicalRuleElement(rule));
            var aprule = rule as AffixProcessRule;

            if (aprule != null)
            {
                trace.Add(CreateAllomorphElement(aprule.Allomorphs[subruleIndex]));
            }
            trace.Add(CreateWordElement("Output", output, true));
            ((XElement)output.CurrentTrace).Add(trace);
            output.CurrentTrace = trace;
        }
コード例 #12
0
 /// <summary>
 /// Notifies this word synthesis that the specified morphological rule has applied.
 /// </summary>
 internal void MorphologicalRuleApplied(IMorphologicalRule mrule)
 {
     CheckFrozen();
     if (IsMorphologicalRuleApplicable(mrule))
     {
         _mruleAppIndex--;
     }
     // indicate that the current non-head was applied if this is a compounding rule
     if (mrule is CompoundingRule)
     {
         _nonHeadAppIndex--;
     }
     _mrulesApplied.UpdateValue(mrule, () => 0, count => count + 1);
 }
コード例 #13
0
        internal bool HasRemainingRulesFromStratum(Stratum stratum)
        {
            if (_mruleAppIndex < 0)
            {
                return(false);
            }

            IMorphologicalRule curRule = _mruleApps[_mruleAppIndex];

            if (curRule == null)
            {
                return(CurrentNonHead != null && CurrentNonHead.Stratum == stratum);
            }
            return(curRule.Stratum == stratum);
        }
コード例 #14
0
		private static XElement CreateMorphologicalRuleElement(IMorphologicalRule rule)
		{
			XElement elem = CreateHCRuleElement("MorphologicalRule", rule);
			elem.Add(new XAttribute("type", rule is AffixProcessRule ? "affix" : "compound"));
			return elem;
		}
コード例 #15
0
ファイル: TraceManager.cs プロジェクト: sillsdev/hermitcrab
 public void MorphologicalRuleNotUnapplied(IMorphologicalRule rule, int subruleIndex, Word input)
 {
     ((Trace) input.CurrentTrace).Children.Add(new Trace(TraceType.MorphologicalRuleAnalysis, rule) {SubruleIndex = subruleIndex, Input = input});
 }
コード例 #16
0
		public void MorphologicalRuleNotApplied(IMorphologicalRule rule, int subruleIndex, Word input, FailureReason reason, object failureObj)
		{
			var trace = new XElement("MorphologicalRuleSynthesisTrace",
				CreateMorphologicalRuleElement(rule));
			var aprule = rule as AffixProcessRule;
			if (aprule != null)
				trace.Add(CreateAllomorphElement(subruleIndex == -1 ? aprule.Allomorphs.Last() : aprule.Allomorphs[subruleIndex]));
			trace.Add(new XElement("Output", "*None*"));
			switch (reason)
			{
				case FailureReason.RequiredSyntacticFeatureStruct:
					Debug.Assert(aprule != null);
					var requiredFS = (FeatureStruct) failureObj;
					var requiredPos = requiredFS.GetValue<SymbolicFeatureValue>("pos");
					var inputPos = input.SyntacticFeatureStruct.GetValue<SymbolicFeatureValue>("pos");
					if (requiredPos.Values.Intersect(inputPos.Values).Any())
					{
						trace.Add(new XElement("FailureReason", new XAttribute("type", "inflFeats"),
							CreateInflFeaturesElement("InflFeatures", input.SyntacticFeatureStruct),
							CreateInflFeaturesElement("RequiredInflFeatures", requiredFS)));
					}
					else
					{
						trace.Add(new XElement("FailureReason", new XAttribute("type", "pos"),
							new XElement("Pos", string.Join(", ", inputPos.Values.Select(s => s.Description))),
							new XElement("RequiredPos", string.Join(", ", requiredPos.Values.Select(s => s.Description)))));
					}
					break;

				case FailureReason.StemName:
					trace.Add(new XElement("FailureReason", new XAttribute("type", "fromStemName"),
						new XElement("StemName", failureObj)));
					break;

				case FailureReason.RequiredMprFeatures:
					Debug.Assert(aprule != null);
					var group = (MprFeatureGroup) failureObj;
					trace.Add(group.Name == "lexEntryInflTypes" ? new XElement("FailureReason", new XAttribute("type", "requiredInflType"))
						: CreateMprFeaturesFailureElement(true, group, aprule.Allomorphs[subruleIndex].RequiredMprFeatures, input));
					break;

				case FailureReason.ExcludedMprFeatures:
					trace.Add(new XElement("FailureReason", new XAttribute("type", "excludedInflType")));
					break;

				case FailureReason.Pattern:
					Debug.Assert(aprule != null);
					var env = (string) aprule.Allomorphs[subruleIndex].Properties["Env"];
					var prefixEnv = (string) aprule.Allomorphs[subruleIndex].Properties["PrefixEnv"];
					var suffixEnv = (string) aprule.Allomorphs[subruleIndex].Properties["SuffixEnv"];
					if (env != null || prefixEnv != null || suffixEnv != null)
					{
						var reasonElem = new XElement("FailureReason", new XAttribute("type", "environment"));
						if (env != null)
							reasonElem.Add(new XElement("Environment", env));
						if (prefixEnv != null)
							reasonElem.Add(new XElement("Environment", env));
						if (suffixEnv != null)
							reasonElem.Add(new XElement("Environment", env));
						trace.Add(reasonElem);
					}
					else
					{
						trace.Add(new XElement("FailureReason", new XAttribute("type", "affixProcess")));
					}
					break;

				default:
					return;
			}
			((XElement) input.CurrentTrace).Add(trace);
		}
コード例 #17
0
ファイル: Word.cs プロジェクト: papeh/hermitcrab
 /// <summary>
 /// Notifies this word synthesis that the specified morphological rule has applied.
 /// </summary>
 internal void MorphologicalRuleApplied(IMorphologicalRule mrule)
 {
     CheckFrozen();
     _mrulesApplied.UpdateValue(mrule, () => 0, count => count + 1);
 }
コード例 #18
0
        private bool TryLoadAffixProcessRule(XElement mruleElem, CharacterDefinitionTable defaultTable, out IMorphologicalRule mrule)
        {
            var id = (string) mruleElem.Attribute("id");
            var affixProcessRule = new AffixProcessRule
            {
                Name = (string) mruleElem.Element("Name"),
                Gloss = (string) mruleElem.Element("Gloss"),
                Blockable = (bool?) mruleElem.Attribute("blockable") ?? true,
                IsPartial = (bool?) mruleElem.Attribute("partial") ?? false
            };
            var multApp = (string) mruleElem.Attribute("multipleApplication");
            if (!string.IsNullOrEmpty(multApp))
                affixProcessRule.MaxApplicationCount = int.Parse(multApp);

            var fs = new FeatureStruct();
            var requiredPos = (string) mruleElem.Attribute("requiredPartsOfSpeech");
            if (!string.IsNullOrEmpty(requiredPos))
                fs.AddValue(_posFeature, ParsePartsOfSpeech(requiredPos));
            XElement requiredHeadFeatElem = mruleElem.Element("RequiredHeadFeatures");
            if (requiredHeadFeatElem != null)
                fs.AddValue(_headFeature, LoadFeatureStruct(requiredHeadFeatElem, _language.SyntacticFeatureSystem));
            XElement requiredFootFeatElem = mruleElem.Element("RequiredFootFeatures");
            if (requiredFootFeatElem != null)
                fs.AddValue(_footFeature, LoadFeatureStruct(requiredFootFeatElem, _language.SyntacticFeatureSystem));
            fs.Freeze();
            affixProcessRule.RequiredSyntacticFeatureStruct = fs;

            fs = new FeatureStruct();
            var outPos = (string) mruleElem.Attribute("outputPartOfSpeech");
            if (!string.IsNullOrEmpty(outPos))
                fs.AddValue(_posFeature, ParsePartsOfSpeech(outPos));
            XElement outHeadFeatElem = mruleElem.Element("OutputHeadFeatures");
            if (outHeadFeatElem != null)
                fs.AddValue(_headFeature, LoadFeatureStruct(outHeadFeatElem, _language.SyntacticFeatureSystem));
            XElement outFootFeatElem = mruleElem.Element("OutputFootFeatures");
            if (outFootFeatElem != null)
                fs.AddValue(_footFeature, LoadFeatureStruct(outFootFeatElem, _language.SyntacticFeatureSystem));
            fs.Freeze();
            affixProcessRule.OutSyntacticFeatureStruct = fs;

            var obligHeadIDsStr = (string) mruleElem.Attribute("outputObligatoryFeatures");
            if (!string.IsNullOrEmpty(obligHeadIDsStr))
            {
                foreach (string obligHeadID in obligHeadIDsStr.Split(' '))
                    affixProcessRule.ObligatorySyntacticFeatures.Add(_language.SyntacticFeatureSystem.GetFeature(obligHeadID));
            }

            var stemNameIDStr = (string) mruleElem.Attribute("requiredStemName");
            if (!string.IsNullOrEmpty(stemNameIDStr))
                affixProcessRule.RequiredStemName = _stemNames[stemNameIDStr];

            LoadProperties(mruleElem.Element("Properties"), affixProcessRule.Properties);

            foreach (XElement subruleElem in mruleElem.Elements("MorphologicalSubrules").Elements("MorphologicalSubrule").Where(IsActive))
            {
                try
                {
                    AffixProcessAllomorph allomorph = LoadAffixProcessAllomorph(subruleElem, defaultTable);
                    affixProcessRule.Allomorphs.Add(allomorph);
                    _allomorphs[(string) subruleElem.Attribute("id")] = allomorph;
                }
                catch (Exception e)
                {
                    if (_errorHandler != null)
                        _errorHandler(e, id);
                    else
                        throw;
                }
            }

            if (affixProcessRule.Allomorphs.Count > 0)
            {
                _morphemes[id] = affixProcessRule;
                mrule = affixProcessRule;
                return true;
            }

            mrule = null;
            return false;
        }
コード例 #19
0
ファイル: TraceManager.cs プロジェクト: sillsdev/hermitcrab
 public void MorphologicalRuleUnapplied(IMorphologicalRule rule, int subruleIndex, Word input, Word output)
 {
     var trace = new Trace(TraceType.MorphologicalRuleAnalysis, rule) {SubruleIndex = subruleIndex, Input = input, Output = output};
     ((Trace) output.CurrentTrace).Children.Add(trace);
     output.CurrentTrace = trace;
 }
コード例 #20
0
 public void MorphologicalRuleNotUnapplied(IMorphologicalRule rule, int subruleIndex, Word input)
 {
 }
コード例 #21
0
        private bool TryLoadRealizationalRule(XElement realRuleElem, CharacterDefinitionTable defaultTable, out IMorphologicalRule mrule)
        {
            var realRuleID = (string) realRuleElem.Attribute("id");
            var realRule = new RealizationalAffixProcessRule
            {
                Name = (string) realRuleElem.Element("Name"),
                Gloss = (string) realRuleElem.Element("Gloss"),
                Blockable = (bool?) realRuleElem.Attribute("blockable") ?? true
            };

            var fs = new FeatureStruct();
            XElement requiredHeadFeatElem = realRuleElem.Element("RequiredHeadFeatures");
            if (requiredHeadFeatElem != null)
                fs.AddValue(_headFeature, LoadFeatureStruct(requiredHeadFeatElem, _language.SyntacticFeatureSystem));
            XElement requiredFootFeatElem = realRuleElem.Element("RequiredFootFeatures");
            if (requiredFootFeatElem != null)
                fs.AddValue(_footFeature, LoadFeatureStruct(requiredFootFeatElem, _language.SyntacticFeatureSystem));
            fs.Freeze();
            realRule.RequiredSyntacticFeatureStruct = fs;

            XElement realFeatElem = realRuleElem.Element("RealizationalFeatures");
            if (realFeatElem != null)
                realRule.RealizationalFeatureStruct = FeatureStruct.New().Feature(_headFeature).EqualTo(LoadFeatureStruct(realFeatElem, _language.SyntacticFeatureSystem)).Value;
            LoadProperties(realRuleElem.Element("Properties"), realRule.Properties);

            foreach (XElement subruleElem in realRuleElem.Elements("MorphologicalSubrules").Elements("MorphologicalSubrule").Where(IsActive))
            {
                try
                {
                    AffixProcessAllomorph allomorph = LoadAffixProcessAllomorph(subruleElem, defaultTable);
                    realRule.Allomorphs.Add(allomorph);
                    _allomorphs[(string) subruleElem.Attribute("id")] = allomorph;
                }
                catch (Exception e)
                {
                    if (_errorHandler != null)
                        _errorHandler(e, (string) realRuleElem.Attribute("id"));
                    else
                        throw;
                }
            }

            if (realRule.Allomorphs.Count > 0)
            {
                _morphemes[realRuleID] = realRule;
                mrule = realRule;
                return true;
            }

            mrule = null;
            return false;
        }
コード例 #22
0
ファイル: TraceManager.cs プロジェクト: sillsdev/hermitcrab
 public void MorphologicalRuleNotApplied(IMorphologicalRule rule, int subruleIndex, Word input, FailureReason reason, object failureObj)
 {
     ((Trace) input.CurrentTrace).Children.Add(new Trace(TraceType.MorphologicalRuleSynthesis, rule) {SubruleIndex = subruleIndex, Input = input, FailureReason = reason});
 }
コード例 #23
0
        public void MorphologicalRuleNotApplied(IMorphologicalRule rule, int subruleIndex, Word input, FailureReason reason, object failureObj)
        {
            var trace = new XElement("MorphologicalRuleSynthesisTrace",
                                     CreateMorphologicalRuleElement(rule));
            var aprule = rule as AffixProcessRule;

            if (aprule != null)
            {
                trace.Add(CreateAllomorphElement(subruleIndex == -1 ? aprule.Allomorphs.Last() : aprule.Allomorphs[subruleIndex]));
            }
            trace.Add(new XElement("Output", "*None*"));
            switch (reason)
            {
            case FailureReason.RequiredSyntacticFeatureStruct:
                Debug.Assert(aprule != null);
                var             requiredFS  = (FeatureStruct)failureObj;
                FeatureSymbol[] requiredPos = requiredFS.PartsOfSpeech().ToArray();
                FeatureSymbol[] inputPos    = input.SyntacticFeatureStruct.PartsOfSpeech().ToArray();
                if (requiredPos.Intersect(inputPos).Any())
                {
                    trace.Add(new XElement("FailureReason", new XAttribute("type", "inflFeats"),
                                           CreateInflFeaturesElement("InflFeatures", input.SyntacticFeatureStruct),
                                           CreateInflFeaturesElement("RequiredInflFeatures", requiredFS)));
                }
                else
                {
                    trace.Add(new XElement("FailureReason", new XAttribute("type", "pos"),
                                           new XElement("Pos", string.Join(", ", inputPos.Select(s => s.Description))),
                                           new XElement("RequiredPos", string.Join(", ", requiredPos.Select(s => s.Description)))));
                }
                break;

            case FailureReason.RequiredStemName:
                trace.Add(new XElement("FailureReason", new XAttribute("type", "fromStemName"),
                                       new XElement("StemName", failureObj)));
                break;

            case FailureReason.RequiredMprFeatures:
                Debug.Assert(aprule != null);
                var group = (MprFeatureGroup)failureObj;
                trace.Add(group.Name == "lexEntryInflTypes" ? new XElement("FailureReason", new XAttribute("type", "requiredInflType"))
                                                : CreateMprFeaturesFailureElement(true, group, aprule.Allomorphs[subruleIndex].RequiredMprFeatures, input));
                break;

            case FailureReason.ExcludedMprFeatures:
                trace.Add(new XElement("FailureReason", new XAttribute("type", "excludedInflType")));
                break;

            case FailureReason.Pattern:
                Debug.Assert(aprule != null);
                var env       = (string)aprule.Allomorphs[subruleIndex].Properties["Env"];
                var prefixEnv = (string)aprule.Allomorphs[subruleIndex].Properties["PrefixEnv"];
                var suffixEnv = (string)aprule.Allomorphs[subruleIndex].Properties["SuffixEnv"];
                if (env != null || prefixEnv != null || suffixEnv != null)
                {
                    var reasonElem = new XElement("FailureReason", new XAttribute("type", "environment"));
                    if (env != null)
                    {
                        reasonElem.Add(new XElement("Environment", env));
                    }
                    if (prefixEnv != null)
                    {
                        reasonElem.Add(new XElement("Environment", env));
                    }
                    if (suffixEnv != null)
                    {
                        reasonElem.Add(new XElement("Environment", env));
                    }
                    trace.Add(reasonElem);
                }
                else
                {
                    trace.Add(new XElement("FailureReason", new XAttribute("type", "affixProcess")));
                }
                break;

            case FailureReason.MaxApplicationCount:
                trace.Add(new XElement("FailureReason", new XAttribute("type", "maxAppCount")));
                break;

            case FailureReason.NonPartialRuleProhibitedAfterFinalTemplate:
                trace.Add(new XElement("FailureReason", new XAttribute("type", "nonPartialRuleAfterFinalTemplate")));
                break;

            case FailureReason.NonPartialRuleRequiredAfterNonFinalTemplate:
                trace.Add(new XElement("FailureReason", new XAttribute("type", "partialRuleAfterNonFinalTemplate")));
                break;

            default:
                return;
            }
            ((XElement)input.CurrentTrace).Add(trace);
        }
コード例 #24
0
		public void MorphologicalRuleNotUnapplied(IMorphologicalRule rule, int subruleIndex, Word input)
		{
		}
コード例 #25
0
        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;
        }