refactor refactor

This commit is contained in:
Folkert 2021-03-05 20:16:09 +01:00
parent 5b2c2bee33
commit e07ef4e744

View file

@ -1661,8 +1661,8 @@ fn ident_etc_help<'a>(min_indent: u16) -> impl Parser<'a, Expr<'a>, EExpr<'a>> {
enum Next { enum Next {
Equals(u16), Equals(u16),
Colon(u16), Colon(u16),
Comma(u16), // Comma(u16),
Backarrow(u16), // Backarrow(u16),
} }
then( then(
@ -1684,82 +1684,29 @@ fn ident_etc_help<'a>(min_indent: u16) -> impl Parser<'a, Expr<'a>, EExpr<'a>> {
)) ))
) )
), ),
move |arena, state, progress, (loc_ident, opt_extras)| { move |arena, state, progress, (loc_ident, (opt_arguments, next))| {
debug_assert_eq!(progress, MadeProgress); debug_assert_eq!(progress, MadeProgress);
// This appears to be a var, keyword, or function application. // This appears to be a var, keyword, or function application.
match opt_extras { match opt_arguments {
(Some(loc_args), Some((_spaces_before_equals, Next::Equals(_equals_indent)))) => { Some(arguments) => {
// We got args with an '=' after them, e.g. `foo a b = ...` This is a syntax error! match next {
let region = Region::across_all(loc_args.iter().map(|v| &v.region)); Some((_ident_spaces, Next::Equals(_equals_indent))) => {
let fail = EExpr::ElmStyleFunction(region, state.line, state.column); // We got args with an '=' after them, e.g. `foo a b = ...` This is a syntax error!
Err((MadeProgress, fail, state)) let region = Region::across_all(arguments.iter().map(|v| &v.region));
} let fail = EExpr::ElmStyleFunction(region, state.line, state.column);
(None, Some((spaces_before_equals, Next::Equals(equals_indent)))) => { Err((MadeProgress, fail, state))
// We got '=' with no args before it }
let pattern: Pattern<'a> = Pattern::from_ident(arena, loc_ident.value); Some((ident_spaces, Next::Colon(colon_indent))) => {
let value = if spaces_before_equals.is_empty() { let pattern: Pattern<'a> = {
pattern let pattern = Pattern::from_ident(arena, loc_ident.value);
} else {
Pattern::SpaceAfter(arena.alloc(pattern), spaces_before_equals)
};
let region = loc_ident.region;
let def_start_col = state.indent_col;
let loc_pattern = Located { region, value };
// TODO use equals_indent below?
let (_, spaces_after_equals, state) =
space0_e(min_indent, EExpr::Space, EExpr::IndentDefBody)
.parse(arena, state)?;
let (_, parsed_expr, state) = parse_def_expr_help(
min_indent,
def_start_col,
equals_indent,
arena,
state,
loc_pattern,
spaces_after_equals,
)?;
Ok((MadeProgress, parsed_expr, state))
}
(Some(loc_args), None) => {
// We got args and nothing else
let loc_expr = Located {
region: loc_ident.region,
value: ident_to_expr(arena, loc_ident.value),
};
let mut allocated_args = Vec::with_capacity_in(loc_args.len(), arena);
for loc_arg in loc_args {
allocated_args.push(&*arena.alloc(loc_arg));
}
Ok((
MadeProgress,
Expr::Apply(
arena.alloc(loc_expr),
allocated_args.into_bump_slice(),
CalledVia::Space,
),
state,
))
}
(opt_args, Some((spaces_before_colon, Next::Colon(colon_indent)))) => {
// We may have gotten args, but we definitely got a ':'
// (meaning this is an annotation or alias;
// parse_def_signature will translate it into one or the other.)
let pattern: Pattern<'a> = {
let pattern = Pattern::from_ident(arena, loc_ident.value);
match opt_args {
Some(loc_args) => {
// Translate the loc_args Exprs into a Pattern::Apply // Translate the loc_args Exprs into a Pattern::Apply
// They are probably type alias variables (e.g. `List a : ...`) // They are probably type alias variables (e.g. `List a : ...`)
let mut arg_patterns = Vec::with_capacity_in(loc_args.len(), arena); let mut arg_patterns =
Vec::with_capacity_in(arguments.len(), arena);
for loc_arg in loc_args { for loc_arg in arguments {
match expr_to_pattern_help(arena, &loc_arg.value) { match expr_to_pattern_help(arena, &loc_arg.value) {
Ok(arg_pat) => { Ok(arg_pat) => {
arg_patterns.push(Located { arg_patterns.push(Located {
@ -1786,27 +1733,107 @@ fn ident_etc_help<'a>(min_indent: u16) -> impl Parser<'a, Expr<'a>, EExpr<'a>> {
arena.alloc(loc_pattern), arena.alloc(loc_pattern),
arg_patterns.into_bump_slice(), arg_patterns.into_bump_slice(),
) )
} };
None => pattern, let region = loc_ident.region;
let value = if ident_spaces.is_empty() {
pattern
} else {
Pattern::SpaceAfter(arena.alloc(pattern), ident_spaces)
};
let loc_pattern = Located { region, value };
parse_def_signature_help(
min_indent,
colon_indent,
arena,
state,
loc_pattern,
)
} }
}; None => {
let value = if spaces_before_colon.is_empty() { // We got args and nothing else
pattern let loc_expr = Located {
} else { region: loc_ident.region,
Pattern::SpaceAfter(arena.alloc(pattern), spaces_before_colon) value: ident_to_expr(arena, loc_ident.value),
}; };
let region = loc_ident.region;
let loc_pattern = Located { region, value };
parse_def_signature_help(min_indent, colon_indent, arena, state, loc_pattern) let mut allocated_args = Vec::with_capacity_in(arguments.len(), arena);
}
(None, None) => {
// We got nothin'
let ident = loc_ident.value.clone();
Ok((MadeProgress, ident_to_expr(arena, ident), state)) for loc_arg in arguments {
allocated_args.push(&*arena.alloc(loc_arg));
}
Ok((
MadeProgress,
Expr::Apply(
arena.alloc(loc_expr),
allocated_args.into_bump_slice(),
CalledVia::Space,
),
state,
))
}
}
}
None => {
// no arguments, that limits the options
match next {
Some((ident_spaces, Next::Equals(equals_indent))) => {
// We got '=' with no args before it
let pattern: Pattern<'a> = Pattern::from_ident(arena, loc_ident.value);
let value = if ident_spaces.is_empty() {
pattern
} else {
Pattern::SpaceAfter(arena.alloc(pattern), ident_spaces)
};
let region = loc_ident.region;
let def_start_col = state.indent_col;
let loc_pattern = Located { region, value };
// TODO use equals_indent below?
let (_, spaces_after_equals, state) =
space0_e(min_indent, EExpr::Space, EExpr::IndentDefBody)
.parse(arena, state)?;
let (_, parsed_expr, state) = parse_def_expr_help(
min_indent,
def_start_col,
equals_indent,
arena,
state,
loc_pattern,
spaces_after_equals,
)?;
Ok((MadeProgress, parsed_expr, state))
}
Some((ident_spaces, Next::Colon(colon_indent))) => {
let pattern = Pattern::from_ident(arena, loc_ident.value);
let value = if ident_spaces.is_empty() {
pattern
} else {
Pattern::SpaceAfter(arena.alloc(pattern), ident_spaces)
};
let region = loc_ident.region;
let loc_pattern = Located { region, value };
parse_def_signature_help(
min_indent,
colon_indent,
arena,
state,
loc_pattern,
)
}
None => {
let ident = loc_ident.value.clone();
Ok((MadeProgress, ident_to_expr(arena, ident), state))
}
}
} }
_ => todo!(),
} }
}, },
) )