private static bool IsAttachingOrderCorrect(IAdTree adTree, AttachingPosition position) { bool result = false; // If the attaching position is on the left. if (position == AttachingPosition.ChildOnLeft) { // If left is before the right if (adTree.Pattern.IsLeftFirst || // or right is already set adTree.Right != null || // or right is not supposed to be set. adTree.Pattern.RightRule.Equals(MorphemeRule.Nothing)) { result = true; } } else { if (!adTree.Pattern.IsLeftFirst || adTree.Left != null || adTree.Pattern.LeftRule.Equals(MorphemeRule.Nothing)) { result = true; } } return(result); }
/// <summary> /// Appends the adtree to the adtree. /// </summary> /// <param name="adTree">The adtree into which it shall be attached.</param> /// <param name="toAttach">The adtree which shall be appended.</param> /// <param name="appendPosition">The position how it shall be appended.</param> public static void Attach(this IAdTree adTree, IAdTree toAttach, AttachingPosition appendPosition) { if (appendPosition == AttachingPosition.ChildOnLeft) { adTree.Left = toAttach; } else if (appendPosition == AttachingPosition.ChildOnRight) { adTree.Right = toAttach; } }
/// <summary> /// Inserts the adtree into the adtree. /// </summary> /// <param name="adTree">The adtree into which it shall be inserted.</param> /// <param name="toInsert">The adtree which shall be inserted.</param> /// <param name="whereReattach">The adtree which shall reatach the adtree disconnected by the insertion.</param> /// <param name="reattachPosition">The position where the adtree shall be reattached after the insertion.</param> public static void Insert(this IAdTree adTree, IAdTree toInsert, IAdTree whereReattach, AttachingPosition reattachPosition) { // Insert the toInsert instead of the adTree. if (adTree.IsOnLeft) { adTree.AdPosition.Left = toInsert; } else if (adTree.IsOnRight) { adTree.AdPosition.Right = toInsert; } // Attach the adtree to the inserted adtree. whereReattach.Attach(adTree, reattachPosition); }
private static bool CanAttachViaRule(this IAdTree adTree, IAdTree adTreeToAttach, AttachingPosition attachPosition, IAttributesModel attributesModel) { // Get rule to evalute. MorphemeRule rule = attachPosition == AttachingPosition.ChildOnLeft ? adTree.Pattern.LeftRule : adTree.Pattern.RightRule; // If the rule allows to attach and the order of attaching is correct. if (!rule.Equals(MorphemeRule.Nothing) && IsAttachingOrderCorrect(adTree, attachPosition)) { // If the adtree where to attach is morphematic then it is not possible to attach the second child until the morpheme is set. if (adTree.Pattern.IsMorphematicAdPosition() && (adTree.Right != null || adTree.Left != null) && string.IsNullOrEmpty(adTree.Morpheme.Morph)) { return(false); } // Note: from the tree to attach we need to get the adtree representing the morpheme which shall be evaluated. IAdTree morphemeAdTree = null; // If the adTreeToAttach is a morpheme or a transference. if (adTreeToAttach.Pattern.IsLikeMorpheme) { morphemeAdTree = adTreeToAttach; } // It is an adposition. else if (adTreeToAttach.Pattern.IsEpsilonAdPosition() || adTreeToAttach.Pattern.IsMorphematicAdPosition()) { // If a substitution (because adTreeToAttach is adposition) can be attached. if (rule.SubstitutionRule.Evaluate(adTreeToAttach.Morpheme.GrammarCharacter)) { // If it shall be attached to the right and // the valency position is specified then check correctness with regard to presence of previously filled valencies. if (attachPosition == AttachingPosition.ChildOnRight) { IAdTree valencyElement = adTree.GetSequenceToRoot() .TakeUntil(x => x.IsOnRight) .FirstOrDefault(x => x.Pattern.ValencyPosition > 0); if (valencyElement != null) { IAdTree previousValencyElement = adTreeToAttach.GetRightSequence() .FirstOrDefault(x => x.Pattern.ValencyPosition > 0); if (previousValencyElement == null && valencyElement.Pattern.ValencyPosition > 1 || previousValencyElement != null && valencyElement.Pattern.ValencyPosition != previousValencyElement.Pattern.ValencyPosition + 1) { return(false); } } } // Try to get the driving morpheme. morphemeAdTree = adTreeToAttach.RightChildren.FirstOrDefault(x => x.Pattern.IsLikeMorpheme); // If the governor is not attached yet then check only rules. if (morphemeAdTree == null) { IEnumerable <IAdTree> rightSequence = new IAdTree[] { adTreeToAttach }.Concat(adTreeToAttach.RightChildren); if (rightSequence.Any(x => !x.Pattern.RightRule.IsSubruleOf(rule) && !rule.IsSubruleOf(x.Pattern.RightRule))) { return(false); } return(true); } } } if (morphemeAdTree != null) { // If it shall be attached to the right the morpheme is a verb then check the valency. if (attachPosition == AttachingPosition.ChildOnRight && attributesModel.IsVerb(morphemeAdTree.Morpheme.Attributes)) { int valency = attributesModel.GetNumberOfValencies(morphemeAdTree.Morpheme.Attributes); if (valency > -1) { // Get already filled valency positions. int[] valencyPositions = morphemeAdTree.GetSequenceToRoot() .TakeWhile(x => x != adTree) // This is to not make an assuption if it is already attached or not. .TakeUntil(x => x.IsOnRight) .Concat(adTree.GetSequenceToRoot().TakeUntil(x => x.IsOnRight)) .Where(x => x.Pattern.ValencyPosition > 0) .Select(x => x.Pattern.ValencyPosition) .ToArray(); // If such valency is already filled. if (valencyPositions.Length > valency) { return(false); } for (int i = 0; i < valencyPositions.Length; ++i) { if (valencyPositions[i] != i + 1) { return(false); } } } } Morpheme morphemeToEvaluate = morphemeAdTree.TryGetTransferenceMorpheme(); if (string.IsNullOrEmpty(morphemeToEvaluate?.Morph) && morphemeAdTree.Pattern.IsPairTransference) { // The morpheme with the morph is not attached yet so check only attributes. if (rule.AttributesRule.Evaluate(morphemeAdTree.Morpheme.Attributes)) { return(true); } else { return(false); } } // Check if the morpheme passes the rule. bool result = rule.Evaluate(morphemeToEvaluate); return(result); } } return(false); }
// Note: indirect append means that adtress (with unfilled values) will be inserted inbetween start and end adtree. // Unfilled values are expected to be filled later otherwise the adtree will be not valid. private void TryToAppendIndirectly(AttachingPosition appendingPositionOfStartElement, IAdTree start, IAdTree end, string expectedSignature, List <IAdTree> results) { using (Trace.Entering()) { GrammarCharacter startGrammarCharacter = GrammarCharacter.e; GrammarCharacter endGrammarCharacter = GrammarCharacter.e; // If start adTree connects the bridge on its left. if (appendingPositionOfStartElement == AttachingPosition.ParrentForLeft) { startGrammarCharacter = start.Pattern.LeftRule.GrammarCharacter; endGrammarCharacter = end.RulingGrammarCharacter; } // If start adTree connects the bridge on its right. else if (appendingPositionOfStartElement == AttachingPosition.ParrentForRight) { startGrammarCharacter = start.Pattern.RightRule.GrammarCharacter; endGrammarCharacter = end.RulingGrammarCharacter; } // If the bridge connects the start adtree on its left. else if (appendingPositionOfStartElement == AttachingPosition.ChildOnLeft) { startGrammarCharacter = start.RulingGrammarCharacter; endGrammarCharacter = end.RulingGrammarCharacter; } // If the bridge connects the start adtree on its right. else if (appendingPositionOfStartElement == AttachingPosition.ChildOnRight) { startGrammarCharacter = start.RulingGrammarCharacter; endGrammarCharacter = end.RulingGrammarCharacter; } // Get all possibile ways how to get from start to end grammar character and path is not greater than 4. IEnumerable <IReadOnlyList <DirectedEdge <GrammarCharacter, Pattern> > > connectionPaths = myConstructiveDictionary.PatternGraph .FindAllEdges(startGrammarCharacter, endGrammarCharacter).ToList(); // Go via all possible ways. foreach (IReadOnlyList <DirectedEdge <GrammarCharacter, Pattern> > path in connectionPaths) { IAdTree startCopy = start.MakeShallowCopy(); IAdTree endCopy = end.MakeShallowCopy(); IAdTree previousBridge = null; // Go via the path. for (int i = 0; i < path.Count; ++i) { DirectedEdge <GrammarCharacter, Pattern> edge = path[i]; BigInteger attributes = edge.Value.UpRule.AttributesRule is IReferenceValueRule <BigInteger> referenceAttributes ? referenceAttributes.ReferenceValue : myConstructiveDictionary.AttributesModel.GetAttributes(edge.Value.UpRule.GrammarCharacter); IAdTree bridge = new AdTree(new Morpheme(myConstructiveDictionary.AttributesModel, "", attributes), edge.Value); // If it is the first item on the path. if (i == 0) { if (appendingPositionOfStartElement == AttachingPosition.ParrentForLeft) { if (startCopy.Left == null && startCopy.CanAttachToLeft(bridge, myConstructiveDictionary.AttributesModel)) { startCopy.Left = bridge; } else { break; } } else if (appendingPositionOfStartElement == AttachingPosition.ParrentForRight) { if (startCopy.Right == null && startCopy.CanAttachToRight(bridge, myConstructiveDictionary.AttributesModel)) { startCopy.Right = bridge; } else { break; } } else if (appendingPositionOfStartElement == AttachingPosition.ChildOnLeft) { if (bridge.Left == null && bridge.CanAttachToLeft(startCopy, myConstructiveDictionary.AttributesModel)) { bridge.Left = startCopy; } else { break; } } else if (appendingPositionOfStartElement == AttachingPosition.ChildOnRight) { if (bridge.Right == null && bridge.CanAttachToRight(startCopy, myConstructiveDictionary.AttributesModel)) { bridge.Right = startCopy; } else { break; } } } else { if (previousBridge.Left == null && previousBridge.CanAttachToLeft(bridge, myConstructiveDictionary.AttributesModel)) { previousBridge.Left = bridge; } else if (previousBridge.Right == null && previousBridge.CanAttachToRight(bridge, myConstructiveDictionary.AttributesModel)) { previousBridge.Right = bridge; } else { break; } } // If the signature does not match then break it. var currentSignature = bridge.Root.GetSignature(); if (!expectedSignature.StartsWith(currentSignature)) { break; } // If it is the last item in the path. if (i == path.Count - 1) { if (bridge.Left == null && bridge.CanAttachToLeft(endCopy, myConstructiveDictionary.AttributesModel)) { bridge.Left = endCopy; currentSignature = endCopy.Root.GetSignature(); if (expectedSignature.StartsWith(currentSignature)) { results.Add(endCopy); } } else if (bridge.Right == null && bridge.CanAttachToRight(endCopy, myConstructiveDictionary.AttributesModel)) { bridge.Right = endCopy; currentSignature = endCopy.Root.GetSignature(); if (expectedSignature.StartsWith(currentSignature)) { results.Add(endCopy); } } else { break; } } previousBridge = bridge; } } } }