Skip to content

Commit 27c6703

Browse files
committed
Add to Ssurgeon the ability to update features without overwriting the whole feature map
Allow EditNode with morpho updates and no other attributes changed
1 parent 0e35efe commit 27c6703

File tree

3 files changed

+43
-5
lines changed

3 files changed

+43
-5
lines changed

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

+35-3
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
package edu.stanford.nlp.semgraph.semgrex.ssurgeon;
22

3+
import java.util.Collections;
4+
import java.util.HashMap;
35
import java.util.Map;
46
import java.util.TreeMap;
57

8+
import edu.stanford.nlp.ling.CoreAnnotations;
69
import edu.stanford.nlp.ling.CoreLabel;
710
import edu.stanford.nlp.ling.IndexedWord;
811
import edu.stanford.nlp.semgraph.SemanticGraph;
912
import edu.stanford.nlp.semgraph.semgrex.SemgrexMatcher;
13+
import edu.stanford.nlp.trees.ud.CoNLLUUtils;
1014

1115
/**
1216
* Edit an existing node to have new attributes.
@@ -18,17 +22,23 @@ public class EditNode extends SsurgeonEdit {
1822

1923
final String nodeName;
2024
final Map<String, String> attributes;
25+
final Map<String, String> updateMorphoFeatures;
2126

22-
public EditNode(String nodeName, Map<String, String> attributes) {
27+
public EditNode(String nodeName, Map<String, String> attributes, String updateMorphoFeatures) {
2328
if (nodeName == null) {
2429
throw new SsurgeonParseException("Cannot make an EditNode with no nodeName");
2530
}
26-
if (attributes.size() == 0) {
27-
throw new SsurgeonParseException("Cannot make an EditNode with no attributes");
31+
if (attributes.size() == 0 && updateMorphoFeatures == null) {
32+
throw new SsurgeonParseException("Cannot make an EditNode with no attributes or updated morphological features");
2833
}
2934
AddDep.checkIllegalAttributes(attributes);
3035
this.nodeName = nodeName;
3136
this.attributes = new TreeMap<>(attributes);
37+
if (updateMorphoFeatures != null) {
38+
this.updateMorphoFeatures = CoNLLUUtils.parseFeatures(updateMorphoFeatures);
39+
} else {
40+
this.updateMorphoFeatures = Collections.emptyMap();
41+
}
3242
}
3343

3444

@@ -47,9 +57,16 @@ public String toEditString() {
4757
buf.append(key);
4858
buf.append(" ");
4959
buf.append(attributes.get(key));
60+
// TODO: why the stray quote characters?
5061
buf.append("\"\t");
5162
}
5263

64+
if (this.updateMorphoFeatures.size() > 0) {
65+
buf.append(Ssurgeon.UPDATE_MORPHO_FEATURES);
66+
buf.append(" ");
67+
buf.append(CoNLLUUtils.toFeatureString(this.updateMorphoFeatures));
68+
}
69+
5370
return buf.toString();
5471
}
5572

@@ -76,6 +93,21 @@ public boolean evaluate(SemanticGraph sg, SemgrexMatcher sm) {
7693
}
7794
}
7895

96+
for (String key : updateMorphoFeatures.keySet()) {
97+
HashMap<String, String> features = word.get(CoreAnnotations.CoNLLUFeats.class);
98+
if (features == null) {
99+
changed = true;
100+
features = new HashMap<>();
101+
word.set(CoreAnnotations.CoNLLUFeats.class, features);
102+
}
103+
104+
// this test will catch null, eg not yet assigned, features as well
105+
if (!updateMorphoFeatures.get(key).equals(features.get(key))) {
106+
changed = true;
107+
features.put(key, updateMorphoFeatures.get(key));
108+
}
109+
}
110+
79111
return changed;
80112
}
81113
}

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

+7-1
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,7 @@ public Collection<SsurgeonWordlist> getResources() {
397397
public static final String WEIGHT_ARG = "-weight";
398398
public static final String NAME_ARG = "-name";
399399
public static final String POSITION_ARG = "-position";
400+
public static final String UPDATE_MORPHO_FEATURES = "-updateMorphoFeatures";
400401

401402

402403
// args for Ssurgeon edits, allowing us to not
@@ -422,6 +423,8 @@ protected static class SsurgeonArgs {
422423

423424
public String position = null;
424425

426+
public String updateMorphoFeatures = null;
427+
425428
public Map<String, String> annotations = new TreeMap<>();
426429
}
427430

@@ -492,6 +495,9 @@ private static SsurgeonArgs parseArgsBox(String args, Map<String, String> additi
492495
case POSITION_ARG:
493496
argsBox.position = argsValue;
494497
break;
498+
case UPDATE_MORPHO_FEATURES:
499+
argsBox.updateMorphoFeatures = argsValue;
500+
break;
495501
default:
496502
String key = argsKey.substring(1);
497503
Class<? extends CoreAnnotation<?>> annotation = AnnotationLookup.toCoreKey(key);
@@ -557,7 +563,7 @@ public static SsurgeonEdit parseEditLine(String editLine, Map<String, String> at
557563
if (argsBox.nodes.size() != 1) {
558564
throw new SsurgeonParseException("Cannot make an EditNode out of " + argsBox.nodes.size() + " nodes. Please use exactly one -node");
559565
}
560-
return new EditNode(argsBox.nodes.get(0), argsBox.annotations);
566+
return new EditNode(argsBox.nodes.get(0), argsBox.annotations, argsBox.updateMorphoFeatures);
561567
} else if (command.equalsIgnoreCase(MergeNodes.LABEL)) {
562568
if (argsBox.nodes.size() < 2) {
563569
throw new SsurgeonParseException("Cannot make a MergeNodes out of fewer than 2 nodes (got " + argsBox.nodes.size() + ")");

src/edu/stanford/nlp/trees/ud/CoNLLUUtils.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public static HashMap<String,String> parseFeatures(String featureString) {
3535
*
3636
* @return The feature string.
3737
*/
38-
public static String toFeatureString(HashMap<String,String> features) {
38+
public static String toFeatureString(Map<String,String> features) {
3939
StringBuilder sb = new StringBuilder();
4040
boolean first = true;
4141
if (features != null) {

0 commit comments

Comments
 (0)