public virtual void SimpleTest() { SemanticGraph sg = SemanticGraph.ValueOf("[mixed/VBN nsubj>[Joe/NNP appos>[bartender/NN det>the/DT]] dobj>[drink/NN det>a/DT]]"); SemgrexPattern semgrexPattern = SemgrexPattern.Compile("{}=a1 >appos=e1 {}=a2 <nsubj=e2 {}=a3"); SsurgeonPattern pattern = new SsurgeonPattern(semgrexPattern); System.Console.Out.WriteLine("Start = " + sg.ToCompactString()); // Find and snip the appos and root to nsubj links SsurgeonEdit apposSnip = new RemoveNamedEdge("e1", "a1", "a2"); pattern.AddEdit(apposSnip); SsurgeonEdit nsubjSnip = new RemoveNamedEdge("e2", "a3", "a1"); pattern.AddEdit(nsubjSnip); // Attach Joe to be the nsubj of bartender SsurgeonEdit reattachSubj = new AddEdge("a2", "a1", EnglishGrammaticalRelations.NominalSubject); pattern.AddEdit(reattachSubj); // Attach copula IndexedWord isNode = new IndexedWord(); isNode.Set(typeof(CoreAnnotations.TextAnnotation), "is"); isNode.Set(typeof(CoreAnnotations.LemmaAnnotation), "is"); isNode.Set(typeof(CoreAnnotations.OriginalTextAnnotation), "is"); isNode.Set(typeof(CoreAnnotations.PartOfSpeechAnnotation), "VBN"); SsurgeonEdit addCopula = new AddDep("a2", EnglishGrammaticalRelations.Copula, isNode); pattern.AddEdit(addCopula); // Destroy subgraph SsurgeonEdit destroySubgraph = new DeleteGraphFromNode("a3"); pattern.AddEdit(destroySubgraph); // Process and output modified ICollection <SemanticGraph> newSgs = pattern.Execute(sg); foreach (SemanticGraph newSg in newSgs) { System.Console.Out.WriteLine("Modified = " + newSg.ToCompactString()); } string firstGraphString = newSgs.GetEnumerator().Current.ToCompactString().Trim(); NUnit.Framework.Assert.AreEqual(firstGraphString, "[bartender cop>is nsubj>Joe det>the]"); }
/// <summary>Given a string entry, converts it into a SsurgeonEdit object.</summary> public static SsurgeonEdit ParseEditLine(string editLine) { // Extract the operation name first string[] tuples1 = editLine.Split("\\s+", 2); if (tuples1.Length < 2) { throw new ArgumentException("Error in SsurgeonEdit.parseEditLine: invalid number of arguments"); } string command = tuples1[0]; string[] argsArray = ParseArgs(tuples1[1]); Ssurgeon.SsurgeonArgs argsBox = new Ssurgeon.SsurgeonArgs(); for (int argIndex = 0; argIndex < argsArray.Length; ++argIndex) { switch (argsArray[argIndex]) { case GovNodenameArg: { argsBox.govNodeName = argsArray[argIndex + 1]; argIndex += 2; break; } case DepNodenameArg: { argsBox.dep = argsArray[argIndex + 1]; argIndex += 2; break; } case EdgeNameArg: { argsBox.edge = argsArray[argIndex + 1]; argIndex += 2; break; } case RelnArg: { argsBox.reln = argsArray[argIndex + 1]; argIndex += 2; break; } case NodenameArg: { argsBox.node = argsArray[argIndex + 1]; argIndex += 2; break; } case NodeProtoArg: { argsBox.nodeString = argsArray[argIndex + 1]; argIndex += 2; break; } case WeightArg: { argsBox.weight = double.ValueOf(argsArray[argIndex + 1]); argIndex += 2; break; } case NameArg: { argsBox.name = argsArray[argIndex + 1]; argIndex += 2; break; } default: { throw new ArgumentException("Parsing Ssurgeon args: unknown flag " + argsArray[argIndex]); } } } // Parse the arguments based upon the type of command to execute. // TODO: this logic really should be moved into the individual classes. The string-->class // mappings should also be stored in more appropriate data structure. SsurgeonEdit retEdit; if (Sharpen.Runtime.EqualsIgnoreCase(command, AddDep.Label)) { retEdit = AddDep.CreateEngAddDep(argsBox.govNodeName, argsBox.reln, argsBox.nodeString); } else { if (Sharpen.Runtime.EqualsIgnoreCase(command, AddNode.Label)) { retEdit = AddNode.CreateAddNode(argsBox.nodeString, argsBox.name); } else { if (Sharpen.Runtime.EqualsIgnoreCase(command, AddEdge.Label)) { retEdit = AddEdge.CreateEngAddEdge(argsBox.govNodeName, argsBox.dep, argsBox.reln); } else { if (Sharpen.Runtime.EqualsIgnoreCase(command, DeleteGraphFromNode.Label)) { retEdit = new DeleteGraphFromNode(argsBox.node); } else { if (Sharpen.Runtime.EqualsIgnoreCase(command, RemoveEdge.Label)) { retEdit = new RemoveEdge(GrammaticalRelation.ValueOf(argsBox.reln), argsBox.govNodeName, argsBox.dep); } else { if (Sharpen.Runtime.EqualsIgnoreCase(command, RemoveNamedEdge.Label)) { retEdit = new RemoveNamedEdge(argsBox.edge, argsBox.govNodeName, argsBox.dep); } else { if (Sharpen.Runtime.EqualsIgnoreCase(command, SetRoots.Label)) { string[] names = tuples1[1].Split("\\s+"); IList <string> newRoots = Arrays.AsList(names); retEdit = new SetRoots(newRoots); } else { if (Sharpen.Runtime.EqualsIgnoreCase(command, KillNonRootedNodes.Label)) { retEdit = new KillNonRootedNodes(); } else { if (Sharpen.Runtime.EqualsIgnoreCase(command, KillAllIncomingEdges.Label)) { retEdit = new KillAllIncomingEdges(argsBox.node); } else { throw new ArgumentException("Error in SsurgeonEdit.parseEditLine: command '" + command + "' is not supported"); } } } } } } } } } return(retEdit); }