rual-core 0.0.4

A slim, embeddable language
Documentation
use super::*;
use crate::syntax::Keyword;

fn get_tokens(s: &str) -> Vec<Token> {
    dbg!(s);
    let mut l = Lexer::from(s);
    l.lex_all().unwrap()
}

// --- Straight scenarios ---

#[test]
fn single_comment() {
    let tokens = get_tokens("   -- a comment");

    assert_eq!(
        Token::new(1, 4, TokenType::Comment { start: 6, end: 15 }),
        tokens[0]
    );
}

#[test]
fn new_line() {
    let tokens = get_tokens(
        r#"-- first line
let x = 5

  -- last line
"#,
    );

    assert_eq!(
        Token::new(1, 1, TokenType::Comment { start: 3, end: 13 }),
        tokens[0]
    );
    assert_eq!(Token::new(1, 14, TokenType::Term), tokens[1]);
    assert_eq!(
        Token::new(2, 1, TokenType::Keyword(Keyword::Let)),
        tokens[2]
    );
    assert_eq!(
        Token::new(4, 3, TokenType::Comment { start: 30, end: 39 }),
        tokens[8]
    );
}

#[test]
fn discard() {
    let tokens = get_tokens("let _ = 'discarded'");

    assert_eq!(
        vec![
            Token::new(1, 1, TokenType::Keyword(Keyword::Let)),
            Token::new(1, 5, TokenType::Discard)
        ][..],
        tokens[..2]
    );
}

#[test]
fn sub_punct() {
    let tokens = get_tokens("  -      ");

    assert_eq!(Token::new(1, 3, TokenType::Punct(Punct::Sub)), tokens[0]);
}

#[test]
fn func() {
    let tokens = get_tokens("f: g, y -> g(y)");

    assert_eq!(
        Token::new(1, 1, TokenType::Ident { start: 0, end: 1 }),
        tokens[0]
    );
    assert_eq!(Token::new(1, 2, TokenType::Punct(Punct::Colon)), tokens[1]);
    assert_eq!(
        Token::new(1, 4, TokenType::Ident { start: 3, end: 4 }),
        tokens[2]
    );
    assert_eq!(Token::new(1, 5, TokenType::Punct(Punct::Comma)), tokens[3]);
    assert_eq!(
        Token::new(1, 7, TokenType::Ident { start: 6, end: 7 }),
        tokens[4]
    );
    assert_eq!(Token::new(1, 9, TokenType::Punct(Punct::Arrow)), tokens[5]);
    assert_eq!(
        Token::new(1, 12, TokenType::Ident { start: 11, end: 12 }),
        tokens[6]
    );
    assert_eq!(
        Token::new(1, 13, TokenType::Punct(Punct::OpenParen)),
        tokens[7]
    );
    assert_eq!(
        Token::new(1, 14, TokenType::Ident { start: 13, end: 14 }),
        tokens[8]
    );
    assert_eq!(
        Token::new(1, 15, TokenType::Punct(Punct::CloseParen)),
        tokens[9]
    );
}

#[test]
fn hi_ord_func() {
    let tokens = get_tokens("func(\\x -> x - 1, 11)");

    assert_eq!(
        Token::new(1, 1, TokenType::Ident { start: 0, end: 4 }),
        tokens[0]
    );
    assert_eq!(
        Token::new(1, 5, TokenType::Punct(Punct::OpenParen)),
        tokens[1]
    );
    assert_eq!(Token::new(1, 6, TokenType::Punct(Punct::Lambda)), tokens[2]);
    assert_eq!(
        Token::new(1, 7, TokenType::Ident { start: 6, end: 7 }),
        tokens[3]
    );
    assert_eq!(Token::new(1, 9, TokenType::Punct(Punct::Arrow)), tokens[4]);
    assert_eq!(
        Token::new(1, 12, TokenType::Ident { start: 11, end: 12 }),
        tokens[5]
    );
    assert_eq!(Token::new(1, 14, TokenType::Punct(Punct::Sub)), tokens[6]);
}

#[test]
fn nums() {
    let tokens = get_tokens("4 91");

    assert_eq!(Token::new(1, 1, TokenType::Num(4)), tokens[0]);
    assert_eq!(Token::new(1, 3, TokenType::Num(91)), tokens[1]);
}

#[test]
fn strings() {
    let tokens = get_tokens("'a string'");

    assert_eq!(
        Token::new(1, 1, TokenType::Str { start: 1, end: 9 }),
        tokens[0]
    );
}

#[test]
fn tuples() {
    let tokens = get_tokens("let (fs_, sn_) = (4, 91)");

    assert_eq!(
        Token::new(1, 5, TokenType::Punct(Punct::OpenParen)),
        tokens[1]
    );
    assert_eq!(
        Token::new(1, 6, TokenType::Ident { start: 5, end: 8 }),
        tokens[2]
    );
    assert_eq!(Token::new(1, 9, TokenType::Punct(Punct::Comma)), tokens[3]);
    assert_eq!(
        Token::new(1, 11, TokenType::Ident { start: 10, end: 13 }),
        tokens[4]
    );
    assert_eq!(
        Token::new(1, 14, TokenType::Punct(Punct::CloseParen)),
        tokens[5]
    );
    assert_eq!(
        Token::new(1, 16, TokenType::Punct(Punct::Assign)),
        tokens[6]
    );
    assert_eq!(
        Token::new(1, 18, TokenType::Punct(Punct::OpenParen)),
        tokens[7]
    );
    assert_eq!(Token::new(1, 19, TokenType::Num(4)), tokens[8]);
    assert_eq!(Token::new(1, 20, TokenType::Punct(Punct::Comma)), tokens[9]);
    assert_eq!(Token::new(1, 22, TokenType::Num(91)), tokens[10]);
    assert_eq!(
        Token::new(1, 24, TokenType::Punct(Punct::CloseParen)),
        tokens[11]
    );
}

#[test]
fn lists() {
    let tokens = get_tokens("let [x, y, ...xs] = [ 5..83 ]");

    assert_eq!(
        Token::new(1, 5, TokenType::Punct(Punct::OpenBracket)),
        tokens[1]
    );
    assert_eq!(
        Token::new(1, 6, TokenType::Ident { start: 5, end: 6 }),
        tokens[2]
    );
    assert_eq!(Token::new(1, 7, TokenType::Punct(Punct::Comma)), tokens[3]);
    assert_eq!(
        Token::new(1, 9, TokenType::Ident { start: 8, end: 9 }),
        tokens[4]
    );
    assert_eq!(Token::new(1, 10, TokenType::Punct(Punct::Comma)), tokens[5]);
    assert_eq!(
        Token::new(1, 12, TokenType::Punct(Punct::Spread)),
        tokens[6]
    );
    assert_eq!(
        Token::new(1, 15, TokenType::Ident { start: 14, end: 16 }),
        tokens[7]
    );
    assert_eq!(
        Token::new(1, 17, TokenType::Punct(Punct::CloseBracket)),
        tokens[8]
    );
    assert_eq!(
        Token::new(1, 19, TokenType::Punct(Punct::Assign)),
        tokens[9]
    );
    assert_eq!(
        Token::new(1, 21, TokenType::Punct(Punct::OpenBracket)),
        tokens[10]
    );
    assert_eq!(Token::new(1, 23, TokenType::Num(5)), tokens[11]);
    assert_eq!(
        Token::new(1, 24, TokenType::Punct(Punct::Range)),
        tokens[12]
    );
    assert_eq!(Token::new(1, 26, TokenType::Num(83)), tokens[13]);
    assert_eq!(
        Token::new(1, 29, TokenType::Punct(Punct::CloseBracket)),
        tokens[14]
    );
}

#[test]
fn maps() {
    let tokens = get_tokens("let m = { 5: true, 0: false }");

    assert_eq!(
        Token::new(1, 1, TokenType::Keyword(Keyword::Let)),
        tokens[0]
    );
    assert_eq!(
        Token::new(1, 5, TokenType::Ident { start: 4, end: 5 }),
        tokens[1]
    );
    assert_eq!(Token::new(1, 7, TokenType::Punct(Punct::Assign)), tokens[2]);
    assert_eq!(
        Token::new(1, 9, TokenType::Punct(Punct::OpenCurly)),
        tokens[3]
    );
    assert_eq!(Token::new(1, 11, TokenType::Num(5)), tokens[4]);
    assert_eq!(Token::new(1, 12, TokenType::Punct(Punct::Colon)), tokens[5]);
    assert_eq!(Token::new(1, 14, TokenType::Bool(true)), tokens[6]);
    assert_eq!(Token::new(1, 18, TokenType::Punct(Punct::Comma)), tokens[7]);
    assert_eq!(Token::new(1, 20, TokenType::Num(0)), tokens[8]);
    assert_eq!(Token::new(1, 21, TokenType::Punct(Punct::Colon)), tokens[9]);
    assert_eq!(Token::new(1, 23, TokenType::Bool(false)), tokens[10]);
    assert_eq!(
        Token::new(1, 29, TokenType::Punct(Punct::CloseCurly)),
        tokens[11]
    );
}

#[test]
fn a_couple_declarations() {
    let tokens = get_tokens(
        r#"
let x = (5 - 9)

let y = 'this is y'
"#,
    );

    assert_eq!(
        vec![
            Token::new(1, 1, TokenType::Term),
            Token::new(2, 1, TokenType::Keyword(Keyword::Let)),
            Token::new(2, 5, TokenType::Ident { start: 5, end: 6 }),
            Token::new(2, 7, TokenType::Punct(Punct::Assign)),
            Token::new(2, 9, TokenType::Punct(Punct::OpenParen)),
            Token::new(2, 10, TokenType::Num(5)),
            Token::new(2, 12, TokenType::Punct(Punct::Sub)),
            Token::new(2, 14, TokenType::Num(9)),
            Token::new(2, 15, TokenType::Punct(Punct::CloseParen)),
            Token::new(2, 16, TokenType::Term),
            Token::new(3, 1, TokenType::Term),
            Token::new(4, 1, TokenType::Keyword(Keyword::Let)),
            Token::new(4, 5, TokenType::Ident { start: 22, end: 23 }),
            Token::new(4, 7, TokenType::Punct(Punct::Assign)),
            Token::new(4, 9, TokenType::Str { start: 27, end: 36 }),
            Token::new(4, 20, TokenType::Term),
        ],
        tokens
    );
}