Ejemplo n.º 1
0
        //******************************************************************
        #region [ClearNodePairFromStack() Method]
        //******************************************************************
        /// <summary>
        /// Pops node pairs from the MatchingNodes stack until the indicated
        /// node pair (oNodePair) has been popped. (The indicated node pair
        /// must exist on the stack.)
        /// </summary>
        private void ClearNodePairFromStack(SyntaxNodePair oNodePair)
        {
            Debug.Assert(oNodePair != null);
            Debug.Assert(oNodePair.ParseTreeNode != null);
            Debug.Assert(oNodePair.FindPatternNode != null);

            while (MatchingNodes.Count > 0)
            {
                SyntaxNodePair oStackPair = MatchingNodes.Pop();
                if (oStackPair == oNodePair)
                {
                    return;
                }
            }
            Debug.Fail("Node pair not found in MatchingNodes stack.");
        }
Ejemplo n.º 2
0
        //******************************************************************
        #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);
        }
Ejemplo n.º 3
0
        //******************************************************************
        #region [FeaturesAndChildrenMatch() Method]
        //******************************************************************
        /// <summary>
        /// Compares the sub-trees dominated by oNodePair.ParseTreeNode and
        /// oNodePair.FindPatternNode. If the features and children of the
        /// pattern sub-tree match the features and children of the parse
        /// sub-tree, the matching node pairs are pushed onto the
        /// MatchingNodes stack and true is returned. Otherwise, false is
        /// returned (after any added partial matches are popped of the
        /// MatchingNodes stack, restoring it to the same state as when this
        /// method was called).
        /// </summary>
        private bool FeaturesAndChildrenMatch(SyntaxNodePair oNodePair)
        {
            Debug.Assert(oNodePair != null);

            //**************************************************************
            // Compare the features of oNodePair.ParseTreeNode and
            // oNodePair.FindPatternNode.
            //
            // If the features do not match (or if either node is null),
            // return false.
            //
            // Otherwise, push the oNodePair onto the MatchingNodes stack.

            if (!FeaturesMatch(oNodePair))
            {
                return(false);
            }

            Debug.Assert(oNodePair.ParseTreeNode != null);
            Debug.Assert(oNodePair.FindPatternNode != null);

            MatchingNodes.Push(oNodePair);

            Debug.WriteLineIf(VerboseDebugging,
                              "MatchingNodes: " + MatchingNodes.ToString() + ".");

            //**************************************************************
            // If oNodePair.FindPatternNode has children, compare these
            // children to the children of oNodePair.ParseTreeNode.
            //
            // (Note that the children of the ParseTreeNode do not need to
            // be matched if the FindPatternNode does not have children.)
            //
            // If the children do not match, pop everything off the
            // MatchingNodes stack up to and including the oNodePair, and
            // then return false.

            if (oNodePair.FindPatternNode.ChildNodes.Count > 0)
            {
                //**********************************************************
                // If oNodePair.ParseTreeNode is a syntax leaf node, call
                // LeafChildrenMatch() to compare the children.
                //
                // Otherwise, call NodeChildrenMatch() to compare the
                // children.

                bool bChildrenMatch = false;
                if (oNodePair.ParseTreeNode.IsSyntaxLeaf)
                {
                    bChildrenMatch = LeafChildrenMatch(oNodePair);
                }
                else
                {
                    bChildrenMatch = NodeChildrenMatch(oNodePair);
                }

                //**********************************************************
                // If the children do not match, pop everything off the
                // MatchingNodes stack up to and including the oNodePair,
                // and then return false.

                if (!bChildrenMatch)
                {
                    ClearNodePairFromStack(oNodePair);
                    return(false);
                }
            }

            //**************************************************************
            // The features and children match, so return true.

            return(true);
        }
Ejemplo n.º 4
0
        //******************************************************************
        #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);
        }