1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
//! Core traits.
use crate::types::ParserOutput;
use crate::{ParseContext, Reported, Result};
/// Trait implemented by all parsers.
///
/// This is implemented by the built-in parsers, like `i32`, as well as
/// user-defined parsers created with `parser!`.
///
/// To run a parser, pass some text to [the `parse` method][Parser::parse].
pub trait Parser {
    /// The type of value this parser produces from text.
    type Output;
    /// The type this parser produces internally before converting to the output type.
    ///
    /// Some combinators use the `RawOutput` to determine how types should combine.
    /// For example, if `A::RawOutput = ()`, then `A` produces no output;
    /// and if `B::RawOutput = (i32,)` then `B` produces an integer;
    /// `SequenceParser<A, B>::RawOutput` will then be `(i32,)`, the
    /// result of concatenating the two raw tuples, rather than `((), i32)`.
    ///
    /// However, `RawOutput` is very often a singleton tuple, and these are
    /// awkward for users, so we convert to the `Output` type before presenting a
    /// result to the user.
    type RawOutput: ParserOutput<UserType = Self::Output>;
    /// The type that implements matching, backtracking, and type conversion
    /// for this parser, an implementation detail.
    type Iter<'parse>: ParseIter<'parse, RawOutput = Self::RawOutput>
    where
        Self: 'parse;
    /// Fully parse the given source string `s` and return the resulting value.
    ///
    /// This is the main way of using a `Parser`.
    ///
    /// This succeeds only if this parser matches the entire input string. It's
    /// an error if any unmatched characters are left over at the end of `s`.
    fn parse(&self, s: &str) -> Result<Self::Output> {
        self.parse_raw(s).map(|v| v.into_user_type())
    }
    /// Produce a [parse iterator][ParseIter]. This is an internal implementation detail of
    /// the parser and shouldn't normally be called directly from application code.
    fn parse_iter<'parse>(
        &'parse self,
        context: &mut ParseContext<'parse>,
        start: usize,
    ) -> Result<Self::Iter<'parse>, Reported>;
    /// Like `parse` but produce the output in its [raw form][Self::RawOutput].
    fn parse_raw(&self, s: &str) -> Result<Self::RawOutput> {
        let mut ctx = ParseContext::new(s);
        let mut it = match self.parse_iter(&mut ctx, 0) {
            Ok(iter) => iter,
            Err(Reported) => return Err(ctx.into_reported_error()),
        };
        while it.match_end() != s.len() {
            ctx.error_extra(it.match_end());
            if it.backtrack(&mut ctx).is_err() {
                return Err(ctx.into_reported_error());
            }
        }
        Ok(it.convert())
    }
}
/// A parser in action. Some parsers can match in several different ways (for
/// example, in `foo* bar` backtracking is accomplished by `foo*` first
/// matching as much as possible, then backing off one match at a time), so
/// this is an iterator.
///
/// This doesn't return a `RawOutput` value from `next_parse` but instead waits
/// until you're sure you have a complete, successful parse, and are thus ready
/// to destroy the iterator. This helps us avoid building values only to drop
/// them later when some downstream parser fails to match, so it makes
/// backtracking faster. It also means we don't call `.map` closures until
/// there is a successful overall match and the values are actually needed.
pub trait ParseIter<'parse> {
    /// The type this iterator can produce on a successful match.
    type RawOutput;
    /// Position at the end of the current match.
    fn match_end(&self) -> usize;
    /// Reject the current match and find the next-most-preferable match.
    /// Returns true if another match was found, false if not.
    ///
    /// Once this returns `false`, no more method calls should be made.
    fn backtrack(&mut self, context: &mut ParseContext<'parse>) -> Result<(), Reported>;
    /// Convert the matched text to a Rust value.
    fn convert(&self) -> Self::RawOutput;
}
impl<'a, P> Parser for &'a P
where
    P: Parser + ?Sized,
{
    type Output = P::Output;
    type RawOutput = P::RawOutput;
    type Iter<'parse> = P::Iter<'parse>
    where
        P: 'parse,
        'a: 'parse;
    fn parse_iter<'parse>(
        &'parse self,
        context: &mut ParseContext<'parse>,
        start: usize,
    ) -> Result<Self::Iter<'parse>, Reported> {
        <P as Parser>::parse_iter(self, context, start)
    }
}