proc_macro_regex/lib.rs
1mod character;
2mod dfa;
3mod macro_input;
4mod nfa;
5
6use crate::{
7 dfa::{Dfa, DfaToTokens},
8 macro_input::MacroInput,
9 nfa::Nfa,
10};
11use proc_macro::TokenStream;
12use quote::quote;
13use syn::parse_macro_input;
14
15/// The macro creates a function which returns `true` if the argument matches the regex.
16///
17/// If the first argument is an identifier (name), then this is the name of the function, which
18/// would be generated. Example:
19/// ```rust
20/// use proc_macro_regex::regex;
21///
22/// regex!(the_name_of_the_function "the regex to check");
23/// ```
24///
25/// Alternative, if the first argument is a visibility keyword, then this is the visibility of the
26/// function. Otherwise, the function is private. Example:
27/// ```rust
28/// # use proc_macro_regex::regex;
29/// regex!(pub public_function "the function is public");
30/// regex!(private_function "the function is private");
31/// ```
32///
33/// The next argument is a string of the regex, which the function should check. Alternative, a
34/// byte string can be given, if the input should be a byte array (`&[u8]`). otherwise a string is
35/// taken.
36/// ```rust
37/// # use proc_macro_regex::regex;
38/// regex!(string_function "This function takes a string");
39/// regex!(bytes_function "This function takes a byte array");
40/// ```
41///
42/// At the end, a positive number can be given to set the limit of the lookup table
43/// (see `README.md`).
44/// ```rust
45/// # use proc_macro_regex::regex;
46/// regex!(limit_function "The limit is set to 100 bytes" 100);
47/// ```
48///
49/// # Syntax
50/// The given regex works the same as in the [regex](https://crates.io/crates/regex) crate.
51/// * If the `^` is at the beginning of the regex, then it is checked if the input is match at the
52/// beginning of the text.
53/// * If the `$` is at the end, then it is checked if the input is match at the end of the text.
54/// * If both are present then the whole input is checked.
55/// * Otherwise, is check if the string contains the regex.
56#[proc_macro]
57pub fn regex(input: TokenStream) -> TokenStream {
58 let input = parse_macro_input!(input as MacroInput);
59 let visibility = input.get_visibility();
60 let name = input.get_name();
61 let threshold = input.get_threshold();
62 let (argument_type, body) = if input.is_str() {
63 let nfa = Nfa::<char>::try_from(&input).unwrap();
64 let dfa = Dfa::from(nfa);
65 (
66 quote! {
67 str
68 },
69 DfaToTokens::new(dfa, threshold).get_token_streams(),
70 )
71 } else {
72 let nfa = Nfa::<u8>::try_from(&input).unwrap();
73 let dfa = Dfa::from(nfa);
74 (
75 quote! {
76 [u8]
77 },
78 DfaToTokens::new(dfa, threshold).get_token_streams(),
79 )
80 };
81 let function = quote! {
82 #visibility fn #name(s: &#argument_type) -> bool {
83 #body
84 }
85 };
86 function.into()
87}