Change closure syntax to \a b => c

This commit is contained in:
Richard Feldman 2019-07-07 10:53:53 -04:00
parent 3651151f12
commit 36bea3a13f
2 changed files with 39 additions and 37 deletions

View file

@ -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<Item = char, Position = IndentablePosition>,
})
}
/// Closure *without* parens around the args
///
/// e.g. (x, y -> stuff) as opposed to (x, y) -> stuff
pub fn enclosed_closure<I>(min_indent: u32) -> impl Parser<Input = I, Output = Expr>
where I: Stream<Item = char, Position = IndentablePosition>,
I::Error: ParseError<I::Item, I::Range, I::Position>
{
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<I>(min_indent: u32) -> impl Parser<Input = I, Output = Expr>
where I: Stream<Item = char, Position = IndentablePosition>,
I::Error: ParseError<I::Item, I::Range, I::Position>
{
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::<Vec<_>, _>(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))

View file

@ -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<Located<Expr>>) {
@ -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())),