//****************************************************************** #region [CurrentBranchMatchesPattern() Method] //****************************************************************** /// <summary> /// Compares the trees dominated by the CurrentParseTreeNode and the /// FindPatternRoot. If these trees match, true is returned and the /// MatchingNodes stack contains the list of matching node pairs. /// Otherwise, false is returned. /// </summary> public bool CurrentBranchMatchesPattern() { Debug.WriteLineIf(VerboseDebugging, "MatchAlgorithm.CurrentBranchMatchesPattern() called."); //************************************************************** // Validate the current state. if (FindPatternRoot == null) { string sMessage = "CurrentBranchMatchesPattern() " + "called with an invalid state: " + "FindPatternRoot is null."; throw new Exception(sMessage); } if (CurrentParseTreeNode == null) { string sMessage = "CurrentBranchMatchesPattern() " + "called with an invalid state: " + "CurrentParseTreeNode is null."; throw new Exception(sMessage); } //************************************************************** // Clear the stack of matching node pairs. MatchingNodes.Clear(); //************************************************************** // Call FeaturesAndChildrenMatch() to check if the current // parse-tree branch matches the find-pattern tree. If so, // return true. SyntaxNodePair oNodePair = new SyntaxNodePair(); oNodePair.ParseTreeNode = CurrentParseTreeNode; oNodePair.FindPatternNode = FindPatternRoot; if (FeaturesAndChildrenMatch(oNodePair)) { Debug.Assert(MatchingNodes.Count > 0); Debug.WriteLineIf(VerboseDebugging, "MatchAlgorithm.CurrentBranchMatchesPattern() returns " + "true."); return(true); } //************************************************************** // The current parse-tree branch does not match the find-pattern // tree, so return false. // // Note: The matching procedure should have cleared all node // pairs from the MatchingNodes stack if the match failed. Debug.Assert(MatchingNodes.Count == 0); MatchingNodes.Clear(); Debug.WriteLineIf(VerboseDebugging, "MatchAlgorithm.CurrentBranchMatchesPattern() returns " + "false."); return(false); }
//****************************************************************** #region [FindNextMatchingBranch() Method] //****************************************************************** /// <summary> /// Moves the CurrentParseTreeNode forward in the parse tree, until /// the sub-tree dominated by this node matches the pattern /// dominated by FindPatternRoot. If CurrentParseTreeNode is null /// when this method is called, the search starts with the first /// node in the parse tree. Otherwise, the search continues with the /// next node in the tree. If a matching sub-tree is found, true is /// returned and the MatchingNodes stack contains the list of /// matching node pairs. If no match is found, CurrentParseTreeNode /// is set to null and false is returned. /// </summary> public bool FindNextMatchingBranch() { Debug.WriteLineIf(VerboseDebugging, "FindAlgorithm.FindNextMatchingBranch() called."); //************************************************************** // Validate the current state. if (CurrentParseTreeNode != null) { SyntaxNode oNode = CurrentParseTreeNode; while (oNode != ParseTreeRoot) { if (oNode.ParentNode == null) { string sMessage = "FindNextMatchingBranch() " + "called with an invalid state: " + "the ParseTreeRoot tree does not contain " + "the CurrentParseTreeNode."; throw new Exception(sMessage); } oNode = oNode.ParentNode; } } //************************************************************** // Clear the lists of MatchingNodes and ReplacedNodes. MatchingNodes.Clear(); ReplacedNodes.Clear(); //************************************************************** // Save the previous value of the CurrentParseTreeNode. SyntaxNode oPreviousParseTreeNode = CurrentParseTreeNode; //************************************************************** // Move the CurrentParseTreeNode to the next branch to compare: // // If CurrentParseTreeNode is null, start with the first // parse-tree node in post order. // // Otherwise, move to the next node in post order. // // Note: The parse tree is traversed in post-order (parent after // its children) to prevent infinite recursion that could occur // if an XP node was replaced by a node with XP children, and // then the rule was applied recursively to these children. if (CurrentParseTreeNode == null) { CurrentParseTreeNode = GetFirstNodeInPostOrder(ParseTreeRoot); } else { CurrentParseTreeNode = GetNextNodeInPostOrder(CurrentParseTreeNode); } //************************************************************** // Check if the previous branch should be deleted. // // When the ReplaceCurrentMatchingBranch() method needs to // delete the current parse-tree node, it sets it to an empty // node (one with no features and no children) instead. This is // so we can use the current parse-tree node to determine where // to find the next node to compare. // // If the previous branch is an empty node (with no features and // no children), delete it. if (oPreviousParseTreeNode != null) { if ((oPreviousParseTreeNode.Features.Count == 0) && (oPreviousParseTreeNode.ChildNodes.Count == 0)) { //****************************************************** // Remove the empty node from its parent's ChildNodes // collection. If the empty node is the same as the // ParseTreeRoot, set the ParseTreeRoot to null. SyntaxNode oParent = oPreviousParseTreeNode.ParentNode; if (oParent != null) { oParent.ChildNodes.Remove(oPreviousParseTreeNode); } if (oPreviousParseTreeNode == ParseTreeRoot) { ParseTreeRoot = null; } } } //************************************************************** // If FindPatternRoot is null, nothing can match this pattern. // In this case, set CurrentParseTreeNode to null so there will // be no comparisons and false will be returned. if (FindPatternRoot == null) { CurrentParseTreeNode = null; } //************************************************************** // Traverse the parse tree (in post order), looking for a match, // until there are no more nodes to traverse. Return true if a // match is found. while (CurrentParseTreeNode != null) { //********************************************************** // Return true if the current branch matches the pattern. if (CurrentBranchMatchesPattern()) { Debug.Assert(MatchingNodes.Count > 0); Debug.Assert(ReplacedNodes.Count == 0); Debug.Assert(CurrentParseTreeNode != null); Debug.WriteLineIf(VerboseDebugging, "FindAlgorithm.FindNextMatchingBranch() returns " + "true."); return(true); } //********************************************************** // Move to the next node in post order. CurrentParseTreeNode = GetNextNodeInPostOrder(CurrentParseTreeNode); } //************************************************************** // A matching branch was not found, so return false. Debug.Assert(MatchingNodes.Count == 0); Debug.Assert(ReplacedNodes.Count == 0); Debug.Assert(CurrentParseTreeNode == null); Debug.WriteLineIf(VerboseDebugging, "FindAlgorithm.FindNextMatchingBranch() returns false."); return(false); }