cypress 0.1.0

Build simple yet expressive parsers
Documentation
use cypress::prelude::*;

#[test]
fn t_just() {
    let input = b"ABC".into_input();

    let parser = just('A');

    match parser.parse(input) {
        Ok(PSuccess { val, rest: _ }) => assert_eq!(val, b'A'),
        Err(_) => assert!(false),
    }
}

#[test]
fn t_then() {
    let input = b"ABC".into_input();

    let parser = just('A').then(just('B'));

    match parser.parse(input) {
        Ok(PSuccess { val, rest: _ }) => assert_eq!(val, (b'A', b'B')),
        Err(_) => assert!(false),
    }
}

#[test]
fn t_or() {
    let input = b"B".into_input();

    let parser = just('A').or(just('B'));

    match parser.parse(input) {
        Ok(PSuccess { val, rest: _ }) => assert_eq!(val, b'B'),
        Err(_) => assert!(false),
    }
}

#[test]
fn t_map() {
    let input = b"A".into_input();

    let parser = just('A').map(|_| 1);

    match parser.parse(input) {
        Ok(PSuccess { val, rest: _ }) => assert_eq!(val, 1),
        Err(_) => assert!(false),
    }
}

#[test]
fn t_choice() {
    let input = b"A".into_input();

    let parser = choice!(just('C'), just('A'), just('C'));

    match parser.parse(input) {
        Ok(PSuccess { val, rest: _ }) => assert_eq!(val, b'A'),
        Err(_) => assert!(false),
    }
}

#[test]
fn t_pbetween() {
    let input = "[A]".as_bytes().into_input();

    let parser = pbetween(just('['), just('A'), just(']'));

    match parser.parse(input) {
        Ok(PSuccess { val, rest: _ }) => assert_eq!(val, b'A'),
        Err(_) => assert!(false),
    }
}

#[test]
fn t_pmany() {
    let input = b"ABCDE".into_input();

    let parser = pletter().many();

    match parser.parse(input) {
        Ok(PSuccess { val, rest: _ }) => assert_eq!(val, [b'A', b'B', b'C', b'D', b'E']),
        Err(_) => assert!(false),
    }
}

#[test]
fn t_padded() {
    let input = b"   A   ".into_input();

    let parser = ppadded(just('A'), pws::<u8>());

    match parser.parse(input) {
        Ok(PSuccess { val, rest }) => {
            assert_eq!(val, b'A');
            assert_eq!(rest.loc, rest.tokens.len())
        }
        Err(_) => assert!(false),
    }
}

#[test]
fn t_ident() {
    let input = b"Noah Cape".into_input();

    let parser = pident("Noah")
        .padded_by(pws())
        .then(pident("Cape").padded_by(pws()));

    match parser.parse(input) {
        Ok(PSuccess { val, rest: _ }) => {
            assert_eq!(val, ("Noah", "Cape"))
        }
        Err(_) => assert!(false),
    }
}

#[test]
fn t_pstring() {
    let input = "\"This is a string\"".into_input();

    let parser = just('\"')
        .then(any().and(just('\"').not()).many())
        .then(just('\"'))
        .map(|((_, xs), _)| String::from_utf8(xs).unwrap());

    match parser.parse(input) {
        Ok(PSuccess { val, rest: _ }) => assert_eq!(val, String::from("This is a string")),
        Err(_) => assert!(false),
    }
}

#[test]
fn t_recursive() {
    let input = b"(1+(2+3))".into_input();

    #[derive(Debug, PartialEq)]
    enum AST {
        Num(u32),
        Expr(Box<AST>, Box<AST>),
    }

    let parser = recursive(|expr| {
        Box::new(choice!(
            pnum().map(|a: u8| AST::Num((a - b'0').into())),
            just('(')
                .then(expr.clone())
                .then(just('+').then(expr))
                .then(just(')'))
                .map(|(((_, lhs), (_, rhs)), _)| AST::Expr(Box::new(lhs), Box::new(rhs)))
        ))
    });

    match parser.parse(input) {
        Ok(PSuccess { val, rest: _ }) => assert_eq!(
            val,
            AST::Expr(
                Box::new(AST::Num(1)),
                Box::new(AST::Expr(Box::new(AST::Num(2)), Box::new(AST::Num(3))))
            )
        ),
        Err(_) => assert!(false),
    }
}

#[test]
fn t_select() {
    #[derive(Debug, PartialEq)]
    enum Expr {
        Left,
        Right,
    }
    let input = "<><".into_input();

    let parser = select! {
        '<' => Expr::Left,
        (just('>')) => Expr::Right,
    }
    .many();

    match parser.parse(input) {
        Ok(PSuccess { val, rest: _ }) => assert_eq!(val, vec![Expr::Left, Expr::Right, Expr::Left]),
        Err(_) => assert!(false),
    }
}

#[test]
fn t_parser_macro() {
    let input = "A+B";

    #[derive(Debug, PartialEq)]
    enum Expr {
        A,
        B,
    }

    let parser = sequence!((just('A')) > '+' > 'B' => |_| (Expr::A, Expr::B));

    match parser.parse(input.into_input()) {
        Ok(PSuccess { val, rest: _ }) => assert_eq!(val, (Expr::A, Expr::B)),
        Err(_) => assert!(false),
    }
}