@@ -488,12 +488,15 @@ public Node(Token nodeType, Node child) {
488
488
Preconditions .checkArgument (child .parent == null ,
489
489
"new child has existing parent" );
490
490
Preconditions .checkArgument (child .next == null ,
491
- "new child has existing sibling" );
491
+ "new child has existing next sibling" );
492
+ Preconditions .checkArgument (child .previous == null ,
493
+ "new child has existing previous sibling" );
492
494
493
495
token = nodeType ;
494
496
parent = null ;
495
497
first = last = child ;
496
498
child .next = null ;
499
+ child .previous = null ;
497
500
child .parent = this ;
498
501
sourcePosition = -1 ;
499
502
}
@@ -502,62 +505,82 @@ public Node(Token nodeType, Node left, Node right) {
502
505
Preconditions .checkArgument (left .parent == null ,
503
506
"first new child has existing parent" );
504
507
Preconditions .checkArgument (left .next == null ,
505
- "first new child has existing sibling" );
508
+ "first new child has existing next sibling" );
509
+ Preconditions .checkArgument (left .previous == null ,
510
+ "first new child has existing previous sibling" );
506
511
Preconditions .checkArgument (right .parent == null ,
507
512
"second new child has existing parent" );
508
513
Preconditions .checkArgument (right .next == null ,
509
- "second new child has existing sibling" );
514
+ "second new child has existing next sibling" );
515
+ Preconditions .checkArgument (right .previous == null ,
516
+ "second new child has existing previous sibling" );
510
517
token = nodeType ;
511
518
parent = null ;
512
519
first = left ;
513
520
last = right ;
514
521
left .next = right ;
522
+ left .previous = null ;
515
523
left .parent = this ;
516
524
right .next = null ;
525
+ right .previous = left ;
517
526
right .parent = this ;
518
527
sourcePosition = -1 ;
519
528
}
520
529
521
530
public Node (Token nodeType , Node left , Node mid , Node right ) {
522
531
Preconditions .checkArgument (left .parent == null );
523
532
Preconditions .checkArgument (left .next == null );
533
+ Preconditions .checkArgument (left .previous == null );
524
534
Preconditions .checkArgument (mid .parent == null );
525
535
Preconditions .checkArgument (mid .next == null );
536
+ Preconditions .checkArgument (mid .previous == null );
526
537
Preconditions .checkArgument (right .parent == null );
527
538
Preconditions .checkArgument (right .next == null );
539
+ Preconditions .checkArgument (right .previous == null );
528
540
token = nodeType ;
529
541
parent = null ;
530
542
first = left ;
531
543
last = right ;
532
544
left .next = mid ;
545
+ left .previous = null ;
533
546
left .parent = this ;
534
547
mid .next = right ;
548
+ mid .previous = left ;
535
549
mid .parent = this ;
536
550
right .next = null ;
551
+ right .previous = mid ;
537
552
right .parent = this ;
538
553
sourcePosition = -1 ;
539
554
}
540
555
541
556
Node (Token nodeType , Node left , Node mid , Node mid2 , Node right ) {
542
557
Preconditions .checkArgument (left .parent == null );
543
558
Preconditions .checkArgument (left .next == null );
559
+ Preconditions .checkArgument (left .previous == null );
544
560
Preconditions .checkArgument (mid .parent == null );
545
561
Preconditions .checkArgument (mid .next == null );
562
+ Preconditions .checkArgument (mid .previous == null );
546
563
Preconditions .checkArgument (mid2 .parent == null );
547
564
Preconditions .checkArgument (mid2 .next == null );
565
+ Preconditions .checkArgument (mid2 .previous == null );
548
566
Preconditions .checkArgument (right .parent == null );
549
567
Preconditions .checkArgument (right .next == null );
568
+ Preconditions .checkArgument (right .previous == null );
550
569
token = nodeType ;
551
570
parent = null ;
552
571
first = left ;
553
572
last = right ;
554
573
left .next = mid ;
574
+ left .previous = null ;
555
575
left .parent = this ;
556
576
mid .next = mid2 ;
577
+ mid .previous = left ;
557
578
mid .parent = this ;
558
579
mid2 .next = right ;
580
+ mid2 .previous = mid ;
559
581
mid2 .parent = this ;
560
582
right .next = null ;
583
+ right .previous = mid2 ;
561
584
right .parent = this ;
562
585
sourcePosition = -1 ;
563
586
}
@@ -638,21 +661,7 @@ public Node getNext() {
638
661
}
639
662
640
663
public Node getChildBefore (Node child ) {
641
- if (child == first ) {
642
- return null ;
643
- }
644
- Node n = first ;
645
- if (n == null ) {
646
- throw new RuntimeException ("node is not a child" );
647
- }
648
-
649
- while (n .next != child ) {
650
- n = n .next ;
651
- if (n == null ) {
652
- throw new RuntimeException ("node is not a child" );
653
- }
654
- }
655
- return n ;
664
+ return child .previous ;
656
665
}
657
666
658
667
public Node getChildAtIndex (int i ) {
@@ -689,8 +698,12 @@ public Node getLastSibling() {
689
698
public void addChildToFront (Node child ) {
690
699
Preconditions .checkArgument (child .parent == null );
691
700
Preconditions .checkArgument (child .next == null );
701
+ Preconditions .checkArgument (child .previous == null );
692
702
child .parent = this ;
693
703
child .next = first ;
704
+ if (first != null ) {
705
+ first .previous = child ;
706
+ }
694
707
first = child ;
695
708
if (last == null ) {
696
709
last = child ;
@@ -700,8 +713,10 @@ public void addChildToFront(Node child) {
700
713
public void addChildToBack (Node child ) {
701
714
Preconditions .checkArgument (child .parent == null );
702
715
Preconditions .checkArgument (child .next == null );
716
+ Preconditions .checkArgument (child .previous == null );
703
717
child .parent = this ;
704
718
child .next = null ;
719
+ child .previous = last ;
705
720
if (last == null ) {
706
721
first = last = child ;
707
722
return ;
@@ -716,7 +731,11 @@ public void addChildrenToFront(Node children) {
716
731
child .parent = this ;
717
732
}
718
733
Node lastSib = children .getLastSibling ();
734
+ Preconditions .checkState (lastSib .next == null );
719
735
lastSib .next = first ;
736
+ if (first != null ) {
737
+ first .previous = lastSib ;
738
+ }
720
739
first = children ;
721
740
if (last == null ) {
722
741
last = lastSib ;
@@ -734,25 +753,29 @@ public void addChildBefore(Node newChild, Node node) {
734
753
Preconditions .checkArgument (node != null && node .parent == this ,
735
754
"The existing child node of the parent should not be null." );
736
755
Preconditions .checkArgument (newChild .next == null ,
737
- "The new child node has siblings." );
756
+ "The new child node has next siblings." );
757
+ Preconditions .checkArgument (newChild .previous == null ,
758
+ "The new child node has previous siblings." );
738
759
Preconditions .checkArgument (newChild .parent == null ,
739
760
"The new child node already has a parent." );
740
761
if (first == node ) {
741
762
newChild .parent = this ;
742
763
newChild .next = first ;
764
+ first .previous = newChild ;
743
765
first = newChild ;
744
766
return ;
745
767
}
746
- Node prev = getChildBefore (node );
747
- addChildAfter (newChild , prev );
768
+ addChildAfter (newChild , node .previous );
748
769
}
749
770
750
771
/**
751
772
* Add 'child' after 'node'.
752
773
*/
753
774
public void addChildAfter (Node newChild , Node node ) {
754
775
Preconditions .checkArgument (newChild .next == null ,
755
- "The new child node has siblings." );
776
+ "The new child node has next siblings." );
777
+ Preconditions .checkArgument (newChild .previous == null ,
778
+ "The new child node has previous siblings." );
756
779
addChildrenAfter (newChild , node );
757
780
}
758
781
@@ -770,14 +793,19 @@ public void addChildrenAfter(Node children, Node node) {
770
793
if (node != null ) {
771
794
Node oldNext = node .next ;
772
795
node .next = children ;
796
+ children .previous = node ;
773
797
lastSibling .next = oldNext ;
798
+ if (oldNext != null ) {
799
+ oldNext .previous = lastSibling ;
800
+ }
774
801
if (node == last ) {
775
802
last = lastSibling ;
776
803
}
777
804
} else {
778
805
// Append to the beginning.
779
806
if (first != null ) {
780
807
lastSibling .next = first ;
808
+ first .previous = lastSibling ;
781
809
} else {
782
810
last = lastSibling ;
783
811
}
@@ -789,16 +817,21 @@ public void addChildrenAfter(Node children, Node node) {
789
817
* Detach a child from its parent and siblings.
790
818
*/
791
819
public void removeChild (Node child ) {
792
- Node prev = getChildBefore (child );
793
- if (prev == null ) {
794
- first = first .next ;
795
- } else {
820
+ Node prev = child .previous ;
821
+ if (first == child ) {
822
+ first = child .next ;
823
+ }
824
+ if (prev != null ) {
796
825
prev .next = child .next ;
797
826
}
798
- if (child == last ) {
827
+ if (last == child ) {
799
828
last = prev ;
800
829
}
830
+ if (child .next != null ) {
831
+ child .next .previous = prev ;
832
+ }
801
833
child .next = null ;
834
+ child .previous = null ;
802
835
child .parent = null ;
803
836
}
804
837
@@ -807,49 +840,61 @@ public void removeChild(Node child) {
807
840
*/
808
841
public void replaceChild (Node child , Node newChild ) {
809
842
Preconditions .checkArgument (newChild .next == null ,
810
- "The new child node has siblings." );
843
+ "The new child node has next siblings." );
844
+ Preconditions .checkArgument (newChild .previous == null ,
845
+ "The new child node has previous siblings." );
811
846
Preconditions .checkArgument (newChild .parent == null ,
812
847
"The new child node already has a parent." );
813
848
814
849
// Copy over important information.
815
850
newChild .copyInformationFrom (child );
816
851
817
852
newChild .next = child .next ;
853
+ newChild .previous = child .previous ;
818
854
newChild .parent = this ;
819
855
if (child == first ) {
820
856
first = newChild ;
821
857
} else {
822
- Node prev = getChildBefore (child );
823
- prev .next = newChild ;
858
+ child .previous .next = newChild ;
824
859
}
825
860
if (child == last ) {
826
861
last = newChild ;
862
+ } else {
863
+ child .next .previous = newChild ;
827
864
}
828
865
child .next = null ;
866
+ child .previous = null ;
829
867
child .parent = null ;
830
868
}
831
869
832
870
public void replaceChildAfter (Node prevChild , Node newChild ) {
833
871
Preconditions .checkArgument (prevChild .parent == this ,
834
872
"prev is not a child of this node." );
835
-
873
+ Preconditions .checkArgument (prevChild .next != null ,
874
+ "prev is doesn't have a sibling to replace." );
836
875
Preconditions .checkArgument (newChild .next == null ,
837
- "The new child node has siblings." );
876
+ "The new child node has next siblings." );
877
+ Preconditions .checkArgument (newChild .previous == null ,
878
+ "The new child node has previous siblings." );
838
879
Preconditions .checkArgument (newChild .parent == null ,
839
880
"The new child node already has a parent." );
840
881
841
882
// Copy over important information.
842
- newChild .copyInformationFrom (prevChild );
883
+ newChild .copyInformationFrom (prevChild . next );
843
884
844
- Node child = prevChild .next ;
845
- newChild .next = child .next ;
885
+ Node childToReplace = prevChild .next ;
886
+ newChild .next = childToReplace .next ;
887
+ newChild .previous = prevChild ;
846
888
newChild .parent = this ;
847
889
prevChild .next = newChild ;
848
- if (child == last ) {
890
+ if (childToReplace == last ) {
849
891
last = newChild ;
892
+ } else {
893
+ childToReplace .next .previous = newChild ;
850
894
}
851
- child .next = null ;
852
- child .parent = null ;
895
+ childToReplace .next = null ;
896
+ childToReplace .previous = null ;
897
+ childToReplace .parent = null ;
853
898
}
854
899
855
900
/** Detaches the child after the given child, or the first child if prev is null. */
@@ -1163,6 +1208,7 @@ private static void toStringTreeHelper(Node n, int level, Appendable sb)
1163
1208
1164
1209
Token token ; // Type of the token of the node; NAME for example
1165
1210
Node next ; // next sibling
1211
+ Node previous ; // previous sibling
1166
1212
private Node first ; // first element of a linked list of children
1167
1213
private Node last ; // last element of a linked list of children
1168
1214
@@ -1977,6 +2023,7 @@ public void detachChildren() {
1977
2023
Node nextChild = child .getNext ();
1978
2024
child .parent = null ;
1979
2025
child .next = null ;
2026
+ child .previous = null ;
1980
2027
child = nextChild ;
1981
2028
}
1982
2029
first = null ;
@@ -1989,14 +2036,18 @@ public Node removeChildAfter(Node prev) {
1989
2036
Preconditions .checkArgument (prev .next != null ,
1990
2037
"no next sibling." );
1991
2038
1992
- Node child = prev .next ;
1993
- prev .next = child .next ;
1994
- if (child == last ) {
2039
+ Node childToRemove = prev .next ;
2040
+ prev .next = childToRemove .next ;
2041
+ if (childToRemove == last ) {
1995
2042
last = prev ;
1996
2043
}
1997
- child .next = null ;
1998
- child .parent = null ;
1999
- return child ;
2044
+ if (childToRemove .next != null ) {
2045
+ childToRemove .next .previous = prev ;
2046
+ }
2047
+ childToRemove .next = null ;
2048
+ childToRemove .previous = null ;
2049
+ childToRemove .parent = null ;
2050
+ return childToRemove ;
2000
2051
}
2001
2052
2002
2053
/** Remove the child after the given child, or the first child if given null. */
@@ -2051,6 +2102,7 @@ public Node cloneTree(boolean cloneTypeExprs) {
2051
2102
n2clone .parent = result ;
2052
2103
if (result .last != null ) {
2053
2104
result .last .next = n2clone ;
2105
+ n2clone .previous = result .last ;
2054
2106
}
2055
2107
if (result .first == null ) {
2056
2108
result .first = n2clone ;
0 commit comments