add as for list rest patterns

This commit is contained in:
Folkert 2022-12-30 23:17:29 +01:00
parent aff70bb6bd
commit 8305d078a0
No known key found for this signature in database
GPG key ID: 1F17F6FFD112B97C
4 changed files with 44 additions and 14 deletions

View file

@ -60,7 +60,7 @@ impl<'a> Formattable for Pattern<'a> {
Pattern::As(pattern, pattern_as) => pattern.is_multiline() || pattern_as.is_multiline(),
Pattern::ListRest (opt_pattern_as) => match opt_pattern_as {
None => false,
Some(pattern_as) => pattern_as.is_multiline(),
Some((list_rest_spaces, pattern_as)) => list_rest_spaces.iter().any(|s| s.is_comment()) || pattern_as.is_multiline(),
},
Pattern::Identifier(_)
@ -232,7 +232,10 @@ impl<'a> Formattable for Pattern<'a> {
buf.indent(indent);
buf.push_str("..");
if let Some(pattern_as) = opt_pattern_as {
if let Some((list_rest_spaces, pattern_as)) = opt_pattern_as {
// these spaces "belong" to the `..`, which can never be multiline
fmt_comments_only(buf, list_rest_spaces.iter(), NewlineAt::Bottom, indent);
pattern_as.format(buf, indent + INDENT);
}
}

View file

@ -712,7 +712,7 @@ pub enum Pattern<'a> {
/// A list-rest pattern ".."
/// Can only occur inside of a [Pattern::List]
ListRest(Option<PatternAs<'a>>),
ListRest(Option<(&'a [CommentOrNewline<'a>], PatternAs<'a>)>),
As(&'a Loc<Pattern<'a>>, PatternAs<'a>),
@ -950,7 +950,7 @@ impl<'a> Pattern<'a> {
ListRest(pattern_as) => match other {
ListRest(other_pattern_as) => match (pattern_as, other_pattern_as) {
(Some(a), Some(b)) => a.equivalent(b),
(Some((_, a)), Some((_, b))) => a.equivalent(b),
_ => false,
},
_ => false,

View file

@ -555,9 +555,9 @@ pub enum EExpect<'a> {
pub enum EPattern<'a> {
Record(PRecord<'a>, Position),
List(PList<'a>, Position),
Underscore(Position),
As(Position),
AsKeyword(Position),
AsIdentifier(Position),
Underscore(Position),
NotAPattern(Position),
Start(Position),

View file

@ -48,10 +48,11 @@ pub fn loc_pattern_help<'a>() -> impl Parser<'a, Loc<Pattern<'a>>, EPattern<'a>>
let pattern_state = state.clone();
let (pattern_spaces, state) = match space0_e(EPattern::As).parse(arena, state, min_indent) {
Err(_) => return Ok((MadeProgress, pattern, pattern_state)),
Ok((_, pattern_spaces, state)) => (pattern_spaces, state),
};
let (pattern_spaces, state) =
match space0_e(EPattern::AsKeyword).parse(arena, state, min_indent) {
Err(_) => return Ok((MadeProgress, pattern, pattern_state)),
Ok((_, pattern_spaces, state)) => (pattern_spaces, state),
};
match pattern_as().parse(arena, state, min_indent) {
Err((progress, e)) => match progress {
@ -90,7 +91,7 @@ fn loc_pattern_help_help<'a>() -> impl Parser<'a, Loc<Pattern<'a>>, EPattern<'a>
fn pattern_as<'a>() -> impl Parser<'a, PatternAs<'a>, EPattern<'a>> {
move |arena, state: State<'a>, min_indent| {
let (_, _, state) =
parser::keyword_e(keyword::AS, EPattern::As).parse(arena, state, min_indent)?;
parser::keyword_e(keyword::AS, EPattern::AsKeyword).parse(arena, state, min_indent)?;
let (_, spaces, state) =
space0_e(EPattern::AsIdentifier).parse(arena, state, min_indent)?;
@ -282,9 +283,35 @@ fn three_list_rest_pattern_error<'a>() -> impl Parser<'a, Loc<Pattern<'a>>, PLis
}
fn list_rest_pattern<'a>() -> impl Parser<'a, Loc<Pattern<'a>>, PList<'a>> {
map!(loc!(word2(b'.', b'.', PList::Open)), |loc_word: Loc<_>| {
loc_word.map(|_| Pattern::ListRest(None))
})
move |arena: &'a Bump, state: State<'a>, min_indent: u32| {
let (_, loc_word, state) =
loc!(word2(b'.', b'.', PList::Open)).parse(arena, state, min_indent)?;
let no_as = Loc::at(loc_word.region, Pattern::ListRest(None));
let pattern_state = state.clone();
let (pattern_spaces, state) =
match space0_e(EPattern::AsKeyword).parse(arena, state, min_indent) {
Err(_) => return Ok((MadeProgress, no_as, pattern_state)),
Ok((_, pattern_spaces, state)) => (pattern_spaces, state),
};
let position = state.pos();
match pattern_as().parse(arena, state, min_indent) {
Err((progress, e)) => match progress {
MadeProgress => Err((MadeProgress, PList::Pattern(arena.alloc(e), position))),
NoProgress => Ok((MadeProgress, no_as, pattern_state)),
},
Ok((_, pattern_as, state)) => {
let region = Region::span_across(&loc_word.region, &pattern_as.identifier.region);
let as_pattern = Pattern::ListRest(Some((pattern_spaces, pattern_as)));
Ok((MadeProgress, Loc::at(region, as_pattern), state))
}
}
}
}
fn loc_ident_pattern_help<'a>(