Skip to main content

parse

Function parse 

Source
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
Hide additional 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}