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
80
use grammar::{self, MatchesEmpty, MaybeKnown};
use std::char;
use std::ops::{self, Bound, RangeBounds};
pub type Grammar<S = String> = grammar::Grammar<Pat<S>>;
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum Pat<S = String, C = char> {
String(S),
Range(C, C),
}
impl<'a, C> From<&'a str> for Pat<&'a str, C> {
fn from(s: &'a str) -> Self {
Pat::String(s)
}
}
impl<'a, C> From<&'a str> for Pat<String, C> {
fn from(s: &str) -> Self {
Pat::String(s.to_string())
}
}
impl<C> From<String> for Pat<String, C> {
fn from(s: String) -> Self {
Pat::String(s)
}
}
impl<'a, S> From<(Bound<&'a char>, Bound<&'a char>)> for Pat<S> {
fn from(range: (Bound<&char>, Bound<&char>)) -> Self {
let start = match range.start_bound() {
Bound::Included(&c) => c,
Bound::Excluded(&c) => {
char::from_u32(c as u32 + 1).expect("excluded lower char bound too high")
}
Bound::Unbounded => '\0',
};
let end = match range.end_bound() {
Bound::Included(&c) => c,
Bound::Excluded(&c) => {
char::from_u32(c as u32 - 1).expect("excluded upper char bound too low")
}
Bound::Unbounded => char::MAX,
};
Pat::Range(start, end)
}
}
macro_rules! range_impls {
($($ty:ty),*) => {
$(impl<S> From<$ty> for Pat<S> {
fn from(range: $ty) -> Self {
Self::from((range.start_bound(), range.end_bound()))
}
})*
}
}
range_impls! {
(Bound<char>, Bound<char>),
ops::RangeTo<char>,
ops::Range<char>,
ops::RangeInclusive<char>,
ops::RangeFull,
ops::RangeFrom<char>,
ops::RangeToInclusive<char>
}
impl<S: AsRef<str>> MatchesEmpty for Pat<S> {
fn matches_empty(&self) -> MaybeKnown<bool> {
MaybeKnown::Known(match self {
Pat::String(s) => s.as_ref().is_empty(),
Pat::Range(..) => false,
})
}
}