2021-09-22 20:47:23 +00:00
|
|
|
use nom::{
|
|
|
|
branch::alt,
|
2021-09-26 15:05:30 +00:00
|
|
|
bytes::complete::{escaped, is_not, tag, take_until},
|
|
|
|
character::complete::{alpha1, alphanumeric1, char, multispace0, one_of, space0},
|
2021-09-26 16:49:46 +00:00
|
|
|
combinator::{cut, map, opt, recognize, value},
|
2021-09-26 15:05:30 +00:00
|
|
|
error::ParseError,
|
2021-09-22 20:47:23 +00:00
|
|
|
multi::{fold_many0, many0, separated_list0},
|
|
|
|
number::complete::double,
|
2021-09-26 15:05:30 +00:00
|
|
|
sequence::{delimited, pair, preceded, terminated, tuple},
|
2021-09-22 20:47:23 +00:00
|
|
|
IResult, Parser,
|
|
|
|
};
|
|
|
|
|
|
|
|
use crate::ast::*;
|
|
|
|
|
|
|
|
fn sc<'a, E>(i: &'a str) -> IResult<&'a str, (), E>
|
|
|
|
where
|
|
|
|
E: ParseError<&'a str>,
|
|
|
|
{
|
|
|
|
alt((value((), multispace0), pinline_comment, peol_comment))(i)
|
|
|
|
}
|
|
|
|
fn pinline_comment<'a, E>(i: &'a str) -> IResult<&'a str, (), E>
|
|
|
|
where
|
|
|
|
E: ParseError<&'a str>,
|
|
|
|
{
|
2021-09-26 15:05:30 +00:00
|
|
|
value((), tuple((tag("/*"), take_until("*/"), tag("*/"))))(i)
|
2021-09-22 20:47:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn peol_comment<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&'a str, (), E> {
|
2021-09-26 15:05:30 +00:00
|
|
|
value((), pair(char('/'), is_not("\n\r")))(i)
|
2021-09-22 20:47:23 +00:00
|
|
|
}
|
|
|
|
|
2021-09-26 16:49:46 +00:00
|
|
|
fn semi(i: &str) -> IResult<&str, &str> {
|
|
|
|
preceded(sc, tag(";"))(i)
|
|
|
|
}
|
|
|
|
|
2021-09-22 20:47:23 +00:00
|
|
|
fn braces<'a, P, O, E>(a: P) -> impl FnMut(&'a str) -> IResult<&'a str, O, E>
|
|
|
|
where
|
|
|
|
P: Parser<&'a str, O, E>,
|
|
|
|
E: ParseError<&'a str>,
|
|
|
|
{
|
2021-09-26 16:49:46 +00:00
|
|
|
map(tuple((tag("{"), sc, a, sc, tag("}"))), |(_, _, a, _, _)| a)
|
2021-09-22 20:47:23 +00:00
|
|
|
}
|
|
|
|
fn parens<'a, P, O, E>(a: P) -> impl FnMut(&'a str) -> IResult<&'a str, O, E>
|
|
|
|
where
|
|
|
|
P: Parser<&'a str, O, E>,
|
|
|
|
E: ParseError<&'a str>,
|
|
|
|
{
|
2021-09-26 16:49:46 +00:00
|
|
|
map(tuple((tag("("), sc, a, sc, tag(")"))), |(_, _, a, _, _)| a)
|
2021-09-22 20:47:23 +00:00
|
|
|
}
|
2021-09-26 14:56:41 +00:00
|
|
|
fn identifier(i: &str) -> IResult<&str, &str> {
|
|
|
|
println!("identifier: {}", i);
|
2021-09-26 16:49:46 +00:00
|
|
|
preceded(
|
|
|
|
sc,
|
|
|
|
recognize(pair(
|
|
|
|
alt((alpha1, tag("_"))),
|
|
|
|
many0(alt((alphanumeric1, tag("_")))),
|
|
|
|
)),
|
|
|
|
)(i)
|
2021-09-26 14:56:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn variable(i: &str) -> IResult<&str, Expr> {
|
|
|
|
println!("variable: {}", i);
|
|
|
|
map(identifier, |a| Expr::Var(a.to_string()))(i)
|
2021-09-22 20:47:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn parse_str<'a>(i: &'a str) -> IResult<&'a str, &'a str> {
|
|
|
|
escaped(alphanumeric1, '\\', one_of("\"n\\"))(i)
|
|
|
|
}
|
|
|
|
|
2021-09-26 13:58:55 +00:00
|
|
|
fn string<'a>(i: &'a str) -> IResult<&'a str, Expr> {
|
2021-09-26 14:56:41 +00:00
|
|
|
println!("string: {}", i);
|
2021-09-26 13:58:55 +00:00
|
|
|
map(
|
|
|
|
preceded(char('\"'), cut(terminated(parse_str, char('\"')))),
|
|
|
|
|s| Expr::LStr(String::from(s)),
|
|
|
|
)(i)
|
2021-09-22 20:47:23 +00:00
|
|
|
}
|
|
|
|
|
2021-09-26 13:58:55 +00:00
|
|
|
fn boolean<'a>(i: &'a str) -> IResult<&'a str, Expr> {
|
2021-09-22 20:47:23 +00:00
|
|
|
println!("boolean: {}", i);
|
2021-09-26 13:58:55 +00:00
|
|
|
alt((
|
|
|
|
map(tag("true"), |_| Expr::LBool(true)),
|
|
|
|
map(tag("false"), |_| Expr::LBool(false)),
|
|
|
|
))(i)
|
2021-09-22 20:47:23 +00:00
|
|
|
}
|
|
|
|
|
2021-09-26 14:56:41 +00:00
|
|
|
fn call<'a>(i: &'a str) -> IResult<&'a str, Expr> {
|
2021-09-22 20:47:23 +00:00
|
|
|
println!("call: {}", i);
|
|
|
|
map(
|
|
|
|
tuple((
|
|
|
|
identifier,
|
2021-09-26 14:56:41 +00:00
|
|
|
sc,
|
|
|
|
alt((
|
|
|
|
value(vec![], tuple((char('('), sc, char(')')))),
|
|
|
|
delimited(
|
|
|
|
char('('),
|
|
|
|
separated_list0(tuple((sc, tag(","), sc)), expr),
|
|
|
|
char(')'),
|
|
|
|
),
|
|
|
|
)),
|
2021-09-22 20:47:23 +00:00
|
|
|
)),
|
2021-09-26 14:56:41 +00:00
|
|
|
|(i, _, v)| Expr::Call(i.to_string(), v),
|
2021-09-22 20:47:23 +00:00
|
|
|
)(i)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn num(i: &str) -> IResult<&str, Expr> {
|
|
|
|
println!("num: {}", i);
|
|
|
|
map(double, Expr::LNum)(i)
|
|
|
|
}
|
2021-09-26 13:58:55 +00:00
|
|
|
fn literal(i: &str) -> IResult<&str, Expr> {
|
|
|
|
println!("literal: {}", i);
|
|
|
|
alt((num, string, map(tag("null"), |_| Expr::LNull), boolean))(i)
|
2021-09-22 20:47:23 +00:00
|
|
|
}
|
2021-09-26 15:36:06 +00:00
|
|
|
fn receive<'a>(i: &'a str) -> IResult<&'a str, Expr> {
|
|
|
|
println!("receive: {}", i);
|
|
|
|
map(tuple((sc, tag("<-"), expr)), |(_, _, expr)| {
|
|
|
|
Expr::Receive(Box::new(expr))
|
|
|
|
})(i)
|
|
|
|
}
|
2021-09-22 20:47:23 +00:00
|
|
|
|
|
|
|
fn factor_bin(i: &str) -> IResult<&str, Expr> {
|
2021-09-26 15:36:06 +00:00
|
|
|
println!("factor bin: {}", i);
|
|
|
|
alt((delimited(space0, alt((receive, term)), space0), expr))(i)
|
2021-09-22 20:47:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn bin_less_greater(i: &str) -> IResult<&str, Expr> {
|
|
|
|
let (i, init) = factor_bin(i)?;
|
|
|
|
|
|
|
|
fold_many0(
|
|
|
|
pair(alt((char('<'), char('>'))), factor_bin),
|
|
|
|
move || init.clone(),
|
|
|
|
|acc, (op, val): (char, Expr)| {
|
|
|
|
if op == '<' {
|
|
|
|
Expr::Binary(BinOp::LessThan, Box::new(acc), Box::new(val))
|
|
|
|
} else {
|
|
|
|
Expr::Binary(BinOp::GreaterThan, Box::new(acc), Box::new(val))
|
|
|
|
}
|
|
|
|
},
|
|
|
|
)(i)
|
|
|
|
}
|
|
|
|
fn bin_equal_not(i: &str) -> IResult<&str, Expr> {
|
|
|
|
let (i, init) = bin_less_greater(i)?;
|
|
|
|
|
|
|
|
fold_many0(
|
2021-09-26 15:05:30 +00:00
|
|
|
pair(alt((tag("=="), tag("!="))), bin_less_greater),
|
2021-09-22 20:47:23 +00:00
|
|
|
move || init.clone(),
|
2021-09-26 15:05:30 +00:00
|
|
|
|acc, (op, val)| {
|
|
|
|
if op == "==" {
|
|
|
|
Expr::Binary(BinOp::Equals, Box::new(acc), Box::new(val))
|
2021-09-22 20:47:23 +00:00
|
|
|
} else {
|
2021-09-26 15:05:30 +00:00
|
|
|
Expr::Binary(BinOp::NotEquals, Box::new(acc), Box::new(val))
|
2021-09-22 20:47:23 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
)(i)
|
|
|
|
}
|
|
|
|
fn bin_mult_div(i: &str) -> IResult<&str, Expr> {
|
|
|
|
let (i, init) = bin_equal_not(i)?;
|
|
|
|
|
|
|
|
fold_many0(
|
|
|
|
pair(alt((char('*'), char('/'))), bin_equal_not),
|
|
|
|
move || init.clone(),
|
|
|
|
|acc, (op, val): (char, Expr)| {
|
|
|
|
if op == '*' {
|
|
|
|
Expr::Binary(BinOp::Mult, Box::new(acc), Box::new(val))
|
|
|
|
} else {
|
|
|
|
Expr::Binary(BinOp::Div, Box::new(acc), Box::new(val))
|
|
|
|
}
|
|
|
|
},
|
|
|
|
)(i)
|
|
|
|
}
|
|
|
|
fn binary<'a>(i: &'a str) -> IResult<&'a str, Expr> {
|
|
|
|
println!("binary: {}", i);
|
|
|
|
let (i, init) = bin_mult_div(i)?;
|
|
|
|
|
|
|
|
fold_many0(
|
|
|
|
pair(alt((char('+'), char('-'))), bin_mult_div),
|
|
|
|
move || init.clone(),
|
|
|
|
|acc, (op, val): (char, Expr)| {
|
|
|
|
if op == '+' {
|
|
|
|
Expr::Binary(BinOp::Plus, Box::new(acc), Box::new(val))
|
|
|
|
} else {
|
|
|
|
Expr::Binary(BinOp::Minus, Box::new(acc), Box::new(val))
|
|
|
|
}
|
|
|
|
},
|
|
|
|
)(i)
|
|
|
|
}
|
2021-09-26 14:56:41 +00:00
|
|
|
|
|
|
|
fn term<'a>(i: &'a str) -> IResult<&'a str, Expr> {
|
2021-09-22 20:47:23 +00:00
|
|
|
println!("expr: {}", i);
|
2021-09-26 14:56:41 +00:00
|
|
|
delimited(sc, alt((literal, call, variable, parens(expr))), sc)(i)
|
2021-09-22 20:47:23 +00:00
|
|
|
}
|
|
|
|
|
2021-09-26 15:36:06 +00:00
|
|
|
pub fn expr<'a>(i: &'a str) -> IResult<&'a str, Expr> {
|
|
|
|
binary(i)
|
|
|
|
}
|
|
|
|
|
2021-09-26 16:49:46 +00:00
|
|
|
fn if_stmt(i: &str) -> IResult<&str, Stmt> {
|
|
|
|
println!("if: {}", i);
|
|
|
|
map(
|
|
|
|
tuple((tag("if"), sc, parens(expr), sc, braces(many0(stmt)))),
|
|
|
|
|(_, _, expr, _, stmts)| Stmt::If(expr, stmts),
|
|
|
|
)(i)
|
|
|
|
}
|
|
|
|
fn while_stmt(i: &str) -> IResult<&str, Stmt> {
|
|
|
|
println!("while: {}", i);
|
|
|
|
map(
|
|
|
|
tuple((tag("while"), sc, parens(expr), sc, braces(many0(stmt)))),
|
|
|
|
|(_, _, expr, _, stmts)| Stmt::While(expr, stmts),
|
|
|
|
)(i)
|
|
|
|
}
|
|
|
|
fn let_stmt(i: &str) -> IResult<&str, Stmt> {
|
|
|
|
println!("let: {}", i);
|
|
|
|
map(
|
|
|
|
tuple((
|
|
|
|
tag("let"),
|
|
|
|
sc,
|
|
|
|
identifier,
|
|
|
|
tuple((sc, tag("="), sc)),
|
|
|
|
expr,
|
|
|
|
semi,
|
|
|
|
)),
|
|
|
|
|(_, _, id, _, expr, _)| Stmt::Let(id.to_string(), expr),
|
|
|
|
)(i)
|
|
|
|
}
|
|
|
|
fn yield_stmt(i: &str) -> IResult<&str, Stmt> {
|
|
|
|
println!("yield: {}", i);
|
|
|
|
map(tuple((tag("yield"), semi)), |_| Stmt::Yield)(i)
|
|
|
|
}
|
|
|
|
fn spawn_stmt(i: &str) -> IResult<&str, Stmt> {
|
|
|
|
println!("spawn: {}", i);
|
|
|
|
map(tuple((tag("spawn"), sc, expr, semi)), |(_, _, expr, _)| {
|
|
|
|
Stmt::Spawn(expr)
|
|
|
|
})(i)
|
|
|
|
}
|
|
|
|
fn return_stmt(i: &str) -> IResult<&str, Stmt> {
|
|
|
|
println!("return: {}", i);
|
|
|
|
map(
|
|
|
|
tuple((tag("return"), sc, opt(expr), semi)),
|
|
|
|
|(_, _, expr, _)| Stmt::Return(expr),
|
|
|
|
)(i)
|
|
|
|
}
|
|
|
|
fn func_stmt(i: &str) -> IResult<&str, Stmt> {
|
|
|
|
println!("func: {}", i);
|
|
|
|
map(
|
|
|
|
tuple((
|
|
|
|
tag("fn"),
|
|
|
|
sc,
|
|
|
|
identifier,
|
|
|
|
sc,
|
|
|
|
alt((
|
|
|
|
value(vec![], tuple((char('('), sc, char(')')))),
|
|
|
|
delimited(
|
|
|
|
char('('),
|
|
|
|
separated_list0(
|
|
|
|
tuple((sc, tag(","), sc)),
|
|
|
|
map(identifier, |a| a.to_string()),
|
|
|
|
),
|
|
|
|
char(')'),
|
|
|
|
),
|
|
|
|
)),
|
|
|
|
sc,
|
|
|
|
braces(many0(stmt)),
|
|
|
|
)),
|
|
|
|
|(_, _, id, _, params, _, stmts)| Stmt::Func(id.to_string(), params, stmts),
|
|
|
|
)(i)
|
|
|
|
}
|
|
|
|
fn assign_stmt(i: &str) -> IResult<&str, Stmt> {
|
|
|
|
println!("assign: {}", i);
|
|
|
|
map(
|
|
|
|
tuple((identifier, tuple((sc, tag("="), sc)), expr, semi)),
|
|
|
|
|(id, _, expr, _)| Stmt::Assign(id.to_string(), expr),
|
|
|
|
)(i)
|
|
|
|
}
|
|
|
|
fn send_stmt(i: &str) -> IResult<&str, Stmt> {
|
|
|
|
println!("send: {}", i);
|
|
|
|
map(
|
|
|
|
tuple((expr, tuple((sc, tag("->"), sc)), identifier, semi)),
|
|
|
|
|(expr, _, id, _)| Stmt::Send(expr, id.to_string()),
|
|
|
|
)(i)
|
|
|
|
}
|
|
|
|
fn expr_stmt(i: &str) -> IResult<&str, Stmt> {
|
|
|
|
println!("expr: {}", i);
|
|
|
|
map(tuple((expr, semi)), |(expr, _)| Stmt::Expr(expr))(i)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn stmt(i: &str) -> IResult<&str, Stmt> {
|
|
|
|
preceded(
|
|
|
|
sc,
|
|
|
|
alt((
|
|
|
|
if_stmt,
|
|
|
|
while_stmt,
|
|
|
|
let_stmt,
|
|
|
|
yield_stmt,
|
|
|
|
spawn_stmt,
|
|
|
|
return_stmt,
|
|
|
|
func_stmt,
|
|
|
|
assign_stmt,
|
|
|
|
send_stmt,
|
|
|
|
expr_stmt,
|
|
|
|
)),
|
|
|
|
)(i)
|
|
|
|
}
|
|
|
|
|
2021-09-22 20:47:23 +00:00
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn can_parse_string_lit() {
|
|
|
|
let a = r#""hey" "#;
|
|
|
|
let (rest, res) = string(a).unwrap();
|
|
|
|
|
2021-09-26 13:58:55 +00:00
|
|
|
assert_eq!(res, Expr::LStr("hey".to_string()));
|
2021-09-22 20:47:23 +00:00
|
|
|
assert_eq!(rest, " ");
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn can_parse_binary_op() {
|
|
|
|
let a = "3 +3 + 6";
|
2021-09-26 14:56:41 +00:00
|
|
|
let (_rest, res) = expr(a).unwrap();
|
2021-09-22 20:47:23 +00:00
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
res,
|
|
|
|
Expr::Binary(
|
|
|
|
BinOp::Plus,
|
|
|
|
Box::new(Expr::Binary(
|
|
|
|
BinOp::Plus,
|
|
|
|
Box::new(Expr::LNum(3.0)),
|
|
|
|
Box::new(Expr::LNum(3.0)),
|
|
|
|
)),
|
|
|
|
Box::new(Expr::LNum(6.0))
|
|
|
|
)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2021-09-26 13:58:55 +00:00
|
|
|
#[test]
|
|
|
|
fn can_parse_binary_op_with_str() {
|
|
|
|
let a = r#"3 +3 + 6 + "hey""#;
|
2021-09-26 14:56:41 +00:00
|
|
|
let (_rest, res) = expr(a).unwrap();
|
2021-09-26 13:58:55 +00:00
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
res,
|
|
|
|
Expr::Binary(
|
|
|
|
BinOp::Plus,
|
|
|
|
Box::new(Expr::Binary(
|
|
|
|
BinOp::Plus,
|
|
|
|
Box::new(Expr::Binary(
|
|
|
|
BinOp::Plus,
|
|
|
|
Box::new(Expr::LNum(3.0)),
|
|
|
|
Box::new(Expr::LNum(3.0)),
|
|
|
|
)),
|
|
|
|
Box::new(Expr::LNum(6.0))
|
|
|
|
)),
|
|
|
|
Box::new(Expr::LStr("hey".to_string()))
|
|
|
|
)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2021-09-26 14:56:41 +00:00
|
|
|
#[test]
|
|
|
|
fn can_parse_var() {
|
|
|
|
let a = "hello";
|
|
|
|
let (rest, res) = expr(a).unwrap();
|
|
|
|
|
|
|
|
assert_eq!(res, Expr::Var("hello".to_string()));
|
|
|
|
assert_eq!(rest, "");
|
|
|
|
}
|
|
|
|
|
2021-09-22 20:47:23 +00:00
|
|
|
#[test]
|
|
|
|
fn can_parse_empty_call() {
|
|
|
|
let a = "hello()";
|
|
|
|
let (rest, res) = expr(a).unwrap();
|
|
|
|
|
|
|
|
assert_eq!(res, Expr::Call("hello".to_string(), vec![]));
|
|
|
|
assert_eq!(rest, "");
|
|
|
|
}
|
|
|
|
|
2021-09-26 14:56:41 +00:00
|
|
|
#[test]
|
|
|
|
fn can_parse_call_with_var() {
|
|
|
|
let a = "hello(hey)";
|
|
|
|
let (rest, res) = expr(a).unwrap();
|
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
res,
|
|
|
|
Expr::Call("hello".to_string(), vec![Expr::Var("hey".to_string())])
|
|
|
|
);
|
|
|
|
assert_eq!(rest, "");
|
|
|
|
}
|
|
|
|
|
2021-09-22 20:47:23 +00:00
|
|
|
#[test]
|
|
|
|
fn can_parse_call() {
|
|
|
|
let a = "hello(1.0, 45 , yeah)";
|
|
|
|
let (rest, res) = expr(a).unwrap();
|
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
res,
|
|
|
|
Expr::Call(
|
|
|
|
"hello".to_string(),
|
|
|
|
vec![
|
|
|
|
Expr::LNum(1.0),
|
|
|
|
Expr::LNum(45.0),
|
|
|
|
Expr::Var("yeah".to_string())
|
|
|
|
]
|
|
|
|
)
|
|
|
|
);
|
|
|
|
assert_eq!(rest, "");
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn can_parse_call_with_bin_op() {
|
|
|
|
let a = "hello(1.0, 45 + 33, yeah)";
|
|
|
|
let (rest, res) = expr(a).unwrap();
|
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
res,
|
|
|
|
Expr::Call(
|
|
|
|
"hello".to_string(),
|
|
|
|
vec![
|
|
|
|
Expr::LNum(1.0),
|
|
|
|
Expr::Binary(
|
|
|
|
BinOp::Plus,
|
|
|
|
Box::new(Expr::LNum(45.0)),
|
|
|
|
Box::new(Expr::LNum(33.0))
|
|
|
|
),
|
|
|
|
Expr::Var("yeah".to_string())
|
|
|
|
]
|
|
|
|
)
|
|
|
|
);
|
|
|
|
assert_eq!(rest, "");
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2021-09-26 13:58:55 +00:00
|
|
|
fn can_parse_call_with_string_binop() {
|
2021-09-26 15:36:06 +00:00
|
|
|
let a = r#"funFun(null == "ss" + 12, true)"#;
|
2021-09-26 13:58:55 +00:00
|
|
|
let (rest, res) = expr(a).unwrap();
|
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
res,
|
|
|
|
Expr::Call(
|
|
|
|
"funFun".to_string(),
|
|
|
|
vec![
|
|
|
|
Expr::Binary(
|
|
|
|
BinOp::Plus,
|
2021-09-26 15:36:06 +00:00
|
|
|
Box::new(Expr::Binary(
|
|
|
|
BinOp::Equals,
|
|
|
|
Box::new(Expr::LNull),
|
|
|
|
Box::new(Expr::LStr("ss".to_string())),
|
|
|
|
)),
|
2021-09-26 13:58:55 +00:00
|
|
|
Box::new(Expr::LNum(12.0))
|
|
|
|
),
|
|
|
|
Expr::LBool(true)
|
|
|
|
]
|
|
|
|
)
|
|
|
|
);
|
|
|
|
assert_eq!(rest, "");
|
2021-09-22 20:47:23 +00:00
|
|
|
}
|
2021-09-26 15:36:06 +00:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn can_parse_binop_with_receive() {
|
|
|
|
let a = r#"1 + a < 9 - <- chan"#;
|
|
|
|
let (rest, res) = expr(a).unwrap();
|
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
res,
|
|
|
|
Expr::Binary(
|
|
|
|
BinOp::Minus,
|
|
|
|
Box::new(Expr::Binary(
|
|
|
|
BinOp::Plus,
|
|
|
|
Box::new(Expr::LNum(1.0)),
|
|
|
|
Box::new(Expr::Binary(
|
|
|
|
BinOp::LessThan,
|
|
|
|
Box::new(Expr::Var("a".to_string())),
|
|
|
|
Box::new(Expr::LNum(9.0)),
|
|
|
|
)),
|
|
|
|
)),
|
|
|
|
Box::new(Expr::Receive(Box::new(Expr::Var("chan".to_string())))),
|
|
|
|
)
|
|
|
|
);
|
|
|
|
assert_eq!(rest, "");
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn can_parse_binop_with_receive_and_fun_call() {
|
|
|
|
let a = r#"-99 - <- chan + funkyFun(a, false, "hey")"#;
|
|
|
|
let (rest, res) = expr(a).unwrap();
|
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
res,
|
|
|
|
Expr::Binary(
|
|
|
|
BinOp::Minus,
|
|
|
|
Box::new(Expr::LNum(-99.0)),
|
|
|
|
Box::new(Expr::Receive(Box::new(Expr::Binary(
|
|
|
|
BinOp::Plus,
|
|
|
|
Box::new(Expr::Var("chan".to_string())),
|
|
|
|
Box::new(Expr::Call(
|
|
|
|
"funkyFun".to_string(),
|
|
|
|
vec![
|
|
|
|
Expr::Var("a".to_string()),
|
|
|
|
Expr::LBool(false),
|
|
|
|
Expr::LStr("hey".to_string())
|
|
|
|
]
|
|
|
|
))
|
|
|
|
))))
|
|
|
|
)
|
|
|
|
);
|
|
|
|
assert_eq!(rest, "");
|
|
|
|
}
|
2021-09-26 16:49:46 +00:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn can_parse_let_stmt() {
|
|
|
|
let a = r#"let a = 0;"#;
|
|
|
|
let (rest, res) = stmt(a).unwrap();
|
|
|
|
|
|
|
|
assert_eq!(res, Stmt::Let("a".to_string(), Expr::LNum(0.0)));
|
|
|
|
assert_eq!(rest, "");
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn can_parse_if_stmt() {
|
|
|
|
let a = r#"
|
|
|
|
if (n < 2) {
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
"#;
|
|
|
|
let (rest, res) = stmt(a).unwrap();
|
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
res,
|
|
|
|
Stmt::If(
|
|
|
|
Expr::Binary(
|
|
|
|
BinOp::LessThan,
|
|
|
|
Box::new(Expr::Var("n".to_string())),
|
|
|
|
Box::new(Expr::LNum(2.0)),
|
|
|
|
),
|
|
|
|
vec![Stmt::Return(Some(Expr::Var("n".to_string())))]
|
|
|
|
)
|
|
|
|
);
|
|
|
|
assert_eq!(rest, "");
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn can_parse_func() {
|
|
|
|
let a = r#"
|
|
|
|
fn fib(n) {
|
|
|
|
if (n < 2) {
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
return fib(n - 2)
|
|
|
|
+ fib(n - 1);
|
|
|
|
}
|
|
|
|
"#;
|
|
|
|
let (rest, res) = stmt(a).unwrap();
|
|
|
|
|
|
|
|
assert_eq!(res, Stmt::Let("a".to_string(), Expr::LNum(0.0)));
|
|
|
|
assert_eq!(rest, "");
|
|
|
|
}
|
2021-09-22 20:47:23 +00:00
|
|
|
}
|