@@ -672,11 +672,12 @@ struct Tokens(Vec<Token>);
672
672
impl Tokens {
673
673
fn push ( & mut self , mut token : Token ) {
674
674
// Normalize / clean the token.
675
- if let Token :: Alternates ( alternates) = & mut token {
675
+ if let Token :: Alternates ( mut alternates) = token {
676
+ let mut contains_empty = false ;
676
677
let mut contains_wildcard = false ;
677
678
alternates. retain_mut ( |alternate| {
678
- // Empty groups can just be ignored and skipped.
679
679
if alternate. 0 . is_empty ( ) {
680
+ contains_empty = true ;
680
681
return false ;
681
682
}
682
683
@@ -687,10 +688,38 @@ impl Tokens {
687
688
true
688
689
} ) ;
689
690
690
- // If any of the alternations contains a wildcard, we can fold the entire
691
- // alternation into a single wildcard.
691
+ // At this point `alternates` contains only the nonempty branches
692
+ // and we additionally know
693
+ // * if one of the branches was just a wildcard
694
+ // * if there were any empty branches.
695
+ //
696
+ // We can push different tokens based on this.
692
697
if contains_wildcard {
698
+ // Case: {foo,*,} -> reduces to *
693
699
token = Token :: Wildcard ;
700
+ } else if alternates. len ( ) == 1 {
701
+ if contains_empty {
702
+ // Case: {foo*bar,} -> Optional(foo*bar)
703
+ token = Token :: Optional ( alternates. remove ( 0 ) . 0 ) ;
704
+ } else {
705
+ // Case: {foo*bar} -> remove the alternation and
706
+ // push foo*bar directly
707
+ for t in alternates. remove ( 0 ) . 0 {
708
+ self . push ( t) ;
709
+ }
710
+ return ;
711
+ }
712
+ } else if alternates. len ( ) > 1 {
713
+ if contains_empty {
714
+ // Case: {foo,bar,} -> Optional({foo,bar})
715
+ token = Token :: Optional ( vec ! [ Token :: Alternates ( alternates) ] ) ;
716
+ } else {
717
+ // Case: {foo, bar} -> can stay as it is
718
+ token = Token :: Alternates ( alternates) ;
719
+ }
720
+ } else {
721
+ // Case: {,,,} -> reduces to {}
722
+ token = Token :: Alternates ( vec ! [ ] ) ;
694
723
}
695
724
}
696
725
0 commit comments