mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-28 22:34:45 +00:00
cleanup
This commit is contained in:
parent
35e7f01362
commit
2fc9d20867
2 changed files with 1 additions and 557 deletions
|
@ -247,65 +247,6 @@ fn chomp_line_comment(buffer: &[u8]) -> Result<&str, Progress> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Advance the parser while also indenting as appropriate.
|
|
||||||
/// This assumes we are only advancing with spaces, since they can indent.
|
|
||||||
fn advance_spaces_e<TE, E>(
|
|
||||||
state: State,
|
|
||||||
spaces: usize,
|
|
||||||
to_error: TE,
|
|
||||||
) -> Result<State, (Progress, E, State)>
|
|
||||||
where
|
|
||||||
TE: Fn(Row, Col) -> E,
|
|
||||||
{
|
|
||||||
match (state.column as usize).checked_add(spaces) {
|
|
||||||
Some(column_usize) => Ok(State {
|
|
||||||
bytes: &state.bytes[spaces..],
|
|
||||||
column: column_usize as u16,
|
|
||||||
..state
|
|
||||||
}),
|
|
||||||
_ => Err((NoProgress, to_error(state.line, state.column), state)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
pub fn spaces_exactly_e<'a>(spaces_expected: u16) -> impl Parser<'a, (), parser::EExpr<'a>> {
|
|
||||||
use parser::EExpr;
|
|
||||||
|
|
||||||
move |_, state: State<'a>| {
|
|
||||||
if spaces_expected == 0 {
|
|
||||||
return Ok((NoProgress, (), state));
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut spaces_seen: u16 = 0;
|
|
||||||
|
|
||||||
for c in state.bytes {
|
|
||||||
match c {
|
|
||||||
b' ' => {
|
|
||||||
spaces_seen += 1;
|
|
||||||
if spaces_seen == spaces_expected {
|
|
||||||
let state =
|
|
||||||
advance_spaces_e(state, spaces_expected as usize, EExpr::IndentStart)?;
|
|
||||||
return Ok((MadeProgress, (), state));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
return Err((
|
|
||||||
NoProgress,
|
|
||||||
EExpr::IndentStart(state.line, state.column + spaces_seen),
|
|
||||||
state,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Err((
|
|
||||||
NoProgress,
|
|
||||||
EExpr::IndentStart(state.line, state.column + spaces_seen),
|
|
||||||
state,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn spaces_help_help<'a, E>(
|
fn spaces_help_help<'a, E>(
|
||||||
min_indent: u16,
|
min_indent: u16,
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
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::{space0_after_e, space0_around_ee, space0_before_e, space0_e};
|
||||||
space0_after_e, space0_around_ee, space0_before_e, space0_e, spaces_exactly_e,
|
|
||||||
};
|
|
||||||
use crate::ident::{lowercase_ident, parse_ident_help, Ident};
|
use crate::ident::{lowercase_ident, parse_ident_help, Ident};
|
||||||
use crate::keyword;
|
use crate::keyword;
|
||||||
use crate::parser::{
|
use crate::parser::{
|
||||||
|
@ -166,138 +164,6 @@ fn record_field_access<'a>() -> impl Parser<'a, &'a str, EExpr<'a>> {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
type Extras<'a> = Located<(
|
|
||||||
Located<Expr<'a>>,
|
|
||||||
(
|
|
||||||
Vec<'a, &'a str>,
|
|
||||||
Option<Either<Vec<'a, Located<Expr<'a>>>, (&'a [CommentOrNewline<'a>], u16)>>,
|
|
||||||
),
|
|
||||||
)>;
|
|
||||||
|
|
||||||
fn helper_help<'a>(
|
|
||||||
arena: &'a Bump,
|
|
||||||
state: State<'a>,
|
|
||||||
loc_expr_with_extras: Extras<'a>,
|
|
||||||
min_indent: u16,
|
|
||||||
) -> ParseResult<'a, Located<Expr<'a>>, EExpr<'a>> {
|
|
||||||
// We parse the parenthetical expression *and* the arguments after it
|
|
||||||
// in one region, so that (for example) the region for Apply includes its args.
|
|
||||||
let (mut loc_expr, (accesses, opt_extras)) = loc_expr_with_extras.value;
|
|
||||||
|
|
||||||
let mut value = loc_expr.value;
|
|
||||||
|
|
||||||
for field in accesses {
|
|
||||||
// Wrap the previous answer in the new one, so we end up
|
|
||||||
// with a nested Expr. That way, `foo.bar.baz` gets represented
|
|
||||||
// in the AST as if it had been written (foo.bar).baz all along.
|
|
||||||
value = Expr::Access(arena.alloc(value), field);
|
|
||||||
}
|
|
||||||
|
|
||||||
loc_expr = Located {
|
|
||||||
region: loc_expr.region,
|
|
||||||
value,
|
|
||||||
};
|
|
||||||
|
|
||||||
match opt_extras {
|
|
||||||
Some(Either::First(loc_args)) => Ok((
|
|
||||||
MadeProgress,
|
|
||||||
expr_in_parens_then_arguments(arena, loc_expr, loc_args, loc_expr_with_extras.region),
|
|
||||||
state,
|
|
||||||
)),
|
|
||||||
Some(Either::Second((spaces_before_equals, equals_indent))) => {
|
|
||||||
// '=' after optional spaces
|
|
||||||
expr_in_parens_then_equals_help(
|
|
||||||
min_indent,
|
|
||||||
loc_expr,
|
|
||||||
spaces_before_equals,
|
|
||||||
equals_indent,
|
|
||||||
loc_expr_with_extras.region.start_col,
|
|
||||||
)
|
|
||||||
.parse(arena, state)
|
|
||||||
}
|
|
||||||
None => Ok((MadeProgress, loc_expr, state)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn expr_in_parens_then_equals_help<'a>(
|
|
||||||
min_indent: u16,
|
|
||||||
loc_expr: Located<Expr<'a>>,
|
|
||||||
spaces_before_equals: &'a [CommentOrNewline],
|
|
||||||
equals_indent: u16,
|
|
||||||
def_start_col: u16,
|
|
||||||
) -> impl Parser<'a, Located<Expr<'a>>, EExpr<'a>> {
|
|
||||||
move |arena, state: State<'a>| {
|
|
||||||
let region = loc_expr.region;
|
|
||||||
|
|
||||||
// Re-parse the Expr as a Pattern.
|
|
||||||
let pattern = match expr_to_pattern_help(arena, &loc_expr.value) {
|
|
||||||
Ok(valid) => valid,
|
|
||||||
Err(_) => {
|
|
||||||
return Err((
|
|
||||||
MadeProgress,
|
|
||||||
EExpr::MalformedPattern(state.line, state.column),
|
|
||||||
state,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Make sure we don't discard the spaces - might be comments in there!
|
|
||||||
let value = if spaces_before_equals.is_empty() {
|
|
||||||
pattern
|
|
||||||
} else {
|
|
||||||
Pattern::SpaceAfter(arena.alloc(pattern), spaces_before_equals)
|
|
||||||
};
|
|
||||||
|
|
||||||
let loc_first_pattern = Located { region, value };
|
|
||||||
|
|
||||||
// Continue parsing the expression as a Def.
|
|
||||||
let (_, spaces_after_equals, state) =
|
|
||||||
space0_e(min_indent, EExpr::Space, EExpr::IndentDefBody).parse(arena, state)?;
|
|
||||||
|
|
||||||
// Use loc_expr_with_extras because we want to include the opening '(' char.
|
|
||||||
let (_, parsed_expr, state) = parse_def_expr_help(
|
|
||||||
min_indent,
|
|
||||||
def_start_col,
|
|
||||||
equals_indent,
|
|
||||||
arena,
|
|
||||||
state,
|
|
||||||
loc_first_pattern,
|
|
||||||
spaces_after_equals,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
Ok((
|
|
||||||
MadeProgress,
|
|
||||||
Located {
|
|
||||||
value: parsed_expr,
|
|
||||||
region,
|
|
||||||
},
|
|
||||||
state,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn expr_in_parens_then_arguments<'a>(
|
|
||||||
arena: &'a Bump,
|
|
||||||
loc_expr: Located<Expr<'a>>,
|
|
||||||
loc_args: Vec<'a, Located<Expr<'a>>>,
|
|
||||||
region: Region,
|
|
||||||
) -> Located<Expr<'a>> {
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
|
|
||||||
Located {
|
|
||||||
region,
|
|
||||||
value: Expr::Apply(
|
|
||||||
arena.alloc(loc_expr),
|
|
||||||
allocated_args.into_bump_slice(),
|
|
||||||
CalledVia::Space,
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_loc_term_better<'a>(
|
fn parse_loc_term_better<'a>(
|
||||||
min_indent: u16,
|
min_indent: u16,
|
||||||
arena: &'a Bump,
|
arena: &'a Bump,
|
||||||
|
@ -1478,32 +1344,6 @@ fn assigned_expr_field_to_pattern_help<'a>(
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_defs_help<'a>(
|
|
||||||
min_indent: u16,
|
|
||||||
) -> impl Parser<'a, Vec<'a, &'a Located<Def<'a>>>, EExpr<'a>> {
|
|
||||||
let parse_def = move |arena, state| {
|
|
||||||
let (_, (spaces, def), state) = and!(
|
|
||||||
backtrackable(space0_e(min_indent, EExpr::Space, EExpr::IndentStart)),
|
|
||||||
loc!(def_help(min_indent))
|
|
||||||
)
|
|
||||||
.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),
|
|
||||||
)
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok((MadeProgress, result, state))
|
|
||||||
};
|
|
||||||
|
|
||||||
zero_or_more!(parse_def)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A definition, consisting of one of these:
|
/// A definition, consisting of one of these:
|
||||||
///
|
///
|
||||||
/// * A type alias using `:`
|
/// * A type alias using `:`
|
||||||
|
@ -1569,307 +1409,8 @@ pub fn def_help_help<'a>(min_indent: u16) -> impl Parser<'a, Vec<'a, Located<Def
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn def_help<'a>(min_indent: u16) -> impl Parser<'a, Def<'a>, EExpr<'a>> {
|
|
||||||
let indented_more = min_indent + 1;
|
|
||||||
|
|
||||||
enum DefKind {
|
|
||||||
Colon,
|
|
||||||
Equal,
|
|
||||||
}
|
|
||||||
|
|
||||||
let def_colon_or_equals = one_of![
|
|
||||||
map!(equals_with_indent_help(), |_| DefKind::Equal),
|
|
||||||
map!(colon_with_indent(), |_| DefKind::Colon),
|
|
||||||
];
|
|
||||||
|
|
||||||
then(
|
|
||||||
// backtrackable because
|
|
||||||
//
|
|
||||||
// i = 0
|
|
||||||
// i
|
|
||||||
//
|
|
||||||
// on the last line, we parse a pattern `i`, but it's not actually a def, so need to
|
|
||||||
// backtrack
|
|
||||||
and!(backtrackable(pattern_help(min_indent)), def_colon_or_equals),
|
|
||||||
move |arena, state, _progress, (loc_pattern, def_kind)| match def_kind {
|
|
||||||
DefKind::Colon => {
|
|
||||||
// Spaces after the ':' (at a normal indentation level) and then the type.
|
|
||||||
// The type itself must be indented more than the pattern and ':'
|
|
||||||
let (_, ann_type, state) = specialize(
|
|
||||||
EExpr::Type,
|
|
||||||
space0_before_e(
|
|
||||||
type_annotation::located_help(indented_more),
|
|
||||||
min_indent,
|
|
||||||
Type::TSpace,
|
|
||||||
Type::TIndentStart,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.parse(arena, state)?;
|
|
||||||
|
|
||||||
// see if there is a definition (assuming the preceding characters were a type
|
|
||||||
// annotation
|
|
||||||
// TODO parse all the spaces, and check if we moved more than >= 1 line down
|
|
||||||
let (_, opt_rest, state) = optional(and!(
|
|
||||||
spaces_till_end_of_line(),
|
|
||||||
body_at_indent_help(min_indent)
|
|
||||||
))
|
|
||||||
.parse(arena, state)?;
|
|
||||||
|
|
||||||
let def = match opt_rest {
|
|
||||||
None => {
|
|
||||||
annotation_or_alias(arena, &loc_pattern.value, loc_pattern.region, ann_type)
|
|
||||||
}
|
|
||||||
Some((opt_comment, (body_pattern, body_expr))) => Def::AnnotatedBody {
|
|
||||||
ann_pattern: arena.alloc(loc_pattern),
|
|
||||||
ann_type: arena.alloc(ann_type),
|
|
||||||
comment: opt_comment,
|
|
||||||
body_pattern: arena.alloc(body_pattern),
|
|
||||||
body_expr: arena.alloc(body_expr),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok((MadeProgress, def, state))
|
|
||||||
}
|
|
||||||
DefKind::Equal => {
|
|
||||||
// Spaces after the '=' (at a normal indentation level) and then the expr.
|
|
||||||
// The expr itself must be indented more than the pattern and '='
|
|
||||||
let (_, body_expr, state) = space0_before_e(
|
|
||||||
move |arena, state| parse_expr_help(indented_more, arena, state),
|
|
||||||
min_indent,
|
|
||||||
EExpr::Space,
|
|
||||||
EExpr::IndentStart,
|
|
||||||
)
|
|
||||||
.parse(arena, state)?;
|
|
||||||
|
|
||||||
Ok((
|
|
||||||
MadeProgress,
|
|
||||||
Def::Body(arena.alloc(loc_pattern), arena.alloc(body_expr)),
|
|
||||||
state,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// PARSER HELPERS
|
// PARSER HELPERS
|
||||||
|
|
||||||
fn pattern_help<'a>(min_indent: u16) -> impl Parser<'a, Located<Pattern<'a>>, EExpr<'a>> {
|
|
||||||
specialize_ref(
|
|
||||||
EExpr::Pattern,
|
|
||||||
space0_after_e(
|
|
||||||
loc_closure_param(min_indent),
|
|
||||||
min_indent,
|
|
||||||
EPattern::Space,
|
|
||||||
EPattern::IndentStart,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn spaces_till_end_of_line<'a>() -> impl Parser<'a, Option<&'a str>, EExpr<'a>> {
|
|
||||||
crate::blankspace::spaces_till_end_of_line(|r, c| {
|
|
||||||
EExpr::Space(parser::BadInputError::HasTab, r, c)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
type Body<'a> = (Located<Pattern<'a>>, Located<Expr<'a>>);
|
|
||||||
|
|
||||||
fn body_at_indent_help<'a>(indent_level: u16) -> impl Parser<'a, Body<'a>, EExpr<'a>> {
|
|
||||||
let indented_more = indent_level + 1;
|
|
||||||
and!(
|
|
||||||
skip_first!(spaces_exactly_e(indent_level), pattern_help(indent_level)),
|
|
||||||
skip_first!(
|
|
||||||
equals_with_indent_help(),
|
|
||||||
// Spaces after the '=' (at a normal indentation level) and then the expr.
|
|
||||||
// The expr itself must be indented more than the pattern and '='
|
|
||||||
space0_before_e(
|
|
||||||
move |arena, state| parse_expr_help(indented_more, arena, state),
|
|
||||||
indent_level,
|
|
||||||
EExpr::Space,
|
|
||||||
EExpr::IndentStart,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn annotation_or_alias<'a>(
|
|
||||||
arena: &'a Bump,
|
|
||||||
pattern: &Pattern<'a>,
|
|
||||||
pattern_region: Region,
|
|
||||||
loc_ann: Located<TypeAnnotation<'a>>,
|
|
||||||
) -> Def<'a> {
|
|
||||||
use crate::ast::Pattern::*;
|
|
||||||
|
|
||||||
match pattern {
|
|
||||||
// Type aliases initially parse as either global tags
|
|
||||||
// or applied global tags, because they are always uppercase
|
|
||||||
GlobalTag(name) => Def::Alias {
|
|
||||||
name: Located {
|
|
||||||
value: name,
|
|
||||||
region: pattern_region,
|
|
||||||
},
|
|
||||||
vars: &[],
|
|
||||||
ann: loc_ann,
|
|
||||||
},
|
|
||||||
Apply(
|
|
||||||
Located {
|
|
||||||
region: pattern_region,
|
|
||||||
value: Pattern::GlobalTag(name),
|
|
||||||
},
|
|
||||||
loc_vars,
|
|
||||||
) => Def::Alias {
|
|
||||||
name: Located {
|
|
||||||
value: name,
|
|
||||||
region: *pattern_region,
|
|
||||||
},
|
|
||||||
vars: loc_vars,
|
|
||||||
ann: loc_ann,
|
|
||||||
},
|
|
||||||
Apply(_, _) => {
|
|
||||||
Def::NotYetImplemented("TODO gracefully handle invalid Apply in type annotation")
|
|
||||||
}
|
|
||||||
SpaceAfter(value, spaces_before) => Def::SpaceAfter(
|
|
||||||
arena.alloc(annotation_or_alias(arena, value, pattern_region, loc_ann)),
|
|
||||||
spaces_before,
|
|
||||||
),
|
|
||||||
SpaceBefore(value, spaces_before) => Def::SpaceBefore(
|
|
||||||
arena.alloc(annotation_or_alias(arena, value, pattern_region, loc_ann)),
|
|
||||||
spaces_before,
|
|
||||||
),
|
|
||||||
Nested(value) => annotation_or_alias(arena, value, pattern_region, loc_ann),
|
|
||||||
|
|
||||||
PrivateTag(_) => {
|
|
||||||
Def::NotYetImplemented("TODO gracefully handle trying to use a private tag as an annotation.")
|
|
||||||
}
|
|
||||||
QualifiedIdentifier { .. } => {
|
|
||||||
Def::NotYetImplemented("TODO gracefully handle trying to annotate a qualified identifier, e.g. `Foo.bar : ...`")
|
|
||||||
}
|
|
||||||
NumLiteral(_) | NonBase10Literal { .. } | FloatLiteral(_) | StrLiteral(_) => {
|
|
||||||
Def::NotYetImplemented("TODO gracefully handle trying to annotate a litera")
|
|
||||||
}
|
|
||||||
Underscore(_) => {
|
|
||||||
Def::NotYetImplemented("TODO gracefully handle trying to give a type annotation to an undrscore")
|
|
||||||
}
|
|
||||||
Malformed(_) => {
|
|
||||||
Def::NotYetImplemented("TODO translate a malformed pattern into a malformed annotation")
|
|
||||||
}
|
|
||||||
MalformedIdent(_, _) => {
|
|
||||||
Def::NotYetImplemented("TODO translate a malformed pattern into a malformed annotation")
|
|
||||||
}
|
|
||||||
Identifier(ident) => {
|
|
||||||
// This is a regular Annotation
|
|
||||||
Def::Annotation(
|
|
||||||
Located {
|
|
||||||
region: pattern_region,
|
|
||||||
value: Pattern::Identifier(ident),
|
|
||||||
},
|
|
||||||
loc_ann,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
RecordDestructure(loc_patterns) => {
|
|
||||||
// This is a record destructure Annotation
|
|
||||||
Def::Annotation(
|
|
||||||
Located {
|
|
||||||
region: pattern_region,
|
|
||||||
value: Pattern::RecordDestructure(loc_patterns),
|
|
||||||
},
|
|
||||||
loc_ann,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
RequiredField(_, _) | OptionalField(_, _) => {
|
|
||||||
unreachable!("This should only be possible inside a record destruture.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn check_def_indent(
|
|
||||||
min_indent: u16,
|
|
||||||
def_start_column: u16,
|
|
||||||
special_token_indent: u16,
|
|
||||||
state: State,
|
|
||||||
) -> Result<State, (Progress, EExpr, State)> {
|
|
||||||
if def_start_column < min_indent || special_token_indent < def_start_column {
|
|
||||||
Err((
|
|
||||||
NoProgress,
|
|
||||||
EExpr::IndentDefBody(state.line, state.column),
|
|
||||||
state,
|
|
||||||
))
|
|
||||||
} else {
|
|
||||||
Ok(state)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_def_expr_help<'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>, EExpr<'a>> {
|
|
||||||
let state = check_def_indent(min_indent, def_start_col, equals_sign_indent, state)?;
|
|
||||||
|
|
||||||
// Indented more beyond the original indent of the entire def-expr.
|
|
||||||
let indented_more = def_start_col + 1;
|
|
||||||
|
|
||||||
then(
|
|
||||||
and!(
|
|
||||||
// Parse the body of the first def. It doesn't need any spaces
|
|
||||||
// around it parsed, because both the subsquent defs and the
|
|
||||||
// final body will have space1_before on them.
|
|
||||||
//
|
|
||||||
// It should be indented more than the original, and it will
|
|
||||||
// end when outdented again.
|
|
||||||
move |arena, state| parse_expr_help(indented_more, arena, state),
|
|
||||||
and!(
|
|
||||||
// Optionally parse additional defs.
|
|
||||||
parse_defs_help(def_start_col),
|
|
||||||
// Parse the final expression that will be returned.
|
|
||||||
// It should be indented the same amount as the original.
|
|
||||||
space0_before_e(
|
|
||||||
move |arena, state: State<'a>| { parse_expr_help(def_start_col, arena, state) },
|
|
||||||
def_start_col,
|
|
||||||
EExpr::Space,
|
|
||||||
EExpr::IndentStart,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
move |arena, state, progress, (loc_first_body, (mut defs, loc_ret))| {
|
|
||||||
let loc_first_body = if spaces_after_equals.is_empty() {
|
|
||||||
loc_first_body
|
|
||||||
} else {
|
|
||||||
Located {
|
|
||||||
value: Expr::SpaceBefore(
|
|
||||||
arena.alloc(loc_first_body.value),
|
|
||||||
spaces_after_equals,
|
|
||||||
),
|
|
||||||
region: loc_first_body.region,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let def_region = Region::span_across(&loc_first_pattern.region, &loc_first_body.region);
|
|
||||||
|
|
||||||
let first_def: Def<'a> =
|
|
||||||
// TODO is there some way to eliminate this .clone() here?
|
|
||||||
Def::Body(arena.alloc(loc_first_pattern.clone()), arena.alloc(loc_first_body));
|
|
||||||
|
|
||||||
let loc_first_def = Located {
|
|
||||||
value: first_def,
|
|
||||||
region: def_region,
|
|
||||||
};
|
|
||||||
|
|
||||||
// for formatting reasons, we must insert the first def first!
|
|
||||||
defs.insert(0, &*arena.alloc(loc_first_def));
|
|
||||||
|
|
||||||
Ok((
|
|
||||||
progress,
|
|
||||||
Expr::Defs(defs.into_bump_slice(), arena.alloc(loc_ret)),
|
|
||||||
state,
|
|
||||||
))
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.parse(arena, state)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn closure_help<'a>(min_indent: u16) -> impl Parser<'a, Expr<'a>, ELambda<'a>> {
|
fn closure_help<'a>(min_indent: u16) -> impl Parser<'a, Expr<'a>, ELambda<'a>> {
|
||||||
map_with_arena!(
|
map_with_arena!(
|
||||||
skip_first!(
|
skip_first!(
|
||||||
|
@ -2258,44 +1799,6 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn equals_with_indent_help<'a>() -> impl Parser<'a, u16, EExpr<'a>> {
|
|
||||||
move |_arena, state: State<'a>| {
|
|
||||||
let indent_col = state.indent_col;
|
|
||||||
let good = state.bytes.starts_with(b"=") && !state.bytes.starts_with(b"==");
|
|
||||||
|
|
||||||
if good {
|
|
||||||
match state.advance_without_indenting_e(1, EExpr::Space) {
|
|
||||||
Err(bad) => Err(bad),
|
|
||||||
Ok(good) => Ok((MadeProgress, indent_col, good)),
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
let equals = EExpr::Equals(state.line, state.column);
|
|
||||||
Err((NoProgress, equals, state))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn colon_with_indent<'a>() -> impl Parser<'a, u16, EExpr<'a>> {
|
|
||||||
move |_arena, state: State<'a>| {
|
|
||||||
let indent_col = state.indent_col;
|
|
||||||
|
|
||||||
if let Some(b':') = state.bytes.get(0) {
|
|
||||||
if let Some(b':') = state.bytes.get(1) {
|
|
||||||
let double = EExpr::DoubleColon(state.line, state.column);
|
|
||||||
Err((NoProgress, double, state))
|
|
||||||
} else {
|
|
||||||
match state.advance_without_indenting_e(1, EExpr::Space) {
|
|
||||||
Err(bad) => Err(bad),
|
|
||||||
Ok(good) => Ok((MadeProgress, indent_col, good)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
let colon = EExpr::Colon(state.line, state.column);
|
|
||||||
Err((NoProgress, colon, state))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn ident_to_expr<'a>(arena: &'a Bump, src: Ident<'a>) -> Expr<'a> {
|
fn ident_to_expr<'a>(arena: &'a Bump, src: Ident<'a>) -> Expr<'a> {
|
||||||
match src {
|
match src {
|
||||||
Ident::GlobalTag(string) => Expr::GlobalTag(string),
|
Ident::GlobalTag(string) => Expr::GlobalTag(string),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue