Skip to main content

ct_regex_internal/codegen/create_type/
parse.rs

1use proc_macro2::TokenStream;
2use quote::quote;
3use regex_syntax::hir::{Capture, Hir, HirKind, Look, Properties};
4use syn::Ident;
5
6use crate::codegen::{CodegenItem, ConfigExt, ExprMetadata, IntoMatcherExpr, classes};
7
8#[derive(#[automatically_derived]
impl ::core::fmt::Debug for TypeExpressions {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field3_finish(f,
            "TypeExpressions", "matcher", &self.matcher, "anchors",
            &self.anchors, "meta", &&self.meta)
    }
}Debug, #[automatically_derived]
impl ::core::clone::Clone for TypeExpressions {
    #[inline]
    fn clone(&self) -> TypeExpressions {
        TypeExpressions {
            matcher: ::core::clone::Clone::clone(&self.matcher),
            anchors: ::core::clone::Clone::clone(&self.anchors),
            meta: ::core::clone::Clone::clone(&self.meta),
        }
    }
}Clone)]
9pub(crate) struct TypeExpressions {
10    pub matcher: TokenStream,
11    pub anchors: TokenStream,
12    pub meta: ExprMetadata,
13}
14
15impl TypeExpressions {
16    pub fn parse_regex<I: CodegenItem>(name: &Ident, pat: &str, config: &ConfigExt) -> TypeExpressions {
17        let mut ast = config.ast.build()
18            .parse(pat)
19            .expect("failed to parse regex");
20
21        if !config.complex_classes {
22            classes::simplify_classes(&mut ast);
23        }
24
25        let hir = config.hir.build()
26            .translate(pat, &ast)
27            .expect("failed to parse regex");
28
29        TypeExpressions::create::<I>(hir, name)
30    }
31
32    pub fn create<I: CodegenItem>(hir: Hir, name: &Ident) -> TypeExpressions {
33        let mut meta = ExprMetadata::new(name.clone());
34        let anchors = TypeExpressions::create_anchor_expression(hir.properties());
35
36        TypeExpressions {
37            matcher: Self::remove_redundant_lookarounds(hir).into_matcher_expr::<I>(&mut meta),
38            anchors,
39            meta
40        }
41    }
42
43    pub fn create_anchor_expression(props: &Properties) -> TokenStream {
44        let mut anchors = Vec::new();
45
46        if props.look_set_prefix().contains(Look::Start) {
47            anchors.push({
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "ct_regex");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "internal");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "anchor");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "Start");
    _s
}quote!(::ct_regex::internal::anchor::Start));
48        }
49        if let Some(min) = props.minimum_len() && min != 0 {
50            anchors.push({
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "ct_regex");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "internal");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "anchor");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "MinLen");
    ::quote::__private::push_lt(&mut _s);
    ::quote::ToTokens::to_tokens(&min, &mut _s);
    ::quote::__private::push_gt(&mut _s);
    _s
}quote!(::ct_regex::internal::anchor::MinLen<#min>));
51        }
52        if let Some(max) = props.maximum_len() {
53            if props.look_set_suffix().contains(Look::End) {
54                anchors.push({
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "ct_regex");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "internal");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "anchor");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "EndAndMaxLen");
    ::quote::__private::push_lt(&mut _s);
    ::quote::ToTokens::to_tokens(&max, &mut _s);
    ::quote::__private::push_gt(&mut _s);
    _s
}quote!(::ct_regex::internal::anchor::EndAndMaxLen<#max>));
55            } else {
56                anchors.push({
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "ct_regex");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "internal");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "anchor");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "MaxLen");
    ::quote::__private::push_lt(&mut _s);
    ::quote::ToTokens::to_tokens(&max, &mut _s);
    ::quote::__private::push_gt(&mut _s);
    _s
}quote!(::ct_regex::internal::anchor::MaxLen<#max>));
57            }
58        }
59
60        match &anchors[..] {
61            [] => {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "ct_regex");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "internal");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "anchor");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "AnchorNone");
    _s
}quote!(::ct_regex::internal::anchor::AnchorNone),
62            [a] => {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::ToTokens::to_tokens(&a, &mut _s);
    _s
}quote!(#a),
63            [a, b] => {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "ct_regex");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "internal");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "anchor");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "AnchorPair");
    ::quote::__private::push_lt(&mut _s);
    ::quote::ToTokens::to_tokens(&a, &mut _s);
    ::quote::__private::push_comma(&mut _s);
    ::quote::ToTokens::to_tokens(&b, &mut _s);
    ::quote::__private::push_gt(&mut _s);
    _s
}quote!(::ct_regex::internal::anchor::AnchorPair<#a, #b>),
64            [a, b, c] => {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "ct_regex");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "internal");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "anchor");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "AnchorSet");
    ::quote::__private::push_lt(&mut _s);
    ::quote::ToTokens::to_tokens(&a, &mut _s);
    ::quote::__private::push_comma(&mut _s);
    ::quote::ToTokens::to_tokens(&b, &mut _s);
    ::quote::__private::push_comma(&mut _s);
    ::quote::ToTokens::to_tokens(&c, &mut _s);
    ::quote::__private::push_gt(&mut _s);
    _s
}quote!(::ct_regex::internal::anchor::AnchorSet<#a, #b, #c>),
65            _ => {
    ::core::panicking::panic_fmt(format_args!("an excessive number for anchor assertions were found"));
}panic!("an excessive number for anchor assertions were found"),
66        }
67    }
68
69    pub fn remove_redundant_lookarounds(hir: Hir) -> Hir {
70        match hir.kind() {
71            HirKind::Look(Look::Start) => Hir::empty(),
72            HirKind::Concat(sub) => match &sub[..] {
73                [first, other] if first.kind() == &HirKind::Look(Look::Start) => {
74                    other.clone()
75                },
76                [first, remainder @ ..] if first.kind() == &HirKind::Look(Look::Start) => {
77                    Hir::concat(remainder.to_vec())
78                },
79                _ => hir,
80            },
81            HirKind::Capture(cap) => Hir::capture(Capture {
82                index: cap.index,
83                name: cap.name.clone(),
84                sub: Box::new(Self::remove_redundant_lookarounds((*cap.sub).clone())),
85            }),
86            _ => hir,
87        }
88    }
89}