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}