basic-lang 0.2.0

The BASIC programming language as it was in 1978.
Documentation
use super::super::lex;
use super::*;

fn parse_str(s: &str) -> Option<Statement> {
    let (lin, tokens) = lex(s);
    match parse(lin, &tokens) {
        Ok(mut v) => v.pop(),
        Err(_) => None,
    }
}

#[test]
fn test_let_foo_eq_bar() {
    let answer = Statement::Let(
        0..3,
        Ident::Plain(3..6, "TER".to_string()),
        Expression::Var(7..10, Ident::Plain(7..10, "BAR".to_string())),
    );
    assert_eq!(parse_str("letter=bar:"), Some(answer));
    let answer = Statement::Let(
        0..3,
        Ident::Plain(0..3, "TER".to_string()),
        Expression::Var(4..7, Ident::Plain(4..7, "BAR".to_string())),
    );
    assert_eq!(parse_str("ter=bar:"), Some(answer));
}

#[test]
fn test_literals() {
    let answer = Statement::Let(
        0..1,
        Ident::Plain(0..1, "A".to_string()),
        Expression::Integer(2..4, 12),
    );
    assert_eq!(parse_str("A=12"), Some(answer));
    let answer = Statement::Let(
        0..1,
        Ident::Plain(0..1, "A".to_string()),
        Expression::Single(2..5, 12.0),
    );
    assert_eq!(parse_str("A=12!"), Some(answer));
    let answer = Statement::Let(
        0..1,
        Ident::Plain(0..1, "A".to_string()),
        Expression::Double(2..6, 12e4),
    );
    assert_eq!(parse_str("A=12d4"), Some(answer));
    let answer = Statement::Let(
        0..1,
        Ident::Plain(0..1, "A".to_string()),
        Expression::String(2..8, "food".to_string()),
    );
    assert_eq!(parse_str("A=\"food\""), Some(answer));
    let answer = Statement::Let(
        0..1,
        Ident::Plain(0..1, "A".to_string()),
        Expression::Double(2..58, 0.0),
    );
    assert_eq!(
        parse_str("A=798347598234765983475983248592d-234721398742391847982344"),
        Some(answer)
    );
}

#[test]
fn test_unary() {
    let answer = Statement::Let(
        0..1,
        Ident::Plain(0..1, "A".to_string()),
        Expression::Negation(
            2..3,
            Box::new(Expression::Add(
                5..6,
                Box::new(Expression::Integer(4..5, 1)),
                Box::new(Expression::Integer(7..8, 1)),
            )),
        ),
    );
    assert_eq!(parse_str("A=-(1++1)"), Some(answer));
}

#[test]
fn test_functions() {
    let answer = Statement::Let(
        0..1,
        Ident::Plain(0..1, "A".to_string()),
        Expression::Function(
            2..5,
            Ident::Plain(2..5, "COS".to_string()),
            vec![Expression::Single(6..10, 3.11)],
        ),
    );
    assert_eq!(parse_str("A=cos(3.11)"), Some(answer));
}

#[test]
fn test_precedence_and_paren() {
    let answer = Statement::Let(
        0..3,
        Ident::Plain(4..5, "A".to_string()),
        Expression::Subtract(
            8..9,
            Box::new(Expression::Integer(7..8, 2)),
            Box::new(Expression::Multiply(
                22..23,
                Box::new(Expression::Add(
                    11..12,
                    Box::new(Expression::Integer(10..11, 3)),
                    Box::new(Expression::Function(
                        12..15,
                        Ident::Plain(12..15, "COS".to_string()),
                        vec![Expression::Single(16..20, 3.11)],
                    )),
                )),
                Box::new(Expression::Integer(23..24, 4)),
            )),
        ),
    );
    assert_eq!(parse_str("let A=(2-(3+cos(3.11))*4)"), Some(answer));
}

#[test]
fn test_printer_list() {
    let (lin, tokens) = lex("? 1 2,3;:?");
    assert_eq!(
        parse(lin, &tokens).ok(),
        Some(vec!(
            Statement::Print(
                0..1,
                vec!(
                    Expression::Integer(2..3, 1),
                    Expression::Integer(4..5, 2),
                    Expression::Char(5..6, '\t'),
                    Expression::Integer(6..7, 3),
                )
            ),
            Statement::Print(9..10, vec!(Expression::Char(10..10, '\n'),)),
        ))
    );
}