1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
use crate;
/// Creates a [StringMatcher] from the given [StringPattern].
/// Approximately a shorthand for `&string_pattern!(pattern).matcher()`.
///
/// Matchers are self-referential, so the output can't be moved after it's created.
/// All predefined patterns in the [patterns] module are brought into scope for the pattern expression.
///
/// # Example
///
/// ```
/// let quotes_matcher = gramma::string_matcher!(
/// char('"') + char(..).repeat(..).lazy() + !follows(char('\\')) + char('"')
/// );
///
/// assert!(quotes_matcher.match_string(4, r#"s = "hello, \"world\"!";"#).is_some());
/// ```
/// Compose a [StringPattern].
/// All predefined patterns in the [patterns] module are brought into scope.
///
/// # Example
///
/// ```
/// let quotes_pattern = gramma::string_pattern!(
/// char('"') + char(..).repeat(..).lazy() + !follows(char('\\')) + char('"')
/// );
///
/// assert!(quotes_pattern.matcher().match_string(4, r#"s = "hello, \"world\"!";"#).is_some());
/// ```
///
/// ```
/// # use gramma::{define_string_pattern, string_matcher};
/// define_string_pattern!(
/// fn identifier(max_len: impl Into<Option<u32>>) {
/// !precedes(ascii_digit())
/// + word().repeat(1..=max_len.into().unwrap_or(u32::MAX)).simple()
/// + word_boundary()
/// }
/// );
///
/// assert_eq!(string_matcher!(identifier(4)).match_string(0, "foo"), Some(0..3));
/// assert_eq!(string_matcher!(identifier(4)).match_string(0, "foobar"), None);
/// assert_eq!(string_matcher!(identifier(None)).match_string(0, "foobarbaz"), Some(0..9));
/// ```
=> ;
}