small steps

This commit is contained in:
Folkert 2021-02-28 02:00:13 +01:00
parent d3bf8d73e7
commit 43550bf18e
3 changed files with 60 additions and 56 deletions

View file

@ -1,7 +1,7 @@
use crate::ast::{AssignedField, CommentOrNewline, Def, Expr, Pattern, Spaceable, TypeAnnotation}; use crate::ast::{AssignedField, CommentOrNewline, Def, Expr, Pattern, Spaceable, TypeAnnotation};
use crate::blankspace::{ use crate::blankspace::{
line_comment, space0, space0_after_e, space0_around_ee, space0_before, space0_before_e, line_comment, space0, space0_after_e, space0_around_ee, space0_before, space0_before_e,
space0_e, space1, space1_before, spaces_exactly_e, space0_e, space1, spaces_exactly_e,
}; };
use crate::ident::{ident, lowercase_ident, Ident}; use crate::ident::{ident, lowercase_ident, Ident};
use crate::keyword; use crate::keyword;
@ -776,26 +776,30 @@ fn equals_for_def_help<'a>() -> impl Parser<'a, (), EExpr<'a>> {
} }
} }
fn parse_defs<'a>(
min_indent: u16,
) -> impl Parser<'a, Vec<'a, &'a Located<Def<'a>>>, SyntaxError<'a>> {
specialize(|e, _, _| SyntaxError::Expr(e), parse_defs_help(min_indent))
}
fn parse_defs_help<'a>( fn parse_defs_help<'a>(
min_indent: u16, min_indent: u16,
) -> impl Parser<'a, Vec<'a, &'a Located<Def<'a>>>, EExpr<'a>> { ) -> impl Parser<'a, Vec<'a, &'a Located<Def<'a>>>, EExpr<'a>> {
let parse_def = move |a, s| { let parse_def = move |arena, state| {
space0_before_e( let (_, (spaces, def), state) = and!(
loc!(def_help(min_indent)), backtrackable(space0_e(min_indent, EExpr::Space, EExpr::IndentStart)),
min_indent, loc!(def_help(min_indent))
EExpr::Space, )
EExpr::IndentStart, .parse(arena, state)?;
let result = if spaces.is_empty() {
&*arena.alloc(def)
} else {
&*arena.alloc(
arena
.alloc(def.value)
.with_spaces_before(spaces, def.region),
) )
.parse(a, s)
}; };
zero_or_more!(allocated(parse_def)) Ok((MadeProgress, result, state))
};
zero_or_more!(parse_def)
} }
/// A definition, consisting of one of these: /// A definition, consisting of one of these:
@ -1035,44 +1039,19 @@ fn parse_def_expr_help<'a>(
loc_first_pattern: Located<Pattern<'a>>, loc_first_pattern: Located<Pattern<'a>>,
spaces_after_equals: &'a [CommentOrNewline<'a>], spaces_after_equals: &'a [CommentOrNewline<'a>],
) -> ParseResult<'a, Expr<'a>, EExpr<'a>> { ) -> ParseResult<'a, Expr<'a>, EExpr<'a>> {
let result = parse_def_expr(
min_indent,
def_start_col,
equals_sign_indent,
arena,
state,
loc_first_pattern,
spaces_after_equals,
);
match result {
Ok(good) => Ok(good),
Err((progress, fail, state)) => {
let row = state.line;
let col = state.column;
Err((progress, EExpr::Def(arena.alloc(fail), row, col), state))
}
}
}
fn parse_def_expr<'a>(
min_indent: u16,
def_start_col: u16,
equals_sign_indent: u16,
arena: &'a Bump,
state: State<'a>,
loc_first_pattern: Located<Pattern<'a>>,
spaces_after_equals: &'a [CommentOrNewline<'a>],
) -> ParseResult<'a, Expr<'a>, SyntaxError<'a>> {
if def_start_col < min_indent { if def_start_col < min_indent {
Err((NoProgress, SyntaxError::OutdentedTooFar, state)) Err((
// `<` because '=' should be same indent (or greater) as the entire def-expr NoProgress,
EExpr::IndentDefBody(state.line, state.column),
state,
))
} else if equals_sign_indent < def_start_col { } else if equals_sign_indent < def_start_col {
let msg = format!( // `<` because '=' should be same indent or greater
r"TODO the = in this declaration seems outdented. equals_sign_indent was {} and def_start_col was {}", Err((
equals_sign_indent, def_start_col NoProgress,
); EExpr::IndentDefBody(state.line, state.column),
Err((NoProgress, SyntaxError::NotYetImplemented(msg), state)) state,
))
} else { } else {
// Indented more beyond the original indent of the entire def-expr. // Indented more beyond the original indent of the entire def-expr.
let indented_more = def_start_col + 1; let indented_more = def_start_col + 1;
@ -1085,18 +1064,20 @@ fn parse_def_expr<'a>(
// //
// It should be indented more than the original, and it will // It should be indented more than the original, and it will
// end when outdented again. // end when outdented again.
loc!(move |arena, state| parse_expr(indented_more, arena, state)), loc!(move |arena, state| parse_expr_help(indented_more, arena, state)),
and!( and!(
// Optionally parse additional defs. // Optionally parse additional defs.
parse_defs(def_start_col), debug!(parse_defs_help(def_start_col)),
// Parse the final expression that will be returned. // Parse the final expression that will be returned.
// It should be indented the same amount as the original. // It should be indented the same amount as the original.
space1_before( debug!(space0_before_e(
loc!(move |arena, state: State<'a>| { loc!(move |arena, state: State<'a>| {
parse_expr(def_start_col, arena, state) parse_expr_help(def_start_col, arena, state)
}), }),
def_start_col, def_start_col,
) EExpr::Space,
EExpr::IndentStart,
))
) )
), ),
move |arena, state, progress, (loc_first_body, (mut defs, loc_ret))| { move |arena, state, progress, (loc_first_body, (mut defs, loc_ret))| {

View file

@ -276,6 +276,28 @@ fn to_expr_report<'a>(
} }
} }
EExpr::Colon(row, col) => {
let surroundings = Region::from_rows_cols(start_row, start_col, *row, *col);
let region = Region::from_row_col(*row, *col);
let doc = alloc.stack(vec![
alloc.reflow(r"I am in the middle of parsing a definition, but I got stuck here:"),
alloc.region_with_subregion(surroundings, region),
alloc.concat(vec![
alloc.reflow("Looks like you are trying to define a function. "),
alloc.reflow("In roc, functions are always written as a lambda, like "),
alloc.parser_suggestion("increment = \\n -> n + 1"),
alloc.reflow("."),
]),
]);
Report {
filename,
doc,
title: "ARGUMENTS BEFORE EQUALS".to_string(),
}
}
_ => todo!("unhandled parse error: {:?}", parse_problem), _ => todo!("unhandled parse error: {:?}", parse_problem),
} }
} }

View file

@ -4103,6 +4103,7 @@ mod test_reporting {
I am partway through parsing a definition, but I got stuck here: I am partway through parsing a definition, but I got stuck here:
1 main =
2 5 ** 3 2 5 ** 3
^ ^