oom/match/
production.rs

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}