mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-01 07:41:12 +00:00
Add match keyword
This commit is contained in:
parent
7cb0facacd
commit
878513b1ea
3 changed files with 43 additions and 6 deletions
10
src/eval.rs
10
src/eval.rs
|
@ -80,13 +80,19 @@ pub fn scoped_eval(expr: Expr, vars: &HashMap<String, Rc<Expr>>) -> Expr {
|
|||
}
|
||||
},
|
||||
|
||||
Operator(left_arg, op, right_arg) =>
|
||||
Operator(left_arg, op, right_arg) => {
|
||||
eval_operator(
|
||||
&scoped_eval(*left_arg, vars),
|
||||
&op,
|
||||
&scoped_eval(*right_arg, vars)
|
||||
)
|
||||
,
|
||||
},
|
||||
|
||||
Match(condition, branches) => {
|
||||
match scoped_eval(*condition, vars) {
|
||||
_ => { panic!("TODO implement eval for match-expressions"); }
|
||||
}
|
||||
},
|
||||
|
||||
If(condition, if_true, if_false) => {
|
||||
match scoped_eval(*condition, vars) {
|
||||
|
|
|
@ -22,8 +22,11 @@ pub enum Expr {
|
|||
// Sum Types
|
||||
ApplyVariant(String, Option<Vec<Expr>>),
|
||||
|
||||
|
||||
// Conditionals
|
||||
If(Box<Expr>, Box<Expr>, Box<Expr>),
|
||||
Match(Box<Expr>, Vec<(Pattern, Box<Expr>)>),
|
||||
|
||||
// Error
|
||||
Error(Problem),
|
||||
}
|
||||
|
||||
|
|
34
src/parse.rs
34
src/parse.rs
|
@ -129,6 +129,7 @@ parser! {
|
|||
number_literal(),
|
||||
char_literal(),
|
||||
if_expr(min_indent),
|
||||
match_expr(min_indent),
|
||||
closure(min_indent),
|
||||
let_expr(min_indent),
|
||||
apply_variant(min_indent),
|
||||
|
@ -184,7 +185,7 @@ pub fn if_expr<I>(min_indent: i32) -> impl Parser<Input = I, Output = Expr>
|
|||
where I: Stream<Item = char, Position = IndentablePosition>,
|
||||
I::Error: ParseError<I::Item, I::Range, I::Position>
|
||||
{
|
||||
string("if").with(indented_whitespaces1(min_indent))
|
||||
string("if").skip(indented_whitespaces1(min_indent))
|
||||
.with(expr_body(min_indent)).skip(indented_whitespaces1(min_indent))
|
||||
.skip(string("then")).skip(indented_whitespaces1(min_indent))
|
||||
.and(expr_body(min_indent)).skip(indented_whitespaces1(min_indent))
|
||||
|
@ -199,6 +200,30 @@ where I: Stream<Item = char, Position = IndentablePosition>,
|
|||
)
|
||||
}
|
||||
|
||||
pub fn match_expr<I>(min_indent: i32) -> impl Parser<Input = I, Output = Expr>
|
||||
where I: Stream<Item = char, Position = IndentablePosition>,
|
||||
I::Error: ParseError<I::Item, I::Range, I::Position>
|
||||
{
|
||||
string("match").skip(indented_whitespaces1(min_indent))
|
||||
.with(expr_body(min_indent)).skip(indented_whitespaces1(min_indent))
|
||||
.and(
|
||||
many::<Vec<_>, _>(
|
||||
string("when").skip(indented_whitespaces1(min_indent))
|
||||
.with(pattern(min_indent)).skip(indented_whitespaces1(min_indent))
|
||||
.skip(string("then")).skip(indented_whitespaces1(min_indent))
|
||||
.and(expr_body(min_indent).map(|expr| Box::new(expr)))
|
||||
)
|
||||
)
|
||||
.map(|(conditional, branches)|
|
||||
if branches.is_empty() {
|
||||
// TODO handle this more gracefully
|
||||
panic!("encountered match-expression with no branches!")
|
||||
} else {
|
||||
Expr::Match(Box::new(conditional), branches)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
pub fn parenthetical_expr<I>(min_indent: i32) -> impl Parser<Input = I, Output = Expr>
|
||||
where I: Stream<Item = char, Position = IndentablePosition>,
|
||||
I::Error: ParseError<I::Item, I::Range, I::Position>
|
||||
|
@ -229,7 +254,7 @@ where I: Stream<Item = char, Position = IndentablePosition>,
|
|||
sep_by1(
|
||||
attempt(
|
||||
// Keywords like "then" and "else" are not function application!
|
||||
not_followed_by(choice((string("then"), string("else"))))
|
||||
not_followed_by(choice((string("then"), string("else"), string("when"))))
|
||||
// Don't parse operators because they have a higher
|
||||
// precedence than function application. If we see one,
|
||||
// we're done!
|
||||
|
@ -404,6 +429,9 @@ where I: Stream<Item = char, Position = IndentablePosition>,
|
|||
match ident_str.as_str() {
|
||||
"if" => unexpected_any("Reserved keyword `if`").left(),
|
||||
"then" => unexpected_any("Reserved keyword `then`").left(),
|
||||
"else" => unexpected_any("Reserved keyword `else`").left(),
|
||||
"match" => unexpected_any("Reserved keyword `match`").left(),
|
||||
"when" => unexpected_any("Reserved keyword `when`").left(),
|
||||
_ => value(ident_str).right()
|
||||
}
|
||||
} else {
|
||||
|
@ -561,7 +589,7 @@ where I: Stream<Item = char, Position = IndentablePosition>,
|
|||
char(' ').skip(
|
||||
// Don't mistake keywords like `then` and `else` for
|
||||
// space-separated digits!
|
||||
not_followed_by(choice((string("then"), string("else"))))
|
||||
not_followed_by(choice((string("then"), string("else"), string("when"))))
|
||||
)
|
||||
)
|
||||
))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue