Implement initial tuple syntax

This commit is contained in:
Joshua Warner 2022-11-05 17:39:13 -04:00
parent 9abed3472a
commit 1753c9cf5b
No known key found for this signature in database
GPG key ID: 89AD497003F93FDD
11 changed files with 152 additions and 52 deletions

View file

@ -12,7 +12,7 @@ use crate::parser::{
self, backtrackable, increment_min_indent, line_min_indent, optional, reset_min_indent,
sep_by1, sep_by1_e, set_min_indent, specialize, specialize_ref, then, trailing_sep_by0, word1,
word1_indent, word2, EClosure, EExpect, EExpr, EIf, EInParens, EList, ENumber, EPattern,
ERecord, EString, EType, EWhen, Either, ParseResult, Parser,
ERecord, EString, ETuple, EType, EWhen, Either, ParseResult, Parser,
};
use crate::pattern::{loc_closure_param, loc_has_parser};
use crate::state::State;
@ -81,72 +81,79 @@ pub fn expr_help<'a>() -> impl Parser<'a, Expr<'a>, EExpr<'a>> {
}
fn loc_expr_in_parens_help<'a>() -> impl Parser<'a, Loc<Expr<'a>>, EInParens<'a>> {
move |arena, state, min_indent| {
let (_, loc_expr, state) =
loc_expr_in_parens_help_help().parse(arena, state, min_indent)?;
Ok((
MadeProgress,
Loc {
region: loc_expr.region,
value: Expr::ParensAround(arena.alloc(loc_expr.value)),
},
state,
))
}
}
fn loc_expr_in_parens_help_help<'a>() -> impl Parser<'a, Loc<Expr<'a>>, EInParens<'a>> {
between!(
word1(b'(', EInParens::Open),
space0_around_ee(
specialize_ref(EInParens::Expr, loc_expr()),
EInParens::IndentOpen,
then(
loc!(collection_trailing_sep_e!(
word1(b'(', EInParens::Open),
specialize_ref(EInParens::Expr, loc_expr_no_multi_backpassing()),
word1(b',', EInParens::End),
word1(b')', EInParens::End),
EInParens::Open,
EInParens::IndentEnd,
),
word1(b')', EInParens::End)
Expr::SpaceBefore
)),
move |arena, state, _, loc_elements| {
let elements = loc_elements.value;
let region = loc_elements.region;
if elements.len() > 1 {
Ok((
MadeProgress,
Loc::at(region, Expr::List(elements.ptrify_items(arena))),
state,
))
} else if elements.is_empty() {
Err((NoProgress, EInParens::Empty(state.pos()), state))
} else {
// TODO: don't discard comments before/after
// (stored in the Collection)
Ok((
MadeProgress,
Loc::at(
elements.items[0].region,
Expr::ParensAround(&elements.items[0].value),
),
state,
))
}
},
)
.trace("in_parens")
}
fn loc_expr_in_parens_etc_help<'a>() -> impl Parser<'a, Loc<Expr<'a>>, EExpr<'a>> {
move |arena, state: State<'a>, min_indent: u32| {
let parser = loc!(and!(
map_with_arena!(
loc!(and!(
specialize(EExpr::InParens, loc_expr_in_parens_help()),
one_of![record_field_access_chain(), |a, s, _m| Ok((
NoProgress,
Vec::new_in(a),
s
))]
));
let (
_,
Loc {
)),
move |arena: &'a Bump, value: Loc<(Loc<Expr<'a>>, Vec<'a, &'a str>)>| {
let Loc {
mut region,
value: (loc_expr, field_accesses),
},
state,
) = parser.parse(arena, state, min_indent)?;
} = value;
let mut value = loc_expr.value;
let mut value = loc_expr.value;
// if there are field accesses, include the parentheses in the region
// otherwise, don't include the parentheses
if field_accesses.is_empty() {
region = loc_expr.region;
} else {
for field in field_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);
// if there are field accesses, include the parentheses in the region
// otherwise, don't include the parentheses
if field_accesses.is_empty() {
region = loc_expr.region;
} else {
for field in field_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::at(region, value)
}
let loc_expr = Loc::at(region, value);
Ok((MadeProgress, loc_expr, state))
}
)
}
fn record_field_access_chain<'a>() -> impl Parser<'a, Vec<'a, &'a str>, EExpr<'a>> {
@ -1845,6 +1852,10 @@ fn expr_to_pattern_help<'a>(arena: &'a Bump, expr: &Expr<'a>) -> Result<Pattern<
Ok(Pattern::RecordDestructure(patterns))
}
Expr::Tuple(_fields) => {
todo!("tuple patterns")
}
&Expr::Float(string) => Ok(Pattern::FloatLiteral(string)),
&Expr::Num(string) => Ok(Pattern::NumLiteral(string)),
Expr::NonBase10Int {
@ -2435,6 +2446,13 @@ fn list_literal_help<'a>() -> impl Parser<'a, Expr<'a>, EList<'a>> {
.trace("list_literal")
}
pub fn tuple_value_field<'a>() -> impl Parser<'a, Loc<Expr<'a>>, ETuple<'a>> {
space0_before_e(
specialize_ref(ETuple::Expr, loc_expr_no_multi_backpassing()),
ETuple::IndentEnd,
)
}
pub fn record_value_field<'a>() -> impl Parser<'a, AssignedField<'a, Expr<'a>>, ERecord<'a>> {
use AssignedField::*;