1#![allow(unused, static_mut_refs)]
2use std::cmp::{Eq, Ord, PartialEq, PartialOrd};
3use std::collections::BTreeMap;
4use std::fmt::{Debug, Display, Formatter};
5use std::ops::Range;
6
7use unique_pointer::UniquePointer;
8
9use crate::{
10 impl_matcher_for_ref, Ascii, Buffer, Match, Matcher, Position, Span, Special, StackRange, State,
11};
12
13#[derive(Debug, Clone, PartialEq, Eq)]
14pub enum Production {
15 And(Vec<Production>),
16 Ascii(Ascii),
17 Atomic(Box<Production>),
18 CompoundAtomic(Box<Production>),
19 Literal(String),
20 Named(String),
21 Not(Box<Production>),
22 OneOrMore(Box<Production>),
23 Optional(Box<Production>),
24 Or(Vec<Production>),
25 Range(Range<char>),
26 Special(Special),
27 ZeroOrMore(Box<Production>),
28}
29impl Production {
30 fn match_literal(
31 &self,
32 state: &mut State,
33 input: &str,
34 start: &Position,
35 literal: &str,
36 ) -> Option<Match> {
37 if input.len() != literal.len() {
38 None
39 } else {
40 (literal == input)
41 .then_some((Production::Literal(literal.to_string()), start.span_to(&input)).into())
42 }
43 }
44
45 fn match_named(
46 &self,
47 state: &mut State,
48 input: &str,
49 start: &Position,
50 name: &str,
51 ) -> Option<Match> {
52 let matcher = state.matcher(name).expect("named matcher");
53 if let Some(r#match) = matcher.is_match(state.as_mut(), input, start) {
54 Some(
55 Into::<Match>::into((self.clone(), self.span(start, input)))
56 .with_inner(vec![r#match]),
57 )
58 } else {
59 None
60 }
61 }
62
63 fn match_ascii(
64 &self,
65 state: &mut State,
66 input: &str,
67 start: &Position,
68 ascii: &Ascii,
69 ) -> Option<Match> {
70 ascii.is_match(state.as_mut(), input, start)
71 }
72
73 fn match_range(
74 &self,
75 state: &mut State,
76 input: &str,
77 start: &Position,
78 range: Range<char>,
79 ) -> Option<Match> {
80 self.match_or(
81 state,
82 input,
83 start,
84 &range
85 .map(String::from)
86 .map(|literal| Production::Literal(literal))
87 .collect::<Vec<Production>>(),
88 )
89 }
90
91 fn match_not(
92 &self,
93 state: &mut State,
94 input: &str,
95 start: &Position,
96 matcher: &Production,
97 ) -> Option<Match> {
98 if input.is_empty() {
99 return Some((self.clone(), self.span(start, input)).into());
100 }
101 let mut buffer = Buffer::new(input, false);
102 if let Some(r#match) = buffer.produce(state.as_mut(), start, matcher) {
103 None
104 } else {
105 Some((self.clone(), self.span(start, input)).into())
106 }
107 }
108
109 fn match_optional(
110 &self,
111 state: &mut State,
112 input: &str,
113 start: &Position,
114 matcher: &Production,
115 ) -> Option<Match> {
116 if input.is_empty() {
117 return Some((self.clone(), self.span(start, input)).into());
118 }
119 let mut buffer = Buffer::new(input, false);
120 if let Some(r#match) = buffer.produce(state.as_mut(), start, matcher) {
121 Some(
122 Into::<Match>::into((self.clone(), self.span(start, input)))
123 .with_inner(vec![r#match]),
124 )
125 } else {
126 None
127 }
128 }
129
130 fn match_special(
131 &self,
132 state: &mut State,
133 input: &str,
134 start: &Position,
135 matcher: &Special,
136 ) -> Option<Match> {
137 if let Some(r#match) = matcher.is_match(state.as_mut(), input, start) {
138 Some(
139 Into::<Match>::into((self.as_production(), self.span(start, input)))
140 .with_inner(r#match.inner()),
141 )
142 } else {
143 None
144 }
145 }
146
147 fn match_atomic(
148 &self,
149 state: &mut State,
150 input: &str,
151 start: &Position,
152 matcher: &Production,
153 ) -> Option<Match> {
154 if (*state).has_epsilon(input) {
155 None
156 } else {
157 let mut buffer = Buffer::new(input, true);
158 if let Some(r#match) = buffer.produce(state.as_mut(), start, matcher) {
159 Some(
160 Into::<Match>::into((self.clone(), self.span(start, input)))
161 .with_inner(vec![r#match.clone()]),
162 )
163 } else {
164 None
165 }
166 }
167 }
168
169 fn match_compound_atomic(
170 &self,
171 state: &mut State,
172 input: &str,
173 start: &Position,
174 matcher: &Production,
175 ) -> Option<Match> {
176 if (*state).has_epsilon(input) {
177 None
178 } else {
179 let mut buffer = Buffer::new(input, true);
180 if let Some(r#match) = buffer.produce(state.as_mut(), start, matcher) {
181 Some(
182 Into::<Match>::into((self.clone(), self.span(start, input)))
183 .with_inner(vec![r#match.clone()]),
184 )
185 } else {
186 None
187 }
188 }
189 }
190
191 fn match_and(
192 &self,
193 state: &mut State,
194 input: &str,
195 start: &Position,
196 matchers: &Vec<Production>,
197 ) -> Option<Match> {
198 let mut mindex = 0;
199 let maxdex = matchers.len();
200 if maxdex == mindex {
201 return None;
202 }
203 let mut buffer = Buffer::new(input, false);
204 let mut matches = Vec::new();
205 for (index, matcher) in matchers.iter().enumerate() {
206 if let Some(r#match) = buffer.produce(state.as_mut(), start, matcher) {
207 matches.push(r#match);
208 } else {
209 return None;
210 }
211 }
212 if matches.is_empty() {
213 None
214 } else {
215 Some(Into::<Match>::into((self.clone(), self.span(start, input))).with_inner(matches))
216 }
217 }
218
219 fn match_or(
220 &self,
221 state: &mut State,
222 input: &str,
223 start: &Position,
224 matchers: &Vec<Production>,
225 ) -> Option<Match> {
226 for matcher in matchers {
227 let mut buffer = Buffer::new(input, false);
228 if let Some(r#match) = buffer.produce(state.as_mut(), start, matcher) {
229 return Some(r#match.clone());
230 }
231 }
232 None
233 }
234
235 fn match_one_or_more(
236 &self,
237 state: &mut State,
238 input: &str,
239 start: &Position,
240 matcher: &Production,
241 ) -> Option<Match> {
242 let mut buffer = Buffer::new(input, false);
243 let mut matches = Vec::new();
244 while let Some(r#match) = buffer.produce(state.as_mut(), start, matcher) {
245 matches.push(r#match);
246 }
247
248 if matches.len() > 0 {
249 Some(Into::<Match>::into((self.clone(), start.span_to(input))).with_inner(matches))
250 } else {
251 None
252 }
253 }
254
255 fn match_zero_or_more(
256 &self,
257 state: &mut State,
258 input: &str,
259 start: &Position,
260 matcher: &Production,
261 ) -> Option<Match> {
262 if input.is_empty() {
263 return Some((self.clone(), start.span_to(input)).into());
264 }
265 self.match_one_or_more(state, input, start, matcher)
266 }
267}
268
269impl_matcher_for_ref!(Production);
270impl Matcher for Production {
271 fn is_match(&self, state: &mut State, input: &str, start: &Position) -> Option<Match> {
272 match self {
273 Production::And(matchers) => self.match_and(state, input, start, matchers),
274 Production::Ascii(ascii) => self.match_ascii(state, input, start, ascii),
275 Production::Atomic(matcher) => self.match_atomic(state, input, start, matcher.as_ref()),
276 Production::CompoundAtomic(matcher) =>
277 self.match_compound_atomic(state, input, start, matcher.as_ref()),
278 Production::Literal(literal) => self.match_literal(state, input, start, literal),
279 Production::Named(name) => self.match_named(state, input, start, name),
280 Production::Not(matcher) => self.match_not(state, input, start, matcher),
281 Production::OneOrMore(matcher) =>
282 self.match_one_or_more(state, input, start, matcher.as_ref()),
283 Production::Optional(matcher) => self.match_optional(state, input, start, matcher),
284 Production::Or(matchers) => self.match_or(state, input, start, matchers),
285 Production::Range(range) => self.match_range(state, input, start, range.clone()),
286 Production::Special(matcher) => self.match_special(state, input, start, &matcher),
287 Production::ZeroOrMore(matcher) =>
288 self.match_zero_or_more(state, input, start, matcher.as_ref()),
289 }
290 }
291
292 fn name(&self) -> &str {
293 match self {
294 Production::And(string) => "Production::And",
295 Production::Ascii(ascii) => ascii.name(),
296 Production::Atomic(atomic) => "Production::Atomic",
297 Production::CompoundAtomic(compound_atomic) => "Production::CompoundAtomic",
298 Production::Literal(string) => string.as_str(),
299 Production::Named(name) => name.as_str(),
300 Production::Not(string) => "Production::Not",
301 Production::OneOrMore(string) => "Production::OneOrMore",
302 Production::Optional(string) => "Production::Optional",
303 Production::Or(string) => "Production::Or",
304 Production::Range(range) =>
305 format!("Production::Range({}..{})", range.start, range.end).leak(),
306 Production::Special(string) => string.name(),
307 Production::ZeroOrMore(string) => "Production::ZeroOrMore",
308 }
309 }
310
311 fn to_str(&self) -> String {
312 match self {
313 Production::Atomic(string) => {
314 format!("Production::Atomic({})", string.to_str())
315 },
316 Production::CompoundAtomic(string) => {
317 format!("Production::CompoundAtomic({})", string.to_str())
318 },
319 Production::Ascii(string) => {
320 format!("Production::Ascii({})", string.to_string())
321 },
322 Production::Not(matcher) => {
323 format!("Production::Not({})", matcher.to_str())
324 },
325 Production::Optional(matcher) => {
326 format!("Production::Optional({})", matcher.to_str())
327 },
328 Production::Literal(string) => {
329 format!("Production::Literal({})", string.to_string())
330 },
331 Production::Range(range) => {
332 format!("Production::Range({}..{})", range.start, range.end)
333 },
334 Production::Named(string) => {
335 format!("Production::Named({})", string.to_string())
336 },
337 Production::Special(string) => {
338 format!("Production::Special({})", string.name())
339 },
340 Production::And(items) => {
341 format!(
342 "Production::And({})",
343 items
344 .iter()
345 .map(|matcher| matcher.to_str())
346 .collect::<Vec<String>>()
347 .join(", ")
348 )
349 },
350 Production::Or(items) => {
351 format!(
352 "Production::Or({})",
353 items
354 .iter()
355 .map(|matcher| matcher.to_str())
356 .collect::<Vec<String>>()
357 .join(", ")
358 )
359 },
360 Production::OneOrMore(matcher) => {
361 format!("Production::OneOrMore({})", matcher.as_ref().to_str())
362 },
363 Production::ZeroOrMore(matcher) => {
364 format!("Production::ZeroOrMore({})", matcher.as_ref().to_str())
365 },
366 }
367 }
368
369 fn as_production(&self) -> Production {
370 (*self).clone()
371 }
372}
373
374impl From<&str> for Production {
375 fn from(string: &str) -> Production {
376 Production::Named(string.to_string())
377 }
378}
379impl From<String> for Production {
380 fn from(string: String) -> Production {
381 Production::Named(string.clone())
382 }
383}
384impl From<Special> for Production {
385 fn from(matcher: Special) -> Production {
386 Production::Special(matcher)
387 }
388}
389impl From<Range<char>> for Production {
390 fn from(range: Range<char>) -> Production {
391 Production::Range(range)
392 }
393}
394
395impl From<Ascii> for Production {
396 fn from(ascii: Ascii) -> Production {
397 Production::Ascii(ascii)
398 }
399}