Skip to main content

alpm_parsers/error/
layer_parser.rs

1//! The [`LayerParser`], which is used to mark beginnings of a new layer.
2
3use winnow::{Parser, error::ErrMode, stream::Location};
4
5use super::{Input, PResult, ParseStack};
6
7/// The parser returned by [`LayerExt::layer`]
8#[derive(Debug)]
9pub struct LayerParser<P> {
10    pub(crate) parser: P,
11    pub(crate) name: String,
12}
13
14impl<'i, O, P> Parser<Input<'i>, O, ErrMode<ParseStack<'i>>> for LayerParser<P>
15where
16    P: Parser<Input<'i>, O, ErrMode<ParseStack<'i>>>,
17{
18    #[inline]
19    fn parse_next(&mut self, i: &mut Input<'i>) -> PResult<'i, O> {
20        let start = i.current_token_start();
21        self.parser
22            .parse_next(i)
23            .map_err(|e| e.map(|stack| stack.close_layer(self.name.clone(), start)))
24    }
25}
26
27/// Extension trait that adds a [`LayerExt::layer`] function to all parsers
28///
29/// Calling `layer` allows creation of nested [`LayerParser`] on any parser over the
30/// [`Input`] type.
31///
32/// A layer acts as a boundary of the currently parsed unit of "grammar".
33/// All context errors since the last layer (if existing) are bound to this layer.
34///
35/// # Note
36///
37/// The order in which [`Parser::context`] and `layer` functions are called is important!
38/// A layer contains all `context` calls that were called **beforehand**.
39///
40/// Any context calls after `layer` will be part of the next layer.
41///
42/// # Example
43///
44/// ```rust
45/// use alpm_parsers::prelude::*;
46/// use winnow::ascii::alphanumeric1;
47///
48/// # fn main() -> testresult::TestResult {
49/// let mut parser = alphanumeric1.label("alphanumeric number").layer("version");
50///
51/// parser.parse(Input::new("a1"))?;
52/// # Ok(())
53/// # }
54/// ```
55pub trait LayerExt<'i, O>: Parser<Input<'i>, O, ErrMode<ParseStack<'i>>> + Sized {
56    /// Wraps this parser in a named nesting layer.
57    ///
58    /// On failure any pending context messages are moved into a named layer, spanning from where
59    /// the parser started to where it failed.
60    fn layer(self, name: impl Into<String>) -> LayerParser<Self> {
61        LayerParser {
62            parser: self,
63            name: name.into(),
64        }
65    }
66}
67
68impl<'i, O, P> LayerExt<'i, O> for P where P: Parser<Input<'i>, O, ErrMode<ParseStack<'i>>> {}