Parse closures

This commit is contained in:
Richard Feldman 2019-09-20 00:26:49 -04:00
parent 8fe4c749a2
commit 2c61817c7c
3 changed files with 89 additions and 10 deletions

View file

@ -50,7 +50,7 @@ pub enum Expr<'a> {
// Pattern Matching // Pattern Matching
When(&'a [(Loc<Pattern<'a>>, Loc<Expr<'a>>)]), When(&'a [(Loc<Pattern<'a>>, Loc<Expr<'a>>)]),
Closure(&'a (&'a [Loc<Pattern<'a>>], Loc<Expr<'a>>)), Closure(&'a (Loc<Vec<'a, Loc<Pattern<'a>>>>, Loc<Expr<'a>>)),
// /// basically Assign(Vec<(Loc<Pattern>, Loc<Expr>)>, Loc<Expr>) // /// basically Assign(Vec<(Loc<Pattern>, Loc<Expr>)>, Loc<Expr>)
// Assign(&'a (&'a [(Loc<Pattern<'a>>, Loc<Expr<'a>>)], Loc<Expr<'a>>)), // Assign(&'a (&'a [(Loc<Pattern<'a>>, Loc<Expr<'a>>)], Loc<Expr<'a>>)),
@ -87,9 +87,9 @@ pub enum Pattern<'a> {
// Identifier // Identifier
Identifier(&'a str), Identifier(&'a str),
// Variant // Variant, optionally qualified
Variant(&'a VariantName), Variant(&'a [&'a str], &'a VariantName),
AppliedVariant(&'a (Loc<&'a VariantName>, [Loc<Pattern<'a>>])), Apply(&'a (Loc<&'a Pattern<'a>>, [Loc<Pattern<'a>>])),
// Literal // Literal
IntLiteral(i64), IntLiteral(i64),
@ -205,7 +205,7 @@ fn pattern_size() {
// better performance, due to more data structures being inlinable, // better performance, due to more data structures being inlinable,
// and therefore having fewer pointers to chase. This seems worth // and therefore having fewer pointers to chase. This seems worth
// investigating as well. // investigating as well.
std::mem::size_of::<usize>() * 4 std::mem::size_of::<usize>() * 5
); );
} }

View file

@ -17,7 +17,7 @@ use parse::blankspace::{space0, space0_around, space0_before, space1_before};
use parse::ident::{ident, Ident}; use parse::ident::{ident, Ident};
use parse::number_literal::number_literal; use parse::number_literal::number_literal;
use parse::parser::{ use parse::parser::{
and, attempt, between, char, either, loc, map, map_with_arena, one_of2, one_of4, one_of8, and, attempt, between, char, either, loc, map, map_with_arena, one_of2, one_of4, one_of9,
one_or_more, optional, sep_by0, skip_first, skip_second, string, unexpected, unexpected_eof, one_or_more, optional, sep_by0, skip_first, skip_second, string, unexpected, unexpected_eof,
Either, ParseResult, Parser, State, Either, ParseResult, Parser, State,
}; };
@ -36,11 +36,12 @@ fn loc_parse_expr_body_without_operators<'a>(
arena: &'a Bump, arena: &'a Bump,
state: State<'a>, state: State<'a>,
) -> ParseResult<'a, Located<Expr<'a>>> { ) -> ParseResult<'a, Located<Expr<'a>>> {
one_of8( one_of9(
loc_parenthetical_expr(min_indent), loc_parenthetical_expr(min_indent),
loc(string_literal()), loc(string_literal()),
loc(number_literal()), loc(number_literal()),
loc(record_literal(min_indent)), loc(record_literal(min_indent)),
loc(closure(min_indent)),
loc(list_literal(min_indent)), loc(list_literal(min_indent)),
loc(when(min_indent)), loc(when(min_indent)),
loc(conditional(min_indent)), loc(conditional(min_indent)),
@ -156,9 +157,25 @@ fn loc_function_arg<'a>(min_indent: u16) -> impl Parser<'a, Located<Expr<'a>>> {
} }
fn closure<'a>(min_indent: u16) -> impl Parser<'a, Expr<'a>> { fn closure<'a>(min_indent: u16) -> impl Parser<'a, Expr<'a>> {
map(skip_first(char('\\'), one_or_more(loc_closure_param(min_indent))), map_with_arena(
|params skip_first(
) char('\\'),
and(
loc(one_or_more(space0_around(
loc_closure_param(min_indent),
min_indent,
))),
skip_first(
string("->"),
space0_before(
loc(move |arena, state| parse_expr(min_indent, arena, state)),
min_indent,
),
),
),
),
|arena, (params, loc_body)| Expr::Closure(arena.alloc((params, loc_body))),
)
} }
fn loc_closure_param<'a>(min_indent: u16) -> impl Parser<'a, Located<Pattern<'a>>> { fn loc_closure_param<'a>(min_indent: u16) -> impl Parser<'a, Located<Pattern<'a>>> {

View file

@ -907,3 +907,65 @@ where
} }
} }
} }
pub fn one_of9<'a, P1, P2, P3, P4, P5, P6, P7, P8, P9, A>(
p1: P1,
p2: P2,
p3: P3,
p4: P4,
p5: P5,
p6: P6,
p7: P7,
p8: P8,
p9: P9,
) -> impl Parser<'a, A>
where
P1: Parser<'a, A>,
P2: Parser<'a, A>,
P3: Parser<'a, A>,
P4: Parser<'a, A>,
P5: Parser<'a, A>,
P6: Parser<'a, A>,
P7: Parser<'a, A>,
P8: Parser<'a, A>,
P9: Parser<'a, A>,
{
move |arena: &'a Bump, state: State<'a>| {
let original_attempting = state.attempting;
match p1.parse(arena, state) {
valid @ Ok(_) => valid,
Err((_, state)) => match p2.parse(arena, state) {
valid @ Ok(_) => valid,
Err((_, state)) => match p3.parse(arena, state) {
valid @ Ok(_) => valid,
Err((_, state)) => match p4.parse(arena, state) {
valid @ Ok(_) => valid,
Err((_, state)) => match p5.parse(arena, state) {
valid @ Ok(_) => valid,
Err((_, state)) => match p6.parse(arena, state) {
valid @ Ok(_) => valid,
Err((_, state)) => match p7.parse(arena, state) {
valid @ Ok(_) => valid,
Err((_, state)) => match p8.parse(arena, state) {
valid @ Ok(_) => valid,
Err((_, state)) => match p9.parse(arena, state) {
valid @ Ok(_) => valid,
Err((fail, state)) => Err((
Fail {
attempting: original_attempting,
..fail
},
state,
)),
},
},
},
},
},
},
},
},
}
}
}