Skip to content

Commit 350f142

Browse files
committed
syntax: simplify alternations
This commit simplifies alternations by flattening them, similar to how a recent commit flattened concatenations. Although, this is simpler than concatenations, because we can't do anything with literals. Like concatenations, we only need to look one layer deep, since this is applied inductively.
1 parent da38fe7 commit 350f142

File tree

2 files changed

+41
-12
lines changed

2 files changed

+41
-12
lines changed

regex-syntax/src/hir/mod.rs

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -398,20 +398,29 @@ impl Hir {
398398
/// Returns the alternation of the given expressions.
399399
///
400400
/// This flattens the alternation as appropriate.
401-
pub fn alternation(mut exprs: Vec<Hir>) -> Hir {
402-
if exprs.is_empty() {
403-
return Hir::fail();
404-
} else if exprs.len() == 1 {
405-
return exprs.pop().unwrap();
406-
}
407-
match exprs.len() {
408-
0 => Hir::empty(),
409-
1 => exprs.pop().unwrap(),
410-
_ => {
411-
let props = Properties::alternation(&exprs);
412-
Hir { kind: HirKind::Alternation(exprs), props }
401+
pub fn alternation(hirs: Vec<Hir>) -> Hir {
402+
// We rebuild the alternation by simplifying it. We proceed similarly
403+
// as the concatenation case. But in this case, there's no literal
404+
// simplification happening. We're just flattening alternations.
405+
let mut new = vec![];
406+
for hir in hirs {
407+
let (kind, props) = hir.into_parts();
408+
match kind {
409+
HirKind::Alternation(hirs2) => {
410+
new.extend(hirs2);
411+
}
412+
kind => {
413+
new.push(Hir { kind, props });
414+
}
413415
}
414416
}
417+
if new.is_empty() {
418+
return Hir::fail();
419+
} else if new.len() == 1 {
420+
return new.pop().unwrap();
421+
}
422+
let props = Properties::alternation(&new);
423+
Hir { kind: HirKind::Alternation(new), props }
415424
}
416425

417426
/// Returns an HIR expression for `.`.

regex-syntax/src/hir/translate.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3335,4 +3335,24 @@ mod tests {
33353335
])
33363336
);
33373337
}
3338+
3339+
// This tests that the smart Hir::alternation constructor simplifies the
3340+
// given exprs in a way we expect.
3341+
#[test]
3342+
fn smart_alternation() {
3343+
assert_eq!(
3344+
t("(?:foo)|(?:bar)"),
3345+
hir_alt(vec![hir_lit("foo"), hir_lit("bar")])
3346+
);
3347+
assert_eq!(
3348+
t("quux|(?:abc|def|xyz)|baz"),
3349+
hir_alt(vec![
3350+
hir_lit("quux"),
3351+
hir_lit("abc"),
3352+
hir_lit("def"),
3353+
hir_lit("xyz"),
3354+
hir_lit("baz"),
3355+
])
3356+
);
3357+
}
33383358
}

0 commit comments

Comments
 (0)