fn_bnf/
rules.rs

1use core::ops::{Index, Range, RangeTo};
2
3#[allow(clippy::wildcard_imports)]
4use super::*;
5
6#[macro_export]
7/// Convenience macro for quickly defining errors with static messages for use in your grammars.
8/// 
9/// # Usage
10/// ```ignore
11/// err! {
12///     pub InvalidFloat: "floating point literals must have an integer part",
13///     pub(crate) InternalError: "internal error (this is a bug, please report)"
14/// }
15/// ```
16macro_rules! err {
17    ($($vis: vis $name: ident: $message: literal),*$(,)?) => {$(
18        #[derive(Debug, Copy, Clone, Default)]
19        #[doc = $message]
20        $vis struct $name;
21        impl ::core::fmt::Display for $name {
22            fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
23                write!(f, $message)
24            }
25        }
26        impl ::core::error::Error for $name {}
27    )*};
28}
29
30/// Maps a function over the output of a rule. See [`Rule::map_parsed`].
31#[derive(Debug, Clone, PartialEq, NamedRule)]
32pub struct Map<
33    'input, SliceType: ?Sized, 
34    R: Rule<'input, SliceType>, O, 
35    Func: Fn(R::Output) -> O
36> {
37    pub(crate) inner: R,
38    pub(crate) func: Func,
39    pub(crate) _p: PhantomData<(&'input SliceType, O)>
40}
41impl<
42    'input, SliceType: ?Sized, 
43    R: Rule<'input, SliceType>, O, 
44    Func: Fn(R::Output) -> O
45> Rule<'input, SliceType> for Map<'input, SliceType, R, O, Func> {
46    type Output = Func::Output;
47
48    fn parse_at<'cursor, 'this, 'index>(&'this self, input: &'cursor mut &'input SliceType, index: &'index mut usize)
49        -> Result<Self::Output, ParseError> where 'input: 'this 
50    {
51        self.inner.parse_at(input, index)
52            .map(&self.func)
53    }
54}
55
56
57/// Attempts to map a function over the output of a rule. See [`Rule::try_map_parsed`].
58#[derive(Debug, Clone, PartialEq, NamedRule)]
59pub struct TryMap<
60    'input, SliceType: ?Sized, 
61    R: Rule<'input, SliceType>, O, E: Error + 'static,
62    Func: Fn(R::Output) -> Result<O, E>
63> {
64    pub(crate) inner: R,
65    pub(crate) func: Func,
66    pub(crate) _p: PhantomData<(&'input SliceType, O)>
67}
68impl<
69    'input, SliceType: ?Sized, 
70    R: Rule<'input, SliceType>, O, E: Error + 'static,
71    Func: Fn(R::Output) -> Result<O, E>
72> Rule<'input, SliceType> for TryMap<'input, SliceType, R, O, E, Func> {
73    type Output = O;
74
75    fn parse_at<'cursor, 'this, 'index>(&'this self, input: &'cursor mut &'input SliceType, index: &'index mut usize)
76        -> Result<Self::Output, ParseError> where 'input: 'this 
77    {
78        let start_index = *index;
79        let start_input = *input;
80        self.inner.parse_at(input, index)
81            .and_then(|res| (self.func)(res)
82                .map_err(|err| {
83                    *index = start_index;
84                    *input = start_input;
85                    ParseError::new(Some(Box::new(err)), self.inner.name(), start_index)
86                })
87            )
88    }
89}
90
91
92/// Errors if a rule matches.  See [`Rule::prevent`].
93#[derive(Debug, Clone, PartialEq, NamedRule)]
94pub struct Not<R>(pub(crate) R);
95
96impl<'input, T: ?Sized + 'input, R: Rule<'input, T>> Rule<'input, T> for Not<R> {
97    type Output = ();
98
99    fn parse_at<'cursor, 'this, 'index>(&'this self, input: &'cursor mut &'input T, index: &'index mut usize) -> Result<Self::Output, ParseError> where 'input: 'this {
100        let start = *index;
101        let res = self.0.parse_at(input, index);
102        *index = start;
103        let Err(_) = res else {
104            return Err(ParseError::new(
105                Some(Box::new(UnexpectedMatch)),
106                self.name(), start
107            ));
108        };
109        Ok(())
110    }
111}
112
113/// Attempts to parse a rule, returning its result. See [`Rule::attempt`].
114#[derive(NamedRule)]
115pub struct Attempt<'input, T: 'input + ?Sized, R: Rule<'input, T>>(pub R, pub(crate) PhantomData<&'input T>);
116
117impl<'input, T: 'input + ?Sized, R: Rule<'input, T>> Rule<'input, T> for Attempt<'input, T, R> {
118    type Output = Result<R::Output, ParseError>;
119    
120    fn parse_at<'cursor, 'this, 'index>(&'this self, input: &'cursor mut &'input T, index: &'index mut usize) -> Result<Self::Output, ParseError> where 'input: 'this {
121        // core::array::try_from_fn(|_| self.0.parse_at(input, index))
122        let before = (*input, *index);
123        let res = self.0.parse_at(input, index);
124        if res.is_err() { (*input, *index) = before; }
125        Ok(res)
126    }
127}
128
129/// Matches a rule forever, failing if it does. See [`Rule::consume_all`].
130#[derive(NamedRule)]
131pub struct Consume<'input, T: 'input + ?Sized, R: Rule<'input, T>>(pub R, pub(crate) PhantomData<&'input T>);
132
133impl<'input, R: Rule<'input, str>> Rule<'input, str> for Consume<'input, str, R> {
134    type Output = Vec<R::Output>;
135    
136    fn parse_at<'cursor, 'this, 'index>(&'this self, input: &'cursor mut &'input str, index: &'index mut usize) -> Result<Self::Output, ParseError> where 'input: 'this {
137        // core::array::try_from_fn(|_| self.0.parse_at(input, index))
138        let before = (*input, *index);
139        let mut els = Vec::new();
140        while !input.is_empty() {
141            let el = match self.0.parse_at(input, index) {
142                Ok(v) => v,
143                Err(err) => { (*input, *index) = before; return Err(err); }
144            };
145            els.push(el);
146        }
147        Ok(els)
148    }
149}
150impl<'input, T: 'input, R: Rule<'input, [T]>> Rule<'input, [T]> for Consume<'input, [T], R> {
151    type Output = Vec<R::Output>;
152    
153    fn parse_at<'cursor, 'this, 'index>(&'this self, input: &'cursor mut &'input [T], index: &'index mut usize) -> Result<Self::Output, ParseError> where 'input: 'this {
154        // core::array::try_from_fn(|_| self.0.parse_at(input, index))
155        let before = (*input, *index);
156        let mut els = Vec::new();
157        while !input.is_empty() {
158            let el = match self.0.parse_at(input, index) {
159                Ok(v) => v,
160                Err(err) => { (*input, *index) = before; return Err(err); }
161            };
162            els.push(el);
163        }
164        Ok(els)
165    }
166}
167
168/// Repeatedly matches a rule a known amount of times. See [`Rule::repeat_for`].
169#[derive(NamedRule)]
170pub struct RepeatFor<'input, T: 'input + ?Sized, R: Rule<'input, T>, const REPETITIONS: usize>(pub R, pub(crate) PhantomData<&'input T>);
171impl<'input, T: 'input + ?Sized, R: Rule<'input, T>, const REPETITIONS: usize> Rule<'input, T> for RepeatFor<'input, T, R, REPETITIONS> {
172    type Output = [R::Output; REPETITIONS];
173    
174    fn parse_at<'cursor, 'this, 'index>(&'this self, input: &'cursor mut &'input T, index: &'index mut usize) -> Result<Self::Output, ParseError> where 'input: 'this {
175        // core::array::try_from_fn(|_| self.0.parse_at(input, index))
176        let before = (*input, *index);
177        let mut arr: [Option<R::Output>; REPETITIONS] = [const { None }; REPETITIONS];
178        for el in &mut arr {
179            el.replace(match self.0.parse_at(input, index) {
180                Ok(v) => v,
181                Err(err) => {
182                    (*input, *index) = before;
183                    return Err(err);
184                }
185            });
186        }
187        Ok(arr.map(|v| v.unwrap()))
188    }
189}
190
191/// Matches a rule a set amount of times. See [`Rule::repeat`]
192#[derive(NamedRule)]
193pub struct Repeat<'input, T: 'input + ?Sized, R: Rule<'input, T>>(pub R, pub usize, pub(crate) PhantomData<&'input T>);
194impl<'input, T: 'input + ?Sized, R: Rule<'input, T>> Rule<'input, T> for Repeat<'input, T, R> {
195    type Output = Vec<R::Output>;
196    
197    fn parse_at<'cursor, 'this, 'index>(&'this self, input: &'cursor mut &'input T, index: &'index mut usize) -> Result<Self::Output, ParseError> where 'input: 'this {
198        // core::array::try_from_fn(|_| self.0.parse_at(input, index))
199        let before = (*input, *index);
200        let mut arr = Vec::with_capacity(self.1);
201        for _ in 0..self.1 {
202            arr.push(match self.0.parse_at(input, index) {
203                Ok(v) => v,
204                Err(err) => {
205                    (*input, *index) = before;
206                    return Err(err);
207                }
208            });
209        }
210        Ok(arr)
211    }
212}
213
214/// Matches a rule an arbitrary amount of times. See [`Rule::take`].
215#[derive(NamedRule)]
216pub struct Many<'input, T: 'input + ?Sized, R: Rule<'input, T>> {
217    rule: R,
218    limit: Option<usize>,
219    _p: PhantomData<&'input T>
220}
221
222impl<'input, T: 'input + ?Sized, R: Rule<'input, T>> Many<'input, T, R> {
223    /// Matches a potentially infinite amount of times.
224    pub fn unlimited(rule: R) -> Self {
225        Self { rule, limit: None, _p: PhantomData }
226    }
227
228    /// Matches at most a set amount of times.
229    pub fn limited(rule: R, limit: usize) -> Self {
230        Self { rule, limit: Some(limit), _p: PhantomData }
231    }
232}
233
234impl<'input, T: 'input + ?Sized, R: Rule<'input, T>> Rule<'input, T> for Many<'input, T, R> {
235    type Output = Vec<R::Output>;
236    
237    fn parse_at<'cursor, 'this, 'index>(&'this self, input: &'cursor mut &'input T, index: &'index mut usize) -> Result<Self::Output, ParseError> where 'input: 'this {
238        // core::array::try_from_fn(|_| self.0.parse_at(input, index))
239        let mut arr = Vec::new();
240        let mut i = 0;
241        while let Ok(res) = self.rule.parse_at(input, index) {
242            arr.push(res);
243            i += 1;
244            if self.limit.is_some_and(|limit| limit >= i) {
245                break;
246            }
247        }
248        Ok(arr)
249    }
250}
251
252/// Matches one of any character or slice member. Fails on empty input.
253/// 
254/// # Example
255/// ```ignore
256/// Double: (char, char) = Any, arg_0;
257/// ```
258#[derive(Debug, Copy, Clone, NamedRule)]
259pub struct Any;
260impl<'input, T: 'input> Rule<'input, [T]> for Any {
261    type Output = &'input T;
262
263    fn parse_at<'cursor, 'this, 'index>(&'this self, input: &'cursor mut &'input [T], index: &'index mut usize) -> Result<Self::Output, ParseError> where 'input: 'this {
264        (!input.is_empty())
265            .then(|| {
266                let source = &input[0];
267                *input = &input[1..];
268                *index += 1;
269                source
270            })
271            .ok_or(ParseError::new(Some(Box::new(UnexpectedEOF)), self.name(), *index))
272    }
273}
274
275impl<'input> Rule<'input, str> for Any {
276    type Output = char;
277
278    fn parse_at<'cursor, 'this, 'index>(&'this self, input: &'cursor mut &'input str, index: &'index mut usize) -> Result<Self::Output, ParseError> where 'input: 'this {
279        input.chars().next()
280            .inspect(|chr| {
281                let len = chr.len_utf8();
282                *input = &input[len..];
283                *index += len;
284            })
285            .ok_or(ParseError::new(Some(Box::new(UnexpectedEOF)), self.name(), *index))
286    }
287}
288
289/// Takes input until a given function fails.
290/// 
291/// # Example
292/// ```ignore
293/// number: &'input str = While::from(char::is_ascii_digit)
294/// ```
295#[derive(Debug, Clone, PartialEq, NamedRule)]
296pub struct While<F, T> { func: F, _p: PhantomData<T> }
297
298impl<T, F: Fn(&T) -> bool> While<F, T> {
299    /// Creates a [`While`] rule from a function. 
300    pub fn from(func: F) -> Self {
301        Self { func, _p: PhantomData }
302    }
303}
304
305impl<'input, F: Fn(&char) -> bool> Rule<'input, str> for While<F, char> {
306    type Output = &'input str;
307
308    fn parse_at<'cursor, 'this, 'index>(&'this self, input: &'cursor mut &'input str, index: &'index mut usize)
309        -> Result<Self::Output, ParseError> where 'input: 'this
310    {
311        let offset = input.find(|c: char| !(self.func)(&c))
312            .unwrap_or(input.len());
313
314        let res = &input[..offset];
315        *input = &input[offset..];
316        *index += offset;
317        Ok(res)
318    }
319}
320
321impl<'input, T: 'input, F: Fn(&T) -> bool> Rule<'input, [T]> for While<F, T> {
322    type Output = &'input [T];
323
324    fn parse_at<'cursor, 'this, 'index>(&'this self, input: &'cursor mut &'input [T], index: &'index mut usize)
325        -> Result<Self::Output, ParseError> where 'input: 'this
326    {
327        let offset = (*input).iter().position(|c: &T| !(self.func)(c))
328            .unwrap_or(input.len());
329
330        let res = &input[..offset];
331        *input = &input[offset..];
332        *index += offset;
333        Ok(res)
334    }
335}
336
337/// Struct returned by [`Rule::spanned`] to store the span and source of a given parsed rule.
338#[derive(Debug, Clone, PartialEq, Eq)]
339pub struct Span<'input, T: 'input + ?Sized, O> {
340    /// The range of the input that the rule parsed over.
341    pub span: Range<usize>,
342    /// The original input that the rule parsed.
343    pub source: &'input T,
344    /// The output of the rule's parsing.
345    pub output: O
346}
347
348/// Records the span of a given rule. See [`Rule::spanned`].
349#[derive(NamedRule)]
350pub struct Spanned<'input, T: 'input + ?Sized, R: Rule<'input, T>> { pub(crate) rule: R, pub(crate) _p: PhantomData<&'input T> }
351
352impl<'input, T: 'input + Index<RangeTo<usize>, Output = T> + ?Sized, R: Rule<'input, T>> Rule<'input, T> for Spanned<'input, T, R> {
353    type Output = Span<'input, T, R::Output>;
354    
355    fn parse_at<'cursor, 'this, 'index>(&'this self, input: &'cursor mut &'input T, index: &'index mut usize) -> Result<Self::Output, ParseError> where 'input: 'this {
356        let before = (*input, *index);
357        let res = self.rule.parse_at(input, index)?;
358        Ok(Span {
359            span: before.1 .. *index,
360            source: &before.0[..*index - before.1],
361            output: res
362        })
363    }
364}
365
366
367/// Always fails with a given error.
368/// 
369/// # Example
370/// ```ignore
371/// uh_oh: u32 = Fail::new(Error::new("oh no!"))
372/// ```
373#[derive(Debug, PartialEq, NamedRule)]
374pub struct Fail<E: core::error::Error + Clone + 'static>(pub E);
375
376impl<E: core::error::Error + Clone + 'static> Fail<E> {
377    /// Creates a new instance of this type.
378    #[inline]
379    pub fn new(err: E) -> Self {
380        Self(err)
381    }
382}
383
384impl<'input, T: ?Sized + 'input, E: core::error::Error + Clone + 'static> Rule<'input, T> for Fail<E> {
385    type Output = crate::Never;
386
387    fn parse_at<'cursor, 'this, 'index>(&'this self, _input: &'cursor mut &'input T, index: &'index mut usize)
388        -> Result<Self::Output, ParseError> where 'input: 'this
389    {
390        Err(ParseError::new(Some(Box::new(self.0.clone())), self.name(), *index))
391    }
392}
393
394/// Alias for a refernce to a `dyn` Rule object of a given type and output.
395/// 
396/// You can use this with an `as` cast in a `match` statement to allow each statement to be a separate rule:
397/// ```ignore
398/// t: (char, char) = Any, match arg_0 {
399///     'a' => &'b' as AnyRule<str, char>,
400///     'b' => &Any as AnyRule<str, char>,
401///     other => &Fail(Unexpected::new(other)) as AnyRule<str, char>
402/// };
403/// ```
404pub type AnyRule<'rule, 'input, In, Out> = &'rule dyn Rule<'input, In, Output = Out>;
405
406
407/// Runs a function when parsed. Parses nothing, and returns the function's output.
408/// 
409/// The inner function _must not_ recursively parse this rule! Doing so will cause a runtime panic.
410/// 
411/// ```rust, should_panic
412/// # use fn_bnf::{Action, Rule};
413/// thread_local! {
414///     static ACTION: Action<(), fn()> = Action::new(adversarial);
415/// }
416/// 
417/// fn adversarial() {
418///     ACTION.with(|a| { let _res = a.parse(""); });
419/// }
420/// 
421/// adversarial();
422/// ```
423pub struct Action<O, F: FnMut() -> O>(core::cell::Cell<Option<F>>);
424impl<O, F: FnMut() -> O> Action<O, F> {
425    /// Creates a new [`Action`] using a specified function.
426    pub fn new(func: F) -> Self {
427        Self(core::cell::Cell::new(Some(func)))
428    }
429}
430impl<O, F: FnMut() -> O> NamedRule for Action<O, F> {
431    fn name(&self) -> Option<&'static str> { Some("Action") }
432}
433impl<'i, S: 'i + ?Sized, O, F: FnMut() -> O> Rule<'i, S> for Action<O, F> {
434    type Output = O;
435
436    fn parse_at<'cursor, 'this, 'index>(&'this self, _input: &'cursor mut &'i S, _index: &'index mut usize)
437        -> Result<Self::Output, ParseError> where 'i: 'this
438    {
439        let mut f = self.0.take().expect("actions must not parse themselves within their own bodies");
440        let ret = f();
441        self.0.set(Some(f));
442        Ok(ret)
443    }
444}
445
446/// Parses similar to [`Many`], but with an separator rule between each parse.
447/// See [`Rule::separated`].
448#[derive(NamedRule)]
449pub struct Separated<'input, T: 'input + ?Sized, R: Rule<'input, T>, S: Rule<'input, T>> {
450    rule: R,
451    separator: S,
452    limit: Option<usize>,
453    _p: PhantomData<&'input T>
454}
455
456impl<'input, T: 'input + ?Sized, R: Rule<'input, T>, S: Rule<'input, T>> Separated<'input, T, R, S> {
457    /// Matches a potentially infinite amount of times.
458    pub fn unlimited(rule: R, separator: S) -> Self {
459        Self { rule, separator, limit: None, _p: PhantomData }
460    }
461
462    /// Matches at most a set amount of times.
463    pub fn limited(rule: R, separator: S, limit: usize) -> Self {
464        Self { rule, separator, limit: Some(limit), _p: PhantomData }
465    }
466}
467
468impl<'input, T: 'input + ?Sized, R: Rule<'input, T>, S: Rule<'input, T>> Rule<'input, T> for Separated<'input, T, R, S> {
469    type Output = Vec<(R::Output, Option<S::Output>)>;
470    
471    fn parse_at<'cursor, 'this, 'index>(&'this self, input: &'cursor mut &'input T, index: &'index mut usize) -> Result<Self::Output, ParseError> where 'input: 'this {
472        let mut arr = Vec::new();
473        let mut i = 0;
474        while let Ok(res) = self.rule.parse_at(input, index) {
475            let Ok(sep_res) = self.separator.parse_at(input, index) else {
476                arr.push((res, None));
477                break;
478            };
479            arr.push((res, Some(sep_res)));
480            i += 1;
481            if self.limit.is_some_and(|lim| i >= lim) { break; }
482        }
483        Ok(arr)
484    }
485}