use super::*;
use crate::lexing::Lexer;
fn parse(s: &str) -> Result<Expr, String> {
let lexed = Lexer::from(s).lex_all()?;
Parser::from(lexed).parse_all()
}
#[test]
fn simple_num_declaration() {
let expr = parse("let answer = -(+ ( - (-42)))").unwrap();
assert_eq!(
Expr::Declaration {
name: (4, 10),
val: Box::new(Expr::Value(Value::Num(-42)))
},
expr
);
}
#[test]
fn calc_assignment() {
let expr = parse("let x = (3 + 13) * 5 / 2").unwrap();
assert_eq!(
Expr::Declaration {
name: (4, 5),
val: Box::new(Expr::Rpn(vec![
Expr::Value(Value::Num(3)),
Expr::Value(Value::Num(13)),
Expr::Op(Punct::Add),
Expr::Value(Value::Num(5)),
Expr::Op(Punct::Mul),
Expr::Value(Value::Num(2)),
Expr::Op(Punct::Div),
]),)
},
expr
);
}
#[test]
fn simple_string_declaration() {
let expr = parse("let answer_str = 'forty two'").unwrap();
assert_eq!(
Expr::Declaration {
name: (4, 14),
val: Box::new(Expr::Value(Value::Str((18, 27))))
},
expr
);
}
#[test]
fn range_declarations() {
let expr = parse(
r#"
let xs = [ (5 - 4)..100 ]
let xs = [5..(500000 - 500001 + 1) ]
"#,
)
.unwrap();
assert_eq!(
Expr::Multiple(vec![
Expr::Declaration {
name: (5, 7),
val: Box::new(Expr::Range {
from: Box::new(Expr::Rpn(vec![
Expr::Value(Value::Num(5)),
Expr::Value(Value::Num(4)),
Expr::Op(Punct::Sub)
])),
to: Box::new(Expr::Value(Value::Num(100)))
})
},
Expr::Declaration {
name: (32, 34),
val: Box::new(Expr::Range {
from: Box::new(Expr::Value(Value::Num(5))),
to: Box::new(Expr::Rpn(vec![
Expr::Value(Value::Num(500000)),
Expr::Value(Value::Num(500001)),
Expr::Op(Punct::Sub),
Expr::Value(Value::Num(1)),
Expr::Op(Punct::Add),
]))
})
}
]),
expr
);
}
#[test]
fn a_couple_of_declarations() {
let expr = parse(
r#"
let x = (5 - 9)
let y = 'this is y'
-- a comment....
"#,
)
.unwrap();
assert_eq!(
Expr::Multiple(vec![
Expr::Declaration {
name: (5, 6),
val: Box::new(Expr::Rpn(vec![
Expr::Value(Value::Num(5)),
Expr::Value(Value::Num(9)),
Expr::Op(Punct::Sub)
]))
},
Expr::Declaration {
name: (22, 23),
val: Box::new(Expr::Value(Value::Str((27, 36))))
}
]),
expr
);
}
#[test]
fn function_declaration() {
let expr = parse(
r#"
function: x, y, z -> {
let sum = x + y
sum - z
}
"#,
)
.unwrap();
assert_eq!(
Expr::FunctionDeclaration {
name: (1, 9),
params: vec![(11, 12), (14, 15), (17, 18)],
body: Box::new(Expr::Multiple(vec![
Expr::Declaration {
name: (30, 33),
val: Box::new(Expr::Rpn(vec![
Expr::IdentLookup((36, 37)),
Expr::IdentLookup((40, 41)),
Expr::Op(Punct::Add)
]))
},
Expr::Rpn(vec![
Expr::IdentLookup((44, 47)),
Expr::IdentLookup((50, 51)),
Expr::Op(Punct::Sub)
])
]))
},
expr
)
}
#[test]
fn function_invocation() {
let expr = parse(
r#"
function((1 - 3) * 7, 'string', x, g())
"#,
)
.unwrap();
assert_eq!(
Expr::FunctionCall {
name: (1, 9),
args: vec![
Expr::Rpn(vec![
Expr::Value(Value::Num(1)),
Expr::Value(Value::Num(3)),
Expr::Op(Punct::Sub),
Expr::Value(Value::Num(7)),
Expr::Op(Punct::Mul)
]),
Expr::Value(Value::Str((24, 30))),
Expr::IdentLookup((33, 34)),
Expr::FunctionCall {
name: (36, 37),
args: vec![]
}
]
},
expr
)
}
#[test]
fn function_invocation_assignment() {
let expr = parse(
r#"
let res = sum(9 * 8, (8 -2) * 15, 4 - 1 * 3)
"#,
)
.unwrap();
assert_eq!(
Expr::Declaration {
name: (5, 8),
val: Box::new(Expr::FunctionCall {
name: (11, 14),
args: vec![
Expr::Rpn(vec![
Expr::Value(Value::Num(9)),
Expr::Value(Value::Num(8)),
Expr::Op(Punct::Mul),
]),
Expr::Rpn(vec![
Expr::Value(Value::Num(8)),
Expr::Value(Value::Num(2)),
Expr::Op(Punct::Sub),
Expr::Value(Value::Num(15)),
Expr::Op(Punct::Mul),
]),
Expr::Rpn(vec![
Expr::Value(Value::Num(4)),
Expr::Value(Value::Num(1)),
Expr::Value(Value::Num(3)),
Expr::Op(Punct::Mul),
Expr::Op(Punct::Sub),
]),
]
})
},
expr
)
}
#[test]
fn parameterless_function_declaration() {
let expr = parse(
r#"
function {
5-8
}
"#,
)
.unwrap();
assert_eq!(
Expr::FunctionDeclaration {
name: (1, 9),
params: vec![],
body: Box::new(Expr::Rpn(vec![
Expr::Value(Value::Num(5)),
Expr::Value(Value::Num(8)),
Expr::Op(Punct::Sub)
]))
},
expr
)
}