コード例 #1
0
        //******************************************************************
        #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);
        }
コード例 #2
0
        //******************************************************************
        #region [Pop() Method]
        //******************************************************************
        /// <summary>
        /// Removes and returns the item at the top of the stack.
        /// </summary>
        public SyntaxNodePair Pop()
        {
            Debug.Assert(InnerList.Count > 0);

            SyntaxNodePair oNodePair
                = (SyntaxNodePair)InnerList[InnerList.Count - 1];

            InnerList.RemoveAt(InnerList.Count - 1);
            return(oNodePair);
        }
コード例 #3
0
        //******************************************************************
        #region [Push() Method]
        //******************************************************************
        /// <summary>
        /// Inserts an item at the top of the stack.
        /// </summary>
        public void Push(SyntaxNodePair oNodePair)
        {
            Debug.Assert(oNodePair != null);

            if (oNodePair == null)
            {
                string sMessage = "Invalid argument: "
                                  + "SyntaxNodePairStack cannot push a null item.";
                throw new Exception(sMessage);
            }

            InnerList.Add(oNodePair);
        }
コード例 #4
0
        //******************************************************************
        #region [FirstChildNodePair() Method]
        //******************************************************************
        /// <summary>
        /// Returns a new node pair containing the first child of the
        /// ParseTreeNode and the first child of the FindPatternNode from
        /// the given oNodePair.
        /// </summary>
        private SyntaxNodePair FirstChildNodePair(SyntaxNodePair oNodePair)
        {
            Debug.Assert(oNodePair != null);
            Debug.Assert(oNodePair.ParseTreeNode != null);
            Debug.Assert(oNodePair.FindPatternNode != null);

            SyntaxNodePair oChildPair = new SyntaxNodePair();

            oChildPair.ParseTreeNode
                = oNodePair.ParseTreeNode.FirstChild;
            oChildPair.FindPatternNode
                = oNodePair.FindPatternNode.FirstChild;
            return(oChildPair);
        }
コード例 #5
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.");
        }
コード例 #6
0
        //******************************************************************
        #region [NextSiblingNodePair() Method]
        //******************************************************************
        /// <summary>
        /// Returns a new node pair containing the next sibling of the
        /// ParseTreeNode and the next sibling of the FindPatternNode from
        /// the given oNodePair.
        /// </summary>
        private SyntaxNodePair NextSiblingNodePair(SyntaxNodePair oNodePair)
        {
            Debug.Assert(oNodePair != null);
            Debug.Assert(oNodePair.ParseTreeNode != null);
            Debug.Assert(oNodePair.FindPatternNode != null);
            Debug.Assert(oNodePair.ParseTreeNode != CurrentParseTreeNode);
            Debug.Assert(oNodePair.FindPatternNode != FindPatternRoot);

            SyntaxNodePair oSiblingPair = new SyntaxNodePair();

            oSiblingPair.ParseTreeNode
                = oNodePair.ParseTreeNode.NextSibling;
            oSiblingPair.FindPatternNode
                = oNodePair.FindPatternNode.NextSibling;
            return(oSiblingPair);
        }
コード例 #7
0
        //******************************************************************
        #region [SkipOptionalNode() Method]
        //******************************************************************
        /// <summary>
        /// Returns a new node pair containing the same ParseTreeNode as the
        /// given oNodePair and the next sibling of the FindPatternNode from
        /// the given oNodePair. (The given oNodePair.FindPatternNode must
        /// be an optional node, so by moving to its next sibling we skip
        /// the optional node.)
        /// </summary>
        private SyntaxNodePair SkipOptionalNode(SyntaxNodePair oNodePair)
        {
            Debug.Assert(oNodePair != null);
            Debug.Assert(oNodePair.FindPatternNode != null);
            Debug.Assert(oNodePair.FindPatternNode.IsOptionalNode);
            Debug.Assert(oNodePair.FindPatternNode != FindPatternRoot);

            SyntaxNodePair oNextNodePair = new SyntaxNodePair();

            oNextNodePair.ParseTreeNode
                = oNodePair.ParseTreeNode;
            oNextNodePair.FindPatternNode
                = oNodePair.FindPatternNode.NextSibling;

            Debug.WriteLineIf(VerboseDebugging,
                              "Skipping optional node....");

            return(oNextNodePair);
        }
コード例 #8
0
        //******************************************************************
        /// <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;
        }
コード例 #9
0
        //******************************************************************
        #region [LeafChildrenMatch() Method]
        //******************************************************************
        /// <summary>
        /// Compares each child of oNodePair.ParseTreeNode by making
        /// recursive calls to FeaturesAndChildrenMatch() to see if it
        /// matches any child of oNodePair.FindPatternNode. Returns true if
        /// at least one child pair matched successfully. Returns false
        /// otherwise. (This is not an ordered comparison. The given
        /// oNodePair.ParseTreeNode must be a syntax leaf.)
        /// </summary>
        private bool LeafChildrenMatch(SyntaxNodePair oNodePair)
        {
            Debug.Assert(oNodePair != null);
            Debug.Assert(oNodePair.ParseTreeNode != null);
            Debug.Assert(oNodePair.FindPatternNode != null);
            Debug.Assert(oNodePair.ParseTreeNode.IsSyntaxLeaf);
            Debug.Assert(oNodePair.FindPatternNode.ChildNodes.Count > 0);

            //**************************************************************
            // Since oNodePair.ParseTreeNode is a syntax leaf, each of its
            // children is the root of a morphology parse. (A syntax leaf
            // may have one or more alternative morphology parses.)
            //
            // For each of these morphology-parse children of
            // oNodePair.ParseTreeNode, see if it matches any child of
            // oNodePair.FindPatternNode. If so, increment the counter.

            int iMatchCount = 0;

            foreach (SyntaxNode oParseChild in
                     oNodePair.ParseTreeNode.ChildNodes)
            {
                //**********************************************************
                // Loop through the oNodePair.FindPatternNode children.
                // Stop if we find a match to the morphology-parse child of
                // oNodePair.ParseTreeNode.

                SyntaxNode oFindChild
                    = oNodePair.FindPatternNode.FirstChild;
                while (oFindChild != null)
                {
                    SyntaxNodePair oChildPair = new SyntaxNodePair();
                    oChildPair.ParseTreeNode   = oParseChild;
                    oChildPair.FindPatternNode = oFindChild;
                    if (FeaturesAndChildrenMatch(oChildPair))
                    {
                        //**************************************************
                        // Found a match. Increment the counter and end the
                        // loop (by setting oFindChild to null).

                        ++iMatchCount;
                        oFindChild = null;
                    }
                    else
                    {
                        //**************************************************
                        // Continue looping (by setting oFindChild to the
                        // next sibling).

                        Debug.Assert(oFindChild != FindPatternRoot);

                        oFindChild = oFindChild.NextSibling;
                    }
                }
            }

            //**************************************************************
            // If at least one child of oNodePair.ParseTreeNode matched,
            // return true. Otherwise, return false.

            if (iMatchCount > 0)
            {
                return(true);
            }
            return(false);
        }
コード例 #10
0
        //******************************************************************
        #region [NodeChildrenMatch() Method]
        //******************************************************************
        // EXAMPLE WALKTHROUGH OF BACKTRACKING
        //
        // Suppose NodeChildrenMatch() is called with the following state:
        //
        // MatchingNodes = {(VP,VP)}
        // oNodePair.ParseTreeNode.ChildNodes = {V,PP}
        // oNodePair.FindPatternNode.ChildNodes = {V,(NP),(PP),PP}
        //
        // 1. Compare the first child pair (V,V). They match, so push the
        // pair onto the stack and move to the next sibling pair (PP,(NP)).
        // The stack now contains:
        //
        // MatchingNodes = {(V,V)(VP,VP)}
        //
        // 2. Compare the child pair (PP,(NP)). They do not match. Since
        // (NP) is optional, skip this node to get the next child pair to
        // compare (PP,(PP)).
        //
        // 3. Compare the child pair (PP,(PP)). They match, so push the pair
        // onto the stack and move to the next sibling pair (null,PP). The
        // stack now contains:
        //
        // MatchingNodes = {(PP,(PP))(V,V)(VP,VP)}
        //
        // 4. Compare the child pair (null,PP). They do not match. Since PP
        // is not optional, we need to backtrack to find a child pair with
        // an optional find-pattern node. The child pair (PP,(PP)) is found
        // on the stack. Skip the optional node to get the next child pair
        // to compare (PP,PP). Backtracking removed one pair from the stack:
        //
        // MatchingNodes = {(V,V)(VP,VP)}
        //
        // 5. Compare the child pair (PP,PP). They match, so push the pair
        // onto the stack and move to the next sibling pair (null,null). The
        // stack now contains:
        //
        // MatchingNodes = {(PP,PP)(V,V)(VP,VP)}
        //
        // 6. We reached the end of both ChildNodes collections at the same
        // time. This means we successfully matched all the children, so
        // return true.
        //******************************************************************
        /// <summary>
        /// Compares the children of oNodePair.ParseTreeNode to the children
        /// of oNodePair.FindPatternNode by making recursive calls to
        /// FeaturesAndChildrenMatch() for each pair of child nodes.
        /// Backtracks and/or skips optional nodes if necessary to find
        /// matching pairs of child nodes. Returns true if all the children
        /// are matched successfully. Returns false otherwise. (This is an
        /// ordered comparison. The given oNodePair.ParseTreeNode must not
        /// be a syntax leaf.)
        /// </summary>
        private bool NodeChildrenMatch(SyntaxNodePair oNodePair)
        {
            Debug.Assert(oNodePair != null);
            Debug.Assert(oNodePair.ParseTreeNode != null);
            Debug.Assert(oNodePair.FindPatternNode != null);
            Debug.Assert(!oNodePair.ParseTreeNode.IsSyntaxLeaf);
            Debug.Assert(oNodePair.FindPatternNode.ChildNodes.Count > 0);

            //**************************************************************
            // Iterate through the children of the oNodePair.ParseTreeNode
            // and the children of the oNodePair.FindPatternNode, starting
            // with the first child in each collection.
            //
            // For each child pair, compare their features and children.
            //
            // If the pair matches:
            //
            //     Get the next child pair to compare by moving forward to
            //     the next sibling in each collection.
            //
            // Otherwise:
            //
            //     Get the next child pair to compare by backtracking and/or
            //     skipping an optional node.
            //
            // If we reach the end of both collections at the same time (the
            // child ParseTreeNode and the child FindPatternNode are both
            // null), we have successfully matched all the children.

            SyntaxNodePair oChildPair = FirstChildNodePair(oNodePair);

            while ((oChildPair.ParseTreeNode != null) ||
                   (oChildPair.FindPatternNode != null))
            {
                if (FeaturesAndChildrenMatch(oChildPair))
                {
                    //******************************************************
                    // The pair matches.
                    //
                    // Move forward to the next sibling pair.

                    oChildPair = NextSiblingNodePair(oChildPair);
                }
                else
                {
                    //******************************************************
                    // The pair does not match.
                    //
                    // Try to find another child pair to compare by skipping
                    // an optional node.
                    //
                    // If the child FindPatternNode is not optional, we need
                    // to backtrack to a node pair on the stack that (1) is
                    // a child of oNodePair and (2) has a FindPatternNode
                    // that is optional. If backtracking fails to find such
                    // a node pair, return false.
                    //
                    // Once we have a child FindPatternNode that is
                    // optional, skip the optional node to get the next
                    // child pair to compare.

                    bool bChildFindPatternNodeIsOptional = false;
                    if (oChildPair.FindPatternNode != null)
                    {
                        if (oChildPair.FindPatternNode.IsOptionalNode)
                        {
                            bChildFindPatternNodeIsOptional = true;
                        }
                    }
                    if (!bChildFindPatternNodeIsOptional)
                    {
                        oChildPair = BacktrackToOptionalNode(oNodePair);
                        if (oChildPair == null)
                        {
                            return(false);
                        }
                    }

                    Debug.Assert(oChildPair.FindPatternNode != null);
                    Debug.Assert(oChildPair.FindPatternNode.IsOptionalNode);

                    oChildPair = SkipOptionalNode(oChildPair);
                }
            }

            //**************************************************************
            // We have successfully matched all the children, so return
            // true.

            return(true);
        }
コード例 #11
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);
        }
コード例 #12
0
        //******************************************************************
        #region [CopyLeafAndChildren() Method]
        //******************************************************************
        /// <summary>
        /// For the given oReplacePatternNode, this method finds the
        /// corresponding find-pattern node and the parse-tree node it
        /// matched. A new node is created by copying features from the
        /// parse-tree node and merging features from the
        /// oReplacePatternNode. Then children are copied recursively from
        /// the parse-tree node. Children are also copied recursively from
        /// the oReplacePatternNode if they do not correspond to children of
        /// the parse-tree node. Returns null if the oReplacePatternNode was
        /// optional and the parse-tree node was not found. Otherwise,
        /// returns the new node after adding it to the ReplacedNodes list.
        /// (Note that this method is only for copying leaf nodes.)
        /// </summary>
        SyntaxNode CopyLeafAndChildren(SyntaxNode oReplacePatternNode)
        {
            Debug.Assert(oReplacePatternNode != null);

            //**************************************************************
            // For the given oReplacePatternNode, find the corresponding
            // find-pattern node and the parse-tree node it matched:
            //
            // Search the MatchingNodes list for a node pair where the
            // .FindPatternNode has the same label as the given
            // oReplacePatternNode.
            //
            // If a matching node pair is found, set oParseTreeNode and
            // oFindPatternNode to the node-pair values. Otherwise, set
            // oParseTreeNode and oFindPatternNode both to null.

            SyntaxNode     oParseTreeNode   = null;
            SyntaxNode     oFindPatternNode = null;
            SyntaxNodePair oNodePair        =
                FindMatchingPairFromLabel(oReplacePatternNode.Label);

            if (oNodePair != null)
            {
                oParseTreeNode   = oNodePair.ParseTreeNode;
                oFindPatternNode = oNodePair.FindPatternNode;
            }

            //**************************************************************
            // If a matching node pair was not found and oReplacePatternNode
            // is optional, nothing will be copied, so return null.

            if ((oNodePair == null) && (oReplacePatternNode.IsOptionalNode))
            {
                return(null);
            }

            //**************************************************************
            // This method should only be called for leaf nodes.

            if (oParseTreeNode != null)
            {
                Debug.Assert(oParseTreeNode.IsSyntaxLeaf ||
                             oReplacePatternNode.IsSyntaxLeaf);
            }
            else
            {
                Debug.Assert(oReplacePatternNode.IsSyntaxLeaf);
            }

            //**************************************************************
            // Create a new parse-tree node by copying the features from the
            // matching oParseTreeNode (if found) and then merging the
            // features from oReplacePatternNode.

            if (VerboseDebugging)
            {
                string sParseString = "null";
                if (oParseTreeNode != null)
                {
                    sParseString = oParseTreeNode.ToString();
                }
                string sReplaceString = "null";
                if (oReplacePatternNode != null)
                {
                    sReplaceString = oReplacePatternNode.ToString();
                }
                Debug.WriteLine("Copying leaf: CopyFeatures("
                                + sParseString + "," + sReplaceString + ").");
            }

            SyntaxNode oNewNode
                = CopyFeatures(oParseTreeNode, oReplacePatternNode);

            //**************************************************************
            // Each child of a syntax leaf is the root of a morphology
            // parse. (A syntax leaf may have one or more alternative
            // morphology parses.)
            //
            // Each child will be copied recursively from oParseTreeNode.
            // Additional children will also be copied recursively from
            // oReplacePatternNode if they do not correspond to children of
            // oParseTreeNode.
            //
            // Create a list to keep track of the oReplacePatternNode
            // children as they are used. (A replace-pattern child is marked
            // as used if it has the same label as a find-pattern child
            // matching one of the oParseTreeNode children.)

            ArrayList oUsedReplaceChildren = new ArrayList();

            //**************************************************************
            // Copy the oParseTreeNode children.

            if (oParseTreeNode != null)
            {
                foreach (SyntaxNode oParseChild in
                         oParseTreeNode.ChildNodes)
                {
                    //******************************************************
                    // Look for the find-pattern node that matched this
                    // parse-tree child:
                    //
                    // Search the MatchingNodes list for a node pair where
                    // the .ParseTreeNode is the same as oParseChild.
                    //
                    // If found, set oFindChild to the .FindPatternNode
                    // value from the node pair. Otherwise, set oFindChild
                    // to null.

                    SyntaxNodePair oChildNodePair
                        = FindMatchingPairFromNode(oParseChild);
                    SyntaxNode oFindChild = null;
                    if (oChildNodePair != null)
                    {
                        oFindChild = oChildNodePair.FindPatternNode;
                    }

                    //******************************************************
                    // If oFindChild is null (no find-pattern matched
                    // this parse-tree child), copy oParseChild.
                    //
                    // Otherwise, copy each oReplacePatternNode child that
                    // has the same label as oFindChild.

                    if (oFindChild == null)
                    {
                        //**************************************************
                        // Copy oParseChild.

                        SyntaxNode oNewChild = oParseChild.CloneBranch();
                        oNewNode.ChildNodes.Add(oNewChild);
                    }
                    else
                    {
                        //**************************************************
                        // Copy each oReplacePatternNode child that has the
                        // same label as oFindChild.

                        foreach (SyntaxNode oReplaceChild in
                                 oReplacePatternNode.ChildNodes)
                        {
                            if (oReplaceChild.Label == oFindChild.Label)
                            {
                                //******************************************
                                // Copy the oReplacePatternNode child.
                                //
                                // Since oParseTreeNode is a syntax leaf,
                                // each of its children is the root of a
                                // morphology parse. So oParseChild is used
                                // as the oMorphologyParseRoot argument to
                                // the CopyNodeAndChildren() method.

                                SyntaxNode oNewChild = CopyNodeAndChildren(
                                    oReplaceChild, oParseChild);
                                if (oNewChild != null)
                                {
                                    oNewNode.ChildNodes.Add(oNewChild);
                                }

                                //******************************************
                                // Add this oReplaceChild to the list of
                                // oUsedReplaceChildren (if not already
                                // there).

                                if (!oUsedReplaceChildren
                                    .Contains(oReplaceChild))
                                {
                                    oUsedReplaceChildren.Add(oReplaceChild);
                                }
                            }
                        }
                    }
                }
            }

            //**************************************************************
            // Copy any oReplacePatternNode children that have not yet been
            // used.

            foreach (SyntaxNode oReplaceChild in
                     oReplacePatternNode.ChildNodes)
            {
                if (!oUsedReplaceChildren.Contains(oReplaceChild))
                {
                    SyntaxNode oNewChild =
                        CopyNodeAndChildren(oReplaceChild);
                    if (oNewChild != null)
                    {
                        oNewNode.ChildNodes.Add(oNewChild);
                    }
                }
            }

            //**************************************************************
            // Return the new parse-tree node after adding it to the
            // ReplacedNodes list.

            SyntaxNodeTriple oNodeTriple = new SyntaxNodeTriple();

            oNodeTriple.ParseTreeNode      = oNewNode;
            oNodeTriple.FindPatternNode    = oFindPatternNode;
            oNodeTriple.ReplacePatternNode = oReplacePatternNode;
            ReplacedNodes.Push(oNodeTriple);
            return(oNewNode);
        }
コード例 #13
0
        //******************************************************************
        /// <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;
        }
コード例 #14
0
        //******************************************************************
        #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);
        }
コード例 #15
0
        //******************************************************************
        // EXAMPLE WALKTHROUGH OF BACKTRACKING
        //
        // Suppose NodeChildrenMatch() is called with the following state:
        //
        // MatchingNodes = {(VP,VP)}
        // oNodePair.ParseTreeNode.ChildNodes = {V,PP}
        // oNodePair.FindPatternNode.ChildNodes = {V,(NP),(PP),PP}
        //
        // 1. Compare the first child pair (V,V). They match, so push the
        // pair onto the stack and move to the next sibling pair (PP,(NP)).
        // The stack now contains:
        //
        // MatchingNodes = {(V,V)(VP,VP)}
        //
        // 2. Compare the child pair (PP,(NP)). They do not match. Since
        // (NP) is optional, skip this node to get the next child pair to
        // compare (PP,(PP)).
        //
        // 3. Compare the child pair (PP,(PP)). They match, so push the pair
        // onto the stack and move to the next sibling pair (null,PP). The
        // stack now contains:
        //
        // MatchingNodes = {(PP,(PP))(V,V)(VP,VP)}
        //
        // 4. Compare the child pair (null,PP). They do not match. Since PP
        // is not optional, we need to backtrack to find a child pair with
        // an optional find-pattern node. The child pair (PP,(PP)) is found
        // on the stack. Skip the optional node to get the next child pair
        // to compare (PP,PP). Backtracking removed one pair from the stack:
        //
        // MatchingNodes = {(V,V)(VP,VP)}
        //
        // 5. Compare the child pair (PP,PP). They match, so push the pair
        // onto the stack and move to the next sibling pair (null,null). The
        // stack now contains:
        //
        // MatchingNodes = {(PP,PP)(V,V)(VP,VP)}
        //
        // 6. We reached the end of both ChildNodes collections at the same
        // time. This means we successfully matched all the children, so
        // return true.
        //******************************************************************
        /// <summary>
        /// Compares the children of oNodePair.ParseTreeNode to the children
        /// of oNodePair.FindPatternNode by making recursive calls to
        /// FeaturesAndChildrenMatch() for each pair of child nodes.
        /// Backtracks and/or skips optional nodes if necessary to find
        /// matching pairs of child nodes. Returns true if all the children
        /// are matched successfully. Returns false otherwise. (This is an
        /// ordered comparison. The given oNodePair.ParseTreeNode must not
        /// be a syntax leaf.)
        /// </summary>
        private bool NodeChildrenMatch(SyntaxNodePair oNodePair)
        {
            Debug.Assert(oNodePair != null);
            Debug.Assert(oNodePair.ParseTreeNode != null);
            Debug.Assert(oNodePair.FindPatternNode != null);
            Debug.Assert(! oNodePair.ParseTreeNode.IsSyntaxLeaf);
            Debug.Assert(oNodePair.FindPatternNode.ChildNodes.Count > 0);

            //**************************************************************
            // Iterate through the children of the oNodePair.ParseTreeNode
            // and the children of the oNodePair.FindPatternNode, starting
            // with the first child in each collection.
            //
            // For each child pair, compare their features and children.
            //
            // If the pair matches:
            //
            //     Get the next child pair to compare by moving forward to
            //     the next sibling in each collection.
            //
            // Otherwise:
            //
            //     Get the next child pair to compare by backtracking and/or
            //     skipping an optional node.
            //
            // If we reach the end of both collections at the same time (the
            // child ParseTreeNode and the child FindPatternNode are both
            // null), we have successfully matched all the children.

            SyntaxNodePair oChildPair = FirstChildNodePair(oNodePair);
            while ((oChildPair.ParseTreeNode != null)
                || (oChildPair.FindPatternNode != null))
            {
                if (FeaturesAndChildrenMatch(oChildPair))
                {
                    //******************************************************
                    // The pair matches.
                    //
                    // Move forward to the next sibling pair.

                    oChildPair = NextSiblingNodePair(oChildPair);
                }
                else
                {
                    //******************************************************
                    // The pair does not match.
                    //
                    // Try to find another child pair to compare by skipping
                    // an optional node.
                    //
                    // If the child FindPatternNode is not optional, we need
                    // to backtrack to a node pair on the stack that (1) is
                    // a child of oNodePair and (2) has a FindPatternNode
                    // that is optional. If backtracking fails to find such
                    // a node pair, return false.
                    //
                    // Once we have a child FindPatternNode that is
                    // optional, skip the optional node to get the next
                    // child pair to compare.

                    bool bChildFindPatternNodeIsOptional = false;
                    if (oChildPair.FindPatternNode != null)
                    {
                        if (oChildPair.FindPatternNode.IsOptionalNode)
                        {
                            bChildFindPatternNodeIsOptional = true;
                        }
                    }
                    if (! bChildFindPatternNodeIsOptional)
                    {
                        oChildPair = BacktrackToOptionalNode(oNodePair);
                        if (oChildPair == null)
                        {
                            return false;
                        }
                    }

                    Debug.Assert(oChildPair.FindPatternNode != null);
                    Debug.Assert(oChildPair.FindPatternNode.IsOptionalNode);

                    oChildPair = SkipOptionalNode(oChildPair);
                }
            }

            //**************************************************************
            // We have successfully matched all the children, so return
            // true.

            return true;
        }
コード例 #16
0
        //******************************************************************
        /// <summary>
        /// Returns a new node pair containing the next sibling of the
        /// ParseTreeNode and the next sibling of the FindPatternNode from
        /// the given oNodePair.
        /// </summary>
        private SyntaxNodePair NextSiblingNodePair(SyntaxNodePair oNodePair)
        {
            Debug.Assert(oNodePair != null);
            Debug.Assert(oNodePair.ParseTreeNode != null);
            Debug.Assert(oNodePair.FindPatternNode != null);
            Debug.Assert(oNodePair.ParseTreeNode != CurrentParseTreeNode);
            Debug.Assert(oNodePair.FindPatternNode != FindPatternRoot);

            SyntaxNodePair oSiblingPair = new SyntaxNodePair();
            oSiblingPair.ParseTreeNode
                = oNodePair.ParseTreeNode.NextSibling;
            oSiblingPair.FindPatternNode
                = oNodePair.FindPatternNode.NextSibling;
            return oSiblingPair;
        }
コード例 #17
0
        //******************************************************************
        /// <summary>
        /// Compares each child of oNodePair.ParseTreeNode by making
        /// recursive calls to FeaturesAndChildrenMatch() to see if it
        /// matches any child of oNodePair.FindPatternNode. Returns true if
        /// at least one child pair matched successfully. Returns false
        /// otherwise. (This is not an ordered comparison. The given
        /// oNodePair.ParseTreeNode must be a syntax leaf.)
        /// </summary>
        private bool LeafChildrenMatch(SyntaxNodePair oNodePair)
        {
            Debug.Assert(oNodePair != null);
            Debug.Assert(oNodePair.ParseTreeNode != null);
            Debug.Assert(oNodePair.FindPatternNode != null);
            Debug.Assert(oNodePair.ParseTreeNode.IsSyntaxLeaf);
            Debug.Assert(oNodePair.FindPatternNode.ChildNodes.Count > 0);

            //**************************************************************
            // Since oNodePair.ParseTreeNode is a syntax leaf, each of its
            // children is the root of a morphology parse. (A syntax leaf
            // may have one or more alternative morphology parses.)
            //
            // For each of these morphology-parse children of
            // oNodePair.ParseTreeNode, see if it matches any child of
            // oNodePair.FindPatternNode. If so, increment the counter.

            int iMatchCount = 0;
            foreach (SyntaxNode oParseChild in
                oNodePair.ParseTreeNode.ChildNodes)
            {
                //**********************************************************
                // Loop through the oNodePair.FindPatternNode children.
                // Stop if we find a match to the morphology-parse child of
                // oNodePair.ParseTreeNode.

                SyntaxNode oFindChild
                    = oNodePair.FindPatternNode.FirstChild;
                while (oFindChild != null)
                {
                    SyntaxNodePair oChildPair = new SyntaxNodePair();
                    oChildPair.ParseTreeNode = oParseChild;
                    oChildPair.FindPatternNode = oFindChild;
                    if (FeaturesAndChildrenMatch(oChildPair))
                    {
                        //**************************************************
                        // Found a match. Increment the counter and end the
                        // loop (by setting oFindChild to null).

                        ++iMatchCount;
                        oFindChild = null;
                    }
                    else
                    {
                        //**************************************************
                        // Continue looping (by setting oFindChild to the
                        // next sibling).

                        Debug.Assert(oFindChild != FindPatternRoot);

                        oFindChild = oFindChild.NextSibling;
                    }
                }
            }

            //**************************************************************
            // If at least one child of oNodePair.ParseTreeNode matched,
            // return true. Otherwise, return false.

            if (iMatchCount > 0)
            {
                return true;
            }
            return false;
        }
コード例 #18
0
        //******************************************************************
        /// <summary>
        /// Returns a new node pair containing the first child of the
        /// ParseTreeNode and the first child of the FindPatternNode from
        /// the given oNodePair.
        /// </summary>
        private SyntaxNodePair FirstChildNodePair(SyntaxNodePair oNodePair)
        {
            Debug.Assert(oNodePair != null);
            Debug.Assert(oNodePair.ParseTreeNode != null);
            Debug.Assert(oNodePair.FindPatternNode != null);

            SyntaxNodePair oChildPair = new SyntaxNodePair();
            oChildPair.ParseTreeNode
                = oNodePair.ParseTreeNode.FirstChild;
            oChildPair.FindPatternNode
                = oNodePair.FindPatternNode.FirstChild;
            return oChildPair;
        }
コード例 #19
0
        //******************************************************************
        /// <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;
        }
コード例 #20
0
        //******************************************************************
        /// <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;
        }
コード例 #21
0
        //******************************************************************
        /// <summary>
        /// Inserts an item at the top of the stack.
        /// </summary>
        public void Push(SyntaxNodePair oNodePair)
        {
            Debug.Assert(oNodePair != null);

            if (oNodePair == null)
            {
                string sMessage = "Invalid argument: "
                    + "SyntaxNodePairStack cannot push a null item.";
                throw new Exception(sMessage);
            }

            InnerList.Add(oNodePair);
        }
コード例 #22
0
        //******************************************************************
        /// <summary>
        /// For the given oReplacePatternNode, this method finds the
        /// corresponding find-pattern node and the parse-tree node it
        /// matched. (The parse-tree node must be in the branch indicated by
        /// oMorphologyParseRoot if this optional argument is not null.) A
        /// new node is created by copying features from the parse-tree node
        /// and merging features from the oReplacePatternNode. Then children
        /// are copied recursively either from the parse-tree node or from
        /// the oReplacePatternNode. Returns null if the oReplacePatternNode
        /// was optional and the parse-tree node was not found. Otherwise,
        /// returns the new node after adding it to the ReplacedNodes list.
        /// (Note that this method calls the CopyLeafAndChildren() method if
        /// it determines that the node is a leaf node.)
        /// </summary>
        SyntaxNode CopyNodeAndChildren(SyntaxNode oReplacePatternNode,
                                       SyntaxNode oMorphologyParseRoot)
        {
            Debug.Assert(oReplacePatternNode != null);

            //**************************************************************
            // For the given oReplacePatternNode, find the corresponding
            // find-pattern node and the parse-tree node it matched:
            //
            // Search the MatchingNodes list for a node pair where the
            // .FindPatternNode has the same label as the given
            // oReplacePatternNode.
            //
            // If oMorphologyParseRoot is not null, restrict this search to
            // node pairs where the .ParseTreeNode is contained in the
            // branch dominated by this oMorphologyParseRoot.
            //
            // If a matching node pair is found, set oParseTreeNode and
            // oFindPatternNode to the node-pair values. Otherwise, set
            // oParseTreeNode and oFindPatternNode both to null.

            SyntaxNode     oParseTreeNode   = null;
            SyntaxNode     oFindPatternNode = null;
            SyntaxNodePair oNodePair        = FindMatchingPairFromLabel(
                oReplacePatternNode.Label, oMorphologyParseRoot);

            if (oNodePair != null)
            {
                oParseTreeNode   = oNodePair.ParseTreeNode;
                oFindPatternNode = oNodePair.FindPatternNode;
            }

            //**************************************************************
            // If a matching node pair was not found and oReplacePatternNode
            // is optional, nothing will be copied, so return null.

            if ((oNodePair == null) && (oReplacePatternNode.IsOptionalNode))
            {
                return(null);
            }

            //**************************************************************
            // If this is a leaf node, call CopyLeafAndChildren() instead.
            //
            // Each child of a syntax leaf is the root of a morphology
            // parse. (A syntax leaf may have one or more alternative
            // morphology parses.) CopyLeafAndChildren() is called because
            // a different algorithm is needed to copy these children.

            bool bIsSyntaxLeaf = false;

            if (oParseTreeNode != null)
            {
                if (oParseTreeNode.IsSyntaxLeaf)
                {
                    bIsSyntaxLeaf = true;
                }
            }
            if (oReplacePatternNode.IsSyntaxLeaf)
            {
                bIsSyntaxLeaf = true;
            }
            if (bIsSyntaxLeaf)
            {
                return(CopyLeafAndChildren(oReplacePatternNode));
            }

            //**************************************************************
            // Create a new parse-tree node by copying the features from the
            // matching oParseTreeNode (if found) and then merging the
            // features from oReplacePatternNode.

            if (VerboseDebugging)
            {
                string sParseString = "null";
                if (oParseTreeNode != null)
                {
                    sParseString = oParseTreeNode.ToString();
                }
                string sReplaceString = "null";
                if (oReplacePatternNode != null)
                {
                    sReplaceString = oReplacePatternNode.ToString();
                }
                Debug.WriteLine("Copying node: CopyFeatures("
                                + sParseString + "," + sReplaceString + ").");
            }

            SyntaxNode oNewNode
                = CopyFeatures(oParseTreeNode, oReplacePatternNode);

            //**************************************************************
            // Check if any children are specified by oFindPatternNode or
            // oReplacePatternNode.

            bool bFindPatternHasChildren = false;

            if (oFindPatternNode != null)
            {
                if (oFindPatternNode.ChildNodes.Count > 0)
                {
                    bFindPatternHasChildren = true;
                }
            }
            bool bReplacePatternHasChildren = false;

            if (oReplacePatternNode.ChildNodes.Count > 0)
            {
                bReplacePatternHasChildren = true;
            }

            //**************************************************************
            // Copy children either from the matching oParseTreeNode or from
            // the oReplacePatternNode:
            //
            // If oParseTreeNode is not null and no children are specified
            // by oFindPatternNode or oReplacePatternNode, copy the
            // oParseTreeNode children.
            //
            // Otherwise, copy the oReplacePatternNode children.

            if ((oParseTreeNode != null) && (!bFindPatternHasChildren) &&
                (!bReplacePatternHasChildren))
            {
                //**********************************************************
                // Copy the oParseTreeNode children.

                foreach (SyntaxNode oParseChild in
                         oParseTreeNode.ChildNodes)
                {
                    SyntaxNode oNewChild = oParseChild.CloneBranch();
                    oNewNode.ChildNodes.Add(oNewChild);
                }
            }
            else
            {
                //**********************************************************
                // Copy the oReplacePatternNode children.

                foreach (SyntaxNode oReplaceChild in
                         oReplacePatternNode.ChildNodes)
                {
                    SyntaxNode oNewChild = CopyNodeAndChildren(
                        oReplaceChild, oMorphologyParseRoot);
                    if (oNewChild != null)
                    {
                        oNewNode.ChildNodes.Add(oNewChild);
                    }
                }
            }

            //**************************************************************
            // Return the new parse-tree node after adding it to the
            // ReplacedNodes list.

            SyntaxNodeTriple oNodeTriple = new SyntaxNodeTriple();

            oNodeTriple.ParseTreeNode      = oNewNode;
            oNodeTriple.FindPatternNode    = oFindPatternNode;
            oNodeTriple.ReplacePatternNode = oReplacePatternNode;
            ReplacedNodes.Push(oNodeTriple);
            return(oNewNode);
        }
コード例 #23
0
        //******************************************************************
        /// <summary>
        /// Returns a new node pair containing the same ParseTreeNode as the
        /// given oNodePair and the next sibling of the FindPatternNode from
        /// the given oNodePair. (The given oNodePair.FindPatternNode must
        /// be an optional node, so by moving to its next sibling we skip
        /// the optional node.)
        /// </summary>
        private SyntaxNodePair SkipOptionalNode(SyntaxNodePair oNodePair)
        {
            Debug.Assert(oNodePair != null);
            Debug.Assert(oNodePair.FindPatternNode != null);
            Debug.Assert(oNodePair.FindPatternNode.IsOptionalNode);
            Debug.Assert(oNodePair.FindPatternNode != FindPatternRoot);

            SyntaxNodePair oNextNodePair = new SyntaxNodePair();
            oNextNodePair.ParseTreeNode
                = oNodePair.ParseTreeNode;
            oNextNodePair.FindPatternNode
                = oNodePair.FindPatternNode.NextSibling;

            Debug.WriteLineIf(VerboseDebugging,
                "Skipping optional node....");

            return oNextNodePair;
        }
コード例 #24
0
        //******************************************************************
        /// <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.");
        }
コード例 #25
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);
        }
コード例 #26
0
        //******************************************************************
        /// <summary>
        /// Creates a branch of SyntaxNode objects representing the nodes
        /// and features displayed by the given oTreeNode and its children
        /// (recursively). If the optional oTreeTransfer argument is given,
        /// its CurrentParseTreeNode is set to indicate the selected node
        /// (if any) in the branch, and items are added to its MatchingNodes
        /// and ReplacedNodes collections to indicate highlighted nodes in
        /// the branch. The root node of the created SyntaxNode branch is
        /// returned.
        /// </summary>
        private SyntaxNode CloneBranch(TreeViewerNode oTreeNode,
			TreeTransfer oTreeTransfer)
        {
            Debug.Assert(oTreeNode != null);
            Debug.Assert(oTreeTransfer != null);

            //**************************************************************
            // Clone the SyntaxNode branch associated with the given
            // oTreeNode.

            SyntaxNode oSyntaxNode = CloneNode(oTreeNode);

            //**************************************************************
            // The oTreeNode can have child nodes. Or the oSyntaxNode can
            // have child nodes (representing morphology nodes that were not
            // shown). But the oTreeNode and oSyntaxNode cannot both have
            // child nodes.

            if (oTreeNode.ChildNodes.Count > 0)
            {
                Debug.Assert(oSyntaxNode.ChildNodes.Count == 0);
            }
            if (oSyntaxNode.ChildNodes.Count > 0)
            {
                Debug.Assert(oTreeNode.ChildNodes.Count == 0);
            }

            //**************************************************************
            // Recursively clone each child branch of oTreeNode, and add
            // each cloned branch as a child of oSyntaxNode.

            foreach (TreeViewerNode oTreeChild in oTreeNode.ChildNodes)
            {
                SyntaxNode oSyntaxChild
                    = CloneBranch(oTreeChild,oTreeTransfer);
                oSyntaxNode.ChildNodes.Add(oSyntaxChild);
            }

            //**************************************************************
            // If this node is the SelectedNode, set the
            // oTreeTransfer.CurrentParseTreeNode property to indicate this
            // node.

            if (oTreeNode == moTreeViewer.SelectedNode)
            {
                oTreeTransfer.CurrentParseTreeNode = oSyntaxNode;
            }

            //**************************************************************
            // If this node is highlighted as a matching node, add an item
            // indicating this node to the oTreeTransfer.MatchingNodes
            // collection.
            //
            // If this node is highlighted as a replaced node, add an item
            // indicating this node to the oTreeTransfer.ReplacedNodes
            // collection.

            if ((! DisplayFindPattern) && (! DisplayReplacePattern))
            {
                if (oTreeNode.BackColor == FindPatternColor)
                {
                    SyntaxNodePair oNodePair = new SyntaxNodePair();
                    oNodePair.ParseTreeNode = oSyntaxNode;
                    oTreeTransfer.MatchingNodes.Push(oNodePair);
                }
                if (oTreeNode.BackColor == ReplacePatternColor)
                {
                    SyntaxNodeTriple oNodeTriple = new SyntaxNodeTriple();
                    oNodeTriple.ParseTreeNode = oSyntaxNode;
                    oTreeTransfer.ReplacedNodes.Push(oNodeTriple);
                }
            }

            //**************************************************************
            // Return the cloned SyntaxNode branch.

            return oSyntaxNode;
        }