fn_bnf/
definitions.rs

1#[allow(clippy::wildcard_imports)]
2use super::*;
3
4#[allow(clippy::needless_lifetimes)] // used in proc macro
5impl<'ty, T, S: ?Sized> NamedRule for for<'index, 'cursor> fn(&'cursor mut &'ty S, &'index mut usize) -> Result<T, ParseError> {
6    fn name(&self) -> Option<&'static str> { Some("<anonymous rule>") }
7}
8impl<'ty, T, S: ?Sized> Rule<'ty, S> for for<'index, 'cursor> fn(&'cursor mut &'ty S, &'index mut usize) -> Result<T, ParseError> {
9    type Output = T;
10
11    fn parse_at<'cursor, 'this, 'index>(&'this self, input: &'cursor mut &'ty S, index: &'index mut usize) -> Result<T, ParseError> where 'ty: 'this {
12        let before = (*input, *index);
13        self(input, index).map_err(|err| {
14            (*input, *index) = before;
15            ParseError::new(Some(Box::new(err)), self.name(), *index)
16        })
17    }
18}
19impl<T> NamedRule for for<'a> fn(&'a T) -> bool {
20    fn name(&self) -> Option<&'static str> { Some("<anonymous pattern>") }
21}
22
23impl<'input, T: 'input> Rule<'input, [T]> for for<'a> fn(&'a T) -> bool {
24    type Output = &'input T;
25
26    fn parse_at<'cursor, 'this, 'index>(&'this self, input: &'cursor mut &'input [T], index: &'index mut usize) -> Result<Self::Output, ParseError> where 'input: 'this {
27        if let Some(first) = input.first().and_then(|v| self(v).then_some(v)) {
28            *input = &input[1..];
29            *index += 1;
30            return Ok(first);
31        }
32        Err(ParseError::new(Some(Box::new(UnmatchedInput)), self.name(), *index))
33    }
34}
35
36impl<'input> Rule<'input, str> for fn(&char) -> bool {
37    type Output = char;
38
39    fn parse_at<'cursor, 'this, 'index>(&'this self, input: &'cursor mut &'input str, index: &'index mut usize) -> Result<Self::Output, ParseError> where 'input: 'this {
40        if let Some((chr, idx)) = input.chars().next().and_then(|chr| self(&chr).then_some((chr, chr.len_utf8()))) {
41            *input = &input[idx..];
42            *index += idx;
43            return Ok(chr);
44        }
45        Err(ParseError::new(Some(Box::new(UnmatchedInput)), self.name(), *index))
46    }
47}
48
49impl NamedRule for char {
50    fn name(&self) -> Option<&'static str> { Some("<single character>") }
51}
52impl<'input> Rule<'input, str> for char {
53    type Output = char;
54
55    fn parse_at<'cursor, 'this, 'index>(&'this self, input: &'cursor mut &'input str, index: &'index mut usize) -> Result<Self::Output, ParseError> where 'input: 'this {
56        let Some(chr) = input.chars().next() else {
57            return Err(ParseError::new(Some(Box::new(UnexpectedEOF)), self.name(), *index))
58        };
59        if chr != *self {
60            return Err(ParseError::new(Some(Box::new(Unexpected::<char>::new(chr))), self.name(), *index))    
61        }
62        let len = chr.len_utf8();
63        *index += len;
64        *input = &input[len..];
65        Ok(*self)
66    }
67}
68
69impl<T> NamedRule for [T] {
70    fn name(&self) -> Option<&'static str> { Some("<slice literal>") }
71}
72impl<'input, T: PartialEq + 'input> Rule<'input, [T]> for [T] {
73    type Output = &'input [T];
74
75    fn parse_at<'cursor, 'this, 'index>(&'this self, input: &'cursor mut &'input [T], index: &'index mut usize) -> Result<Self::Output, ParseError> where 'input: 'this {
76        if let Some(after) = input.strip_prefix(self) {
77            let res = &input[..self.len()];
78            *input = after;
79            *index += self.len();
80            Ok(res)
81        } else { Err(ParseError::new(Some(Box::new(NoMatch)), self.name(), *index)) }
82    }
83}
84
85impl<const N: usize, T> NamedRule for [T; N] {
86    fn name(&self) -> Option<&'static str> { Some("<array literal>") }
87}
88impl<'input, const N: usize, T: PartialEq + 'input> Rule<'input, [T]> for [T; N] {
89    type Output = &'input [T];
90
91    #[inline]
92    fn parse_at<'cursor, 'this, 'index>(&'this self, input: &'cursor mut &'input [T], index: &'index mut usize) -> Result<Self::Output, ParseError> where 'input: 'this {
93        self[..].parse_at(input, index)
94    }
95}
96
97impl NamedRule for str {
98    fn name(&self) -> Option<&'static str> { Some("<string literal>") }
99}
100impl<'input> Rule<'input, str> for str {
101    type Output = &'input str;
102
103    fn parse_at<'cursor, 'this, 'index>(&'this self, input: &'cursor mut &'input str, index: &'index mut usize) -> Result<Self::Output, ParseError> where 'input: 'this {
104        if let Some(after) = input.strip_prefix(self) {
105            let res = &input[..self.len()];
106            *input = after;
107            *index += self.len();
108            Ok(res)
109        } else { Err(ParseError::new(Some(Box::new(NoMatch)), self.name(), *index)) }
110    }
111}
112
113impl<T: NamedRule + ?Sized> NamedRule for &T {
114    #[inline] fn name(&self) -> Option<&'static str> { (*self).name() }
115}
116impl<'input, S: ?Sized + 'input, T: ?Sized + Rule<'input,  S>> Rule<'input, S> for &T {
117    type Output = <T as Rule<'input, S>>::Output;
118
119    fn parse_at<'cursor, 'this, 'index>(&'this self, input: &'cursor mut &'input S, index: &'index mut usize) -> Result<Self::Output, ParseError> where 'input: 'this {
120        (**self).parse_at(input, index)
121    }
122}