mipl 0.2.1

Minimal Imperative Parsing Library
Documentation
//! Concrete parsers. These take [Parser] and provide
//! more specific ways to peek and advance tokens.

use super::*;

/// Interface for the items to peek.
pub trait PeekerItem: Sized {
    /// Converts a token to the type of items to peek.
    fn from_tok(token: Token) -> Option<Self>;
}
impl PeekerItem for String {
    fn from_tok(token: Token) -> Option<Self> {
        if let Token::Str(s) = token {
            Some(s)
        } else {
            None
        }
    }
}

/// The peeking functionality of concrete parsers.
pub trait Peeker {
    /// The type of the elements.
    type Item: PeekerItem;

    /// Peek for the next [Token] that satisfies some criteria defined
    /// by the implementation of this function.
    fn peek_for_token(&self, parser: &mut Parser) -> Option<Token>;

    /// Peek for the next element. Implemented based on 
    /// [Peeker::peek_for_token].
    fn peek_for(&self, parser: &mut Parser) -> Option<Self::Item> {
        Self::Item::from_tok(
            self.peek_for_token(parser)?
        )
    }
}

/// Marks [ContainerCp] input types at the trait-level.
pub trait IsContainerCpInput {}
/// Marks [ContainerCp] types at the trait-level.
pub trait ContainedType {}

/// Interface for containing data in the concrete parser structs.
pub trait ContainerCp {
    /// The type the concrete parsers are constructed from.
    type Input: IsContainerCpInput;
    /// The type the concrete parser structs contain.
    type ContainedType: ContainedType;

    /// Creates a new instance of the type to be contained.
    fn new_contained(value: Self::Input) -> Self::ContainedType;
    /// Creates a new parser struct based on the expected input type.
    fn new(value: Self::Input) -> Self;
}

/// Along with [Peeker], defines the core functionality
/// of concrete parsers.
/// 
/// Has blanket implementation for all concrete parsers.
pub trait ConcreteParser: Peeker + ContainerCp {
    /// Peek the next token in the [Parser] stream. If it
    /// satisfies the criteria as specified by the [Peeker]
    /// implementation, consume and return the [Token].
    fn try_next_token(&self, parser: &mut Parser) -> Option<Token>;
    /// Try to advance to the next element. Implemented based on
    /// [ConcreteParser::try_next_token].
    /// 
    /// If the inner `try_next_token` consumes and returns the token,
    /// constructs and returns the element from it.
    /// 
    /// Return type is the same as that of [Peeker::peek_for].
    fn try_next(&self, parser: &mut Parser) -> Option<Self::Item> {
        Self::Item::from_tok(
            self.try_next_token(parser)?
        )
    }
}

impl<T> ConcreteParser for T 
where
    T: Peeker + ContainerCp
{
    fn try_next_token(&self, parser: &mut Parser) -> Option<Token> {
        if let Some(tok) = self.peek_for_token(parser) {
            parser.next();
            Some(tok)
        } else {
            None
        }
    }
}

impl IsContainerCpInput for String {}
impl ContainedType for String {}

impl IsContainerCpInput for () {}
impl ContainedType for () {}

mod exact_match;
mod or_exact_match;
mod any_str_match;
mod is_newline;
mod is_tab;
/// All concrete parsers.
pub mod list {
    pub use super::{
        exact_match::ExactMatch,
        or_exact_match::OrExactMatch,
        any_str_match::AnyStrMatch,
        is_newline::IsNewline,
        is_tab::IsTab
    };
}