char_classes/
char_classes.rs1use re_parser::ast::{CharClassItem, EscapeClass, Regex};
10use re_parser::parse;
11
12fn describe_item(item: &CharClassItem) -> String {
13 match item {
14 CharClassItem::Literal(c) => format!("literal({c:?})"),
15 CharClassItem::Range(lo, hi) => format!("range({lo:?}..={hi:?})"),
16 CharClassItem::EscapeClass(ec) => {
17 let name = match ec {
18 EscapeClass::Digit => r"\d",
19 EscapeClass::NonDigit => r"\D",
20 EscapeClass::Word => r"\w",
21 EscapeClass::NonWord => r"\W",
22 EscapeClass::Space => r"\s",
23 EscapeClass::NonSpace => r"\S",
24 };
25 format!("escape({name})")
26 }
27 }
28}
29
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_]"); println!("\n=== Mixed ===");
63 print_class(r"[a-z\d_]"); print_class(r"[^a-z\s]"); 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}