Skip to content

Commit 7399e9b

Browse files
committedFeb 22, 2025·
Add the capacity to negate attributes in a node, rather than requiring negative lookahead regex
1 parent 81290ba commit 7399e9b

File tree

8 files changed

+158
-80
lines changed

8 files changed

+158
-80
lines changed
 
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package edu.stanford.nlp.semgraph.semgrex;
2+
3+
import java.io.Serializable;
4+
5+
public class Attribute implements Serializable {
6+
final String key;
7+
final Object cased;
8+
final Object caseless;
9+
final boolean negated;
10+
11+
Attribute(String key, Object cased, Object caseless, boolean negated) {
12+
this.key = key;
13+
this.cased = cased;
14+
this.caseless = caseless;
15+
this.negated = negated;
16+
}
17+
18+
private static final long serialVersionUID = 973567614155612487L;
19+
}

‎src/edu/stanford/nlp/semgraph/semgrex/NodeAttributes.java

+17-8
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
package edu.stanford.nlp.semgraph.semgrex;
22

3-
import java.util.LinkedHashMap;
4-
import java.util.Map;
3+
import java.util.ArrayList;
4+
import java.util.HashSet;
5+
import java.util.List;
6+
import java.util.Set;
7+
8+
import edu.stanford.nlp.util.Triple;
59

610
/**
711
* Stores attributes for a Semgrex NodePattern.
@@ -18,12 +22,14 @@
1822
public class NodeAttributes {
1923
private boolean root;
2024
private boolean empty;
21-
private Map<String, String> attributes;
25+
private List<Triple<String, String, Boolean>> attributes;
26+
private Set<String> positiveAttributes;
2227

2328
public NodeAttributes() {
2429
root = false;
2530
empty = false;
26-
attributes = new LinkedHashMap<>();
31+
attributes = new ArrayList<>();
32+
positiveAttributes = new HashSet<>();
2733
}
2834

2935
public void setRoot(boolean root) {
@@ -42,14 +48,17 @@ public boolean empty() {
4248
return empty;
4349
}
4450

45-
public void setAttribute(String key, String value) {
46-
if (attributes.containsKey(key)) {
51+
public void setAttribute(String key, String value, boolean negated) {
52+
if (positiveAttributes.contains(key)) {
4753
throw new SemgrexParseException("Duplicate attribute " + key + " found in semgrex expression");
4854
}
49-
attributes.put(key, value);
55+
if (!negated) {
56+
positiveAttributes.add(key);
57+
}
58+
attributes.add(new Triple(key, value, negated));
5059
}
5160

52-
public Map<String, String> attributes() {
61+
public List<Triple<String, String, Boolean>> attributes() {
5362
return attributes;
5463
}
5564
}

‎src/edu/stanford/nlp/semgraph/semgrex/NodePattern.java

+28-34
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import java.util.ArrayList;
44
import java.util.Collections;
55
import java.util.Iterator;
6-
import java.util.LinkedHashMap;
76
import java.util.List;
87
import java.util.Map;
98
import java.util.regex.Matcher;
@@ -13,6 +12,7 @@
1312
import edu.stanford.nlp.semgraph.SemanticGraph;
1413
import edu.stanford.nlp.semgraph.SemanticGraphEdge;
1514
import edu.stanford.nlp.util.Pair;
15+
import edu.stanford.nlp.util.Triple;
1616
import edu.stanford.nlp.util.logging.Redwood;
1717

1818
public class NodePattern extends SemgrexPattern {
@@ -31,7 +31,7 @@ public class NodePattern extends SemgrexPattern {
3131
* value.
3232
* Otherwise, the type will be a Pattern, and you must use Pattern.matches().
3333
*/
34-
private final Map<String, Pair<Object, Object>> attributes;
34+
private final List<Attribute> attributes;
3535
private final boolean isRoot;
3636
private final boolean isLink;
3737
private final boolean isEmpty;
@@ -43,33 +43,34 @@ public class NodePattern extends SemgrexPattern {
4343
private List<Pair<Integer, String>> variableGroups;
4444

4545
public NodePattern(GraphRelation r, boolean negDesc,
46-
Map<String, String> attrs,
46+
List<Triple<String, String, Boolean>> attrs,
4747
boolean root, boolean empty, boolean isLink, String name) {
4848
this(r, negDesc, attrs, root, empty, isLink, name,
4949
new ArrayList<>(0));
5050
}
5151

5252
// TODO: there is no capacity for named variable groups in the parser right now
5353
public NodePattern(GraphRelation r, boolean negDesc,
54-
Map<String, String> attrs,
54+
List<Triple<String, String, Boolean>> attrs,
5555
boolean root, boolean empty, boolean isLink, String name,
5656
List<Pair<Integer, String>> variableGroups) {
5757
this.reln = r;
5858
this.negDesc = negDesc;
5959
this.isLink = isLink;
6060
// order the attributes so that the pattern stays the same when
6161
// printing a compiled pattern
62-
attributes = new LinkedHashMap<>();
62+
attributes = new ArrayList<>();
6363
descString = "{";
64-
for (Map.Entry<String, String> entry : attrs.entrySet()) {
64+
for (Triple<String, String, Boolean> entry : attrs) {
6565
if (!descString.equals("{"))
6666
descString += ";";
67-
String key = entry.getKey();
68-
String value = entry.getValue();
67+
String key = entry.first();
68+
String value = entry.second();
69+
boolean negated = entry.third();
6970

7071
// Add the attributes for this key
7172
if (value.equals("__")) {
72-
attributes.put(key, Pair.makePair(true, true));
73+
attributes.add(new Attribute(key, true, true, negated));
7374
} else if (value.matches("/.*/")) {
7475
boolean isRegexp = false;
7576
for (int i = 1; i < value.length() - 1; ++i) {
@@ -81,34 +82,24 @@ public NodePattern(GraphRelation r, boolean negDesc,
8182
}
8283
String patternContent = value.substring(1, value.length() - 1);
8384
if (isRegexp) {
84-
attributes.put(key, Pair.makePair(
85-
Pattern.compile(patternContent),
86-
Pattern.compile(patternContent, Pattern.CASE_INSENSITIVE|Pattern.UNICODE_CASE))
87-
);
85+
attributes.add(new Attribute(key,
86+
Pattern.compile(patternContent),
87+
Pattern.compile(patternContent, Pattern.CASE_INSENSITIVE|Pattern.UNICODE_CASE),
88+
negated));
8889
} else {
89-
attributes.put(key, Pair.makePair(patternContent, patternContent));
90+
attributes.add(new Attribute(key, patternContent, patternContent, negated));
9091
}
9192
} else { // raw description
92-
attributes.put(key, Pair.makePair(value, value));
93+
attributes.add(new Attribute(key, value, value, negated));
9394
}
9495

95-
96-
97-
// if (value.equals("__")) {
98-
// attributes.put(key, Pair.makePair(Pattern.compile(".*"), Pattern.compile(".*", Pattern.CASE_INSENSITIVE)));
99-
// } else if (value.matches("/.*/")) {
100-
// attributes.put(key, Pair.makePair(
101-
// Pattern.compile(value.substring(1, value.length() - 1)),
102-
// Pattern.compile(value.substring(1, value.length() - 1), Pattern.CASE_INSENSITIVE))
103-
// );
104-
// } else { // raw description
105-
// attributes.put(key, Pair.makePair(
106-
// Pattern.compile("^(" + value + ")$"),
107-
// Pattern.compile("^(" + value + ")$", Pattern.CASE_INSENSITIVE))
108-
// );
109-
// }
110-
descString += (key + ':' + value);
96+
if (negated) {
97+
descString += (key + "!:" + value);
98+
} else {
99+
descString += (key + ':' + value);
100+
}
111101
}
102+
112103
if (root) {
113104
if (!descString.equals("{"))
114105
descString += ";";
@@ -145,8 +136,8 @@ public boolean nodeAttrMatch(IndexedWord node, final SemanticGraph sg, boolean i
145136
return (negDesc ? !node.equals(IndexedWord.NO_WORD) : node.equals(IndexedWord.NO_WORD));
146137

147138
// log.info("Attributes are: " + attributes);
148-
for (Map.Entry<String, Pair<Object, Object>> attr : attributes.entrySet()) {
149-
String key = attr.getKey();
139+
for (Attribute attr : attributes) {
140+
String key = attr.key;
150141
// System.out.println(key);
151142
String nodeValue;
152143
// if (key.equals("idx"))
@@ -167,7 +158,7 @@ public boolean nodeAttrMatch(IndexedWord node, final SemanticGraph sg, boolean i
167158
return negDesc;
168159

169160
// Get the node pattern
170-
Object toMatch = ignoreCase ? attr.getValue().second : attr.getValue().first;
161+
Object toMatch = ignoreCase ? attr.caseless : attr.cased;
171162
boolean matches;
172163
if (toMatch instanceof Boolean) {
173164
matches = ((Boolean) toMatch);
@@ -182,6 +173,9 @@ public boolean nodeAttrMatch(IndexedWord node, final SemanticGraph sg, boolean i
182173
} else {
183174
throw new IllegalStateException("Unknown matcher type: " + toMatch + " (of class + " + toMatch.getClass() + ")");
184175
}
176+
if (attr.negated) {
177+
matches = !matches;
178+
}
185179

186180
if (!matches) {
187181
// System.out.println("doesn't match");

‎src/edu/stanford/nlp/semgraph/semgrex/SemgrexParser.java

+45-28
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ final public SemgrexPattern Root() throws ParseException {// Root pattern for th
6565
case 11:
6666
case 15:
6767
case 17:
68-
case 22:{
68+
case 23:{
6969
node = SubNode(GraphRelation.ROOT);
7070
children.add(node);
7171
label_1:
@@ -135,7 +135,7 @@ final public SemgrexPattern Root() throws ParseException {// Root pattern for th
135135
}
136136
case 15:
137137
case 17:
138-
case 22:{
138+
case 23:{
139139
result = ModNode(r);
140140
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
141141
case RELATION:
@@ -397,7 +397,7 @@ final public SemgrexPattern Root() throws ParseException {// Root pattern for th
397397
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
398398
case 15:
399399
case 17:
400-
case 22:{
400+
case 23:{
401401
node = ModNode(reln);
402402
break;
403403
}
@@ -454,7 +454,7 @@ final public SemgrexPattern Root() throws ParseException {// Root pattern for th
454454
case 14:
455455
case 15:
456456
case 17:
457-
case 22:{
457+
case 23:{
458458
;
459459
break;
460460
}
@@ -485,7 +485,7 @@ final public SemgrexPattern Root() throws ParseException {// Root pattern for th
485485
boolean startUnderNeg;
486486
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
487487
case 17:
488-
case 22:{
488+
case 23:{
489489
child = Child(r);
490490
break;
491491
}
@@ -512,7 +512,7 @@ final public SemgrexPattern Root() throws ParseException {// Root pattern for th
512512
child = NodeDisj(r);
513513
break;
514514
}
515-
case 22:{
515+
case 23:{
516516
child = Description(r);
517517
break;
518518
}
@@ -527,10 +527,24 @@ final public SemgrexPattern Root() throws ParseException {// Root pattern for th
527527

528528
final public void AddAttribute(NodeAttributes attributes) throws ParseException {Token attr = null;
529529
Token value = null;
530+
Token attrType = null;
530531
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
531532
case IDENTIFIER:{
532533
attr = jj_consume_token(IDENTIFIER);
533-
jj_consume_token(10);
534+
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
535+
case 10:{
536+
attrType = jj_consume_token(10);
537+
break;
538+
}
539+
case 22:{
540+
attrType = jj_consume_token(22);
541+
break;
542+
}
543+
default:
544+
jj_la1[23] = jj_gen;
545+
jj_consume_token(-1);
546+
throw new ParseException();
547+
}
534548
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
535549
case IDENTIFIER:{
536550
value = jj_consume_token(IDENTIFIER);
@@ -541,11 +555,14 @@ final public SemgrexPattern Root() throws ParseException {// Root pattern for th
541555
break;
542556
}
543557
default:
544-
jj_la1[23] = jj_gen;
558+
jj_la1[24] = jj_gen;
545559
jj_consume_token(-1);
546560
throw new ParseException();
547561
}
548-
if (attr != null && value != null) attributes.setAttribute(attr.image, value.image);
562+
if (attr != null && value != null) {
563+
boolean negated = attrType.image.equals("!:");
564+
attributes.setAttribute(attr.image, value.image, negated);
565+
}
549566
break;
550567
}
551568
case ROOT:{
@@ -559,7 +576,7 @@ final public SemgrexPattern Root() throws ParseException {// Root pattern for th
559576
break;
560577
}
561578
default:
562-
jj_la1[24] = jj_gen;
579+
jj_la1[25] = jj_gen;
563580
jj_consume_token(-1);
564581
throw new ParseException();
565582
}
@@ -569,7 +586,7 @@ final public SemgrexPattern Root() throws ParseException {// Root pattern for th
569586
boolean link = false;
570587
NodeAttributes attributes = new NodeAttributes();
571588
NodePattern pat;
572-
jj_consume_token(22);
589+
jj_consume_token(23);
573590
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
574591
case IDENTIFIER:
575592
case EMPTY:
@@ -578,24 +595,24 @@ final public SemgrexPattern Root() throws ParseException {// Root pattern for th
578595
label_6:
579596
while (true) {
580597
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
581-
case 23:{
598+
case 24:{
582599
;
583600
break;
584601
}
585602
default:
586-
jj_la1[25] = jj_gen;
603+
jj_la1[26] = jj_gen;
587604
break label_6;
588605
}
589-
jj_consume_token(23);
606+
jj_consume_token(24);
590607
AddAttribute(attributes);
591608
}
592609
break;
593610
}
594611
default:
595-
jj_la1[26] = jj_gen;
612+
jj_la1[27] = jj_gen;
596613
;
597614
}
598-
jj_consume_token(24);
615+
jj_consume_token(25);
599616
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
600617
case 21:{
601618
jj_consume_token(21);
@@ -612,7 +629,7 @@ final public SemgrexPattern Root() throws ParseException {// Root pattern for th
612629
break;
613630
}
614631
default:
615-
jj_la1[27] = jj_gen;
632+
jj_la1[28] = jj_gen;
616633
;
617634
}
618635
pat = new NodePattern(r, underNodeNegation, attributes.attributes(), attributes.root(), attributes.empty(), link, name != null ? name.image : null);
@@ -629,13 +646,13 @@ final public SemgrexPattern Root() throws ParseException {// Root pattern for th
629646
public Token jj_nt;
630647
private int jj_ntk;
631648
private int jj_gen;
632-
final private int[] jj_la1 = new int[28];
649+
final private int[] jj_la1 = new int[29];
633650
static private int[] jj_la1_0;
634651
static {
635652
jj_la1_init_0();
636653
}
637654
private static void jj_la1_init_0() {
638-
jj_la1_0 = new int[] {0x400,0x428808,0x3801c,0x3801c,0x428800,0x2000,0x3c01c,0x4000,0x3801c,0x2001c,0x80000,0x10,0x110,0x110,0x100000,0x200000,0x1c,0x428800,0x2000,0x42c000,0x4000,0x428000,0x420000,0x110,0xd0,0x800000,0xd0,0x200000,};
655+
jj_la1_0 = new int[] {0x400,0x828808,0x3801c,0x3801c,0x828800,0x2000,0x3c01c,0x4000,0x3801c,0x2001c,0x80000,0x10,0x110,0x110,0x100000,0x200000,0x1c,0x828800,0x2000,0x82c000,0x4000,0x828000,0x820000,0x400400,0x110,0xd0,0x1000000,0xd0,0x200000,};
639656
}
640657

641658
/** Constructor with InputStream. */
@@ -649,7 +666,7 @@ public SemgrexParser(java.io.InputStream stream, String encoding) {
649666
token = new Token();
650667
jj_ntk = -1;
651668
jj_gen = 0;
652-
for (int i = 0; i < 28; i++) jj_la1[i] = -1;
669+
for (int i = 0; i < 29; i++) jj_la1[i] = -1;
653670
}
654671

655672
/** Reinitialise. */
@@ -663,7 +680,7 @@ public void ReInit(java.io.InputStream stream, String encoding) {
663680
token = new Token();
664681
jj_ntk = -1;
665682
jj_gen = 0;
666-
for (int i = 0; i < 28; i++) jj_la1[i] = -1;
683+
for (int i = 0; i < 29; i++) jj_la1[i] = -1;
667684
}
668685

669686
/** Constructor. */
@@ -673,7 +690,7 @@ public SemgrexParser(java.io.Reader stream) {
673690
token = new Token();
674691
jj_ntk = -1;
675692
jj_gen = 0;
676-
for (int i = 0; i < 28; i++) jj_la1[i] = -1;
693+
for (int i = 0; i < 29; i++) jj_la1[i] = -1;
677694
}
678695

679696
/** Reinitialise. */
@@ -691,7 +708,7 @@ public void ReInit(java.io.Reader stream) {
691708
token = new Token();
692709
jj_ntk = -1;
693710
jj_gen = 0;
694-
for (int i = 0; i < 28; i++) jj_la1[i] = -1;
711+
for (int i = 0; i < 29; i++) jj_la1[i] = -1;
695712
}
696713

697714
/** Constructor with generated Token Manager. */
@@ -700,7 +717,7 @@ public SemgrexParser(SemgrexParserTokenManager tm) {
700717
token = new Token();
701718
jj_ntk = -1;
702719
jj_gen = 0;
703-
for (int i = 0; i < 28; i++) jj_la1[i] = -1;
720+
for (int i = 0; i < 29; i++) jj_la1[i] = -1;
704721
}
705722

706723
/** Reinitialise. */
@@ -709,7 +726,7 @@ public void ReInit(SemgrexParserTokenManager tm) {
709726
token = new Token();
710727
jj_ntk = -1;
711728
jj_gen = 0;
712-
for (int i = 0; i < 28; i++) jj_la1[i] = -1;
729+
for (int i = 0; i < 29; i++) jj_la1[i] = -1;
713730
}
714731

715732
private Token jj_consume_token(int kind) throws ParseException {
@@ -760,12 +777,12 @@ private int jj_ntk_f() {
760777
/** Generate ParseException. */
761778
public ParseException generateParseException() {
762779
jj_expentries.clear();
763-
boolean[] la1tokens = new boolean[25];
780+
boolean[] la1tokens = new boolean[26];
764781
if (jj_kind >= 0) {
765782
la1tokens[jj_kind] = true;
766783
jj_kind = -1;
767784
}
768-
for (int i = 0; i < 28; i++) {
785+
for (int i = 0; i < 29; i++) {
769786
if (jj_la1[i] == jj_gen) {
770787
for (int j = 0; j < 32; j++) {
771788
if ((jj_la1_0[i] & (1<<j)) != 0) {
@@ -774,7 +791,7 @@ public ParseException generateParseException() {
774791
}
775792
}
776793
}
777-
for (int i = 0; i < 25; i++) {
794+
for (int i = 0; i < 26; i++) {
778795
if (la1tokens[i]) {
779796
jj_expentry = new int[1];
780797
jj_expentry[0] = i;

‎src/edu/stanford/nlp/semgraph/semgrex/SemgrexParser.jj

+9-3
Original file line numberDiff line numberDiff line change
@@ -272,9 +272,15 @@ SemgrexPattern Child(GraphRelation r) : {
272272
void AddAttribute(NodeAttributes attributes) : {
273273
Token attr = null;
274274
Token value = null;
275+
Token attrType = null;
275276
} {
276-
((attr = <IDENTIFIER> ":" (value = <IDENTIFIER> | value = <REGEX>) )
277-
{ if (attr != null && value != null) attributes.setAttribute(attr.image, value.image); } )
277+
((attr = <IDENTIFIER> (attrType = ":" | attrType = "!:") (value = <IDENTIFIER> | value = <REGEX>) )
278+
{
279+
if (attr != null && value != null) {
280+
boolean negated = attrType.image.equals("!:");
281+
attributes.setAttribute(attr.image, value.image, negated);
282+
}
283+
})
278284
|
279285
( attr = <ROOT> { attributes.setRoot(true); } )
280286
|
@@ -288,7 +294,7 @@ NodePattern Description(GraphRelation r) : {
288294
NodePattern pat;
289295
} {
290296

291-
( "{" ( AddAttribute(attributes)
297+
( "{" ( AddAttribute(attributes)
292298
(";" AddAttribute(attributes))* )? "}"
293299

294300
(( ("=" { link = true; }) name = <IDENTIFIER> )

‎src/edu/stanford/nlp/semgraph/semgrex/SemgrexParserConstants.java

+1
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ interface SemgrexParserConstants {
5454
"\",\"",
5555
"\"~\"",
5656
"\"=\"",
57+
"\"!:\"",
5758
"\"{\"",
5859
"\";\"",
5960
"\"}\"",

‎src/edu/stanford/nlp/semgraph/semgrex/SemgrexParserTokenManager.java

+32-7
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,12 @@ class SemgrexParserTokenManager implements SemgrexParserConstants {
2121
private final int jjStopStringLiteralDfa_0(int pos, long active0){
2222
switch (pos)
2323
{
24+
case 0:
25+
if ((active0 & 0x200000L) != 0L)
26+
return 2;
27+
if ((active0 & 0x80L) != 0L)
28+
return 25;
29+
return -1;
2430
default :
2531
return -1;
2632
}
@@ -40,7 +46,8 @@ private int jjMoveStringLiteralDfa0_0(){
4046
case 10:
4147
return jjStopAtPos(0, 9);
4248
case 33:
43-
return jjStopAtPos(0, 15);
49+
jjmatchedKind = 15;
50+
return jjMoveStringLiteralDfa1_0(0x400000L);
4451
case 35:
4552
return jjStopAtPos(0, 6);
4653
case 36:
@@ -56,7 +63,7 @@ private int jjMoveStringLiteralDfa0_0(){
5663
case 58:
5764
return jjStopAtPos(0, 10);
5865
case 59:
59-
return jjStopAtPos(0, 23);
66+
return jjStopAtPos(0, 24);
6067
case 61:
6168
return jjStartNfaWithStates_0(0, 21, 2);
6269
case 63:
@@ -68,17 +75,34 @@ private int jjMoveStringLiteralDfa0_0(){
6875
case 93:
6976
return jjStopAtPos(0, 18);
7077
case 123:
71-
return jjStopAtPos(0, 22);
78+
return jjStopAtPos(0, 23);
7279
case 124:
7380
return jjStopAtPos(0, 13);
7481
case 125:
75-
return jjStopAtPos(0, 24);
82+
return jjStopAtPos(0, 25);
7683
case 126:
7784
return jjStopAtPos(0, 20);
7885
default :
7986
return jjMoveNfa_0(1, 0);
8087
}
8188
}
89+
private int jjMoveStringLiteralDfa1_0(long active0){
90+
try { curChar = input_stream.readChar(); }
91+
catch(java.io.IOException e) {
92+
jjStopStringLiteralDfa_0(0, active0);
93+
return 1;
94+
}
95+
switch(curChar)
96+
{
97+
case 58:
98+
if ((active0 & 0x400000L) != 0L)
99+
return jjStopAtPos(1, 22);
100+
break;
101+
default :
102+
break;
103+
}
104+
return jjStartNfa_0(0, active0);
105+
}
82106
private int jjStartNfaWithStates_0(int pos, int kind, int state)
83107
{
84108
jjmatchedKind = kind;
@@ -333,8 +357,8 @@ else if (curChar < 128)
333357
/** Token literal values. */
334358
public static final String[] jjstrLiteralImages = {
335359
"", null, null, "\100", null, null, "\43", "\44", null, "\12", "\72", "\50",
336-
"\51", "\174", "\46", "\41", "\77", "\133", "\135", "\54", "\176", "\75", "\173",
337-
"\73", "\175", };
360+
"\51", "\174", "\46", "\41", "\77", "\133", "\135", "\54", "\176", "\75", "\41\72",
361+
"\173", "\73", "\175", };
338362
protected Token jjFillToken()
339363
{
340364
final Token t;
@@ -571,9 +595,10 @@ public void SwitchTo(int lexState)
571595
/** Lex State array. */
572596
public static final int[] jjnewLexState = {
573597
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
598+
-1,
574599
};
575600
static final long[] jjtoToken = {
576-
0x1fffffdL,
601+
0x3fffffdL,
577602
};
578603
static final long[] jjtoSkip = {
579604
0x2L,

‎test/src/edu/stanford/nlp/semgraph/semgrex/SemgrexTest.java

+7
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,13 @@ public void testRegex() {
215215
"Bill");
216216
}
217217

218+
public void testNegatedRegex() {
219+
runTest("{word!:/Bill/}", "[ate subj>Bill obj>[muffins compound>blueberry]]",
220+
"ate", "blueberry", "muffins");
221+
runTest("{word!:/.*i.*/}", "[ate subj>Bill obj>[muffins compound>blueberry]]",
222+
"ate", "blueberry");
223+
}
224+
218225
public void testReferencedRegex() {
219226
runTest("{word:/Bill/}", "[ate subj>Bill obj>[bill det>the]]",
220227
"Bill");

0 commit comments

Comments
 (0)
Please sign in to comment.