mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-28 14:24:45 +00:00
parse closure
This commit is contained in:
parent
f97e8ae7f3
commit
1a7fd57833
4 changed files with 110 additions and 23 deletions
|
@ -110,6 +110,60 @@ where
|
|||
)
|
||||
}
|
||||
|
||||
pub fn space0_around_ee<'a, P, S, E>(
|
||||
parser: P,
|
||||
min_indent: u16,
|
||||
space_problem: fn(BadInputError, Row, Col) -> E,
|
||||
indent_before_problem: fn(Row, Col) -> E,
|
||||
indent_after_problem: fn(Row, Col) -> E,
|
||||
) -> impl Parser<'a, Located<S>, E>
|
||||
where
|
||||
S: Spaceable<'a>,
|
||||
S: 'a,
|
||||
P: Parser<'a, Located<S>, E>,
|
||||
P: 'a,
|
||||
E: 'a,
|
||||
{
|
||||
parser::map_with_arena(
|
||||
and(
|
||||
space0_e(min_indent, space_problem, indent_before_problem),
|
||||
and(
|
||||
parser,
|
||||
space0_e(min_indent, space_problem, indent_after_problem),
|
||||
),
|
||||
),
|
||||
move |arena: &'a Bump,
|
||||
tuples: (
|
||||
&'a [CommentOrNewline<'a>],
|
||||
(Located<S>, &'a [CommentOrNewline<'a>]),
|
||||
)| {
|
||||
let (spaces_before, (loc_val, spaces_after)) = tuples;
|
||||
|
||||
if spaces_before.is_empty() {
|
||||
if spaces_after.is_empty() {
|
||||
loc_val
|
||||
} else {
|
||||
arena
|
||||
.alloc(loc_val.value)
|
||||
.with_spaces_after(spaces_after, loc_val.region)
|
||||
}
|
||||
} else if spaces_after.is_empty() {
|
||||
arena
|
||||
.alloc(loc_val.value)
|
||||
.with_spaces_before(spaces_before, loc_val.region)
|
||||
} else {
|
||||
let wrapped_expr = arena
|
||||
.alloc(loc_val.value)
|
||||
.with_spaces_after(spaces_after, loc_val.region);
|
||||
|
||||
arena
|
||||
.alloc(wrapped_expr.value)
|
||||
.with_spaces_before(spaces_before, wrapped_expr.region)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
/// Parses the given expression with 1 or more (spaces/comments/newlines) before it,
|
||||
/// and also 1 or more spaces after it.
|
||||
/// Returns a Located<Expr> where the location is around the Expr, ignoring the spaces.
|
||||
|
|
|
@ -3,7 +3,8 @@ use crate::ast::{
|
|||
};
|
||||
use crate::blankspace::{
|
||||
line_comment, space0, space0_after, space0_after_e, space0_around, space0_around_e,
|
||||
space0_before, space0_before_e, space0_e, space1, space1_around, space1_before, spaces_exactly,
|
||||
space0_around_ee, space0_before, space0_before_e, space0_e, space1, space1_around,
|
||||
space1_before, spaces_exactly,
|
||||
};
|
||||
use crate::ident::{global_tag_or_ident, ident, lowercase_ident, Ident};
|
||||
use crate::keyword;
|
||||
|
@ -11,8 +12,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, specialize, specialize_ref,
|
||||
then, unexpected, unexpected_eof, word1, word2, EExpr, Either, ParseResult, Parser, State,
|
||||
SyntaxError, When,
|
||||
then, unexpected, unexpected_eof, word1, word2, EExpr, ELambda, Either, ParseResult, Parser,
|
||||
State, SyntaxError, When,
|
||||
};
|
||||
use crate::pattern::loc_closure_param;
|
||||
use crate::type_annotation;
|
||||
|
@ -596,7 +597,13 @@ pub fn def<'a>(min_indent: u16) -> impl Parser<'a, Def<'a>, SyntaxError<'a>> {
|
|||
// PARSER HELPERS
|
||||
|
||||
fn pattern<'a>(min_indent: u16) -> impl Parser<'a, Located<Pattern<'a>>, SyntaxError<'a>> {
|
||||
space0_after(loc_closure_param(min_indent), min_indent)
|
||||
space0_after(
|
||||
specialize(
|
||||
|e, _, _| SyntaxError::Pattern(e),
|
||||
loc_closure_param(min_indent),
|
||||
),
|
||||
min_indent,
|
||||
)
|
||||
}
|
||||
|
||||
fn spaces_then_comment_or_newline<'a>() -> impl Parser<'a, Option<&'a str>, SyntaxError<'a>> {
|
||||
|
@ -971,32 +978,44 @@ fn reserved_keyword<'a>() -> impl Parser<'a, (), SyntaxError<'a>> {
|
|||
}
|
||||
|
||||
fn closure<'a>(min_indent: u16) -> impl Parser<'a, Expr<'a>, SyntaxError<'a>> {
|
||||
specialize(
|
||||
|e, r, c| SyntaxError::Expr(EExpr::Lambda(e, r, c)),
|
||||
closure_help(min_indent),
|
||||
)
|
||||
}
|
||||
|
||||
fn closure_help<'a>(min_indent: u16) -> impl Parser<'a, Expr<'a>, ELambda<'a>> {
|
||||
map_with_arena!(
|
||||
skip_first!(
|
||||
// All closures start with a '\' - e.g. (\x -> x + 1)
|
||||
ascii_char(b'\\'),
|
||||
word1(b'\\', ELambda::Start),
|
||||
// Once we see the '\', we're committed to parsing this as a closure.
|
||||
// It may turn out to be malformed, but it is definitely a closure.
|
||||
optional(and!(
|
||||
// Parse the params
|
||||
attempt!(
|
||||
Attempting::ClosureParams,
|
||||
// Params are comma-separated
|
||||
sep_by1(
|
||||
ascii_char(b','),
|
||||
space0_around(loc_closure_param(min_indent), min_indent)
|
||||
// Params are comma-separated
|
||||
sep_by1(
|
||||
word1(b',', ELambda::Comma),
|
||||
space0_around_ee(
|
||||
specialize(ELambda::Pattern, loc_closure_param(min_indent)),
|
||||
min_indent,
|
||||
ELambda::Space,
|
||||
ELambda::IndentArg,
|
||||
ELambda::IndentArrow
|
||||
)
|
||||
),
|
||||
skip_first!(
|
||||
// Parse the -> which separates params from body
|
||||
ascii_string("->"),
|
||||
word2(b'-', b'>', ELambda::Arrow),
|
||||
// Parse the body
|
||||
attempt!(
|
||||
Attempting::ClosureBody,
|
||||
space0_before(
|
||||
loc!(move |arena, state| parse_expr(min_indent, arena, state)),
|
||||
min_indent,
|
||||
)
|
||||
space0_before_e(
|
||||
specialize_ref(
|
||||
ELambda::Syntax,
|
||||
loc!(move |arena, state| parse_expr(min_indent, arena, state))
|
||||
),
|
||||
min_indent,
|
||||
ELambda::Space,
|
||||
ELambda::IndentBody
|
||||
)
|
||||
)
|
||||
))
|
||||
|
|
|
@ -379,11 +379,28 @@ pub enum EExpr<'a> {
|
|||
|
||||
When(When<'a>, Row, Col),
|
||||
|
||||
Lambda(ELambda<'a>, Row, Col),
|
||||
|
||||
// EInParens(PInParens<'a>, Row, Col),
|
||||
IndentStart(Row, Col),
|
||||
IndentEnd(Row, Col),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum ELambda<'a> {
|
||||
Space(BadInputError, Row, Col),
|
||||
Start(Row, Col),
|
||||
Arrow(Row, Col),
|
||||
Comma(Row, Col),
|
||||
// TODO make EEXpr
|
||||
Pattern(EPattern<'a>, Row, Col),
|
||||
Syntax(&'a SyntaxError<'a>, Row, Col),
|
||||
|
||||
IndentArrow(Row, Col),
|
||||
IndentBody(Row, Col),
|
||||
IndentArg(Row, Col),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum When<'a> {
|
||||
Space(BadInputError, Row, Col),
|
||||
|
|
|
@ -26,11 +26,8 @@ pub enum PatternType {
|
|||
|
||||
pub fn loc_closure_param<'a>(
|
||||
min_indent: u16,
|
||||
) -> impl Parser<'a, Located<Pattern<'a>>, SyntaxError<'a>> {
|
||||
specialize(
|
||||
|e, _, _| SyntaxError::Pattern(e),
|
||||
move |arena, state| parse_closure_param(arena, state, min_indent),
|
||||
)
|
||||
) -> impl Parser<'a, Located<Pattern<'a>>, EPattern<'a>> {
|
||||
move |arena, state| parse_closure_param(arena, state, min_indent)
|
||||
}
|
||||
|
||||
fn parse_closure_param<'a>(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue