Skip to content

Commit 6d4eec6

Browse files
committed
Parse Optionals
1 parent 0384bcb commit 6d4eec6

File tree

1 file changed

+33
-4
lines changed

1 file changed

+33
-4
lines changed

relay-pattern/src/lib.rs

+33-4
Original file line numberDiff line numberDiff line change
@@ -672,11 +672,12 @@ struct Tokens(Vec<Token>);
672672
impl Tokens {
673673
fn push(&mut self, mut token: Token) {
674674
// 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;
676677
let mut contains_wildcard = false;
677678
alternates.retain_mut(|alternate| {
678-
// Empty groups can just be ignored and skipped.
679679
if alternate.0.is_empty() {
680+
contains_empty = true;
680681
return false;
681682
}
682683

@@ -687,10 +688,38 @@ impl Tokens {
687688
true
688689
});
689690

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.
692697
if contains_wildcard {
698+
// Case: {foo,*,} -> reduces to *
693699
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![]);
694723
}
695724
}
696725

0 commit comments

Comments
 (0)