Skip to content

Commit 2cdd6e5

Browse files
committed
Add the ability to control position with + or - relative to a node
1 parent ec517e1 commit 2cdd6e5

File tree

2 files changed

+87
-7
lines changed

2 files changed

+87
-7
lines changed

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

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ public AddDep(String govNodeName, GrammaticalRelation relation, Map<String, Stri
5252
}
5353

5454
if (position != null) {
55-
if (!position.equals("-") && !position.equals("+")) {
55+
if (!position.startsWith("-") && !position.startsWith("+")) {
5656
throw new SsurgeonParseException("Unknown position " + position + " in AddDep operation");
5757
}
5858
}
@@ -151,16 +151,38 @@ public boolean evaluate(SemanticGraph sg, SemgrexMatcher sm) {
151151
CoreLabel newWord = fromCheapStrings(attributes);
152152
IndexedWord newNode = new IndexedWord(newWord);
153153
final int tempIndex;
154+
final int newIndex;
154155
if (position != null && !position.equals("+")) {
155156
// +2 to leave room: we will increase all other nodes with the
156157
// proper index, so we need +1 of room, then another +1 for
157158
// a temp place to put this node
158159
// TODO: when we implement updating the SemgrexMatcher,
159160
// this won't be necessary
160161
tempIndex = SemanticGraphUtils.maxIndex(sg) + 2;
162+
163+
if (position.equals("-")) {
164+
newIndex = SemanticGraphUtils.minIndex(sg);
165+
} else if (position.startsWith("-") || position.startsWith("+")) {
166+
String targetName = position.substring(1);
167+
IndexedWord target = sm.getNode(targetName);
168+
if (target == null) {
169+
return false;
170+
}
171+
if (position.startsWith("-")) {
172+
// it will be exactly to the left rather than pushing over
173+
// something a word earlier if we do .index(), not .index() - 1
174+
newIndex = target.index();
175+
} else {
176+
newIndex = target.index() + 1;
177+
}
178+
} else {
179+
throw new UnsupportedOperationException("Unknown position in AddDep: |" + position + "|");
180+
}
161181
} else {
162182
tempIndex = SemanticGraphUtils.maxIndex(sg) + 1;
183+
newIndex = -1;
163184
}
185+
164186
newNode.setDocID(govNode.docID());
165187
newNode.setIndex(tempIndex);
166188
newNode.setSentIndex(govNode.sentIndex());
@@ -169,12 +191,6 @@ public boolean evaluate(SemanticGraph sg, SemgrexMatcher sm) {
169191
sg.addEdge(govNode, newNode, relation, weight, false);
170192

171193
if (position != null && !position.equals("+")) {
172-
final int newIndex;
173-
if (position.equals("-")) {
174-
newIndex = SemanticGraphUtils.minIndex(sg);
175-
} else {
176-
throw new UnsupportedOperationException("Unknown position in AddDep: |" + position + "|");
177-
}
178194
// the payoff for tempIndex == maxIndex + 2:
179195
// everything will be moved one higher, unless it's the new node
180196
moveNodes(sg, x -> (x >= newIndex && x != tempIndex), x -> x+1);

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

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -683,6 +683,70 @@ public void readXMLAddDepStartPosition() {
683683
assertEquals("blue", blueVertex.value());
684684
}
685685

686+
/**
687+
* Check that adding a word before or after a named node works as expected
688+
*/
689+
@Test
690+
public void readXMLAddDepRelativePosition() {
691+
Ssurgeon inst = Ssurgeon.inst();
692+
693+
// use "dep" as the dependency so as to be language-agnostic in this test
694+
String add = String.join(newline,
695+
"<ssurgeon-pattern-list>",
696+
" <ssurgeon-pattern>",
697+
" <uid>38</uid>",
698+
" <notes>Add a word before antennae using the position</notes>",
699+
// have to bomb-proof the pattern
700+
" <semgrex>" + XMLUtils.escapeXML("{word:antennae}=antennae !> {word:blue}") + "</semgrex>",
701+
" <edit-list>addDep -gov antennae -reln dep -word blue -position -antennae</edit-list>",
702+
" </ssurgeon-pattern>",
703+
"</ssurgeon-pattern-list>");
704+
List<SsurgeonPattern> patterns = inst.readFromString(add);
705+
assertEquals(patterns.size(), 1);
706+
SsurgeonPattern addSsurgeon = patterns.get(0);
707+
708+
SemanticGraph sg = SemanticGraph.valueOf("[has-2 nsubj> Jennifer-1 obj> antennae-3]");
709+
IndexedWord blueVertex = sg.getNodeByIndexSafe(4);
710+
assertNull(blueVertex);
711+
SemanticGraph newSG = addSsurgeon.iterate(sg);
712+
SemanticGraph expected = SemanticGraph.valueOf("[has-2 nsubj> Jennifer-1 obj> [antennae-4 dep> blue-3]]");
713+
assertEquals(expected, newSG);
714+
// the Ssurgeon we just created should not put a tag on the word
715+
// but it SHOULD put blue immediately before antennae
716+
blueVertex = newSG.getNodeByIndexSafe(3);
717+
assertNotNull(blueVertex);
718+
assertNull(blueVertex.tag());
719+
assertEquals("blue", blueVertex.value());
720+
721+
// use "dep" as the dependency so as to be language-agnostic in this test
722+
add = String.join(newline,
723+
"<ssurgeon-pattern-list>",
724+
" <ssurgeon-pattern>",
725+
" <uid>38</uid>",
726+
" <notes>Add a word after the word before antennae (just to test the position)</notes>",
727+
// have to bomb-proof the pattern
728+
" <semgrex>" + XMLUtils.escapeXML("{word:antennae}=antennae - {}=prev !> {word:blue}") + "</semgrex>",
729+
" <edit-list>addDep -gov antennae -reln dep -word blue -position +prev</edit-list>",
730+
" </ssurgeon-pattern>",
731+
"</ssurgeon-pattern-list>");
732+
patterns = inst.readFromString(add);
733+
assertEquals(patterns.size(), 1);
734+
addSsurgeon = patterns.get(0);
735+
736+
sg = SemanticGraph.valueOf("[has-2 nsubj> Jennifer-1 obj> antennae-3]");
737+
blueVertex = sg.getNodeByIndexSafe(4);
738+
assertNull(blueVertex);
739+
newSG = addSsurgeon.iterate(sg);
740+
expected = SemanticGraph.valueOf("[has-2 nsubj> Jennifer-1 obj> [antennae-4 dep> blue-3]]");
741+
assertEquals(expected, newSG);
742+
// the Ssurgeon we just created should not put a tag on the word
743+
// but it SHOULD put blue immediately before antennae
744+
blueVertex = newSG.getNodeByIndexSafe(3);
745+
assertNotNull(blueVertex);
746+
assertNull(blueVertex.tag());
747+
assertEquals("blue", blueVertex.value());
748+
}
749+
686750
/**
687751
* There should be an exception for an annotation key that does not exist
688752
*/

0 commit comments

Comments
 (0)