diff --git a/src/parse.rs b/src/parse.rs index 7e5f8a7d17..a51f173319 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -195,7 +195,6 @@ parser! { let min_indent = *min_indent_ref; choice(( - enclosed_closure(min_indent), closure(min_indent), parenthetical_expr(min_indent), string("{}").with(value(Expr::EmptyRecord)), @@ -434,48 +433,21 @@ where I: Stream, }) } -/// Closure *without* parens around the args -/// -/// e.g. (x, y -> stuff) as opposed to (x, y) -> stuff -pub fn enclosed_closure(min_indent: u32) -> impl Parser -where I: Stream, - I::Error: ParseError -{ - attempt( - char('(') - .with( - sep_by1( - located(pattern(min_indent)), - char(',').skip(indented_whitespaces(min_indent)) - )) - .skip(indented_whitespaces1(min_indent)) - .skip(string("->")) - .skip(indented_whitespaces1(min_indent)) - ) - .and(located(expr_body(min_indent))) - .skip(char(')')) - .map(|(patterns, closure_body)| { - Expr::Closure(patterns, Box::new(closure_body)) - }) -} - -/// Closure with parens around the args -/// -/// e.g. (x, y) -> stuff as opposde to (x, y -> stuff) +/// e.g. \x y => expr pub fn closure(min_indent: u32) -> impl Parser where I: Stream, I::Error: ParseError { - attempt( - between(char('('), char(')'), + char('\\') + .skip(indented_whitespaces(min_indent)) + .with( sep_by1( located(pattern(min_indent)), - char(',').skip(indented_whitespaces(min_indent)) + attempt(many1::, _>(skipped_indented_whitespace_char(min_indent).skip(not_followed_by(string("=>"))))) )) + .skip(indented_whitespaces(min_indent)) + .skip(string("=>")) .skip(indented_whitespaces1(min_indent)) - .skip(string("->")) - .skip(indented_whitespaces1(min_indent)) - ) .and(located(expr_body(min_indent))) .map(|(patterns, closure_body)| { Expr::Closure(patterns, Box::new(closure_body)) diff --git a/tests/test_parse.rs b/tests/test_parse.rs index 17ba81daeb..f5cec33909 100644 --- a/tests/test_parse.rs +++ b/tests/test_parse.rs @@ -512,6 +512,37 @@ mod test_parse { // all of the above tests except with parens too! // Also, verify them all with variable paren counts; ((foo)) should work. + // CLOSURE + + #[test] + fn single_arg_closure() { + assert_eq!( + parse_without_loc("\\a => b"), + Ok(( + Closure( + vec![loc(Identifier("a".to_string()))], + loc_box(Var("b".to_string())) + ), + "" + )) + ); + } + + #[test] + fn multi_arg_closure() { + assert_eq!( + parse_without_loc("\\a b => c"), + Ok(( + Closure( + vec![loc(Identifier("a".to_string())), loc(Identifier("b".to_string()))], + loc_box(Var("c".to_string())) + ), + "" + )) + ); + } + + // FUNC fn expect_parsed_func<'a>(parse_str: &'a str, func_str: &'a str, args: Vec>) { @@ -1235,12 +1266,11 @@ mod test_parse { ); } - #[test] fn regression_on_calling_function_named_c() { // This was broken because case-expressions were greedily consuming 'c' characters for "case" assert_eq!( - parse_without_loc("f = (x) -> c 1\n\nf"), + parse_without_loc("f = \\x => c 1\n\nf"), Ok(( Assign( loc(Identifier("f".to_string())),