1pub mod vm;
2
3use std::rc::Rc;
4
5use self::vm::CompiledRegexInVm;
6use super::CompiledRegex;
7
8#[derive(Clone)]
9pub enum Regex<T> {
10 Begin,
12 End,
14 Satisfy(Rc<dyn Fn(&T) -> bool>),
16 NotSatisfy(Rc<dyn Fn(&T) -> bool>),
18 Concat(Rc<Regex<T>>, Rc<Regex<T>>),
20 Group(Rc<Regex<T>>),
22 NamedGroup(String, Rc<Regex<T>>),
24 NonCapturingGroup(Rc<Regex<T>>),
26 Or(Rc<Regex<T>>, Rc<Regex<T>>),
28 ZeroOrOne(Rc<Regex<T>>, bool),
30 Repeat0(Rc<Regex<T>>, bool),
32 Repeat1(Rc<Regex<T>>, bool),
34 RepeatN(Rc<Regex<T>>, usize),
36 RepeatMinMax(Rc<Regex<T>>, usize, Option<usize>, bool),
38}
39
40impl<T> std::fmt::Debug for Regex<T> {
41 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
42 match self {
43 Regex::Begin => f.write_str("Begin"),
44 Regex::End => f.write_str("End"),
45 Regex::Satisfy(_) => f.debug_tuple("Satisfy").field(&"<fn>").finish(),
46 Regex::NotSatisfy(_) => f.debug_tuple("NotSatisfy").field(&"<fn>").finish(),
47 Regex::Concat(l, r) => f.debug_tuple("Concat").field(l).field(r).finish(),
48 Regex::Group(r) => f.debug_tuple("Group").field(r).finish(),
49 Regex::NamedGroup(name, r) => f.debug_tuple("NamedGroup").field(name).field(r).finish(),
50 Regex::NonCapturingGroup(r) => f.debug_tuple("NonCaptureGroup").field(r).finish(),
51 Regex::Or(l, r) => f.debug_tuple("Or").field(l).field(r).finish(),
52 Regex::Repeat0(r, greedy) => f.debug_tuple("Repeat0").field(r).field(greedy).finish(),
53 Regex::ZeroOrOne(r, greedy) => {
54 f.debug_tuple("ZeroOrOne").field(r).field(greedy).finish()
55 }
56 Regex::Repeat1(r, greedy) => f.debug_tuple("Repeat1").field(r).field(greedy).finish(),
57 Regex::RepeatN(r, n) => f.debug_tuple("RepeatN").field(r).field(n).finish(),
58 Regex::RepeatMinMax(r, n, m, greedy) => f
59 .debug_tuple("RepeatMinMax")
60 .field(r)
61 .field(n)
62 .field(m)
63 .field(greedy)
64 .finish(),
65 }
66 }
67}
68
69impl<T> std::fmt::Display for Regex<T> {
70 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
71 match self {
72 Regex::Begin => write!(f, "^"),
73 Regex::End => write!(f, "$"),
74 Regex::Satisfy(_) => write!(f, "[<fn>]"),
75 Regex::NotSatisfy(_) => write!(f, "[^ <fn>]"),
76 Regex::Concat(l, r) => write!(f, "{}{}", l, r),
77 Regex::Group(r) => write!(f, "({})", r),
78 Regex::NamedGroup(r, name) => write!(f, "(P<{}>{})", name, r),
79 Regex::NonCapturingGroup(r) => write!(f, "(?:{})", r),
80 Regex::Or(l, r) => write!(f, "{}|{}", l, r),
81 Regex::Repeat0(r, greedy) => {
82 write!(f, "{}*", r)?;
83 if !greedy {
84 write!(f, "?")?;
85 }
86
87 Ok(())
88 }
89 Regex::ZeroOrOne(r, greedy) => {
90 write!(f, "{}?", r)?;
91 if !greedy {
92 write!(f, "?")?;
93 }
94
95 Ok(())
96 }
97 Regex::Repeat1(r, greedy) => {
98 write!(f, "{}+", r)?;
99 if !greedy {
100 write!(f, "?")?;
101 }
102 Ok(())
103 }
104 Regex::RepeatN(r, n) => write!(f, "{}{{{}}}", r, n),
105 Regex::RepeatMinMax(r, n, m, greedy) => {
106 if let Some(m) = m {
107 write!(f, "{}{{{},{}}}", r, n, m)?;
108 } else {
109 write!(f, "{}{{{},}}", r, n)?;
110 }
111 if !greedy {
112 write!(f, "?")?;
113 }
114
115 Ok(())
116 }
117 }
118 }
119}
120
121impl<T: 'static> Regex<T> {
122 pub fn begin() -> Self {
124 Regex::Begin
125 }
126 pub fn end() -> Self {
128 Regex::End
129 }
130 pub fn satisfy(f: impl Fn(&T) -> bool + 'static) -> Self {
132 Regex::Satisfy(Rc::new(f))
133 }
134
135 pub fn not_satisfy(f: impl Fn(&T) -> bool + 'static) -> Self {
137 Regex::NotSatisfy(Rc::new(move |x| !f(x)))
138 }
139
140 pub fn any() -> Self {
142 Regex::Satisfy(Rc::new(|_| true))
143 }
144
145 pub fn zero_or_one(reg: Self, greedy: bool) -> Self {
147 Regex::ZeroOrOne(reg.into(), greedy)
148 }
149
150 pub fn repeat1(reg: Self, greedy: bool) -> Self {
152 Regex::Repeat1(reg.into(), greedy)
153 }
154
155 pub fn repeat0(reg: Self, greedy: bool) -> Self {
157 Regex::Repeat0(reg.into(), greedy)
158 }
159
160 pub fn repeat_n(reg: Self, n: usize) -> Self {
162 Regex::RepeatN(reg.into(), n)
163 }
164
165 pub fn repeat_n_or_more(reg: Self, n: usize, greedy: bool) -> Self {
167 Regex::RepeatMinMax(reg.into(), n, None, greedy)
168 }
169
170 pub fn repeat_min_max(reg: Self, n: usize, m: usize, greedy: bool) -> Self {
172 Regex::RepeatMinMax(reg.into(), n, Some(m), greedy)
173 }
174
175 pub fn concat(r: Self, s: Self) -> Self {
177 Regex::Concat(r.into(), s.into())
178 }
179
180 pub fn or(r: Self, s: Self) -> Self {
182 Regex::Or(r.into(), s.into())
183 }
184
185 pub fn group(r: Self) -> Self {
187 Regex::Group(r.into())
188 }
189
190 pub fn non_capturing_group(r: Self) -> Self {
192 Regex::NonCapturingGroup(r.into())
193 }
194
195 pub fn named_group(name: &str, r: Self) -> Self {
197 Regex::NamedGroup(name.to_owned(), r.into())
198 }
199
200 pub fn is(value: T) -> Self
202 where
203 T: PartialEq + 'static,
204 {
205 Regex::Satisfy(Rc::new(move |v| *v == value))
206 }
207
208 pub fn seq(values: &[T]) -> Self
210 where
211 T: PartialEq + Clone + 'static,
212 {
213 if values.len() == 1 {
214 Regex::is(values[0].clone())
215 } else {
216 let mut reg = Regex::is(values[0].clone());
217 for v in values.iter().skip(1) {
218 reg = Regex::concat(reg, Regex::is(v.clone()));
219 }
220 reg
221 }
222 }
223
224 pub fn compile(self) -> impl CompiledRegex<T> {
225 CompiledRegexInVm::compile(self)
226 }
227}