@@ -603,11 +603,18 @@ class NormalizedOptional implements NormalizedNodeBase {
603
603
)
604
604
}
605
605
606
- public decrementMax ( ) {
606
+ public decrementMax ( dec = 1 ) : NormalizedOptional | null {
607
+ if ( this . max <= dec ) {
608
+ return null
609
+ }
607
610
if ( this . max === Infinity ) {
608
611
return this
609
612
}
610
- const opt = new NormalizedOptional ( this . node , this . flags , this . max - 1 )
613
+ const opt = new NormalizedOptional (
614
+ this . node ,
615
+ this . flags ,
616
+ this . max - dec ,
617
+ )
611
618
opt . normalizedElement = this . normalizedElement
612
619
return opt
613
620
}
@@ -776,82 +783,93 @@ function isCoveredAnyNode(
776
783
/** Check whether the right nodes is covered by the left nodes. */
777
784
function isCoveredAltNodes (
778
785
/* eslint-enable complexity -- X( */
779
- left : NormalizedNode [ ] ,
780
- right : NormalizedNode [ ] ,
786
+ leftNodes : NormalizedNode [ ] ,
787
+ rightNodes : NormalizedNode [ ] ,
781
788
options : Options ,
782
- ) {
783
- let rightLength = right . length
784
- if ( options . canOmitRight ) {
785
- while ( right [ rightLength - 1 ] ) {
786
- const re = right [ rightLength - 1 ]
787
- if ( re . type === "NormalizedOptional" ) {
788
- rightLength --
789
- } else {
790
- break
791
- }
792
- }
793
- }
794
- let leftIndex = 0
795
- let rightIndex = 0
796
- while ( leftIndex < left . length && rightIndex < rightLength ) {
797
- const le = left [ leftIndex ]
798
- const re = right [ rightIndex ]
789
+ ) : boolean {
790
+ const left = options . canOmitRight ? omitEnds ( leftNodes ) : leftNodes
791
+ const right = options . canOmitRight ? omitEnds ( rightNodes ) : rightNodes
792
+ while ( left . length && right . length ) {
793
+ const le = left . shift ( ) !
794
+ const re = right . shift ( ) !
799
795
800
796
if ( re . type === "NormalizedOptional" ) {
801
- let leftElement
802
797
if ( le . type === "NormalizedOptional" ) {
803
- leftElement = le . element
798
+ // Check for elements
799
+ if (
800
+ ! isCoveredForNormalizedNode ( le . element , re . element , options )
801
+ ) {
802
+ return false
803
+ }
804
+ // Check for next
805
+ const decrementLe = le . decrementMax ( re . max )
806
+ if ( decrementLe ) {
807
+ return isCoveredAltNodes (
808
+ [ decrementLe , ...left ] ,
809
+ right ,
810
+ options ,
811
+ )
812
+ }
813
+ const decrementRe = re . decrementMax ( le . max )
814
+ if ( decrementRe ) {
815
+ return isCoveredAltNodes (
816
+ left ,
817
+ [ decrementRe , ...right ] ,
818
+ options ,
819
+ )
820
+ }
804
821
} else {
805
- leftElement = le
806
- }
807
- if ( ! isCoveredForNormalizedNode ( leftElement , re . element , options ) ) {
808
- return false
822
+ // Check for elements
823
+ if ( ! isCoveredForNormalizedNode ( le , re . element , options ) ) {
824
+ return false
825
+ }
826
+ const decrementRe = re . decrementMax ( )
827
+ if ( decrementRe ) {
828
+ // Check for multiple iterations.
829
+ return isCoveredAltNodes (
830
+ left ,
831
+ [ decrementRe , ...right ] ,
832
+ options ,
833
+ )
834
+ }
809
835
}
810
836
} else if ( le . type === "NormalizedOptional" ) {
811
837
// Checks if skipped.
812
- const skippedLeftItems = left . slice ( leftIndex + 1 )
813
- if (
814
- isCoveredAltNodes (
815
- skippedLeftItems ,
816
- right . slice ( rightIndex ) ,
817
- options ,
818
- )
819
- ) {
838
+ if ( isCoveredAltNodes ( left , [ re , ...right ] , options ) ) {
820
839
return true
821
840
}
822
841
if ( ! isCoveredForNormalizedNode ( le . element , re , options ) ) {
823
842
// I know it won't match if I skip it.
824
843
return false
825
844
}
826
- if ( le . max >= 2 ) {
845
+ const decrementLe = le . decrementMax ( )
846
+ if ( decrementLe ) {
827
847
// Check for multiple iterations.
828
- if (
829
- isCoveredAltNodes (
830
- [ le . decrementMax ( ) , ...skippedLeftItems ] ,
831
- right . slice ( rightIndex + 1 ) ,
832
- options ,
833
- )
834
- ) {
848
+ if ( isCoveredAltNodes ( [ decrementLe , ...left ] , right , options ) ) {
835
849
return true
836
850
}
837
851
}
838
852
} else if ( ! isCoveredForNormalizedNode ( le , re , options ) ) {
839
853
return false
840
854
}
841
- leftIndex ++
842
- rightIndex ++
843
855
}
844
856
if ( ! options . canOmitRight ) {
845
- if ( rightIndex < right . length ) {
857
+ if ( right . length ) {
846
858
return false
847
859
}
848
860
}
849
- while ( leftIndex < left . length ) {
850
- const le = left [ leftIndex ]
851
- if ( le . type !== "NormalizedOptional" ) {
852
- return false
861
+ return ! left . length
862
+ }
863
+
864
+ /**
865
+ * Exclude the end optionals.
866
+ */
867
+ function omitEnds ( nodes : NormalizedNode [ ] ) : NormalizedNode [ ] {
868
+ for ( let index = nodes . length - 1 ; index >= 0 ; index -- ) {
869
+ const node = nodes [ index ]
870
+ if ( node . type !== "NormalizedOptional" ) {
871
+ return nodes . slice ( 0 , index + 1 )
853
872
}
854
- leftIndex ++
855
873
}
856
- return leftIndex >= left . length
874
+ return [ ]
857
875
}
0 commit comments