mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-01 19:02:19 +00:00
Merge pull request #4414 from roc-lang/i4412
Parse and format list patterns
This commit is contained in:
commit
67a8bbd6a2
13 changed files with 621 additions and 11 deletions
|
@ -653,6 +653,13 @@ pub enum Pattern<'a> {
|
|||
Underscore(&'a str),
|
||||
SingleQuote(&'a str),
|
||||
|
||||
/// A list pattern like [_, x, ..]
|
||||
List(Collection<'a, Loc<Pattern<'a>>>),
|
||||
|
||||
/// A list-rest pattern ".."
|
||||
/// Can only occur inside of a [Pattern::List]
|
||||
ListRest,
|
||||
|
||||
// Space
|
||||
SpaceBefore(&'a Pattern<'a>, &'a [CommentOrNewline<'a>]),
|
||||
SpaceAfter(&'a Pattern<'a>, &'a [CommentOrNewline<'a>]),
|
||||
|
|
|
@ -107,7 +107,8 @@ impl_space_problem! {
|
|||
EWhen<'a>,
|
||||
EAbility<'a>,
|
||||
PInParens<'a>,
|
||||
PRecord<'a>
|
||||
PRecord<'a>,
|
||||
PList<'a>
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
|
@ -519,6 +520,7 @@ pub enum EExpect<'a> {
|
|||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum EPattern<'a> {
|
||||
Record(PRecord<'a>, Position),
|
||||
List(PList<'a>, Position),
|
||||
Underscore(Position),
|
||||
|
||||
Start(Position),
|
||||
|
@ -553,6 +555,20 @@ pub enum PRecord<'a> {
|
|||
IndentEnd(Position),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum PList<'a> {
|
||||
End(Position),
|
||||
Open(Position),
|
||||
|
||||
Rest(Position),
|
||||
Pattern(&'a EPattern<'a>, Position),
|
||||
|
||||
Space(BadInputError, Position),
|
||||
|
||||
IndentOpen(Position),
|
||||
IndentEnd(Position),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum PInParens<'a> {
|
||||
End(Position),
|
||||
|
|
|
@ -3,8 +3,8 @@ use crate::blankspace::{space0_around_ee, space0_before_e, space0_e};
|
|||
use crate::ident::{lowercase_ident, parse_ident, Ident};
|
||||
use crate::parser::Progress::{self, *};
|
||||
use crate::parser::{
|
||||
backtrackable, optional, specialize, specialize_ref, then, word1, EPattern, PInParens, PRecord,
|
||||
ParseResult, Parser,
|
||||
backtrackable, optional, specialize, specialize_ref, then, word1, word2, word3, EPattern,
|
||||
PInParens, PList, PRecord, ParseResult, Parser,
|
||||
};
|
||||
use crate::state::State;
|
||||
use bumpalo::collections::string::String;
|
||||
|
@ -59,6 +59,7 @@ pub fn loc_pattern_help<'a>(min_indent: u32) -> impl Parser<'a, Loc<Pattern<'a>>
|
|||
EPattern::Record,
|
||||
crate::pattern::record_pattern_help(min_indent)
|
||||
)),
|
||||
loc!(specialize(EPattern::List, list_pattern_help(min_indent))),
|
||||
loc!(number_pattern_help()),
|
||||
loc!(string_pattern_help()),
|
||||
loc!(single_quote_pattern_help()),
|
||||
|
@ -202,6 +203,49 @@ fn single_quote_pattern_help<'a>() -> impl Parser<'a, Pattern<'a>, EPattern<'a>>
|
|||
)
|
||||
}
|
||||
|
||||
fn list_pattern_help<'a>(min_indent: u32) -> impl Parser<'a, Pattern<'a>, PList<'a>> {
|
||||
move |arena, state| {
|
||||
let (_, pats, state) = collection_trailing_sep_e!(
|
||||
word1(b'[', PList::Open),
|
||||
list_element_pattern(min_indent),
|
||||
word1(b',', PList::End),
|
||||
word1(b']', PList::End),
|
||||
min_indent,
|
||||
PList::Open,
|
||||
PList::IndentEnd,
|
||||
Pattern::SpaceBefore
|
||||
)
|
||||
.parse(arena, state)?;
|
||||
|
||||
let result = Pattern::List(pats);
|
||||
|
||||
Ok((MadeProgress, result, state))
|
||||
}
|
||||
}
|
||||
|
||||
fn list_element_pattern<'a>(min_indent: u32) -> impl Parser<'a, Loc<Pattern<'a>>, PList<'a>> {
|
||||
one_of!(
|
||||
three_list_rest_pattern_error(),
|
||||
list_rest_pattern(),
|
||||
specialize_ref(PList::Pattern, loc_pattern_help(min_indent)),
|
||||
)
|
||||
}
|
||||
|
||||
fn three_list_rest_pattern_error<'a>() -> impl Parser<'a, Loc<Pattern<'a>>, PList<'a>> {
|
||||
then(
|
||||
loc!(word3(b'.', b'.', b'.', PList::Rest)),
|
||||
|_arena, state, _progress, word| {
|
||||
Err((MadeProgress, PList::Rest(word.region.start()), state))
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
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)
|
||||
})
|
||||
}
|
||||
|
||||
fn loc_ident_pattern_help<'a>(
|
||||
min_indent: u32,
|
||||
can_have_arguments: bool,
|
||||
|
@ -354,11 +398,9 @@ fn lowercase_ident_pattern<'a>(
|
|||
fn record_pattern_help<'a>(min_indent: u32) -> impl Parser<'a, Pattern<'a>, PRecord<'a>> {
|
||||
move |arena, state| {
|
||||
let (_, fields, state) = collection_trailing_sep_e!(
|
||||
// word1_check_indent!(b'{', PRecord::Open, min_indent, PRecord::IndentOpen),
|
||||
word1(b'{', PRecord::Open),
|
||||
record_pattern_field(min_indent),
|
||||
word1(b',', PRecord::End),
|
||||
// word1_check_indent!(b'}', PRecord::End, min_indent, PRecord::IndentEnd),
|
||||
word1(b'}', PRecord::End),
|
||||
min_indent,
|
||||
PRecord::Open,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue