mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-27 22:09:09 +00:00
Detect outdents too far
This commit is contained in:
parent
362ca1d914
commit
dc2d9ceeac
7 changed files with 238 additions and 41 deletions
|
@ -190,6 +190,7 @@ fn record_field_access<'a>() -> impl Parser<'a, &'a str, EExpr<'a>> {
|
|||
/// pattern later
|
||||
fn parse_loc_term_or_underscore<'a>(
|
||||
min_indent: u32,
|
||||
outdent_col: u32,
|
||||
options: ExprParseOptions,
|
||||
arena: &'a Bump,
|
||||
state: State<'a>,
|
||||
|
@ -201,8 +202,11 @@ fn parse_loc_term_or_underscore<'a>(
|
|||
loc!(specialize(EExpr::Number, positive_number_literal_help())),
|
||||
loc!(specialize(EExpr::Lambda, closure_help(min_indent, options))),
|
||||
loc!(underscore_expression()),
|
||||
loc!(record_literal_help(min_indent)),
|
||||
loc!(specialize(EExpr::List, list_literal_help(min_indent))),
|
||||
loc!(record_literal_help(min_indent, outdent_col)),
|
||||
loc!(specialize(
|
||||
EExpr::List,
|
||||
list_literal_help(min_indent, outdent_col)
|
||||
)),
|
||||
loc!(map_with_arena!(
|
||||
assign_or_destructure_identifier(),
|
||||
ident_to_expr
|
||||
|
@ -213,6 +217,7 @@ fn parse_loc_term_or_underscore<'a>(
|
|||
|
||||
fn parse_loc_term<'a>(
|
||||
min_indent: u32,
|
||||
outdent_col: u32,
|
||||
options: ExprParseOptions,
|
||||
arena: &'a Bump,
|
||||
state: State<'a>,
|
||||
|
@ -223,8 +228,11 @@ fn parse_loc_term<'a>(
|
|||
loc!(specialize(EExpr::SingleQuote, single_quote_literal_help())),
|
||||
loc!(specialize(EExpr::Number, positive_number_literal_help())),
|
||||
loc!(specialize(EExpr::Lambda, closure_help(min_indent, options))),
|
||||
loc!(record_literal_help(min_indent)),
|
||||
loc!(specialize(EExpr::List, list_literal_help(min_indent))),
|
||||
loc!(record_literal_help(min_indent, outdent_col)),
|
||||
loc!(specialize(
|
||||
EExpr::List,
|
||||
list_literal_help(min_indent, outdent_col)
|
||||
)),
|
||||
loc!(map_with_arena!(
|
||||
assign_or_destructure_identifier(),
|
||||
ident_to_expr
|
||||
|
@ -252,6 +260,7 @@ fn underscore_expression<'a>() -> impl Parser<'a, Expr<'a>, EExpr<'a>> {
|
|||
|
||||
fn loc_possibly_negative_or_negated_term<'a>(
|
||||
min_indent: u32,
|
||||
outdent_col: u32,
|
||||
options: ExprParseOptions,
|
||||
) -> impl Parser<'a, Loc<Expr<'a>>, EExpr<'a>> {
|
||||
one_of![
|
||||
|
@ -259,7 +268,11 @@ fn loc_possibly_negative_or_negated_term<'a>(
|
|||
let initial = state.clone();
|
||||
|
||||
let (_, (loc_op, loc_expr), state) = and!(loc!(unary_negate()), |a, s| parse_loc_term(
|
||||
min_indent, options, a, s
|
||||
min_indent,
|
||||
outdent_col,
|
||||
options,
|
||||
a,
|
||||
s
|
||||
))
|
||||
.parse(arena, state)?;
|
||||
|
||||
|
@ -271,13 +284,15 @@ fn loc_possibly_negative_or_negated_term<'a>(
|
|||
loc!(specialize(EExpr::Number, number_literal_help())),
|
||||
loc!(map_with_arena!(
|
||||
and!(loc!(word1(b'!', EExpr::Start)), |a, s| {
|
||||
parse_loc_term(min_indent, options, a, s)
|
||||
parse_loc_term(min_indent, outdent_col, options, a, s)
|
||||
}),
|
||||
|arena: &'a Bump, (loc_op, loc_expr): (Loc<_>, _)| {
|
||||
Expr::UnaryOp(arena.alloc(loc_expr), Loc::at(loc_op.region, UnaryOp::Not))
|
||||
}
|
||||
)),
|
||||
|arena, state| { parse_loc_term_or_underscore(min_indent, options, arena, state) }
|
||||
|arena, state| {
|
||||
parse_loc_term_or_underscore(min_indent, outdent_col, options, arena, state)
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
@ -336,8 +351,8 @@ fn parse_expr_operator_chain<'a>(
|
|||
arena: &'a Bump,
|
||||
state: State<'a>,
|
||||
) -> ParseResult<'a, Expr<'a>, EExpr<'a>> {
|
||||
let (_, expr, state) =
|
||||
loc_possibly_negative_or_negated_term(min_indent, options).parse(arena, state)?;
|
||||
let (_, expr, state) = loc_possibly_negative_or_negated_term(min_indent, start_column, options)
|
||||
.parse(arena, state)?;
|
||||
|
||||
let initial = state.clone();
|
||||
let end = state.pos();
|
||||
|
@ -1333,7 +1348,8 @@ fn parse_expr_operator<'a>(
|
|||
BinOp::Minus if expr_state.end != op_start && op_end == new_start => {
|
||||
// negative terms
|
||||
|
||||
let (_, negated_expr, state) = parse_loc_term(min_indent, options, arena, state)?;
|
||||
let (_, negated_expr, state) =
|
||||
parse_loc_term(min_indent, start_column, options, arena, state)?;
|
||||
let new_end = state.pos();
|
||||
|
||||
let arg = numeric_negate_expression(
|
||||
|
@ -1467,7 +1483,9 @@ fn parse_expr_operator<'a>(
|
|||
_ => unreachable!(),
|
||||
},
|
||||
),
|
||||
_ => match loc_possibly_negative_or_negated_term(min_indent, options).parse(arena, state) {
|
||||
_ => match loc_possibly_negative_or_negated_term(min_indent, start_column, options)
|
||||
.parse(arena, state)
|
||||
{
|
||||
Err((MadeProgress, f, s)) => Err((MadeProgress, f, s)),
|
||||
Ok((_, mut new_expr, state)) => {
|
||||
let new_end = state.pos();
|
||||
|
@ -1526,7 +1544,7 @@ fn parse_expr_end<'a>(
|
|||
) -> ParseResult<'a, Expr<'a>, EExpr<'a>> {
|
||||
let parser = skip_first!(
|
||||
crate::blankspace::check_indent(min_indent, EExpr::IndentEnd),
|
||||
move |a, s| parse_loc_term(min_indent, options, a, s)
|
||||
move |a, s| parse_loc_term(min_indent, start_column, options, a, s)
|
||||
);
|
||||
|
||||
match parser.parse(arena, state.clone()) {
|
||||
|
@ -2467,7 +2485,10 @@ fn ident_to_expr<'a>(arena: &'a Bump, src: Ident<'a>) -> Expr<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn list_literal_help<'a>(min_indent: u32) -> impl Parser<'a, Expr<'a>, EList<'a>> {
|
||||
fn list_literal_help<'a>(
|
||||
min_indent: u32,
|
||||
outdent_col: u32,
|
||||
) -> impl Parser<'a, Expr<'a>, EList<'a>> {
|
||||
move |arena, state| {
|
||||
let (_, elements, state) = collection_trailing_sep_e!(
|
||||
word1(b'[', EList::Open),
|
||||
|
@ -2478,8 +2499,10 @@ fn list_literal_help<'a>(min_indent: u32) -> impl Parser<'a, Expr<'a>, EList<'a>
|
|||
word1(b',', EList::End),
|
||||
word1(b']', EList::End),
|
||||
min_indent,
|
||||
outdent_col,
|
||||
EList::Open,
|
||||
EList::IndentEnd,
|
||||
EList::OutdentEnd,
|
||||
Expr::SpaceBefore
|
||||
)
|
||||
.parse(arena, state)?;
|
||||
|
@ -2555,6 +2578,7 @@ fn record_updateable_identifier<'a>() -> impl Parser<'a, Expr<'a>, ERecord<'a>>
|
|||
|
||||
fn record_help<'a>(
|
||||
min_indent: u32,
|
||||
outdent_col: u32,
|
||||
) -> impl Parser<
|
||||
'a,
|
||||
(
|
||||
|
@ -2589,8 +2613,8 @@ fn record_help<'a>(
|
|||
// `{ }` can be successfully parsed as an empty record, and then
|
||||
// changed by the formatter back into `{}`.
|
||||
zero_or_more!(word1(b' ', ERecord::End)),
|
||||
skip_second!(
|
||||
and!(
|
||||
|arena, state| {
|
||||
let (_, (parsed_elems, comments), state) = and!(
|
||||
trailing_sep_by0(
|
||||
word1(b',', ERecord::End),
|
||||
space0_before_optional_after(
|
||||
|
@ -2600,19 +2624,35 @@ fn record_help<'a>(
|
|||
ERecord::IndentEnd
|
||||
),
|
||||
),
|
||||
// Allow outdented closing braces
|
||||
space0_e(0, ERecord::IndentEnd)
|
||||
),
|
||||
word1(b'}', ERecord::End)
|
||||
)
|
||||
space0_e(0, ERecord::OutdentEnd)
|
||||
)
|
||||
.parse(arena, state)?;
|
||||
|
||||
let closing_brace_col = state.column();
|
||||
let closing_brace_pos = state.pos();
|
||||
|
||||
let (_, _, state) = word1(b'}', ERecord::End).parse(arena, state)?;
|
||||
|
||||
if closing_brace_col < outdent_col {
|
||||
return Err((MadeProgress, ERecord::OutdentEnd(closing_brace_pos), state));
|
||||
}
|
||||
|
||||
Ok((MadeProgress, (parsed_elems, comments), state))
|
||||
}
|
||||
))
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
fn record_literal_help<'a>(min_indent: u32) -> impl Parser<'a, Expr<'a>, EExpr<'a>> {
|
||||
fn record_literal_help<'a>(
|
||||
min_indent: u32,
|
||||
outdent_col: u32,
|
||||
) -> impl Parser<'a, Expr<'a>, EExpr<'a>> {
|
||||
then(
|
||||
loc!(specialize(EExpr::Record, record_help(min_indent))),
|
||||
loc!(specialize(
|
||||
EExpr::Record,
|
||||
record_help(min_indent, outdent_col)
|
||||
)),
|
||||
move |arena, state, _, loc_record| {
|
||||
let (opt_update, loc_assigned_fields_with_comments) = loc_record.value;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue