ct_regex_internal/codegen/create_type/
parse.rs1use proc_macro2::TokenStream;
2use regex_syntax::ast::parse::ParserBuilder;
3use regex_syntax::ast::{
4 Ast, ClassAscii, ClassAsciiKind, ClassBracketed, ClassPerl, ClassPerlKind, ClassSet,
5 ClassSetBinaryOp, ClassSetItem,
6};
7use regex_syntax::hir::translate::TranslatorBuilder;
8
9use crate::codegen::{CodegenItem, Group, HirExtension};
10
11pub fn parse_regex<I: CodegenItem>(pat: &str, config: &ConfigExt) -> (TokenStream, Vec<Group>) {
12 let mut ast = config.ast.build()
13 .parse(pat)
14 .expect("failed to parse regex");
15
16 if !config.complex_classes {
17 simplify_classes(&mut ast);
18 }
19
20 config.hir.build()
21 .translate(pat, &ast)
22 .expect("failed to parse regex")
23 .into_matcher::<I>()
24}
25
26pub fn simplify_classes(ast: &mut Ast) {
27 let replacement = match ast {
28 Ast::ClassPerl(class) => replace_perl_class(class),
29 Ast::ClassBracketed(class) => return replace_in_class(&mut class.kind),
30 Ast::Repetition(rep) => return simplify_classes(&mut rep.ast),
31 Ast::Group(group) => return simplify_classes(&mut group.ast),
32 Ast::Alternation(alt) => return alt.asts.iter_mut().for_each(simplify_classes),
33 Ast::Concat(cat) => return cat.asts.iter_mut().for_each(simplify_classes),
34 _ => return,
35 };
36 *ast = Ast::ClassBracketed(Box::new(ClassBracketed {
37 span: *ast.span(),
38 negated: false,
39 kind: ClassSet::Item(ClassSetItem::Ascii(replacement)),
40 }));
41}
42
43pub fn replace_in_class(class: &mut ClassSet) {
44 match class {
45 ClassSet::BinaryOp(ClassSetBinaryOp { lhs, rhs, .. }) => {
46 replace_in_class(lhs);
47 replace_in_class(rhs);
48 },
49 ClassSet::Item(item) => replace_in_class_set_item(item),
50 }
51}
52
53pub fn replace_in_class_set_item(item: &mut ClassSetItem) {
54 let replacement = match item {
55 ClassSetItem::Perl(class) => replace_perl_class(class),
56 ClassSetItem::Bracketed(class) => return replace_in_class(&mut class.kind),
57 ClassSetItem::Union(class) => {
58 return class.items.iter_mut().for_each(replace_in_class_set_item);
59 },
60 _ => return,
61 };
62 *item = ClassSetItem::Ascii(replacement);
63}
64
65pub fn replace_perl_class(class: &mut ClassPerl) -> ClassAscii {
66 ClassAscii {
67 span: class.span,
68 negated: class.negated,
69 kind: match class.kind {
70 ClassPerlKind::Digit => ClassAsciiKind::Digit,
71 ClassPerlKind::Space => ClassAsciiKind::Space,
72 ClassPerlKind::Word => ClassAsciiKind::Word,
73 },
74 }
75}
76
77#[derive(#[automatically_derived]
impl ::core::fmt::Debug for ConfigExt {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field3_finish(f, "ConfigExt",
"ast", &self.ast, "hir", &self.hir, "complex_classes",
&&self.complex_classes)
}
}Debug, #[automatically_derived]
impl ::core::default::Default for ConfigExt {
#[inline]
fn default() -> ConfigExt {
ConfigExt {
ast: ::core::default::Default::default(),
hir: ::core::default::Default::default(),
complex_classes: ::core::default::Default::default(),
}
}
}Default, #[automatically_derived]
impl ::core::clone::Clone for ConfigExt {
#[inline]
fn clone(&self) -> ConfigExt {
ConfigExt {
ast: ::core::clone::Clone::clone(&self.ast),
hir: ::core::clone::Clone::clone(&self.hir),
complex_classes: ::core::clone::Clone::clone(&self.complex_classes),
}
}
}Clone)]
78pub struct ConfigExt {
79 pub ast: ParserBuilder,
80 pub hir: TranslatorBuilder,
81 pub complex_classes: bool,
82}
83
84macro_rules! impl_hir_methods {
85 ($name:ident) => {
86 pub fn $name(&mut self, flag: bool) -> &mut Self {
87 self.hir.$name(flag);
88 self
89 }
90 };
91 ($name:ident, $($others:ident),+) => {
92 impl_hir_methods! { $name }
93 impl_hir_methods! { $($others),+ }
94 };
95}
96
97impl ConfigExt {
98 self
bool
flag
&mut Self
self.hir.utf8(flag);
self;impl_hir_methods! {
99 case_insensitive,
100 multi_line,
101 dot_matches_new_line,
102 crlf,
103 swap_greed,
104 unicode,
105 utf8
106 }
107
108 pub fn ignore_whitespace(&mut self, flag: bool) -> &mut Self {
109 self.ast.ignore_whitespace(flag);
110 self
111 }
112
113 pub fn complex_classes(&mut self, flag: bool) -> &mut Self {
114 self.complex_classes = flag;
115 self
116 }
117}