diff --git a/compiler/parse/src/expr.rs b/compiler/parse/src/expr.rs index e831cab23b..e034a9f20a 100644 --- a/compiler/parse/src/expr.rs +++ b/compiler/parse/src/expr.rs @@ -2,8 +2,8 @@ use crate::ast::{ AssignedField, Attempting, CommentOrNewline, Def, Expr, Pattern, Spaceable, TypeAnnotation, }; use crate::blankspace::{ - line_comment, space0, space0_after, space0_after_e, space0_around, space0_around_ee, - space0_before, space0_before_e, space0_e, space1, space1_before, spaces_exactly, + line_comment, space0, space0_after, space0_after_e, space0_around_ee, space0_before, + space0_before_e, space0_e, space1, space1_before, spaces_exactly, }; use crate::ident::{ident, lowercase_ident, Ident}; use crate::keyword; @@ -11,8 +11,8 @@ use crate::number_literal::number_literal; use crate::parser::{ self, allocated, and_then_with_indent_level, ascii_char, ascii_string, attempt, backtrackable, fail, map, newline_char, not, not_followed_by, optional, sep_by1, sep_by1_e, specialize, - specialize_ref, then, unexpected, unexpected_eof, word1, word2, EExpr, ELambda, Either, If, - List, ParseResult, Parser, State, SyntaxError, When, + specialize_ref, then, unexpected, unexpected_eof, word1, word2, EExpr, EInParens, ELambda, + Either, If, List, ParseResult, Parser, State, SyntaxError, When, }; use crate::pattern::loc_closure_param; use crate::type_annotation; @@ -29,17 +29,38 @@ pub fn expr<'a>(min_indent: u16) -> impl Parser<'a, Expr<'a>, SyntaxError<'a>> { move |arena, state: State<'a>| parse_expr(min_indent, arena, state) } +fn loc_expr_in_parens<'a>(min_indent: u16) -> impl Parser<'a, Located>, SyntaxError<'a>> { + specialize( + |e, r, c| SyntaxError::Expr(EExpr::InParens(e, r, c)), + loc_expr_in_parens_help(min_indent), + ) +} + +fn loc_expr_in_parens_help<'a>( + min_indent: u16, +) -> impl Parser<'a, Located>, EInParens<'a>> { + between!( + word1(b'(', EInParens::Open), + space0_around_ee( + specialize_ref( + EInParens::Syntax, + loc!(move |arena, state| parse_expr(min_indent, arena, state)) + ), + min_indent, + EInParens::Space, + EInParens::IndentOpen, + EInParens::IndentEnd, + ), + word1(b')', EInParens::End) + ) +} + macro_rules! loc_parenthetical_expr { ($min_indent:expr, $args_parser:expr) => { then( loc!(and!( - between!( - ascii_char(b'(' ), map_with_arena!( - space0_around( - loc!(move |arena, state| parse_expr($min_indent, arena, state)), - $min_indent, - ), + loc_expr_in_parens($min_indent), |arena: &'a Bump, loc_expr: Located>| { Located { region: loc_expr.region, @@ -47,8 +68,7 @@ macro_rules! loc_parenthetical_expr { } } ), - ascii_char(b')' ) - ), + optional(either!( // There may optionally be function args after the ')' // e.g. ((foo bar) baz)