diff --git a/src/parser.rs b/src/parser.rs index 4abeed2..c038c3d 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -61,11 +61,17 @@ where ) } -fn identifier(input: &str) -> IResult<&str, &str> { +fn identifier(i: &str) -> IResult<&str, &str> { + println!("identifier: {}", i); recognize(pair( alt((alpha1, tag("_"))), many0(alt((alphanumeric1, tag("_")))), - ))(input) + ))(i) +} + +fn variable(i: &str) -> IResult<&str, Expr> { + println!("variable: {}", i); + map(identifier, |a| Expr::Var(a.to_string()))(i) } fn parse_str<'a>(i: &'a str) -> IResult<&'a str, &'a str> { @@ -73,6 +79,7 @@ fn parse_str<'a>(i: &'a str) -> IResult<&'a str, &'a str> { } fn string<'a>(i: &'a str) -> IResult<&'a str, Expr> { + println!("string: {}", i); map( preceded(char('\"'), cut(terminated(parse_str, char('\"')))), |s| Expr::LStr(String::from(s)), @@ -87,18 +94,22 @@ fn boolean<'a>(i: &'a str) -> IResult<&'a str, Expr> { ))(i) } -fn call<'a>(i: &'a str) -> IResult<&'a str, (Identifier, Vec)> { +fn call<'a>(i: &'a str) -> IResult<&'a str, Expr> { println!("call: {}", i); map( tuple(( identifier, - delimited( - char('('), - separated_list0(tuple((sc, tag(","), sc)), expr), - char(')'), - ), + sc, + alt(( + value(vec![], tuple((char('('), sc, char(')')))), + delimited( + char('('), + separated_list0(tuple((sc, tag(","), sc)), expr), + char(')'), + ), + )), )), - |(i, v)| (i.to_string(), v), + |(i, _, v)| Expr::Call(i.to_string(), v), )(i) } @@ -112,7 +123,7 @@ fn literal(i: &str) -> IResult<&str, Expr> { } fn factor_bin(i: &str) -> IResult<&str, Expr> { - alt((delimited(space0, literal, space0), expr))(i) + alt((delimited(space0, term, space0), expr))(i) } fn bin_less_greater(i: &str) -> IResult<&str, Expr> { @@ -177,25 +188,19 @@ fn binary<'a>(i: &'a str) -> IResult<&'a str, Expr> { )(i) } fn receive<'a>(i: &'a str) -> IResult<&'a str, Expr> { + println!("receive: {}", i); map(pair(tag("<-"), expr), |(_, expr)| { Expr::Receive(Box::new(expr)) })(i) } pub fn expr<'a>(i: &'a str) -> IResult<&'a str, Expr> { + alt((receive, binary))(i) +} + +fn term<'a>(i: &'a str) -> IResult<&'a str, Expr> { println!("expr: {}", i); - delimited( - sc, - alt(( - parens(expr), - map(call, |(i, v)| Expr::Call(i, v)), - receive, - binary, - literal, - map(identifier, |i| Expr::Var(i.to_string())), - )), - sc, - )(i) + delimited(sc, alt((literal, call, variable, parens(expr))), sc)(i) } #[cfg(test)] @@ -214,7 +219,7 @@ mod tests { #[test] fn can_parse_binary_op() { let a = "3 +3 + 6"; - let (_rest, res) = binary(a).unwrap(); + let (_rest, res) = expr(a).unwrap(); assert_eq!( res, @@ -233,7 +238,7 @@ mod tests { #[test] fn can_parse_binary_op_with_str() { let a = r#"3 +3 + 6 + "hey""#; - let (_rest, res) = binary(a).unwrap(); + let (_rest, res) = expr(a).unwrap(); assert_eq!( res, @@ -253,6 +258,15 @@ mod tests { ); } + #[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, ""); + } + #[test] fn can_parse_empty_call() { let a = "hello()"; @@ -262,6 +276,18 @@ mod tests { assert_eq!(rest, ""); } + #[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, ""); + } + #[test] fn can_parse_call() { let a = "hello(1.0, 45 , yeah)";