1use re_parser::parse;
11use re_parser::pattern_width; fn report(pattern: &str) {
14 match parse(pattern) {
15 Err(e) => println!(" {pattern:40} ERROR: {e}"),
16 Ok(ast) => {
17 let min = ast.min_width();
18 let max = ast.max_width();
19 let max_str = max.map_or("∞".to_owned(), |n| n.to_string());
20 println!(" {pattern:40} min={min} max={max_str}");
21 }
22 }
23}
24
25fn main() {
26 println!("=== Fixed-width patterns ===");
27 report("abc");
28 report(r"\d{4}-\d{2}-\d{2}"); report(r"#[0-9a-fA-F]{6}"); report(r"[A-Z]{2}[0-9]{4}"); println!("\n=== Variable but bounded patterns ===");
33 report(r"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}"); report(r"https?://"); report(r"[a-zA-Z]{2,8}"); report(r"colou?r"); println!("\n=== Unbounded patterns ===");
39 report(r"\w+"); report(r".*"); report(r"\S+@\S+\.\S+"); report(r"(?:ab)+"); println!("\n=== Anchors and lookarounds are zero-width ===");
45 report(r"^hello$"); report(r"foo(?=bar)"); report(r"(?<=\d)px"); report(r"\bword\b"); println!("\n=== Alternation ===");
51 report(r"cat|dog"); report(r"a|bb|ccc"); report(r"yes|no"); report(r"x|\d+"); println!("\n=== pattern_width() convenience wrapper ===");
58 let w = pattern_width(r"a{2,5}").unwrap();
59 println!(" a{{2,5}} => {w}");
60 println!(" is_fixed: {}", w.is_fixed());
61 println!(" is_nullable: {}", w.is_nullable());
62 println!(" is_unbounded: {}", w.is_unbounded());
63
64 println!("\n=== Inspecting sub-nodes ===");
66 let ast = parse(r"(\d{4})-(\d{2})-(\d{2})").unwrap();
67 println!(" full pattern min={} max={:?}", ast.min_width(), ast.max_width());
68
69 if let re_parser::ast::Regex::Concat(nodes) = &ast {
71 for (i, node) in nodes.iter().enumerate() {
72 println!(
73 " child[{i}] min={} max={:?} node={node:?}",
74 node.min_width(),
75 node.max_width(),
76 );
77 }
78 }
79}