//****************************************************************** #region [Pop() Method] //****************************************************************** /// <summary> /// Removes and returns the item at the top of the stack. /// </summary> public SyntaxNodeTriple Pop() { Debug.Assert(InnerList.Count > 0); SyntaxNodeTriple oNodeTriple = (SyntaxNodeTriple)InnerList[InnerList.Count - 1]; InnerList.RemoveAt(InnerList.Count - 1); return(oNodeTriple); }
//****************************************************************** #region [Push() Method] //****************************************************************** /// <summary> /// Inserts an item at the top of the stack. /// </summary> public void Push(SyntaxNodeTriple oNodeTriple) { Debug.Assert(oNodeTriple != null); if (oNodeTriple == null) { string sMessage = "Invalid argument: " + "SyntaxNodeTripleStack cannot push a null item."; throw new Exception(sMessage); } InnerList.Add(oNodeTriple); }
//****************************************************************** /// <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; }
//****************************************************************** /// <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; }
//****************************************************************** /// <summary> /// Replaces the sub-tree dominated by the CurrentParseTreeNode, /// using the tree dominated by the ReplacePatternRoot as a pattern. /// Corresponding nodes (matched by a find-pattern node with the /// same label as the replace-pattern node) are copied from the /// MatchingNodes stack and their features are merged with features /// from the replace pattern. The replaced nodes in the new sub-tree /// are also stored in the ReplacedNodes stack. /// </summary> public void ReplaceCurrentMatchingBranch() { Debug.WriteLineIf(VerboseDebugging, "ReplaceAlgorithm.ReplaceCurrentMatchingBranch() called."); //************************************************************** // Validate the current state. if (ParseTreeRoot == null) { string sMessage = "ReplaceCurrentMatchingBranch() " + "called with an invalid state: " + "ParseTreeRoot is null."; throw new Exception(sMessage); } if (MatchingNodes.Count < 1) { string sMessage = "ReplaceCurrentMatchingBranch() " + "called with an invalid state: " + "MatchingNodes is empty."; throw new Exception(sMessage); } foreach (SyntaxNodePair oNodePair in MatchingNodes) { if (oNodePair.ParseTreeNode == null) { string sMessage = "ReplaceCurrentMatchingBranch() " + "called with an invalid state: " + "MatchingNodes contains an item where " + ".ParseTreeNode is null."; throw new Exception(sMessage); } if (oNodePair.FindPatternNode == null) { string sMessage = "ReplaceCurrentMatchingBranch() " + "called with an invalid state: " + "MatchingNodes contains an item where " + ".FindPatternNode is null."; throw new Exception(sMessage); } } if (ReplacedNodes.Count > 0) { string sMessage = "ReplaceCurrentMatchingBranch() " + "called with an invalid state: " + "ReplacedNodes is not empty."; throw new Exception(sMessage); } if (CurrentParseTreeNode == null) { string sMessage = "ReplaceCurrentMatchingBranch() " + "called with an invalid state: " + "CurrentParseTreeNode is null."; throw new Exception(sMessage); } //************************************************************** // Clear the ReplacedNodes list. ReplacedNodes.Clear(); //************************************************************** // If ReplacePatternRoot is null, use an empty SyntaxNode (one // with no features and no children) instead. SyntaxNode oReplacePatternRoot = ReplacePatternRoot; if (oReplacePatternRoot == null) { oReplacePatternRoot = new SyntaxNode(); } //************************************************************** // Use the oReplacePatternRoot and the MatchingNodes list to // create a new branch to replace the CurrentParseTreeNode. SyntaxNode oNewBranch = CopyNodeAndChildren(oReplacePatternRoot); //************************************************************** // BUGBUG: We may need to make another pass through the new // branch to: // // (1) copy features (or substrings) from another node using a // path <../DP/NP/featurename>. // // (2) recompute any feature values after other features have // changed (like changes to the word string because // morphology strings have changed). //************************************************************** // If the new branch is null, use an empty SyntaxNode (one with // no features and no children) instead, and add this to the // ReplacedNodes list. if (oNewBranch == null) { oNewBranch = new SyntaxNode(); SyntaxNodeTriple oNodeTriple = new SyntaxNodeTriple(); oNodeTriple.ParseTreeNode = oNewBranch; oNodeTriple.FindPatternNode = null; oNodeTriple.ReplacePatternNode = new SyntaxNode(); ReplacedNodes.Push(oNodeTriple); } Debug.Assert(ReplacedNodes.Count > 0); //************************************************************** // If the CurrentParseTreeNode has a parent node, find its // index in the parent's ChildNodes collection, and replace the // child at that index with the new branch. SyntaxNode oParent = CurrentParseTreeNode.ParentNode; if (oParent != null) { int iIndex = oParent.ChildNodes.IndexOf(CurrentParseTreeNode); oParent.ChildNodes.Insert(iIndex,oNewBranch); oParent.ChildNodes.Remove(CurrentParseTreeNode); } //************************************************************** // If the CurrentParseTreeNode is the same as the ParseTreeRoot, // replace the ParseTreeRoot with the new branch. if (CurrentParseTreeNode == ParseTreeRoot) { ParseTreeRoot = oNewBranch; } //************************************************************** // Set CurrentParseTreeNode to the new branch. CurrentParseTreeNode = oNewBranch; //************************************************************** // Dump the ReplacedNodes list for verbose debugging. if (VerboseDebugging) { foreach (SyntaxNodeTriple oNodeTriple in ReplacedNodes) { Debug.Assert(oNodeTriple.ParseTreeNode != null); Debug.Assert(oNodeTriple.ReplacePatternNode != null); } Debug.WriteLine("ReplacedNodes: " + ReplacedNodes.ToString() + "."); } Debug.WriteLineIf(VerboseDebugging, "ReplaceAlgorithm.ReplaceCurrentMatchingBranch() returns."); }
//****************************************************************** #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); }
//****************************************************************** /// <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); }
//****************************************************************** #region [ReplaceCurrentMatchingBranch() Method] //****************************************************************** /// <summary> /// Replaces the sub-tree dominated by the CurrentParseTreeNode, /// using the tree dominated by the ReplacePatternRoot as a pattern. /// Corresponding nodes (matched by a find-pattern node with the /// same label as the replace-pattern node) are copied from the /// MatchingNodes stack and their features are merged with features /// from the replace pattern. The replaced nodes in the new sub-tree /// are also stored in the ReplacedNodes stack. /// </summary> public void ReplaceCurrentMatchingBranch() { Debug.WriteLineIf(VerboseDebugging, "ReplaceAlgorithm.ReplaceCurrentMatchingBranch() called."); //************************************************************** // Validate the current state. if (ParseTreeRoot == null) { string sMessage = "ReplaceCurrentMatchingBranch() " + "called with an invalid state: " + "ParseTreeRoot is null."; throw new Exception(sMessage); } if (MatchingNodes.Count < 1) { string sMessage = "ReplaceCurrentMatchingBranch() " + "called with an invalid state: " + "MatchingNodes is empty."; throw new Exception(sMessage); } foreach (SyntaxNodePair oNodePair in MatchingNodes) { if (oNodePair.ParseTreeNode == null) { string sMessage = "ReplaceCurrentMatchingBranch() " + "called with an invalid state: " + "MatchingNodes contains an item where " + ".ParseTreeNode is null."; throw new Exception(sMessage); } if (oNodePair.FindPatternNode == null) { string sMessage = "ReplaceCurrentMatchingBranch() " + "called with an invalid state: " + "MatchingNodes contains an item where " + ".FindPatternNode is null."; throw new Exception(sMessage); } } if (ReplacedNodes.Count > 0) { string sMessage = "ReplaceCurrentMatchingBranch() " + "called with an invalid state: " + "ReplacedNodes is not empty."; throw new Exception(sMessage); } if (CurrentParseTreeNode == null) { string sMessage = "ReplaceCurrentMatchingBranch() " + "called with an invalid state: " + "CurrentParseTreeNode is null."; throw new Exception(sMessage); } //************************************************************** // Clear the ReplacedNodes list. ReplacedNodes.Clear(); //************************************************************** // If ReplacePatternRoot is null, use an empty SyntaxNode (one // with no features and no children) instead. SyntaxNode oReplacePatternRoot = ReplacePatternRoot; if (oReplacePatternRoot == null) { oReplacePatternRoot = new SyntaxNode(); } //************************************************************** // Use the oReplacePatternRoot and the MatchingNodes list to // create a new branch to replace the CurrentParseTreeNode. SyntaxNode oNewBranch = CopyNodeAndChildren(oReplacePatternRoot); //************************************************************** // BUGBUG: We may need to make another pass through the new // branch to: // // (1) copy features (or substrings) from another node using a // path <../DP/NP/featurename>. // // (2) recompute any feature values after other features have // changed (like changes to the word string because // morphology strings have changed). //************************************************************** // If the new branch is null, use an empty SyntaxNode (one with // no features and no children) instead, and add this to the // ReplacedNodes list. if (oNewBranch == null) { oNewBranch = new SyntaxNode(); SyntaxNodeTriple oNodeTriple = new SyntaxNodeTriple(); oNodeTriple.ParseTreeNode = oNewBranch; oNodeTriple.FindPatternNode = null; oNodeTriple.ReplacePatternNode = new SyntaxNode(); ReplacedNodes.Push(oNodeTriple); } Debug.Assert(ReplacedNodes.Count > 0); //************************************************************** // If the CurrentParseTreeNode has a parent node, find its // index in the parent's ChildNodes collection, and replace the // child at that index with the new branch. SyntaxNode oParent = CurrentParseTreeNode.ParentNode; if (oParent != null) { int iIndex = oParent.ChildNodes.IndexOf(CurrentParseTreeNode); oParent.ChildNodes.Insert(iIndex, oNewBranch); oParent.ChildNodes.Remove(CurrentParseTreeNode); } //************************************************************** // If the CurrentParseTreeNode is the same as the ParseTreeRoot, // replace the ParseTreeRoot with the new branch. if (CurrentParseTreeNode == ParseTreeRoot) { ParseTreeRoot = oNewBranch; } //************************************************************** // Set CurrentParseTreeNode to the new branch. CurrentParseTreeNode = oNewBranch; //************************************************************** // Dump the ReplacedNodes list for verbose debugging. if (VerboseDebugging) { foreach (SyntaxNodeTriple oNodeTriple in ReplacedNodes) { Debug.Assert(oNodeTriple.ParseTreeNode != null); Debug.Assert(oNodeTriple.ReplacePatternNode != null); } Debug.WriteLine("ReplacedNodes: " + ReplacedNodes.ToString() + "."); } Debug.WriteLineIf(VerboseDebugging, "ReplaceAlgorithm.ReplaceCurrentMatchingBranch() returns."); }
//****************************************************************** /// <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; }
//****************************************************************** /// <summary> /// Inserts an item at the top of the stack. /// </summary> public void Push(SyntaxNodeTriple oNodeTriple) { Debug.Assert(oNodeTriple != null); if (oNodeTriple == null) { string sMessage = "Invalid argument: " + "SyntaxNodeTripleStack cannot push a null item."; throw new Exception(sMessage); } InnerList.Add(oNodeTriple); }