mipl 0.2.1

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

mod common;
use common::*;

/// Assert that two parsers successively yield a certain number
/// `n` of the same token.
fn assert_parsers_same_till(
    mut a: Parser,
    mut b: Parser,
    n: usize
) {
    let mut i: usize = 0;
    while i < n {
        assert_eq!(a.next(), b.next());
        i += 1;
    }
}

fn not_assert_parsers_same_till(
    mut a: Parser,
    mut b: Parser,
    n: usize
) {
    let mut i: usize = 0;
    let mut not: bool = false;
    while i < n {
        if a.next() != b.next() {
            not = true;
            break;
        }
        i += i;
    }
    assert!(not)
}

#[test]
fn test_collect_until_exact_match_subparser() {
    let mut parser = setup_space_seps_parser(
        "a b c d e f g h"
    );
    let mut known_subparser = setup_space_seps_parser(
        "a b c d"
    );

    let mut subparser = CollectUntil::<ExactMatch>::subparse(
        "e".to_string(), 
        &mut parser
    );

    let mut i: usize = 0;
    while i < 4 {
        assert_eq!(known_subparser.next(), subparser.next());
        i += 1;
    }
}

#[test]
fn test_collect_until_is_newline() {
    let mut parser = setup_space_seps_parser(
        "a b\n c d e f g h"
    );
    let mut known_subparser = setup_space_seps_parser(
        "a b"
    );

    let mut subparser = CollectUntil::<IsNewline>::subparse(
        (), 
        &mut parser
    );

    let mut i: usize = 0;
    while i < 2 {
        assert_eq!(known_subparser.next(), subparser.next());
        i += 1;
    }
}

#[test]
fn test_collect_while_exact_match() {
    let mut parser = setup_space_seps_parser(
        "a a a a e f g h"
    );
    let mut known_subparser = setup_space_seps_parser(
        "a a a a"
    );

    let mut subparser = CollectWhile::<ExactMatch>::subparse(
        "a".to_string(), 
        &mut parser
    );

    let mut i: usize = 0;
    while i < 4 {
        assert_eq!(known_subparser.next(), subparser.next());
        i += 1;
    }
}

#[test]
fn test_collect_if_sequence() {
    let mut parser = setup_space_seps_parser(
        "a b c d e f g h i j"
    );
    let known_subparser = setup_space_seps_parser(
        "a b c d"
    );

    let values: Vec<String> = vec!["a", "b", "c", "d", "e"]
        .into_iter()
        .map(String::from)
        .collect();
    
    let subparser = CollectIfSeq::<ExactMatch>::subparse(
        values,
        &mut parser
    );

    assert_parsers_same_till(
        known_subparser,
        subparser,
        4
    );
}

#[test]
fn test_collect_if_exact_sequence() {
    let mut parser = setup_space_seps_parser(
        "a b c d e f g h i j"
    );
    let known_subparser = setup_space_seps_parser(
        "a b"
    );

    let values: Vec<String> = vec!["a", "b", "c", "d"]
        .into_iter()
        .map(String::from)
        .collect();
    
    let subparser = CollectIfExactSeq::<ExactMatch>::subparse(
        values,
        &mut parser
    );

    assert_parsers_same_till(
        known_subparser,
        subparser,
        2
    );
}

#[test]
fn test_fail_collect_if_exact_sequence() {
    let mut parser = setup_space_seps_parser(
        "a b c d e f g h i j"
    );
    let known_subparser = setup_space_seps_parser(
        "a b c d"
    );

    let values: Vec<String> = vec!["a", "b", "c", "d", "f"]
        .into_iter()
        .map(String::from)
        .collect();
    
    let subparser = CollectIfExactSeq::<ExactMatch>::subparse(
        values,
        &mut parser
    );
    
    not_assert_parsers_same_till(
        known_subparser,
        subparser,
        4
    );
}

#[test]
fn test_fail_collect_if_exact_keeps_parent_parser_intact() {
    let mut parser = setup_space_seps_parser(
        "a b c d"
    );
    let initial_parser = parser.clone();

    let values: Vec<String> = vec!["a", "b", "c", "e"]
        .into_iter()
        .map(String::from)
        .collect();

    let _subparser = CollectIfExactSeq::<ExactMatch>::subparse(
        values, 
        &mut parser
    );

    println!("{:#?}", parser);

    assert_parsers_same_till(parser, initial_parser, 4);
}


pub fn tokenize(src: String) -> Parser {
    let del_param = DelimitersParam{
        discard: DiscardDelimiters::new(
            vec![
                ' ',
                '\n',
                '\t'
            ]
        ),
        keep: KeepDelimiters::new(
            vec![
                '(',
                ')',
                '~',
                '&',
                '|',
                '=',
                '>',
                '<',
                '*',
                '#'
            ]
        )
    };

    Parser::from(src, del_param)
}

fn test_until_doesnt_eat_ending_states_subparser(parser: &mut Parser) -> Parser {
    let states: Vec<String> = vec!["*", "#"]
        .into_iter()
        .map(String::from)
        .collect();
    let _expr_parser = CollectUntil::<OrExactMatch>::subparse(states.clone(), parser);
    let states_parser = CollectWhile::<OrExactMatch>::subparse(states, parser);

    states_parser
}

#[test]
fn test_until_doesnt_eat_ending() {
    let src = "(l | r) & (~l | ~r) **# 16".to_string();

    let mut flat_parser = tokenize(src);

    let known_parser_a = tokenize("**#".to_string());

    let states_parser = test_until_doesnt_eat_ending_states_subparser(&mut flat_parser);

    assert_parsers_same_till(known_parser_a, states_parser, 3);
}