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