feat: finish when clauses

This commit is contained in:
rvcas 2022-10-01 21:37:45 -04:00 committed by Lucas
parent 722dc4b477
commit c7c11d1bd5
3 changed files with 215 additions and 19 deletions

View File

@ -25,6 +25,9 @@ pub fn lexer() -> impl Parser<char, Vec<(Token, Span)>, Error = ParseError> {
just("|>").to(Token::Pipe), just("|>").to(Token::Pipe),
just(',').to(Token::Comma), just(',').to(Token::Comma),
just(':').to(Token::Colon), just(':').to(Token::Colon),
just('|').to(Token::Vbar),
just("||").to(Token::VbarVbar),
just("&&").to(Token::AmperAmper),
)); ));
let grouping = choice(( let grouping = choice((

View File

@ -236,7 +236,7 @@ pub fn expr_seq_parser() -> impl Parser<Token, expr::UntypedExpr, Error = ParseE
.ignore_then(pattern_parser()) .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(expr_parser()) .then(expr_parser(r.clone()))
.then(r.clone()) .then(r.clone())
.map_with_span(|(((pattern, annotation), value), then_), span| { .map_with_span(|(((pattern, annotation), value), then_), span| {
expr::UntypedExpr::Try { expr::UntypedExpr::Try {
@ -247,14 +247,16 @@ pub fn expr_seq_parser() -> impl Parser<Token, expr::UntypedExpr, Error = ParseE
annotation, annotation,
} }
}), }),
expr_parser() expr_parser(r.clone())
.then(r.repeated()) .then(r.repeated())
.foldl(|current, next| current.append_in_sequence(next)), .foldl(|current, next| current.append_in_sequence(next)),
)) ))
}) })
} }
pub fn expr_parser() -> impl Parser<Token, expr::UntypedExpr, Error = ParseError> { pub fn expr_parser(
seq_r: Recursive<'_, Token, expr::UntypedExpr, ParseError>,
) -> impl Parser<Token, expr::UntypedExpr, Error = ParseError> + '_ {
recursive(|r| { recursive(|r| {
let string_parser = let string_parser =
select! {Token::String {value} => value}.map_with_span(|value, span| { select! {Token::String {value} => value}.map_with_span(|value, span| {
@ -323,30 +325,38 @@ pub fn expr_parser() -> impl Parser<Token, expr::UntypedExpr, Error = ParseError
}, },
); );
let when_clause_guard_parser = just(Token::If); let block_parser = seq_r.delimited_by(just(Token::LeftBrace), just(Token::RightBrace));
// TODO: do guards later
// let when_clause_guard_parser = just(Token::If);
let when_clause_parser = pattern_parser() let when_clause_parser = pattern_parser()
.separated_by(just(Token::Comma)) .separated_by(just(Token::Comma))
.at_least(1)
.then( .then(
just(Token::Vbar)
.ignore_then(
pattern_parser() pattern_parser()
.separated_by(just(Token::Comma)) .separated_by(just(Token::Comma))
.separated_by(just(Token::Vbar)) .at_least(1),
.allow_leading() )
.repeated()
.or_not(), .or_not(),
) )
.then(when_clause_guard_parser) // TODO: do guards later
// .then(when_clause_guard_parser)
// TODO: add hint "Did you mean to wrap a multi line clause in curly braces?" // TODO: add hint "Did you mean to wrap a multi line clause in curly braces?"
.then_ignore(just(Token::RArrow)) .then_ignore(just(Token::RArrow))
.then(r.clone()) .then(r.clone())
.map_with_span( .map_with_span(|((patterns, alternative_patterns_opt), then), span| {
|(((patterns, alternative_patterns_opt), guard), then), span| ast::UntypedClause { ast::UntypedClause {
location: span, location: span,
pattern: patterns, pattern: patterns,
alternative_patterns: alternative_patterns_opt.unwrap_or_default(), alternative_patterns: alternative_patterns_opt.unwrap_or_default(),
guard, guard: None,
then, then,
}, }
); });
let when_parser = just(Token::When) let when_parser = just(Token::When)
// TODO: If subject is empty we should return ParseErrorType::ExpectedExpr, // TODO: If subject is empty we should return ParseErrorType::ExpectedExpr,
@ -369,6 +379,7 @@ pub fn expr_parser() -> impl Parser<Token, expr::UntypedExpr, Error = ParseError
todo_parser, todo_parser,
list_parser, list_parser,
assignment_parser, assignment_parser,
block_parser,
when_parser, when_parser,
)) ))
.boxed(); .boxed();

View File

@ -52,10 +52,20 @@ fn module() {
} }
pub fn wow2(a: Int){ pub fn wow2(a: Int){
when a is { let b = {
0 -> 3 let x = 4
1 | 2 -> 5
3 if a == 3 -> 9 x + 5
}
when a, b is {
1, 2 -> 3
1 | 4, 5 -> {
let amazing = 5
amazing
}
3 -> 9
_ -> 4 _ -> 4
} }
} }
@ -445,6 +455,178 @@ fn module() {
return_annotation: None, return_annotation: None,
return_type: (), return_type: (),
}, },
ast::UntypedDefinition::Fn {
arguments: vec![ast::Arg {
arg_name: ast::ArgName::Named {
name: "a".to_string(),
location: Span::new(SrcId::empty(), 866..867),
},
location: Span::new(SrcId::empty(), 866..872),
annotation: Some(ast::Annotation::Constructor {
location: Span::new(SrcId::empty(), 869..872),
module: None,
name: "Int".to_string(),
arguments: vec![],
},),
tipo: (),
},],
body: expr::UntypedExpr::Sequence {
location: Span::new(SrcId::empty(), 889..1225),
expressions: vec![
expr::UntypedExpr::Assignment {
location: Span::new(SrcId::empty(), 889..980),
value: Box::new(expr::UntypedExpr::Sequence {
location: Span::new(SrcId::empty(), 915..964),
expressions: vec![
expr::UntypedExpr::Assignment {
location: Span::new(SrcId::empty(), 915..924),
value: Box::new(expr::UntypedExpr::Int {
location: Span::new(SrcId::empty(), 923..924),
value: "4".to_string(),
}),
pattern: ast::Pattern::Var {
location: Span::new(SrcId::empty(), 919..920),
name: "x".to_string(),
},
kind: ast::AssignmentKind::Let,
annotation: None,
},
expr::UntypedExpr::BinOp {
location: Span::new(SrcId::empty(), 959..964),
name: ast::BinOp::AddInt,
left: Box::new(expr::UntypedExpr::Var {
location: Span::new(SrcId::empty(), 959..960),
name: "x".to_string(),
}),
right: Box::new(expr::UntypedExpr::Int {
location: Span::new(SrcId::empty(), 963..964),
value: "5".to_string(),
}),
},
],
}),
pattern: ast::Pattern::Var {
location: Span::new(SrcId::empty(), 893..894),
name: "b".to_string(),
},
kind: ast::AssignmentKind::Let,
annotation: None,
},
expr::UntypedExpr::When {
location: Span::new(SrcId::empty(), 996..1225),
subjects: vec![
expr::UntypedExpr::Var {
location: Span::new(SrcId::empty(), 1001..1002),
name: "a".to_string(),
},
expr::UntypedExpr::Var {
location: Span::new(SrcId::empty(), 1004..1005),
name: "b".to_string(),
},
],
clauses: vec![
ast::Clause {
location: Span::new(SrcId::empty(), 1027..1036),
pattern: vec![
ast::Pattern::Int {
location: Span::new(SrcId::empty(), 1027..1028),
value: "1".to_string(),
},
ast::Pattern::Int {
location: Span::new(SrcId::empty(), 1030..1031),
value: "2".to_string(),
},
],
alternative_patterns: vec![],
guard: None,
then: expr::UntypedExpr::Int {
location: Span::new(SrcId::empty(), 1035..1036),
value: "3".to_string(),
},
},
ast::Clause {
location: Span::new(SrcId::empty(), 1053..1163),
pattern: vec![ast::Pattern::Int {
location: Span::new(SrcId::empty(), 1053..1054),
value: "1".to_string(),
},],
alternative_patterns: vec![vec![
ast::Pattern::Int {
location: Span::new(SrcId::empty(), 1057..1058),
value: "4".to_string(),
},
ast::Pattern::Int {
location: Span::new(SrcId::empty(), 1060..1061),
value: "5".to_string(),
},
],],
guard: None,
then: expr::UntypedExpr::Sequence {
location: Span::new(SrcId::empty(), 1085..1145),
expressions: vec![
expr::UntypedExpr::Assignment {
location: Span::new(SrcId::empty(), 1085..1100),
value: Box::new(expr::UntypedExpr::Int {
location: Span::new(
SrcId::empty(),
1099..1100
),
value: "5".to_string(),
}),
pattern: ast::Pattern::Var {
location: Span::new(
SrcId::empty(),
1089..1096
),
name: "amazing".to_string(),
},
kind: ast::AssignmentKind::Let,
annotation: None,
},
expr::UntypedExpr::Var {
location: Span::new(SrcId::empty(), 1138..1145),
name: "amazing".to_string(),
},
],
},
},
ast::Clause {
location: Span::new(SrcId::empty(), 1180..1186),
pattern: vec![ast::Pattern::Int {
location: Span::new(SrcId::empty(), 1180..1181),
value: "3".to_string(),
},],
alternative_patterns: vec![],
guard: None,
then: expr::UntypedExpr::Int {
location: Span::new(SrcId::empty(), 1185..1186),
value: "9".to_string(),
},
},
ast::Clause {
location: Span::new(SrcId::empty(), 1203..1209),
pattern: vec![ast::Pattern::Discard {
name: "_".to_string(),
location: Span::new(SrcId::empty(), 1203..1204),
},],
alternative_patterns: vec![],
guard: None,
then: expr::UntypedExpr::Int {
location: Span::new(SrcId::empty(), 1208..1209),
value: "4".to_string(),
},
},
],
},
],
},
doc: None,
location: Span::new(SrcId::empty(), 854..1239),
name: "wow2".to_string(),
public: true,
return_annotation: None,
return_type: (),
},
] ]
}, },
); );