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/llvm 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/// ```ignore
19/// use ere::Regex;
20/// use 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 into a [`ere_core::Regex<N>`] with the [`ere_core::dfa_u8`] engine.
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/llvm 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 [`Regex<N>::exec`](`ere_core::Regex<N>::exec`), this is the length of the captures returned.
40///
41/// ```ignore
42/// use ere::Regex;
43/// use ere::compile_regex_dfa_u8;
44///
45/// const MY_REGEX: Regex<2> = compile_regex_dfa_u8!("a(b?)c");
46/// ```
47#[proc_macro]
48pub fn compile_regex_dfa_u8(stream: TokenStream) -> TokenStream {
49 return ere_core::__compile_regex_engine_dfa_u8(stream);
50}
51
52/// Checks and compiles a regular expression into a into a [`ere_core::Regex<N>`] with the [`ere_core::flat_lockstep_nfa`] engine.
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/llvm 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 [`Regex<N>::exec`](`ere_core::Regex<N>::exec`), this is the length of the captures returned.
63///
64/// ```ignore
65/// use ere::Regex;
66/// use ere::compile_regex_flat_lockstep_nfa;
67///
68/// const MY_REGEX: Regex<2> = compile_regex_flat_lockstep_nfa!("a(b?)c");
69/// ```
70#[proc_macro]
71pub fn compile_regex_flat_lockstep_nfa(stream: TokenStream) -> TokenStream {
72 return ere_core::__compile_regex_engine_flat_lockstep_nfa(stream);
73}
74
75/// Checks and compiles a regular expression into a into a [`ere_core::Regex<N>`] with the [`ere_core::flat_lockstep_nfa_u8`] engine.
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/llvm 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 [`Regex<N>::exec`](`ere_core::Regex<N>::exec`), this is the length of the captures returned.
86///
87/// ```ignore
88/// use ere::Regex;
89/// use ere::compile_regex_flat_lockstep_nfa_u8;
90///
91/// const MY_REGEX: Regex<2> = compile_regex_flat_lockstep_nfa_u8!("a(b?)c");
92/// ```
93#[proc_macro]
94pub fn compile_regex_flat_lockstep_nfa_u8(stream: TokenStream) -> TokenStream {
95 return ere_core::__compile_regex_engine_flat_lockstep_nfa_u8(stream);
96}
97
98/// Checks and compiles a regular expression into a [`ere_core::Regex<N>`] with the [`ere_core::one_pass_u8`] engine.
99/// Unless you specifically want this engine, you might want to use [`compile_regex!`] instead.
100///
101/// This compilation happens during build using proc macros,
102/// resulting in rust code equivalent to your regex.
103/// This code can then by further optimized by rustc/llvm when compiled directly into the binary.
104///
105/// The generic `const N: usize` will be the number of capture groups present in the regular expression
106/// (including capture group 0 which is the entire matched text).
107/// You will need to properly specify this in the generics for the regex (default if unspecified is 1).
108/// When using [`Regex<N>::exec`](`ere_core::Regex<N>::exec`), this is the length of the captures returned.
109///
110/// ```ignore
111/// use ere::Regex;
112/// use ere::compile_regex_u8onepass;
113///
114/// const MY_REGEX: Regex<2> = compile_regex_u8onepass!("^a(b?)c$");
115/// ```
116///
117/// ---
118///
119/// Note that this engine does not support all valid regular expressions,
120/// and will raise a compile error if necessary.
121/// For example, unanchored regexes are generally not one-pass.
122///
123#[proc_macro]
124pub fn compile_regex_u8onepass(stream: TokenStream) -> TokenStream {
125 return ere_core::__compile_regex_engine_one_pass_u8(stream);
126}
127
128/// Checks and compiles a regular expression into a [`ere_core::Regex<N>`] with the [`ere_core::fixed_offset`] engine.
129/// Unless you specifically want this engine, you might want to use [`compile_regex!`] instead.
130///
131/// This compilation happens during build using proc macros,
132/// resulting in rust code equivalent to your regex.
133/// This code can then by further optimized by rustc/llvm when compiled directly into the binary.
134///
135/// The generic `const N: usize` will be the number of capture groups present in the regular expression
136/// (including capture group 0 which is the entire matched text).
137/// You will need to properly specify this in the generics for the regex (default if unspecified is 1).
138/// When using [`Regex<N>::exec`](`ere_core::Regex<N>::exec`), this is the length of the captures returned.
139///
140/// ```ignore
141/// use ere::Regex;
142/// use ere::compile_regex_fixed_offset;
143///
144/// const MY_REGEX: Regex<2> = compile_regex_fixed_offset!("^#([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$");
145/// ```
146///
147/// ---
148///
149/// Note that this engine does not support all valid regular expressions,
150/// and will raise a compile error if necessary..
151///
152#[proc_macro]
153pub fn compile_regex_fixed_offset(stream: TokenStream) -> TokenStream {
154 return ere_core::__compile_regex_engine_fixed_offset(stream);
155}
156
157/// EXPERIMENTAL: this attribute provides an alternate syntax with finer control for creating regexes.
158///
159/// Compared with [`compile_regex!`], this allows the type system to know which capture groups
160/// should be optional and which should not.
161///
162/// For example:
163///
164/// ```
165/// use ere_macros::regex;
166///
167/// #[derive(Debug, PartialEq, Eq)]
168/// #[regex(r"^#?([[:xdigit:]]{2})([[:xdigit:]]{2})([[:xdigit:]]{2})([[:xdigit:]]{2})?$")]
169/// pub struct HexColor<'a>(
170/// pub &'a str,
171/// pub &'a str,
172/// pub &'a str,
173/// pub &'a str,
174/// pub Option<&'a str>,
175/// );
176///
177/// assert!(HexColor::test("#1F1F1F"));
178/// assert!(HexColor::test("#1F1F1F80"));
179/// assert!(HexColor::test("20202020"));
180///
181/// assert_eq!(
182/// HexColor::exec("#112233"),
183/// Some(HexColor(
184/// "#112233",
185/// "11",
186/// "22",
187/// "33",
188/// None,
189/// )),
190/// );
191/// assert_eq!(
192/// HexColor::exec("#11223344"),
193/// Some(HexColor(
194/// "#11223344",
195/// "11",
196/// "22",
197/// "33",
198/// Some("44"),
199/// )),
200/// );
201/// ```
202///
203/// ---
204///
205/// Note that it is required to specify the fields with the proper type
206/// (i.e. `&'a str` or `Option<&'a str>` depending on the capture group)
207/// and the lifetime should be the first generic argument on the struct.
208///
209/// The field for the 0th capture group should never be an `Option` since if there is a match,
210/// it will always contain the entire match (and otherwise `exec` returns `None`).
211#[cfg(feature = "unstable-attr-regex")]
212#[proc_macro_attribute]
213pub fn regex(attr: TokenStream, input: TokenStream) -> TokenStream {
214 return ere_core::__compile_regex_attr(attr, input);
215}