//****************************************************************** #region [BacktrackToOptionalNode() Method] //****************************************************************** /// <summary> /// Attempts to backtrack to a node pair on the MatchingNodes stack /// that (1) is a child of the given oParentNodePair and (2) has an /// optional FindPatternNode. If such a node pair is found, items /// are popped from the stack until this node pair is popped, and /// then this node pair is returned. If no such node pair is found, /// null is returned (and no items are popped from the stack). /// </summary> private SyntaxNodePair BacktrackToOptionalNode( SyntaxNodePair oParentNodePair) { Debug.Assert(oParentNodePair != null); Debug.Assert(oParentNodePair.ParseTreeNode != null); Debug.Assert(oParentNodePair.FindPatternNode != null); //************************************************************** // Search backwards through the MatchingNodes stack (starting // with the most recently pushed node pair), looking for a node // pair where (1) the ParseTreeNode is a child of the given // oParentNodePair.ParseTreeNode, (2) the FindPatternNode is a // child of the given oParentNodePair.FindPatternNode, and (3) // the FindPatternNode is optional. // // If such a node pair is found, pop items from the stack until // this node pair is popped, and then return this node pair. int iIndex = MatchingNodes.Count - 1; while (iIndex >= 0) { SyntaxNodePair oNodePair = MatchingNodes[iIndex]; if ((oNodePair.ParseTreeNode.ParentNode == oParentNodePair.ParseTreeNode) && (oNodePair.FindPatternNode.ParentNode == oParentNodePair.FindPatternNode) && (oNodePair.FindPatternNode.IsOptionalNode)) { //****************************************************** // Found a node pair that is a child of the given // oParentNodePair and has an optional FindPatternNode. // So pop items from the stack until this node pair is // popped, and then return this node pair. // // This restores the stack to the same state as when // this node pair was matched, but this time we can skip // the optional node and attempt to continue the match. ClearNodePairFromStack(oNodePair); Debug.WriteLineIf(VerboseDebugging, "Backtracking to optional node...."); return(oNodePair); } --iIndex; } //************************************************************** // The stack does not contain a child of the oParentNodePair // with an optional FindPatternNode, so return null. Debug.WriteLineIf(VerboseDebugging, "Backtracking... cannot find an optional child of " + oParentNodePair.ToString() + " on the stack."); return(null); }
//****************************************************************** #region [FeaturesMatch() Method] //****************************************************************** /// <summary> /// Compares the ParseTreeNode and the FindPatternNode specified by /// the given oNodePair. If both nodes are not null, the node /// features are compared, and true is returned if the ParseTreeNode /// has a matching feature value for each feature in the /// FindPatternNode.Features collection. Otherwise, false is /// returned. /// </summary> private bool FeaturesMatch(SyntaxNodePair oNodePair) { Debug.Assert(oNodePair != null); //************************************************************** // For verbose debugging output, determine if the parse-tree // node is a syntax leaf. string sPair = "Node pair"; if (VerboseDebugging) { if (oNodePair.ParseTreeNode != null) { if (oNodePair.ParseTreeNode.IsSyntaxLeaf) { sPair = "Leaf pair"; } } } //************************************************************** // Return false if either node in the node pair is null. if ((oNodePair.ParseTreeNode == null) || (oNodePair.FindPatternNode == null)) { Debug.WriteLineIf(VerboseDebugging, sPair + " does not match: " + oNodePair.ToString() + "."); return(false); } //************************************************************** // For each feature in the find-pattern node (except for the // node label), check if the parse-tree node has a matching // value for that feature. foreach (SyntaxFeature oFeature in oNodePair.FindPatternNode.Features) { if (oFeature.Name != TreeTranEngineString.NodeLabel) { //****************************************************** // Return false if the parse-tree feature does not have // a matching value. // // Note: If the parse-tree node does not have a feature // with the same name, the default feature value is // used: an empty string (""). Because of this, we can // check if a feature matches a pattern like "!xxx", and // the match will succeed if (1) the parse-tree node has // that feature with any value other than "xxx" or (2) // the parse-tree node does not have that feature. string sString = oNodePair.ParseTreeNode.Features[oFeature.Name]; string sPattern = oFeature.Value; if (!StringMatchesPattern(sString, sPattern)) { Debug.WriteLineIf(VerboseDebugging, sPair + " does not match: " + oNodePair.ToString() + " " + oFeature.Name + " = " + "\"" + sString + "\" vs " + "\"" + sPattern + "\"."); return(false); } } } //************************************************************** // Return true if all of the features matched. Debug.WriteLineIf(VerboseDebugging, sPair + " matches: " + oNodePair.ToString() + "."); return(true); }
//****************************************************************** /// <summary> /// Compares the ParseTreeNode and the FindPatternNode specified by /// the given oNodePair. If both nodes are not null, the node /// features are compared, and true is returned if the ParseTreeNode /// has a matching feature value for each feature in the /// FindPatternNode.Features collection. Otherwise, false is /// returned. /// </summary> private bool FeaturesMatch(SyntaxNodePair oNodePair) { Debug.Assert(oNodePair != null); //************************************************************** // For verbose debugging output, determine if the parse-tree // node is a syntax leaf. string sPair = "Node pair"; if (VerboseDebugging) { if (oNodePair.ParseTreeNode != null) { if (oNodePair.ParseTreeNode.IsSyntaxLeaf) { sPair = "Leaf pair"; } } } //************************************************************** // Return false if either node in the node pair is null. if ((oNodePair.ParseTreeNode == null) || (oNodePair.FindPatternNode == null)) { Debug.WriteLineIf(VerboseDebugging, sPair + " does not match: " + oNodePair.ToString() + "."); return false; } //************************************************************** // For each feature in the find-pattern node (except for the // node label), check if the parse-tree node has a matching // value for that feature. foreach (SyntaxFeature oFeature in oNodePair.FindPatternNode.Features) { if (oFeature.Name != TreeTranEngineString.NodeLabel) { //****************************************************** // Return false if the parse-tree feature does not have // a matching value. // // Note: If the parse-tree node does not have a feature // with the same name, the default feature value is // used: an empty string (""). Because of this, we can // check if a feature matches a pattern like "!xxx", and // the match will succeed if (1) the parse-tree node has // that feature with any value other than "xxx" or (2) // the parse-tree node does not have that feature. string sString = oNodePair.ParseTreeNode.Features[oFeature.Name]; string sPattern = oFeature.Value; if (! StringMatchesPattern(sString,sPattern)) { Debug.WriteLineIf(VerboseDebugging, sPair + " does not match: " + oNodePair.ToString() + " " + oFeature.Name + " = " + "\"" + sString + "\" vs " + "\"" + sPattern + "\"."); return false; } } } //************************************************************** // Return true if all of the features matched. Debug.WriteLineIf(VerboseDebugging, sPair + " matches: " + oNodePair.ToString() + "."); return true; }
//****************************************************************** /// <summary> /// Attempts to backtrack to a node pair on the MatchingNodes stack /// that (1) is a child of the given oParentNodePair and (2) has an /// optional FindPatternNode. If such a node pair is found, items /// are popped from the stack until this node pair is popped, and /// then this node pair is returned. If no such node pair is found, /// null is returned (and no items are popped from the stack). /// </summary> private SyntaxNodePair BacktrackToOptionalNode( SyntaxNodePair oParentNodePair) { Debug.Assert(oParentNodePair != null); Debug.Assert(oParentNodePair.ParseTreeNode != null); Debug.Assert(oParentNodePair.FindPatternNode != null); //************************************************************** // Search backwards through the MatchingNodes stack (starting // with the most recently pushed node pair), looking for a node // pair where (1) the ParseTreeNode is a child of the given // oParentNodePair.ParseTreeNode, (2) the FindPatternNode is a // child of the given oParentNodePair.FindPatternNode, and (3) // the FindPatternNode is optional. // // If such a node pair is found, pop items from the stack until // this node pair is popped, and then return this node pair. int iIndex = MatchingNodes.Count - 1; while (iIndex >= 0) { SyntaxNodePair oNodePair = MatchingNodes[iIndex]; if ((oNodePair.ParseTreeNode.ParentNode == oParentNodePair.ParseTreeNode) && (oNodePair.FindPatternNode.ParentNode == oParentNodePair.FindPatternNode) && (oNodePair.FindPatternNode.IsOptionalNode)) { //****************************************************** // Found a node pair that is a child of the given // oParentNodePair and has an optional FindPatternNode. // So pop items from the stack until this node pair is // popped, and then return this node pair. // // This restores the stack to the same state as when // this node pair was matched, but this time we can skip // the optional node and attempt to continue the match. ClearNodePairFromStack(oNodePair); Debug.WriteLineIf(VerboseDebugging, "Backtracking to optional node...."); return oNodePair; } --iIndex; } //************************************************************** // The stack does not contain a child of the oParentNodePair // with an optional FindPatternNode, so return null. Debug.WriteLineIf(VerboseDebugging, "Backtracking... cannot find an optional child of " + oParentNodePair.ToString() + " on the stack."); return null; }