ere_macros/lib.rs
1use ere_core;
2use proc_macro::TokenStream;
3
4extern crate proc_macro;
5
6/// This is the primary entrypoint to the `ere` crate.
7/// Checks and compiles a regular expression into a [`Regex<N>`](`ere_core::Regex<N>`).
8///
9/// This compilation happens during build using proc macros,
10/// resulting in rust code equivalent to your regex.
11/// This code can then by further optimized by rustc when compiled directly into the binary.
12///
13/// The generic `const N: usize` will be the number of capture groups present in the regular expression
14/// (including capture group 0 which is the entire matched text).
15/// You will need to properly specify this in the generics for the regex (default if unspecified is 1).
16/// When using [`Regex<N>::exec`](`ere_core::Regex<N>::exec`), this is the length of the captures returned.
17///
18/// ```
19/// use ere_core::Regex; // usually `ere::Regex`
20/// use ere_macros::compile_regex; // usually `ere::compile_regex`
21///
22/// const MY_REGEX: Regex<2> = compile_regex!("a(b?)c");
23/// ```
24#[proc_macro]
25pub fn compile_regex(stream: TokenStream) -> TokenStream {
26 return ere_core::__compile_regex(stream);
27}
28
29/// Checks and compiles a regular expression into a [`ere_core::pike_vm::PikeVM<N>`].
30/// Unless you specifically want this engine, you might want to use [`compile_regex!`] instead.
31///
32/// This compilation happens during build using proc macros,
33/// resulting in rust code equivalent to your regex.
34/// This code can then by further optimized by rustc when compiled directly into the binary.
35///
36/// The generic `const N: usize` will be the number of capture groups present in the regular expression
37/// (including capture group 0 which is the entire matched text).
38/// You will need to properly specify this in the generics for the regex (default if unspecified is 1).
39/// When using [`PikeVM<N>::exec`](`ere_core::pike_vm::PikeVM<N>::exec`), this is the length of the captures returned.
40///
41/// ```
42/// use ere_core::pike_vm::PikeVM;
43/// use ere_macros::compile_regex_pikevm;
44///
45/// const MY_REGEX: PikeVM<2> = compile_regex_pikevm!("a(b?)c");
46/// ```
47#[proc_macro]
48pub fn compile_regex_pikevm(stream: TokenStream) -> TokenStream {
49 return ere_core::__compile_regex_engine_pike_vm(stream);
50}
51
52/// Checks and compiles a regular expression into a [`ere_core::pike_vm_u8::U8PikeVM<N>`].
53/// Unless you specifically want this engine, you might want to use [`compile_regex!`] instead.
54///
55/// This compilation happens during build using proc macros,
56/// resulting in rust code equivalent to your regex.
57/// This code can then by further optimized by rustc when compiled directly into the binary.
58///
59/// The generic `const N: usize` will be the number of capture groups present in the regular expression
60/// (including capture group 0 which is the entire matched text).
61/// You will need to properly specify this in the generics for the regex (default if unspecified is 1).
62/// When using [`U8PikeVM<N>::exec`](`ere_core::pike_vm_u8::U8PikeVM<N>::exec`), this is the length of the captures returned.
63///
64/// ```
65/// use ere_core::pike_vm_u8::U8PikeVM;
66/// use ere_macros::compile_regex_u8pikevm;
67///
68/// const MY_REGEX: U8PikeVM<2> = compile_regex_u8pikevm!("a(b?)c");
69/// ```
70#[proc_macro]
71pub fn compile_regex_u8pikevm(stream: TokenStream) -> TokenStream {
72 return ere_core::__compile_regex_engine_pike_vm_u8(stream);
73}
74
75/// Checks and compiles a regular expression into a [`ere_core::one_pass_u8::U8OnePass<N>`].
76/// Unless you specifically want this engine, you might want to use [`compile_regex!`] instead.
77///
78/// This compilation happens during build using proc macros,
79/// resulting in rust code equivalent to your regex.
80/// This code can then by further optimized by rustc when compiled directly into the binary.
81///
82/// The generic `const N: usize` will be the number of capture groups present in the regular expression
83/// (including capture group 0 which is the entire matched text).
84/// You will need to properly specify this in the generics for the regex (default if unspecified is 1).
85/// When using [`U8OnePass<N>::exec`](`ere_core::one_pass_u8::U8OnePass<N>::exec`), this is the length of the captures returned.
86///
87/// ```
88/// use ere_core::one_pass_u8::U8OnePass;
89/// use ere_macros::compile_regex_u8onepass;
90///
91/// const MY_REGEX: U8OnePass<2> = compile_regex_u8onepass!("^a(b?)c$");
92/// ```
93///
94/// ---
95///
96/// Note that this engine does not support all valid regular expressions,
97/// and will raise a compile error if necessary.
98/// For example, unanchored regexes are generally not one-pass.
99///
100#[proc_macro]
101pub fn compile_regex_u8onepass(stream: TokenStream) -> TokenStream {
102 return ere_core::__compile_regex_engine_one_pass_u8(stream);
103}
104
105/// EXPERIMENTAL: this attribute provides an alternate syntax with finer control for creating regexes.
106///
107/// Compared with [`compile_regex!`], this allows the type system to know which capture groups
108/// should be optional and which should not.
109///
110/// For example:
111///
112/// ```
113/// use ere_macros::regex;
114///
115/// #[derive(Debug, PartialEq, Eq)]
116/// #[regex(r"^#?([[:xdigit:]]{2})([[:xdigit:]]{2})([[:xdigit:]]{2})([[:xdigit:]]{2})?$")]
117/// pub struct HexColor<'a>(
118/// pub &'a str,
119/// pub &'a str,
120/// pub &'a str,
121/// pub &'a str,
122/// pub Option<&'a str>,
123/// );
124///
125/// assert!(HexColor::test("#1F1F1F"));
126/// assert!(HexColor::test("#1F1F1F80"));
127/// assert!(HexColor::test("20202020"));
128///
129/// assert_eq!(
130/// HexColor::exec("#112233"),
131/// Some(HexColor(
132/// "#112233",
133/// "11",
134/// "22",
135/// "33",
136/// None,
137/// )),
138/// );
139/// assert_eq!(
140/// HexColor::exec("#11223344"),
141/// Some(HexColor(
142/// "#11223344",
143/// "11",
144/// "22",
145/// "33",
146/// Some("44"),
147/// )),
148/// );
149/// ```
150///
151/// ---
152///
153/// Note that it is required to specify the fields with the proper type
154/// (i.e. `&'a str` or `Option<&'a str>` depending on the capture group)
155/// and the lifetime should be the first generic argument on the struct.
156///
157/// The field for the 0th capture group should never be an `Option` since if there is a match,
158/// it will always contain the entire match (and otherwise `exec` returns `None`).
159#[cfg(feature = "unstable-attr-regex")]
160#[proc_macro_attribute]
161pub fn regex(attr: TokenStream, input: TokenStream) -> TokenStream {
162 return ere_core::__compile_regex_attr(attr, input);
163}