feat: lists and flatten sequences

This commit is contained in:
rvcas 2022-09-29 23:28:20 -04:00 committed by Lucas
parent 3208dab718
commit 43b147a9e0
2 changed files with 141 additions and 51 deletions

View File

@ -277,17 +277,42 @@ impl UntypedExpr {
..self.location() ..self.location()
}; };
match self { match (self.clone(), next.clone()) {
(
Self::Sequence { Self::Sequence {
mut expressions, .. expressions: mut current_expressions,
} => { ..
expressions.push(next); },
Self::Sequence {
expressions: mut next_expressions,
..
},
) => {
current_expressions.append(&mut next_expressions);
Self::Sequence { Self::Sequence {
location, location,
expressions, expressions: current_expressions,
} }
} }
_ => Self::Sequence { (
_,
Self::Sequence {
expressions: mut next_expressions,
..
},
) => {
let mut current_expressions = vec![self];
current_expressions.append(&mut next_expressions);
Self::Sequence {
location,
expressions: current_expressions,
}
}
(_, _) => Self::Sequence {
location, location,
expressions: vec![self, next], expressions: vec![self, next],
}, },

View File

@ -249,18 +249,67 @@ pub fn expr_seq_parser() -> impl Parser<Token, expr::UntypedExpr, Error = ParseE
}), }),
expr_parser() expr_parser()
.then(r.repeated()) .then(r.repeated())
.map_with_span(|(expr, exprs), _span| { .foldl(|current, next| current.append_in_sequence(next)),
exprs
.into_iter()
.fold(expr, |acc, elem| acc.append_in_sequence(elem))
}),
)) ))
}) })
} }
pub fn expr_parser() -> impl Parser<Token, expr::UntypedExpr, Error = ParseError> { pub fn expr_parser() -> impl Parser<Token, expr::UntypedExpr, Error = ParseError> {
recursive(|r| { recursive(|r| {
let assignment_parser = pattern_parser() let string_parser =
select! {Token::String {value} => value}.map_with_span(|value, span| {
expr::UntypedExpr::String {
location: span,
value,
}
});
let int_parser = select! { Token::Int {value} => value}.map_with_span(|value, span| {
expr::UntypedExpr::Int {
location: span,
value,
}
});
let var_parser = select! {
Token::Name { name } => name,
Token::UpName { name } => name,
}
.map_with_span(|name, span| expr::UntypedExpr::Var {
location: span,
name,
});
let todo_parser = just(Token::Todo)
.ignore_then(
select! {Token::String {value} => value}
.delimited_by(just(Token::LeftParen), just(Token::RightParen))
.or_not(),
)
.map_with_span(|label, span| expr::UntypedExpr::Todo {
kind: TodoKind::Keyword,
location: span,
label,
});
let list_parser = just(Token::LeftSquare)
.ignore_then(r.clone().separated_by(just(Token::Comma)).allow_trailing())
.then(
just(Token::DotDot)
.ignore_then(r.clone())
.map(Box::new)
.or_not(),
)
.then_ignore(just(Token::RightSquare))
// TODO: check if tail.is_some and elements.is_empty then return ListSpreadWithoutElements error
.map_with_span(|(elements, tail), span| expr::UntypedExpr::List {
location: span,
elements,
tail,
});
let assignment_parser = just(Token::Let)
.ignore_then(pattern_parser())
.then(just(Token::Colon).ignore_then(type_parser()).or_not()) .then(just(Token::Colon).ignore_then(type_parser()).or_not())
.then_ignore(just(Token::Equal)) .then_ignore(just(Token::Equal))
.then(r) .then(r)
@ -275,40 +324,12 @@ pub fn expr_parser() -> impl Parser<Token, expr::UntypedExpr, Error = ParseError
); );
let expr_unit_parser = choice(( let expr_unit_parser = choice((
select! {Token::String {value} => value}.map_with_span(|value, span| { string_parser,
expr::UntypedExpr::String { int_parser,
location: span, var_parser,
value, todo_parser,
} list_parser,
}), assignment_parser,
select! { Token::Int {value} => value}.map_with_span(|value, span| {
expr::UntypedExpr::Int {
location: span,
value,
}
}),
select! {
Token::Name { name } => name,
Token::UpName { name } => name,
}
.map_with_span(|name, span| expr::UntypedExpr::Var {
location: span,
name,
}),
just(Token::Todo)
.ignore_then(
select! {Token::String {value} => value}
.delimited_by(just(Token::LeftParen), just(Token::RightParen))
.or_not(),
)
.map_with_span(|label, span| expr::UntypedExpr::Todo {
kind: TodoKind::Keyword,
location: span,
label,
}),
just(Token::Let)
.then(assignment_parser)
.map(|(_, assign)| assign),
)) ))
.boxed(); .boxed();
@ -659,6 +680,10 @@ mod tests {
|> add_one |> add_one
|> add_one |> add_one
let thing = [ 1, 2, a ]
let idk = thing
y y
} }
"#; "#;
@ -954,10 +979,10 @@ mod tests {
tipo: (), tipo: (),
},], },],
body: expr::UntypedExpr::Sequence { body: expr::UntypedExpr::Sequence {
location: Span::new(SrcId::empty(), 645..741), location: Span::new(SrcId::empty(), 641..819),
expressions: vec![ expressions: vec![
expr::UntypedExpr::Assignment { expr::UntypedExpr::Assignment {
location: Span::new(SrcId::empty(), 645..724), location: Span::new(SrcId::empty(), 641..724),
value: Box::new(expr::UntypedExpr::PipeLine { value: Box::new(expr::UntypedExpr::PipeLine {
expressions: vec1::vec1![ expressions: vec1::vec1![
expr::UntypedExpr::BinOp { expr::UntypedExpr::BinOp {
@ -989,14 +1014,54 @@ mod tests {
kind: ast::AssignmentKind::Let, kind: ast::AssignmentKind::Let,
annotation: None, annotation: None,
}, },
expr::UntypedExpr::Assignment {
location: Span::new(SrcId::empty(), 748..771),
value: Box::new(expr::UntypedExpr::List {
location: Span::new(SrcId::empty(), 760..771),
elements: vec![
expr::UntypedExpr::Int {
location: Span::new(SrcId::empty(), 762..763),
value: "1".to_string(),
},
expr::UntypedExpr::Int {
location: Span::new(SrcId::empty(), 765..766),
value: "2".to_string(),
},
expr::UntypedExpr::Var { expr::UntypedExpr::Var {
location: Span::new(SrcId::empty(), 740..741), location: Span::new(SrcId::empty(), 768..769),
name: "a".to_string(),
},
],
tail: None,
}),
pattern: ast::Pattern::Var {
location: Span::new(SrcId::empty(), 752..757),
name: "thing".to_string(),
},
kind: ast::AssignmentKind::Let,
annotation: None,
},
expr::UntypedExpr::Assignment {
location: Span::new(SrcId::empty(), 787..802),
value: Box::new(expr::UntypedExpr::Var {
location: Span::new(SrcId::empty(), 797..802),
name: "thing".to_string(),
}),
pattern: ast::Pattern::Var {
location: Span::new(SrcId::empty(), 791..794),
name: "idk".to_string(),
},
kind: ast::AssignmentKind::Let,
annotation: None,
},
expr::UntypedExpr::Var {
location: Span::new(SrcId::empty(), 818..819),
name: "y".to_string(), name: "y".to_string(),
}, },
], ],
}, },
doc: None, doc: None,
location: Span::new(SrcId::empty(), 606..755), location: Span::new(SrcId::empty(), 606..833),
name: "wow".to_string(), name: "wow".to_string(),
public: true, public: true,
return_annotation: None, return_annotation: None,