/// <summary> /// Evaluates if the adtree matches its pattern. /// </summary> /// <param name="adTree"></param> /// <returns></returns> public static bool IsCorrect(this IAdTree adTree, IAttributesModel attributesModel) { // Check the morpheme belonging to the adtree. if (!adTree.Pattern.UpRule.Evaluate(adTree.Morpheme)) { if (!adTree.Pattern.UpRule.Equals(MorphemeRule.Nothing) || (adTree.Pattern.UpRule.Equals(MorphemeRule.Nothing) && !string.IsNullOrEmpty(adTree.Morpheme.Morph))) { return(false); } } // Left if (adTree.Left != null) { if (!adTree.CanAttachToLeft(adTree.Left, attributesModel)) { return(false); } } else if (!adTree.Pattern.LeftRule.Equals(MorphemeRule.Nothing) && !adTree.Pattern.LeftRule.Equals(MorphemeRule.Anything)) { return(false); } // Right if (adTree.Right != null) { if (!adTree.CanAttachToRight(adTree.Right, attributesModel)) { return(false); } } else if (!adTree.Pattern.RightRule.Equals(MorphemeRule.Nothing) && !adTree.Pattern.RightRule.Equals(MorphemeRule.Anything)) { return(false); } return(true); }
// 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; } } } }
private void TryToAppend(IAdTree current, IAdTree appendee, string expectedSignature, List <IAdTree> results) { using (Trace.Entering()) { IAdTree placeToAppend = GetPlaceToAppend(current); // If an adposition needs to be filled. if (!placeToAppend.Pattern.UpRule.Equals(MorphemeRule.Nothing) && !placeToAppend.Pattern.UpRule.Evaluate(placeToAppend.Morpheme)) { if (placeToAppend.Pattern.Equals(appendee.Pattern)) { IAdTree newElementCopy = appendee.MakeShallowCopy(); IAdTree adTreeCopy = placeToAppend.MakeShallowCopy(); adTreeCopy.Replace(newElementCopy); results.Add(newElementCopy); } return; } bool isMorphematicAdPosition = appendee.Pattern.IsMorphematicAdPosition(); bool canAppendIndirectly = CanAppendIndirectly(current) && !isMorphematicAdPosition; // If the new element can be attached to left. if (placeToAppend.Left == null && !placeToAppend.Pattern.LeftRule.Equals(MorphemeRule.Nothing)) { // Try to attach the new element directly. if (placeToAppend.CanAttachToLeft(appendee, myConstructiveDictionary.AttributesModel)) { IAdTree newAdTreeElementCopy = appendee.MakeShallowCopy(); IAdTree adTreeCopy = placeToAppend.MakeShallowCopy(); adTreeCopy.Left = newAdTreeElementCopy; results.Add(newAdTreeElementCopy); } if (canAppendIndirectly) { // Try to attach the new element indirectly. TryToAppendIndirectly(AttachingPosition.ParrentForLeft, placeToAppend, appendee, expectedSignature, results); } } // If the new element can be attached to right. if (placeToAppend.Right == null && !placeToAppend.Pattern.RightRule.Equals(MorphemeRule.Nothing)) { // Try to attach the new element directly. if (placeToAppend.CanAttachToRight(appendee, myConstructiveDictionary.AttributesModel)) { IAdTree newAdTreeElementCopy = appendee.MakeShallowCopy(); IAdTree adTreeCopy = placeToAppend.MakeShallowCopy(); adTreeCopy.Right = newAdTreeElementCopy; results.Add(newAdTreeElementCopy); } if (canAppendIndirectly) { // Try to attach the new element indirectly. TryToAppendIndirectly(AttachingPosition.ParrentForRight, placeToAppend, appendee, expectedSignature, results); } } // If the new element can attach the placeToAppend to its left or right. // If the adtree has free adposition - i.e. it can be attached to left or right. if (placeToAppend.AdPosition == null) { // The new element tries to attach the adtree to its left. if (appendee.Left == null && !appendee.Pattern.LeftRule.Equals(MorphemeRule.Nothing)) { if (appendee.CanAttachToLeft(placeToAppend, myConstructiveDictionary.AttributesModel)) { IAdTree newAdTreeElementCopy = appendee.MakeShallowCopy(); IAdTree adTreeCopy = placeToAppend.MakeShallowCopy(); newAdTreeElementCopy.Left = adTreeCopy; results.Add(adTreeCopy); } // Try to attach the adtree indirectly via new element's left. else if (canAppendIndirectly) { TryToAppendIndirectly(AttachingPosition.ParrentForLeft, appendee, placeToAppend, expectedSignature, results); } } // The new element tries to attach the adtree to its right. if (appendee.Right == null && !appendee.Pattern.RightRule.Equals(MorphemeRule.Nothing)) { if (appendee.CanAttachToRight(placeToAppend, myConstructiveDictionary.AttributesModel)) { IAdTree newAdTreeElementCopy = appendee.MakeShallowCopy(); IAdTree adTreeCopy = placeToAppend.MakeShallowCopy(); newAdTreeElementCopy.Right = adTreeCopy; results.Add(adTreeCopy); } // Try to attach the adtree indirectly via new element's right. else if (canAppendIndirectly) { TryToAppendIndirectly(AttachingPosition.ParrentForRight, appendee, placeToAppend, expectedSignature, results); } } if (canAppendIndirectly) { // Also try to connect the adtree and the new element indirectly via adtree adposition. TryToAppendIndirectly(AttachingPosition.ChildOnLeft, placeToAppend, appendee, expectedSignature, results); TryToAppendIndirectly(AttachingPosition.ChildOnRight, placeToAppend, appendee, expectedSignature, results); } } } }