pub fn parse(pattern: &str) -> Result<Regex>Expand description
Parse a regex pattern string into an ast::Regex AST.
Returns error::ParseError on invalid syntax.
Examples found in repository?
examples/width.rs (line 14)
13fn 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}"); // ISO date → 10
29 report(r"#[0-9a-fA-F]{6}"); // CSS hex colour → 7
30 report(r"[A-Z]{2}[0-9]{4}"); // plate → 6
31
32 println!("\n=== Variable but bounded patterns ===");
33 report(r"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}"); // IPv4 → 7..=15
34 report(r"https?://"); // 7..=8
35 report(r"[a-zA-Z]{2,8}"); // 2..=8
36 report(r"colou?r"); // 5..=6
37
38 println!("\n=== Unbounded patterns ===");
39 report(r"\w+"); // 1..∞
40 report(r".*"); // 0..∞
41 report(r"\S+@\S+\.\S+"); // 5..∞
42 report(r"(?:ab)+"); // 2..∞
43
44 println!("\n=== Anchors and lookarounds are zero-width ===");
45 report(r"^hello$"); // anchors → still 5
46 report(r"foo(?=bar)"); // lookahead → 3
47 report(r"(?<=\d)px"); // lookbehind → 2
48 report(r"\bword\b"); // \b → 4
49
50 println!("\n=== Alternation ===");
51 report(r"cat|dog"); // exactly 3
52 report(r"a|bb|ccc"); // 1..=3
53 report(r"yes|no"); // 2..=3
54 report(r"x|\d+"); // 1..∞
55
56 // ── using pattern_width convenience function ───────────────────────────
57 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 // ── calling methods on a sub-node ──────────────────────────────────────
65 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 // Walk the top-level Concat children manually
70 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}More examples
examples/quantifiers.rs (line 26)
25fn print_quantifier(pattern: &str) {
26 let ast = parse(pattern).unwrap();
27 match &ast {
28 Regex::Quantifier(inner, kind, greedy) => {
29 println!(
30 " {pattern:10} => applied to {:?}, {}",
31 inner,
32 describe_quant(kind, *greedy)
33 );
34 }
35 other => println!(" {pattern:10} => {other:?}"),
36 }
37}
38
39fn main() {
40 println!("=== Greedy quantifiers ===");
41 print_quantifier("a*");
42 print_quantifier("a+");
43 print_quantifier("a?");
44 print_quantifier("a{3}");
45 print_quantifier("a{2,}");
46 print_quantifier("a{1,5}");
47
48 println!("\n=== Lazy (non-greedy) quantifiers ===");
49 print_quantifier("a*?");
50 print_quantifier("a+?");
51 print_quantifier("a??");
52 print_quantifier("a{2,6}?");
53
54 println!("\n=== Quantifier applied to a group ===");
55 let pattern = r"(\d+)?";
56 let ast = parse(pattern).unwrap();
57 println!(" {pattern} => {ast:#?}");
58}examples/ast_visitor.rs (line 92)
90fn analyse(pattern: &str) {
91 println!("┌─ Pattern: {pattern}");
92 let ast = parse(pattern).unwrap();
93
94 let total = count_nodes(&ast);
95 let mut lits = Vec::new();
96 collect_literals(&ast, &mut lits);
97 let lit_str: String = lits.iter().collect();
98
99 println!("│ nodes: {total}");
100 println!("│ literals: {lit_str:?}");
101 println!("└─ tree:");
102 pretty_print(&ast, 1);
103 println!();
104}examples/char_classes.rs (line 31)
30fn print_class(pattern: &str) {
31 let ast = parse(pattern).unwrap();
32 match &ast {
33 Regex::CharClass(cls) => {
34 let negated = if cls.negated { "negated, " } else { "" };
35 let items: Vec<_> = cls.items.iter().map(describe_item).collect();
36 println!(" {pattern:15} => [{negated}{}]", items.join(", "));
37 }
38 other => println!(" {pattern:15} => {other:?}"),
39 }
40}
41
42fn main() {
43 println!("=== Literal sets ===");
44 print_class("[abc]");
45 print_class("[aeiou]");
46
47 println!("\n=== Negated classes ===");
48 print_class("[^abc]");
49 print_class("[^0-9]");
50
51 println!("\n=== Character ranges ===");
52 print_class("[a-z]");
53 print_class("[A-Z]");
54 print_class("[0-9]");
55 print_class("[a-zA-Z]");
56
57 println!("\n=== Escape shorthands inside brackets ===");
58 print_class(r"[\d]");
59 print_class(r"[\w\s]");
60 print_class(r"[^\W_]"); // word chars minus underscore
61
62 println!("\n=== Mixed ===");
63 print_class(r"[a-z\d_]"); // lowercase letter, digit, or underscore
64 print_class(r"[^a-z\s]"); // not a lowercase letter and not whitespace
65
66 println!("\n=== Class inside a larger pattern ===");
67 let pattern = r"[A-Z][a-z]+";
68 println!(" Pattern: {pattern}");
69 println!(" AST:\n{:#?}", parse(pattern).unwrap());
70}examples/real_world_patterns.rs (line 60)
56fn report(label: &str, pattern: &str) {
57 println!("── {label} ──");
58 println!(" pattern : {pattern}");
59
60 match parse(pattern) {
61 Err(e) => println!(" ERROR : {e}"),
62 Ok(ast) => {
63 let captures = count_captures(&ast);
64 let anchored = is_fully_anchored(&ast);
65 let mut names = Vec::new();
66 named_groups(&ast, &mut names);
67
68 println!(" captures : {captures}");
69 println!(" anchored : {anchored}");
70 if !names.is_empty() {
71 println!(" named : {}", names.join(", "));
72 }
73 }
74 }
75 println!();
76}examples/groups.rs (line 25)
24fn print_group(pattern: &str) {
25 let ast = parse(pattern).unwrap();
26
27 // The outermost node might be a Concat if there is content outside the group.
28 // Walk one level to find the first Group node for display.
29 let group_node = match &ast {
30 Regex::Group(_, _) => Some(&ast),
31 Regex::Concat(nodes) => nodes.iter().find(|n| matches!(n, Regex::Group(_, _))),
32 _ => None,
33 };
34
35 match group_node {
36 Some(Regex::Group(inner, kind)) => {
37 let label = group_kind_label(kind);
38 let name_part = if let GroupKind::Named(n) = kind {
39 format!(" (name = \"{n}\")")
40 } else {
41 String::new()
42 };
43 println!(
44 " {pattern:20} => {label}{name_part}, inner = {:?}",
45 inner
46 );
47 }
48 _ => println!(" {pattern:20} => {ast:?}"),
49 }
50}
51
52fn main() {
53 println!("=== Capturing & non-capturing ===");
54 print_group("(abc)");
55 print_group("(?:abc)");
56 print_group("(?P<word>\\w+)");
57
58 println!("\n=== Lookahead assertions ===");
59 print_group("foo(?=bar)"); // 'foo' only when followed by 'bar'
60 print_group("foo(?!bar)"); // 'foo' only when NOT followed by 'bar'
61
62 println!("\n=== Lookbehind assertions ===");
63 print_group("(?<=\\d)px"); // 'px' only when preceded by a digit
64 print_group("(?<!\\d)px"); // 'px' only when NOT preceded by a digit
65
66 println!("\n=== Nested groups (full pretty AST) ===");
67 let pattern = "(?P<date>(?P<year>\\d{4})-(?P<month>\\d{2}))";
68 println!(" Pattern: {pattern}");
69 println!(" AST:\n{:#?}", parse(pattern).unwrap());
70}Additional examples can be found in: