@@ -131,7 +131,7 @@ static Relation getRelation(String s,
131
131
/**
132
132
* Static factory method for relations requiring an argument, including
133
133
* HAS_ITH_CHILD, ITH_CHILD_OF, UNBROKEN_CATEGORY_DOMINATES,
134
- * UNBROKEN_CATEGORY_DOMINATED_BY.
134
+ * UNBROKEN_CATEGORY_DOMINATED_BY, ANCESTOR_OF_ITH_LEAF .
135
135
*
136
136
* @param s The String representation of the relation
137
137
* @param arg The argument to the relation, as a string; could be a node
@@ -168,6 +168,9 @@ static Relation getRelation(String s, String arg,
168
168
case ",+" :
169
169
r = new UnbrokenCategoryFollows (arg , basicCatFunction );
170
170
break ;
171
+ case "<<<" :
172
+ r = new AncestorOfIthLeaf (Integer .parseInt (arg ));
173
+ break ;
171
174
default :
172
175
throw new ParseException ("Unrecognized compound relation " + s + ' '
173
176
+ arg );
@@ -362,6 +365,89 @@ void advance() {
362
365
}
363
366
};
364
367
368
+ /**
369
+ * Looks for the ith leaf of the current node
370
+ */
371
+ private static class AncestorOfIthLeaf extends Relation {
372
+
373
+ private static final long serialVersionUID = -6495191354526L ;
374
+
375
+ private final int leafNum ;
376
+
377
+ AncestorOfIthLeaf (int i ) {
378
+ super ("<<<" + String .valueOf (i ));
379
+ if (i == 0 ) {
380
+ throw new IllegalArgumentException ("Error -- no such thing as zeroth leaf!" );
381
+ }
382
+ leafNum = i ;
383
+ }
384
+
385
+ @ Override
386
+ boolean satisfies (Tree t1 , Tree t2 , Tree root , final TregexMatcher matcher ) {
387
+ if (t1 == t2 )
388
+ return false ;
389
+ if (!t2 .isLeaf ())
390
+ return false ;
391
+ // this is kind of lazy
392
+ // if it somehow became a performance limitation,
393
+ // a recursive search would be faster
394
+ List <Tree > leaves = t1 .getLeaves ();
395
+ if (leaves .size () < Math .abs (leafNum ))
396
+ return false ;
397
+
398
+ final int index ;
399
+ if (leafNum > 0 ) {
400
+ index = leafNum - 1 ;
401
+ } else {
402
+ // eg, leafNum == -1 means we check leaves.size() - 1
403
+ index = leaves .size () + leafNum ;
404
+ }
405
+ return leaves .get (index ) == t2 ;
406
+ }
407
+
408
+ @ Override
409
+ Iterator <Tree > searchNodeIterator (final Tree t ,
410
+ final TregexMatcher matcher ) {
411
+ return new SearchNodeIterator () {
412
+ @ Override
413
+ void initialize () {
414
+ List <Tree > leaves = t .getLeaves ();
415
+ if (leaves .size () >= Math .abs (leafNum )) {
416
+ final int index ;
417
+ if (leafNum > 0 ) {
418
+ index = leafNum - 1 ;
419
+ } else {
420
+ index = leafNum + leaves .size ();
421
+ }
422
+ next = leaves .get (index );
423
+ }
424
+ }
425
+ };
426
+ }
427
+
428
+ @ Override
429
+ public boolean equals (Object o ) {
430
+ if (this == o ) {
431
+ return true ;
432
+ }
433
+ if (!(o instanceof AncestorOfIthLeaf )) {
434
+ return false ;
435
+ }
436
+
437
+ final AncestorOfIthLeaf other = (AncestorOfIthLeaf ) o ;
438
+ if (leafNum != other .leafNum ) {
439
+ return false ;
440
+ }
441
+
442
+ return true ;
443
+ }
444
+
445
+ @ Override
446
+ public int hashCode () {
447
+ return leafNum + 20 ;
448
+ }
449
+ };
450
+
365
451
private static final Relation DOMINATES = new Relation ("<<" ) {
366
452
367
453
private static final long serialVersionUID = -2580199434621268260L ;
0 commit comments