//****************************************************************** /// <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 [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); }
//****************************************************************** /// <summary> /// Writes the "mparse" tag containing the morphology-parse record /// specified by features and children of the given node. /// </summary> private void WriteMorphologyParse(SyntaxNode oNode) { Debug.Assert(oNode != null); //************************************************************** // Write the opening <mparse> tag: // // <mparse id="..."> // // The "id" attribute must be unique. Writer.WriteStartElement(ParseXml.MparseElement); Writer.WriteAttributeString(ParseXml.IDAttribute,GenerateID()); //************************************************************** // Write the opening <a> tag: // // <a id="..."> // // The "id" attribute must be unique. Writer.WriteStartElement(ParseXml.AElement); Writer.WriteAttributeString(ParseXml.IDAttribute,GenerateID()); //************************************************************** // Write a <pfx> record for each prefix morpheme: each child // node where the "node:type" feature value is "pfx". foreach (SyntaxNode oChild in oNode.ChildNodes) { string sNodeType = oChild.Features[TreeTranEngineString.NodeType]; if (sNodeType == TreeTranEngineString.PrefixMorpheme) { WriteMorphologyParseMorpheme(oChild); } } //************************************************************** // Write a <root> record for each root morpheme: each child node // where the "node:type" feature value is "root" (or any value // other than "pfx" or "sfx"). There must be at least one root // morpheme. int iRootCount = 0; foreach (SyntaxNode oChild in oNode.ChildNodes) { string sNodeType = oChild.Features[TreeTranEngineString.NodeType]; if ((sNodeType != TreeTranEngineString.PrefixMorpheme) && (sNodeType != TreeTranEngineString.SuffixMorpheme)) { WriteMorphologyParseMorpheme(oChild); ++iRootCount; } } if (iRootCount == 0) { //********************************************************** // Write a blank <root> record if no other child node is a // root morpheme. Debug.WriteLineIf(VerboseDebugging, "ParseWriter.WriteMorphologyParse(): " + "Morphology parse (" + oNode.ToString() + ") " + "has no root morpheme to write."); WriteMorphologyParseMorpheme(new SyntaxNode()); } //************************************************************** // Write a <sfx> record for each suffix morpheme: each child // node where the "node:type" feature value is "sfx". foreach (SyntaxNode oChild in oNode.ChildNodes) { string sNodeType = oChild.Features[TreeTranEngineString.NodeType]; if (sNodeType == TreeTranEngineString.SuffixMorpheme) { WriteMorphologyParseMorpheme(oChild); } } //************************************************************** // Write the closing <a> tag: // // </a> Writer.WriteEndElement(); //************************************************************** // Write the optional <cat> tag: // // <cat id="...">...</cat> // // The "id" attribute must be unique. // // The tag contains the text description of the category for // the morphology parse (from the "cat" feature). if (oNode.Features.Contains(ParseXml.CatElement)) { Writer.WriteStartElement(ParseXml.CatElement); Writer.WriteAttributeString(ParseXml.IDAttribute, GenerateID()); string sValue = oNode.Features[ParseXml.CatElement]; Writer.WriteString(sValue); Writer.WriteEndElement(); } //************************************************************** // Write the closing <mparse> tag: // // </mparse> Writer.WriteEndElement(); }
//****************************************************************** /// <summary> /// Writes the "anaRec" tag containing the morphology record for the /// word represented by the given leaf node. If this is the last /// leaf node in the parse tree, WriteSyntax() is called to write /// the syntactic parse tree for the sentence as well. /// </summary> private void WriteMorphologyNode(SyntaxNode oNode) { Debug.Assert(oNode != null); Debug.Assert(IsSyntaxLeaf(oNode)); //************************************************************** // Write the opening <anaRec> tag: // // <anaRec id="..."> // // The "id" attribute must be unique. Writer.WriteStartElement(ParseXml.AnaRecElement); Writer.WriteAttributeString(ParseXml.IDAttribute,GenerateID()); //************************************************************** // Write the <w> tag: // // <w id="..." cap="...">...</w> // // The "id" attribute must be unique. // // The "cap" attribute is optional capitalization information // (from the "morph:cap" feature). // // The tag contains the text of the word (from the "morph:w" // feature). string sName = ""; string sValue = ""; Writer.WriteStartElement(ParseXml.WElement); Writer.WriteAttributeString(ParseXml.IDAttribute,GenerateID()); sName = TreeTranEngineString.MorphPrefix + ParseXml.CapAttribute; if (oNode.Features.Contains(sName)) { sValue = oNode.Features[sName]; Writer.WriteAttributeString(ParseXml.CapAttribute,sValue); } sName = TreeTranEngineString.MorphPrefix + ParseXml.WElement; sValue = oNode.Features[sName]; Writer.WriteString(sValue); Writer.WriteEndElement(); //************************************************************** // Write an <mparse> record for the morphology parse represented // by each child node. if (oNode.ChildNodes.Count == 0) { Debug.WriteLineIf(VerboseDebugging, "ParseWriter.WriteMorphologyNode(): " + "Leaf node (" + oNode.ToString() + ") " + "has no morphology parses to write."); } foreach (SyntaxNode oChild in oNode.ChildNodes) { WriteMorphologyParse(oChild); } //************************************************************** // Write the optional <fmt> tag: // // <fmt id="...">...</fmt> // // The "id" attribute must be unique. // // The tag contains the text of formatting information that // precedes the word (from the "morph:fmt" feature). sName = TreeTranEngineString.MorphPrefix + ParseXml.FmtElement; if (oNode.Features.Contains(sName)) { sValue = oNode.Features[sName]; Writer.WriteStartElement(ParseXml.FmtElement); Writer.WriteAttributeString(ParseXml.IDAttribute, GenerateID()); Writer.WriteString(sValue); Writer.WriteEndElement(); } //************************************************************** // Write the optional <n> tag: // // <n id="...">...</n> // // The "id" attribute must be unique. // // The tag contains the text of character information that // follows the word (from the "morph:n" feature). sName = TreeTranEngineString.MorphPrefix + ParseXml.NElement; if (oNode.Features.Contains(sName)) { sValue = oNode.Features[sName]; Writer.WriteStartElement(ParseXml.NElement); Writer.WriteAttributeString(ParseXml.IDAttribute, GenerateID()); Writer.WriteString(sValue); Writer.WriteEndElement(); } //************************************************************** // If this <anaRec> represents the last word of the sentence, // call WriteSyntax() to write the <Analysis> tag containing the // syntactic parse tree for the sentence (starting from the // ParseTreeRoot node). if (IsLastSyntaxLeaf(oNode)) { WriteSyntax(); } //************************************************************** // Write the closing <anaRec> tag: // // </anaRec> Writer.WriteEndElement(); }
//****************************************************************** /// <summary> /// Recursively traverses the indicated branch of the parse tree /// (dominiated by oNode) down to the syntax leaf nodes, writing the /// nodes and their features. /// </summary> private void WriteSyntaxNode(SyntaxNode oNode) { Debug.Assert(oNode != null); //************************************************************** // Write the opening <Node> tag: // // <Node id="..." cat="..." rule="..." all="..." fail="..."> // // The "id" attribute must be unique. // // The "cat" attribute indicates the syntactic category of the // node (from the oNode.Category property). // // BUGBUG: The optional "rule" attribute is currently ignored. // Is it needed? If so, a feature named "node:rule" could be // used to store its value. // // The optional "all" attribute is not written. // // The optional "fail" attribute is not written. Writer.WriteStartElement(ParseXml.NodeElement); Writer.WriteAttributeString(ParseXml.IDAttribute,GenerateID()); Writer.WriteAttributeString(ParseXml.CatAttribute, oNode.Category); //************************************************************** // Write the node's syntactic features. // // Note: Within a <Node> tag, only a syntactic feature set <Fs> // can be written. Within a <Leaf> tag, both a syntactic feature // set <Fs> and a lexical feature set <Lexfs> can be written. WriteFeatureSet(oNode); //************************************************************** // Write the child nodes. // // Note: Since the <Parse> tag must have a child that is a // <Node> tag, WriteSyntaxNode() is always called to write the // root node of the parse tree. In the unlikely case that the // root node is also a syntax leaf node, WriteSyntaxNode() is // called anyway and a <Node> tag is written instead of a <Leaf> // tag. Therefore, we must check if we have a syntax leaf node, // because the children of a syntax leaf node should not be // written here (since they represent morphology parses). if (IsSyntaxLeaf(oNode)) { Debug.Assert(oNode == ParseTreeRoot); Debug.WriteLineIf(VerboseDebugging, "ParseWriter.WriteSyntaxNode(): " + "The root node (" + oNode.ToString() + ") " + "is also a syntax leaf node, " + "so its lexical features will not be written."); } else { //********************************************************** // Write the child nodes. foreach (SyntaxNode oChild in oNode.ChildNodes) { //****************************************************** // If the child node is a syntax leaf, call // WriteSyntaxLeaf() to write the <Leaf> record. // // Otherwise, call WriteSyntaxNode() recursively to // write the child <Node> record and its children. if (IsSyntaxLeaf(oChild)) { WriteSyntaxLeaf(oChild); } else { WriteSyntaxNode(oChild); } } } //************************************************************** // Write the closing <Node> tag: // // </Node> Writer.WriteEndElement(); }