diff --git a/src/parse/mod.rs b/src/parse/mod.rs index 3b05c95893..5379bdc1aa 100644 --- a/src/parse/mod.rs +++ b/src/parse/mod.rs @@ -31,10 +31,10 @@ use parse::blankspace::{ use parse::ident::{ident, Ident, MaybeQualified}; use parse::number_literal::number_literal; use parse::parser::{ - and, attempt, between, char, either, loc, map, map_with_arena, not_followed_by, one_of2, - one_of4, one_of5, one_of8, one_of9, one_or_more, optional, sep_by0, skip_first, skip_second, - string, then, unexpected, unexpected_eof, zero_or_more, Either, Fail, FailReason, ParseResult, - Parser, State, + and, attempt, between, char, either, loc, map, map_with_arena, not_followed_by, one_of10, + one_of2, one_of4, one_of5, one_or_more, optional, sep_by0, skip_first, skip_second, string, + then, unexpected, unexpected_eof, zero_or_more, Either, Fail, FailReason, ParseResult, Parser, + State, }; use parse::string_literal::string_literal; use region::Located; @@ -69,8 +69,9 @@ fn loc_parse_expr_body_without_operators<'a>( arena: &'a Bump, state: State<'a>, ) -> ParseResult<'a, Located>> { - one_of9( + one_of10( loc_parenthetical_expr(min_indent), + loc_parenthetical_def(min_indent), loc(string_literal()), loc(number_literal()), loc(closure(min_indent)), @@ -139,40 +140,25 @@ pub fn loc_parenthetical_expr<'a>(min_indent: u16) -> impl Parser<'a, Located Located { region: loc_expr_with_extras.region, value: Expr::Apply(arena.alloc((loc_expr, loc_args))), }, - // '=' after optional spaces - Some(Either::Second(Either::Second((_space_list, Either::First(()))))) => { - panic!("TODO handle def, making sure not to drop comments!"); - } - // ':' after optional spaces - Some(Either::Second(Either::Second((_space_list, Either::Second(()))))) => { - panic!("TODO handle annotation, making sure not to drop comments!"); - } // '.' and a record field immediately after ')', no optional spaces - Some(Either::Second(Either::First(fields))) => Located { + Some(Either::Second(fields)) => Located { region: loc_expr_with_extras.region, value: Expr::Field(arena.alloc(loc_expr), fields), }, @@ -182,6 +168,41 @@ pub fn loc_parenthetical_expr<'a>(min_indent: u16) -> impl Parser<'a, Located(min_indent: u16) -> impl Parser<'a, Located>> { + move |arena, state| { + let (loc_tuple, state) = loc(and( + space0_after( + between( + char('('), + space0_around(loc(pattern(min_indent)), min_indent), + char(')'), + ), + min_indent, + ), + equals_with_indent(), + )) + .parse(arena, state)?; + + let region = loc_tuple.region; + let (loc_first_pattern, equals_sign_indent) = loc_tuple.value; + let (value, state) = parse_def_expr( + min_indent, + equals_sign_indent, + arena, + state, + loc_first_pattern, + )?; + + Ok((Located { value, region }, state)) + } +} + /// The '=' used in a def can't be followed by another '=' (or else it's actually /// an "==") and also it can't be followed by '>' (or else it's actually an "=>") fn equals_for_def<'a>() -> impl Parser<'a, ()> { diff --git a/src/parse/parser.rs b/src/parse/parser.rs index d361d03be0..3c7a1d3dbe 100644 --- a/src/parse/parser.rs +++ b/src/parse/parser.rs @@ -901,6 +901,33 @@ where one_of2(p1, one_of8(p2, p3, p4, p5, p6, p7, p8, p9)) } +pub fn one_of10<'a, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, A>( + p1: P1, + p2: P2, + p3: P3, + p4: P4, + p5: P5, + p6: P6, + p7: P7, + p8: P8, + p9: P9, + p10: P10, +) -> impl Parser<'a, A> +where + P1: Parser<'a, A>, + P2: Parser<'a, A>, + P3: Parser<'a, A>, + P4: Parser<'a, A>, + P5: Parser<'a, A>, + P6: Parser<'a, A>, + P7: Parser<'a, A>, + P8: Parser<'a, A>, + P9: Parser<'a, A>, + P10: Parser<'a, A>, +{ + one_of2(p1, one_of9(p2, p3, p4, p5, p6, p7, p8, p9, p10)) +} + // DEBUG COMBINATORS // // These use dyn for runtime dynamic dispatch. It prevents combinatoric