@@ -1571,6 +1571,89 @@ public void testOptionalToString() {
1571
1571
assertEquals ("Root (A ?[< B | < C ])" , pattern .toString ());
1572
1572
}
1573
1573
1574
+ /**
1575
+ * Tests the subtree pattern, <code><...</code>, which checks for
1576
+ * an exact subtree under our current tree, but test it as an optional relation.
1577
+ *<br>
1578
+ * Checks a bug reported by @tanloong (https://github.com/stanfordnlp/CoreNLP/issues/1375)
1579
+ *<br>
1580
+ * The optional subtree should only match exactly once,
1581
+ * but its buggy form was an infinite loop
1582
+ * (see CoordinationPattern for more notes on why)
1583
+ */
1584
+ public void testOptionalSubtreePattern () {
1585
+ runTest ("A ?<... { B ; C ; D }" , "(A (B 1) (C 2) (D 3))" , "(A (B 1) (C 2) (D 3))" );
1586
+ }
1587
+
1588
+ /**
1589
+ * The bug reported by @tanloong (https://github.com/stanfordnlp/CoreNLP/issues/1375)
1590
+ * actually applied to <i>all</i> optional coordination patterns
1591
+ *<br>
1592
+ * Here we check that a simpler optional conjunction also fails
1593
+ */
1594
+ public void testOptionalChild () {
1595
+ runTest ("A ?(< B <C)" , "(A (B 1) (C 2) (D 3))" , "(A (B 1) (C 2) (D 3))" );
1596
+ }
1597
+
1598
+ /**
1599
+ * An optional coordination which doesn't hit should also match exactly once
1600
+ */
1601
+ public void testOptionalChildMiss () {
1602
+ runTest ("A ?(< B < E)" , "(A (B 1) (C 2) (D 3))" , "(A (B 1) (C 2) (D 3))" );
1603
+ }
1604
+
1605
+ /**
1606
+ * An optional disjunction coordination should match at least once,
1607
+ * but not match any extra times just because of the optional
1608
+ */
1609
+ public void testOptionalDisjunction () {
1610
+ // this matches once as an optional, even though none of the children match
1611
+ runTest ("A ?[< E | < F]" , "(A (B 1) (C 2) (D 3))" , "(A (B 1) (C 2) (D 3))" );
1612
+
1613
+ // this matches twice
1614
+ runTest ("A ?[< B | < C]" , "(A (B 1) (C 2))" , "(A (B 1) (C 2))" , "(A (B 1) (C 2))" );
1615
+ // this matches once, since the (< E) is useless
1616
+ runTest ("A ?[< B | < E]" , "(A (B 1) (C 2) (D 3))" , "(A (B 1) (C 2) (D 3))" );
1617
+ // now it will match twice, since the B should match twice
1618
+ runTest ("A ?[< B | < E]" , "(A (B 1) (C 2) (B 3))" , "(A (B 1) (C 2) (B 3))" , "(A (B 1) (C 2) (B 3))" );
1619
+
1620
+ // check by hand that foo & bar are set as expected for the disjunction matches
1621
+ // note that the order will be the order of the disjunction then subtrees,
1622
+ // not sorted by the order of the subtrees
1623
+ TregexPattern pattern = TregexPattern .compile ("A ?[< B=foo | < C=bar]" );
1624
+ Tree tree = treeFromString ("(A (B 1) (C 2) (B 3))" );
1625
+ TregexMatcher matcher = pattern .matcher (tree );
1626
+ assertTrue (matcher .find ());
1627
+ assertEquals ("(B 1)" , matcher .getNode ("foo" ).toString ());
1628
+ assertNull (matcher .getNode ("bar" ));
1629
+
1630
+ assertTrue (matcher .find ());
1631
+ assertEquals ("(B 3)" , matcher .getNode ("foo" ).toString ());
1632
+ assertNull (matcher .getNode ("bar" ));
1633
+
1634
+ assertTrue (matcher .find ());
1635
+ assertNull (matcher .getNode ("foo" ));
1636
+ assertEquals ("(C 2)" , matcher .getNode ("bar" ).toString ());
1637
+
1638
+ assertFalse (matcher .find ());
1639
+
1640
+ // this example should also work if the same name is used
1641
+ // for both of the children!
1642
+ pattern = TregexPattern .compile ("A ?[< B=foo | < C=foo]" );
1643
+ matcher = pattern .matcher (tree );
1644
+ assertTrue (matcher .find ());
1645
+ assertEquals ("(B 1)" , matcher .getNode ("foo" ).toString ());
1646
+
1647
+ assertTrue (matcher .find ());
1648
+ assertEquals ("(B 3)" , matcher .getNode ("foo" ).toString ());
1649
+
1650
+ assertTrue (matcher .find ());
1651
+ assertEquals ("(C 2)" , matcher .getNode ("foo" ).toString ());
1652
+
1653
+ assertFalse (matcher .find ());
1654
+
1655
+ }
1656
+
1574
1657
/**
1575
1658
* A user supplied an example of a negated disjunction which went into an infinite loop.
1576
1659
* Apparently no one had ever used a negated disjunction of tree structures before!
0 commit comments