Skip to content

Commit b284006

Browse files
committed
Add an EditNode which reuses the attribute parsing from AddDep to update the values on a node
1 parent 7e9e95f commit b284006

File tree

3 files changed

+118
-0
lines changed

3 files changed

+118
-0
lines changed
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
package edu.stanford.nlp.semgraph.semgrex.ssurgeon;
2+
3+
import java.util.Map;
4+
import java.util.TreeMap;
5+
6+
import edu.stanford.nlp.ling.CoreLabel;
7+
import edu.stanford.nlp.ling.IndexedWord;
8+
import edu.stanford.nlp.semgraph.SemanticGraph;
9+
import edu.stanford.nlp.semgraph.semgrex.SemgrexMatcher;
10+
11+
/**
12+
* Edit an existing node to have new attributes.
13+
*
14+
* @author John Bauer
15+
*/
16+
public class EditNode extends SsurgeonEdit {
17+
public static final String LABEL = "editNode";
18+
19+
final String nodeName;
20+
final Map<String, String> attributes;
21+
22+
public EditNode(String nodeName, Map<String, String> attributes) {
23+
if (nodeName == null) {
24+
throw new SsurgeonParseException("Cannot make an EditNode with no nodeName");
25+
}
26+
if (attributes.size() == 0) {
27+
throw new SsurgeonParseException("Cannot make an EditNode with no attributes");
28+
}
29+
this.nodeName = nodeName;
30+
this.attributes = new TreeMap<>(attributes);
31+
}
32+
33+
34+
/**
35+
* Emits a parseable instruction string.
36+
*/
37+
@Override
38+
public String toEditString() {
39+
StringBuilder buf = new StringBuilder();
40+
buf.append(LABEL); buf.append("\t");
41+
buf.append(Ssurgeon.NODENAME_ARG);buf.append(" ");
42+
buf.append(nodeName); buf.append("\t");
43+
44+
for (String key : attributes.keySet()) {
45+
buf.append("-");
46+
buf.append(key);
47+
buf.append(" ");
48+
buf.append(attributes.get(key));
49+
buf.append("\"\t");
50+
}
51+
52+
return buf.toString();
53+
}
54+
55+
public boolean evaluate(SemanticGraph sg, SemgrexMatcher sm) {
56+
IndexedWord word = sm.getNode(nodeName);
57+
if (word == null)
58+
return false;
59+
60+
CoreLabel other = AddDep.fromCheapStrings(attributes);
61+
boolean changed = false;
62+
for (Class key : other.keySet()) {
63+
Object thisV = word.get(key);
64+
Object otherV = other.get(key);
65+
if (thisV == null || otherV == null) {
66+
if (thisV != null || otherV != null) {
67+
changed = true;
68+
word.set(key, otherV);
69+
}
70+
} else {
71+
if (!thisV.equals(otherV)) {
72+
changed = true;
73+
word.set(key, otherV);
74+
}
75+
}
76+
}
77+
78+
return changed;
79+
}
80+
}

src/edu/stanford/nlp/semgraph/semgrex/ssurgeon/Ssurgeon.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,8 @@ public static SsurgeonEdit parseEditLine(String editLine) {
395395
retEdit = AddEdge.createEngAddEdge(argsBox.govNodeName, argsBox.dep, argsBox.reln, argsBox.weight);
396396
} else if (command.equalsIgnoreCase(DeleteGraphFromNode.LABEL)) {
397397
retEdit = new DeleteGraphFromNode(argsBox.node);
398+
} else if (command.equalsIgnoreCase(EditNode.LABEL)) {
399+
retEdit = new EditNode(argsBox.node, argsBox.annotations);
398400
} else if (command.equalsIgnoreCase(RelabelNamedEdge.LABEL)) {
399401
// TODO: pass around a Language (perhaps via ssurgeon argument)
400402
// rather than hardcoding English, which is probably not even true

test/src/edu/stanford/nlp/semgraph/semgrex/ssurgeon/SsurgeonTest.java

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -826,6 +826,42 @@ public void checkAnnotationConversionErrors() {
826826
}
827827
}
828828

829+
830+
/**
831+
* Check that adding a word to the start of a sentence works as expected
832+
*/
833+
@Test
834+
public void readXMLEditNode() {
835+
Ssurgeon inst = Ssurgeon.inst();
836+
837+
// use "dep" as the dependency so as to be language-agnostic in this test
838+
String add = String.join(newline,
839+
"<ssurgeon-pattern-list>",
840+
" <ssurgeon-pattern>",
841+
" <uid>38</uid>",
842+
" <notes>Edit a node</notes>",
843+
" <semgrex>" + XMLUtils.escapeXML("{word:green}=blue") + "</semgrex>",
844+
" <edit-list>EditNode -node blue -word blue</edit-list>",
845+
" </ssurgeon-pattern>",
846+
"</ssurgeon-pattern-list>");
847+
List<SsurgeonPattern> patterns = inst.readFromString(add);
848+
assertEquals(patterns.size(), 1);
849+
SsurgeonPattern editSsurgeon = patterns.get(0);
850+
851+
SemanticGraph sg = SemanticGraph.valueOf("[has-2 nsubj> Jennifer-1 obj> [antennae-4 dep> green-3]]");
852+
IndexedWord blueVertex = sg.getNodeByIndexSafe(3);
853+
assertEquals("green", blueVertex.value());
854+
SemanticGraph newSG = editSsurgeon.iterate(sg);
855+
SemanticGraph expected = SemanticGraph.valueOf("[has-2 nsubj> Jennifer-1 obj> [antennae-4 dep> blue-3]]");
856+
assertEquals(expected, newSG);
857+
// the Ssurgeon we just created should not put a tag on the word
858+
// but it SHOULD put blue at the start of the sentence
859+
blueVertex = newSG.getNodeByIndexSafe(3);
860+
assertNotNull(blueVertex);
861+
assertNull(blueVertex.tag());
862+
assertEquals("blue", blueVertex.value());
863+
}
864+
829865
/**
830866
* Simple test of an Ssurgeon edit script. This instances a simple semantic graph,
831867
* a semgrex pattern, and then the resulting actions over the named nodes in the

0 commit comments

Comments
 (0)