rust_regex_dsl_derive/
lib.rs

1//! Use the [rust-regex-dsl](https://github.com/yift/rust-regex-dsl/) package.
2
3use create_capture::CreateCapture;
4use dsl::Dsl;
5use error_factory::ErrorFactory;
6use functions::parse_list::parse_list_to_vec;
7use proc_macro::TokenStream;
8use syn::{LitStr, parse_macro_input};
9mod create_capture;
10mod dsl;
11mod error_factory;
12mod functions;
13mod group;
14mod ident_parser;
15mod predefined_class;
16mod user_class;
17
18/// A simple regular expression macro.
19///
20/// This macro will validate the regular expression and will produce a compile time error if the expression
21/// is invalid. This can allow a developer to know that the hard coded regular expressions are valid. The result will be a valid [`regex::Regex`].
22///
23/// For example:
24/// ```rust
25/// use rust_regex_dsl::regex;
26/// use regex::Regex;
27/// use std::sync::LazyLock;
28///
29/// static VALID_NAME: LazyLock<Regex> = LazyLock::new(|| regex!("[a-z][a-zA-Z_]*"));
30/// ```
31/// Is equivalent to:
32/// ```rust
33/// use rust_regex_dsl::regex;
34/// use regex::Regex;
35/// use std::sync::LazyLock;
36///
37/// static VALID_NAME: LazyLock<Regex> = LazyLock::new(|| Regex::new("[a-z][a-zA-Z_]*").unwrap());
38/// ```
39///
40/// But this:
41/// ```compile_fail
42/// use rust_regex_dsl::regex;
43/// use regex::Regex;
44///
45///
46/// static VALID_NAME: LazyLock<Regex> = LazyLock::new(|| regex!("[a-z][a-zA-Z_*"));
47/// ```
48/// will fail with compilation error (because of the missing closing square bracket) while using the same without the macro will fail in run time.
49#[proc_macro]
50pub fn regex(input: TokenStream) -> TokenStream {
51    let input = parse_macro_input!(input as LitStr);
52
53    let dsl = Dsl::new(&input.value(), input.value().len() > 1);
54    let error_factory = ErrorFactory::new_obj(input.span());
55    dsl.build(error_factory).into()
56}
57
58/// A DSL for creating Regular Expressions.
59///
60/// This macro will introduce a domain specific language to create a regular expression that is easier to read.
61///
62/// The macro support a few types of arguments, if the macro has more than one argument, it will concat all the arguments.
63///
64/// The supported arguments are:
65/// # A literal string.
66/// That is - `"<something>"` - this is the same as equals, i.e. it will produce a regular expression to compare that the string is exactly the same as the argument. For example:
67/// ```rust
68/// use rust_regex_dsl::regex_dsl;
69///
70/// let regex = regex_dsl!("Foo");
71/// assert!(regex.is_match("Foo"));
72/// assert!(!regex.is_match("Bar"));
73/// ```
74/// It will also escape any character that need to be escaped, for example:
75/// ```rust
76/// use rust_regex_dsl::regex_dsl;
77///
78/// let regex = regex_dsl!("Foo\\Bar");
79/// assert!(regex.is_match("Foo\\Bar"));
80/// assert!(!regex.is_match("Bar-Bar"));
81/// ```
82/// # A literal character.
83/// That is - `'a'` - this is the same as the String but for a single character. For example:
84/// ```rust
85/// use rust_regex_dsl::regex_dsl;
86///
87/// let regex = regex_dsl!(
88///   "Foo",
89///   '-',
90///    "Bar"
91/// );
92/// assert!(regex.is_match("Foo-Bar"));
93/// assert!(!regex.is_match("Bar=Bar"));
94/// ```
95/// # Class name
96/// That is - `#<class_name>` - a character from a unicode class. See more details in [here](https://www.regular-expressions.info/unicode.html). This is equivalent to `\p{<class_name>}`. For example:
97/// ```rust
98/// use rust_regex_dsl::regex_dsl;
99///
100/// let regex = regex_dsl!{
101///     #latin,
102///     #greek,
103/// };
104/// assert!(regex.is_match("aα"));
105/// assert!(!regex.is_match("αa"));
106/// ```
107/// # Not a class name
108/// That is - `~<class_name>` - anything but a character from a unicode class. See more details in [here](https://www.regular-expressions.info/unicode.html). This is equivalent to `\P{<class_name>}`. For example:
109/// ```rust
110/// use rust_regex_dsl::regex_dsl;
111///
112/// let regex = regex_dsl!{
113///     ~latin,
114///     ~greek,
115/// };
116/// assert!(!regex.is_match("aα"));
117/// assert!(regex.is_match("αa"));
118/// ```
119/// # special cases:
120/// That is - `something` - a special regular expression type of character or boundary. Available types are:
121/// * `any_character` - Any character (besides new line unless the `allow_dot` flag is set). This is equivalent to `.`
122/// * `digit` - A digit (similar to `#digit` and `#Nd`). This is equivalent to `\d`
123/// * `not_digit` - Not a digit. This is equivalent to `\D`.
124/// * `white_space` - A white space. . This is equivalent to `\s`.
125/// * `not_white_space` - Not a white space. This is equivalent to `\S`.
126/// * `word_character` - A word character. This is equivalent to `\w`.
127/// * `not_word_character` - Not a word character. This is equivalent to `\W`.
128/// * `beginning_of_line` - A beginning of a line. This is equivalent to `^`.
129/// * `end_of_line` - An end of a line. This is equivalent to `$`.
130/// * `word_boundary` - A word boundary. This is equivalent to `\b`.
131/// * `not_word_boundary` - Not a word boundary. This is equivalent to `\B`.
132/// * `beginning_of_input` - A beginning of the input. This is equivalent to `\A`.
133/// * `end_of_input` - An end of the input. This is equivalent to `\z`.
134///
135/// For example:
136/// ```rust
137/// use rust_regex_dsl::regex_dsl;
138///
139/// let regex = regex_dsl!{
140///     "Foo",
141///     any_character
142///     "Bar",
143/// };
144/// assert!(regex.is_match("Foo Bar"));
145/// assert!(regex.is_match("Foo-Bar"));
146/// assert!(!regex.is_match("FooBar"));
147/// ```
148/// # Function
149/// That is - `func(args)` or `func { args }` -  a function DSL. The available functions are:
150/// ## `eq`
151/// Expect a single literal string arguments. behave the same as literal string above. For example:
152/// ```rust
153/// use rust_regex_dsl::regex_dsl;
154///
155/// let regex = regex_dsl! {
156///     eq {
157///         "Foo"
158///     }
159/// };
160/// assert!(regex.is_match("Foo"));
161/// assert!(!regex.is_match("Bar"));
162/// ```
163/// ## `regex`
164/// Expect a single literal string argument. Use it as raw regular expression. To be used for things that are not covered by this DSL or when the expression is trivial to understand. For example:
165/// ```rust
166/// use rust_regex_dsl::regex_dsl;
167///
168/// let regex = regex_dsl! {
169///     regex("[0-9]+")
170/// };
171/// assert!(regex.is_match("300"));
172/// assert!(!regex.is_match("Bar"));
173/// ```
174/// Invalid regular expression will fail the compilation. For example:
175/// ```compile_fail
176/// use rust_regex_dsl::regex_dsl;
177///
178/// let regex = regex_dsl! {
179///     regex("[0-9+")
180/// };
181/// ```
182/// ## `any`
183/// Must have at least two dsl arguments. Make sure that at least of of them is valid. For example:
184/// ```rust
185/// use rust_regex_dsl::regex_dsl;
186///
187/// let regex = regex_dsl! {
188///     any {
189///         "Foo",
190///         eq("Bar"),
191///         regex("[0-9]+")
192///     }
193/// };
194/// assert!(regex.is_match("Foo"));
195/// assert!(regex.is_match("Bar"));
196/// assert!(regex.is_match("100"));
197/// assert!(!regex.is_match("Bor"));
198/// ```
199/// ## `concat`
200/// Must have at least two dsl arguments. Make sure that all of of them is valid and in the  correct order. For example:
201/// ```rust
202/// use rust_regex_dsl::regex_dsl;
203///
204/// let regex = regex_dsl! {
205///     concat {
206///         "Foo",
207///         eq("Bar"),
208///         regex("[0-9]+")
209///     }
210/// };
211/// assert!(regex.is_match("FooBar300"));
212/// assert!(!regex.is_match("Bar300"));
213/// assert!(!regex.is_match("FooBar"));
214/// ```
215/// ## `any_of`
216/// Creates a user class. The arguments can be:
217/// * A string - in that case, the class will include all the characters in the string. For example:
218///
219/// ```rust
220/// use rust_regex_dsl::regex_dsl;
221///
222/// let regex = regex_dsl! {
223///     any_of {
224///         "Bar",
225///     }
226/// };
227/// assert!(regex.is_match("B"));
228/// assert!(regex.is_match("a"));
229/// assert!(regex.is_match("r"));
230/// assert!(!regex.is_match("F"));
231/// ```
232/// * A character - in that case, the class will include the character. For example:
233/// ```rust
234/// use rust_regex_dsl::regex_dsl;
235///
236/// let regex = regex_dsl! {
237///     any_of {
238///         '1',
239///         '2',
240///         "Bar",
241///     }
242/// };
243/// assert!(regex.is_match("1"));
244/// assert!(regex.is_match("2"));
245/// assert!(regex.is_match("B"));
246/// assert!(regex.is_match("a"));
247/// assert!(regex.is_match("r"));
248/// assert!(!regex.is_match("F"));
249/// assert!(!regex.is_match("3"));
250/// ```
251/// * A predefined unicode class - in that case, the class will include the characters in that class. For example:
252/// ```rust
253/// use rust_regex_dsl::regex_dsl;
254///
255/// let regex = regex_dsl! {
256///     any_of {
257///         #digit,
258///         "Bar",
259///     }
260/// };
261/// assert!(regex.is_match("1"));
262/// assert!(regex.is_match("8"));
263/// assert!(regex.is_match("B"));
264/// assert!(regex.is_match("a"));
265/// assert!(regex.is_match("r"));
266/// assert!(!regex.is_match("F"));
267/// ```
268/// * Not a predefined unicode class - in that case, the class will include anything by the characters in that class. For example:
269/// ```rust
270/// use rust_regex_dsl::regex_dsl;
271///
272/// let regex = regex_dsl! {
273///     any_of {
274///         ~digit,
275///     }
276/// };
277/// assert!(!regex.is_match("1"));
278/// assert!(!regex.is_match("8"));
279/// assert!(regex.is_match("B"));
280/// assert!(regex.is_match("a"));
281/// assert!(regex.is_match("r"));
282/// ```
283/// * A range of characters (from: 'a' to: 'z') - in that case, the class will include all the characters in that range. For example:
284/// ```rust
285/// use rust_regex_dsl::regex_dsl;
286///
287/// let regex = regex_dsl! {
288///     any_of {
289///         '1',
290///         from: '4' to: '6'
291///     }
292/// };
293/// assert!(!regex.is_match("0"));
294/// assert!(regex.is_match("1"));
295/// assert!(!regex.is_match("2"));
296/// assert!(!regex.is_match("3"));
297/// assert!(regex.is_match("4"));
298/// assert!(regex.is_match("5"));
299/// assert!(regex.is_match("6"));
300/// assert!(!regex.is_match("7"));
301/// ```
302/// * A special case (see special cases above). For example:
303/// ```rust
304/// use rust_regex_dsl::regex_dsl;
305///
306/// let regex = regex_dsl! {
307///     any_of {
308///         'a',
309///         digit,
310///     }
311/// };
312/// assert!(regex.is_match("0"));
313/// assert!(regex.is_match("1"));
314/// assert!(regex.is_match("a"));
315/// assert!(!regex.is_match("b"));
316/// ```
317/// * `intersect(<user_class>)` - An intersection of two user created class. For example:
318/// ```rust
319/// use rust_regex_dsl::regex_dsl;
320///
321/// let regex = regex_dsl! {
322///     any_of {
323///         from: '2' to: '5',
324///         intersect {
325///            from: '3' to: '7',
326///         }
327///     }
328/// };
329/// assert!(!regex.is_match("2"));
330/// assert!(regex.is_match("3"));
331/// assert!(regex.is_match("4"));
332/// assert!(regex.is_match("5"));
333/// assert!(!regex.is_match("6"));
334/// assert!(!regex.is_match("7"));
335/// ```
336/// * `subtract(<user_class>)` - Remove characters from the class. For example:
337/// ```rust
338/// use rust_regex_dsl::regex_dsl;
339///
340/// let regex = regex_dsl! {
341///     any_of {
342///         from: '2' to: '7',
343///         subtract {
344///            '3',
345///            '5'
346///         }
347///     }
348/// };
349/// assert!(regex.is_match("2"));
350/// assert!(!regex.is_match("3"));
351/// assert!(regex.is_match("4"));
352/// assert!(!regex.is_match("5"));
353/// assert!(regex.is_match("6"));
354/// assert!(regex.is_match("7"));
355/// ```
356/// * `xor(<user_class>)` - Symmetric difference between the classes. For example:
357/// ```rust
358/// use rust_regex_dsl::regex_dsl;
359///
360/// let regex = regex_dsl! {
361///     any_of {
362///         from: '2' to: '5',
363///         xor {
364///            from: '3' to: '7',
365///         }
366///     }
367/// };
368/// assert!(regex.is_match("2"));
369/// assert!(!regex.is_match("3"));
370/// assert!(!regex.is_match("4"));
371/// assert!(!regex.is_match("5"));
372/// assert!(regex.is_match("6"));
373/// assert!(regex.is_match("7"));
374/// ```
375/// ## `not_any_of`
376/// Revert a user class. The arguments are the same as the user class above. For example:
377/// ```rust
378/// use rust_regex_dsl::regex_dsl;
379///
380/// let regex = regex_dsl! {
381///     not_any_of {
382///         '1',
383///         from: '4' to: '6'
384///     }
385/// };
386/// assert!(regex.is_match("0"));
387/// assert!(!regex.is_match("1"));
388/// assert!(regex.is_match("2"));
389/// assert!(regex.is_match("3"));
390/// assert!(!regex.is_match("4"));
391/// assert!(!regex.is_match("5"));
392/// assert!(!regex.is_match("6"));
393/// assert!(regex.is_match("7"));
394/// ```
395/// ## `group`
396/// Create a capture group.
397/// If the argument is a DSL, the group will be unnamed. For example:
398/// ```rust
399/// use rust_regex_dsl::regex_dsl;
400///
401/// let regex = regex_dsl! {
402///     "|",
403///     group {
404///         digit,
405///     },
406///     "|"
407/// };
408/// let caps = regex.captures("|4|").unwrap();
409/// assert_eq!(caps.get(1).unwrap().as_str(), "4");
410/// ```
411/// If there is a `name:<name>` argument, the group will be named `name`. For example:
412/// ```rust
413/// use rust_regex_dsl::regex_dsl;
414///
415/// let regex = regex_dsl! {
416///     "|",
417///     group {
418///         name: a_digit,
419///         digit,
420///     },
421///     "|"
422/// };
423/// let caps = regex.captures("|4|").unwrap();
424/// assert_eq!(&caps["a_digit"], "4");
425/// ```
426///
427/// One can have more than one group in an expression. For example:
428/// ```rust
429/// use rust_regex_dsl::regex_dsl;
430/// let regex = regex_dsl! {
431///     "|",
432///     group {
433///         group {
434///             name: number_1,
435///             regex("[0-9]+"),
436///         },
437///         ",",
438///         group {
439///             name: number_2,
440///             regex("[0-9]+"),
441///         },
442///     }
443///     "|"
444/// };
445/// let caps = regex.captures("|100,400|").unwrap();
446///
447/// assert_eq!(&caps["number_1"], "100");
448/// assert_eq!(&caps["number_2"], "400");
449/// assert_eq!(caps.get(1).unwrap().as_str(), "100,400");
450/// ```
451///
452/// ## `maybe`
453/// Represent a regular expression that appears once or not at all (i.e. equivalent to the `?` operator).
454/// For example:
455/// ```rust
456/// use rust_regex_dsl::regex_dsl;
457///
458/// let regex = regex_dsl! {
459///     "<",
460///     maybe {
461///         digit,
462///     },
463///     ">"
464/// };
465/// assert!(regex.is_match("<>"));
466/// assert!(regex.is_match("<4>"));
467/// assert!(!regex.is_match("<a>"));
468/// ```
469/// To use a lazy quantifier, use the keyword `lazy`, that is, something like:
470/// ```rust
471/// use rust_regex_dsl::regex_dsl;
472///
473/// let regex = regex_dsl! {
474///     "<",
475///     maybe {
476///         lazy,
477///         digit,
478///     },
479///     ">"
480/// };
481/// assert!(regex.is_match("<>"));
482/// assert!(regex.is_match("<4>"));
483/// assert!(!regex.is_match("<a>"));
484/// ```
485///
486/// ## `repeat`
487/// Represent a regular expression that appears once or more (i.e. equivalent to the `+` operator).
488/// For example:
489/// ```rust
490/// use rust_regex_dsl::regex_dsl;
491///
492/// let regex = regex_dsl! {
493///     "<",
494///     repeat {
495///         digit,
496///     },
497///     ">"
498/// };
499/// assert!(regex.is_match("<1>"));
500/// assert!(regex.is_match("<123>"));
501/// assert!(!regex.is_match("<>"));
502/// assert!(!regex.is_match("<a>"));
503/// ```
504/// To use a lazy quantifier, use the keyword `lazy`, that is, something like:
505/// ```rust
506/// use rust_regex_dsl::regex_dsl;
507///
508/// let regex = regex_dsl! {
509///     "<",
510///     repeat {
511///         lazy,
512///         digit,
513///     },
514///     ">"
515/// };
516/// assert!(regex.is_match("<1>"));
517/// assert!(regex.is_match("<123>"));
518/// assert!(!regex.is_match("<>"));
519/// assert!(!regex.is_match("<a>"));
520/// ```
521///
522/// ## `maybe_repeat`
523/// Represent a regular expression that can appears a few times or never (i.e. equivalent to the `*` operator).
524/// For example:
525/// ```rust
526/// use rust_regex_dsl::regex_dsl;
527///
528/// let regex = regex_dsl! {
529///     "<",
530///     maybe_repeat {
531///         digit,
532///     },
533///     ">"
534/// };
535/// assert!(regex.is_match("<1>"));
536/// assert!(regex.is_match("<123>"));
537/// assert!(regex.is_match("<>"));
538/// assert!(!regex.is_match("<a>"));
539/// ```
540/// To use a lazy quantifier, use the keyword `lazy`, that is, something like:
541/// ```rust
542/// use rust_regex_dsl::regex_dsl;
543///
544/// let regex = regex_dsl! {
545///     "<",
546///     maybe_repeat {
547///         lazy,
548///         digit,
549///     },
550///     ">"
551/// };
552/// assert!(regex.is_match("<1>"));
553/// assert!(regex.is_match("<123>"));
554/// assert!(regex.is_match("<>"));
555/// assert!(!regex.is_match("<a>"));
556/// ```
557///
558/// ## `times`
559/// Represent a regular expression that can appears a few times.
560/// * One can specify exactly how many times, for example:
561/// ```rust
562/// use rust_regex_dsl::regex_dsl;
563///
564/// let regex = regex_dsl! {
565///     "<",
566///     times {
567///         exactly: 4
568///         digit,
569///     },
570///     ">"
571/// };
572/// assert!(regex.is_match("<1234>"));
573/// assert!(!regex.is_match("<1>"));
574/// assert!(!regex.is_match("<123>"));
575/// assert!(!regex.is_match("<>"));
576/// assert!(!regex.is_match("<a>"));
577/// ```
578/// * One can specify lowest limit of the number of times, for example:
579/// ```rust
580/// use rust_regex_dsl::regex_dsl;
581///
582/// let regex = regex_dsl! {
583///     "<",
584///     times {
585///         at_least: 2,
586///         digit,
587///     },
588///     ">"
589/// };
590/// assert!(regex.is_match("<12>"));
591/// assert!(regex.is_match("<123>"));
592/// assert!(regex.is_match("<1234>"));
593/// assert!(regex.is_match("<12345>"));
594/// assert!(!regex.is_match("<>"));
595/// assert!(!regex.is_match("<1>"));
596/// ```
597/// * One can specify a range of the number of times, for example:
598/// ```rust
599/// use rust_regex_dsl::regex_dsl;
600///
601/// let regex = regex_dsl! {
602///     "<",
603///     times {
604///         at_least: 2,
605///         at_most: 4,
606///         digit,
607///     },
608///     ">"
609/// };
610/// assert!(regex.is_match("<1234>"));
611/// assert!(regex.is_match("<123>"));
612/// assert!(regex.is_match("<12>"));
613/// assert!(!regex.is_match("<1>"));
614/// assert!(!regex.is_match("<>"));
615/// assert!(!regex.is_match("<12345>"));
616/// ```
617/// To use a lazy quantifier, use the keyword `lazy`, that is, something like:
618/// ```rust
619/// use rust_regex_dsl::regex_dsl;
620///
621/// let regex = regex_dsl! {
622///     "<",
623///     times {
624///         lazy,
625///         exactly: 2,
626///         digit,
627///     },
628///     ">"
629/// };
630/// assert!(regex.is_match("<12>"));
631/// assert!(!regex.is_match("<1>"));
632/// assert!(!regex.is_match("<>"));
633/// ```
634///
635/// ## `apply`
636/// Apply regular expression flags.
637/// The available flags are:
638/// * `case_insensitive` - When the flag is set, letters match both upper and lower case - equivalent to the `i` flag.
639/// * `multi_line` - When the flag is set, `beginning_of_line` and end_of_line match begin/end of line and not input - equivalent to the `m` flag.
640/// * `allow_dot` - When the flag is set, allow `any_character` to match a new line - equivalent to the `s` flag.
641/// * `enables_crlf_mode` - When `multi_line` flag is set, `\r\n` is used - - equivalent to the `R` flag.
642///
643/// To set a flag, use: `+<flag>`, to unset it, use: `-<flag>`.
644/// One can apply flags on a specific DSL, by adding the DSL as an argument to the apply function - for example:
645/// ```rust
646/// use rust_regex_dsl::regex_dsl;
647///
648/// let regex = regex_dsl! {
649///     apply {
650///         +case_insensitive,
651///         -multi_line,
652///         "foo"
653///     }
654/// };
655/// assert!(regex.is_match("foo"));
656/// assert!(regex.is_match("Foo"));
657/// ```
658/// One can apply flags on the rest of the DSLs, by leaving just the flags as a arguments to the apply function - for example:
659/// ```rust
660/// use rust_regex_dsl::regex_dsl;
661///
662/// let regex = regex_dsl! {
663///     apply {
664///         +case_insensitive,
665///     },
666///     eq("foo"),
667///     apply {
668///         -case_insensitive,
669///     },
670///     eq("Bar"),
671/// };
672/// assert!(regex.is_match("FooBar"));
673/// assert!(regex.is_match("fooBar"));
674/// assert!(!regex.is_match("fooBAR"));
675/// ```
676///
677#[proc_macro]
678pub fn regex_dsl(input: TokenStream) -> TokenStream {
679    let dsls: Vec<Dsl> = parse_macro_input!(input with parse_list_to_vec);
680    let dsl = Dsl::concat(&dsls);
681    let error_factory = ErrorFactory::new_root();
682    dsl.build(error_factory).into()
683}
684
685/// A macro to create a Regular Expression capturing struct.
686///
687/// This macro will create an helper struct for capture regular expression groups for a hard coded regular expression.
688///
689/// The macro has two arguments, the first one should be the name of the struct to create and the second one is the regular expression,
690/// either as raw regular expression or as a DSL (See [regex_dsl!] for syntax).
691///
692/// The struct will be a tuple with the first filed as a `&str` with the entire capture text (i.e. capture group 0) and the rest will be
693/// `Option<&str>` with the content of the capture group (for any capture group in the regular expression). That is, for `[a-z]+` the struct will have
694/// only `(&str)` and for `([a-z]+)([0-9]+)([a-z]+)` the struct will have `(&str, Option<&str>, Option<&str>, Option<&str>)`. If the regular expression has any named
695/// capture groups, the struct will have a public function to retrieve them with the same name as the group name (snake case). The struct will have a `get_capture` method that will return the first member of the tuple.
696///
697/// The struct will have three static public functions:
698/// * `catch` that accept a string reference and return an Option with the struct if it matches the argument.
699/// * `catch_all` that accept a string reference and return an Iterator over all the places the expression was caught in the argument.
700/// * `regex` that return a reference to the regular expression.
701///
702/// Please note, The capturing groups are optionals for regular expressions like: `([a-z]+)|([0-9]+)`.
703///
704/// For example:
705/// ```rust
706/// use rust_regex_dsl::create_capture;
707///
708/// create_capture!(MyRegexCapture, "([0-9]+)");
709///
710/// assert!(MyRegexCapture::catch("Foo").is_none());
711/// let caught = MyRegexCapture::catch("33").unwrap();
712/// assert_eq!(caught.0, "33");
713/// assert_eq!(caught.get_capture(), "33");
714/// assert_eq!(caught.1, Some("33"));
715///
716/// let all: Vec<_> = MyRegexCapture::catch_all("100 90 80").collect();
717/// assert_eq!(all.len(), 3);
718/// assert_eq!(all[0].0, "100");
719/// assert_eq!(all[1].0, "90");
720/// assert_eq!(all[2].0, "80");
721/// ```
722/// A more complex example:
723/// ```rust
724/// use rust_regex_dsl::create_capture;
725///
726/// create_capture!(MyRegexCapture,
727///   any {
728///     group {
729///       name: Letters,
730///       repeat {
731///          any_of {
732///            #letter
733///          }
734///        }
735///     }, group {
736///       name: Digits,
737///       repeat {
738///          any_of {
739///            #digit
740///          }
741///        }
742///    }
743///   });
744///
745/// let caught = MyRegexCapture::catch("hello").unwrap();
746/// assert_eq!(caught.0, "hello");
747/// assert_eq!(caught.get_capture(), "hello");
748/// assert_eq!(caught.1, Some("hello"));
749/// assert_eq!(caught.letters(), Some("hello"));
750/// assert_eq!(caught.2, None);
751/// assert_eq!(caught.digits(), None);
752///
753/// let caught = MyRegexCapture::catch("321").unwrap();
754/// assert_eq!(caught.0, "321");
755/// assert_eq!(caught.get_capture(), "321");
756/// assert_eq!(caught.1, None);
757/// assert_eq!(caught.letters(), None);
758/// assert_eq!(caught.2, Some("321"));
759/// assert_eq!(caught.digits(), Some("321"));
760///
761/// let all: Vec<_> = MyRegexCapture::catch_all("A1234B33").collect();
762/// assert_eq!(all.len(), 4);
763/// assert_eq!(all[0].1, Some("A"));
764/// assert_eq!(all[1].2, Some("1234"));
765/// assert_eq!(all[2].letters(), Some("B"));
766/// assert_eq!(all[3].digits(), Some("33"));
767/// ```
768///
769#[proc_macro]
770pub fn create_capture(input: TokenStream) -> TokenStream {
771    let create_capture = parse_macro_input!(input as CreateCapture);
772    let error_factory = ErrorFactory::new_root();
773    create_capture.build(error_factory).into()
774}