mipl 0.2.1

Minimal Imperative Parsing Library
Documentation
use crate::prelude::*;

/// Consume a sequence of tokens into a new parser while the
/// concrete parsers return something. Stop consuming once
/// all values are exhausted, or if one of then returned
/// `None`.
pub struct CollectIfSeq<Cp: ConcreteParser>(Cp);
impl<Cp> VariadicConcreteSubparser<Cp> for CollectIfSeq<Cp>
where
    Cp: ConcreteParser
{
    fn subparse
    (values: Vec<Cp::Input>, parser: &mut Parser) -> Parser
    where
    Cp: concrete_parser::ContainerCp
    {
        let mut tokens = Tokens::new_empty();
        
        for v in values {
            let cp = Cp::new(v);

            if let Some(token) = cp.try_next_token(parser) {
                tokens.add_token(token);
            }
        }

        Parser::new(tokens)
    }
}

/// Consume a sequence of tokens into a new parser **if**
/// the coming sequence of tokens match a sequence.
pub struct CollectIfExactSeq<Cp: ConcreteParser>(Cp);
impl<Cp> VariadicConcreteSubparser<Cp> for CollectIfExactSeq<Cp>
where 
    Cp: ConcreteParser
{
    fn subparse
    (values: Vec<Cp::Input>, parser: &mut Parser) -> Parser
    where
    Cp: concrete_parser::ContainerCp
    {
        let mut toks_buffer: Tokens = Tokens::new_empty();

        let mut exact: bool = true;
        
        for v in values {
            let cp = Cp::new(v);
            
            if let Some(token) = cp.try_next_token(parser) {
                toks_buffer.add_token(token)
            } else {
                if let Some(token) = parser.next() {
                    toks_buffer.add_token(token);
                }
                exact = false;
            }
        }

        if exact {
            Parser::new(toks_buffer)
        } else {
            parser.extend(toks_buffer);
            Parser::new_empty()
        }
    }
}