From 8f1c64505574f60c805c5b4a32e55e818b9e0eee Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 4 Aug 2018 13:39:03 +0300 Subject: Match expr --- src/grammar.ron | 3 +++ src/grammar/expressions.rs | 56 +++++++++++++++++++++++++++++++++++++++++-- src/syntax_kinds/generated.rs | 6 +++++ 3 files changed, 63 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/grammar.ron b/src/grammar.ron index 8e8a71010..0239a3c1d 100644 --- a/src/grammar.ron +++ b/src/grammar.ron @@ -141,6 +141,9 @@ Grammar( "IF_EXPR", "BLOCK_EXPR", "RETURN_EXPR", + "MATCH_EXPR", + "MATCH_ARM", + "MATCH_GUARD", "EXTERN_BLOCK_EXPR", "ENUM_VARIANT", diff --git a/src/grammar/expressions.rs b/src/grammar/expressions.rs index c68419929..6506892e1 100644 --- a/src/grammar/expressions.rs +++ b/src/grammar/expressions.rs @@ -27,6 +27,7 @@ pub(super) fn literal(p: &mut Parser) -> Option { } const EXPR_FIRST: TokenSet = PREFIX_EXPR_FIRST; + pub(super) fn expr(p: &mut Parser) { let mut lhs = match prefix_expr(p) { Some(lhs) => lhs, @@ -87,6 +88,7 @@ const PREFIX_EXPR_FIRST: TokenSet = token_set![AMPERSAND, STAR, EXCL], ATOM_EXPR_FIRST, ]; + fn prefix_expr(p: &mut Parser) -> Option { let done = match p.current() { AMPERSAND => ref_expr(p), @@ -140,6 +142,7 @@ const ATOM_EXPR_FIRST: TokenSet = LITERAL_FIRST, token_set![L_PAREN, PIPE, MOVE_KW, IF_KW, UNSAFE_KW, L_CURLY, RETURN_KW], ]; + fn atom_expr(p: &mut Parser) -> Option { match literal(p) { Some(m) => return Some(m), @@ -154,6 +157,7 @@ fn atom_expr(p: &mut Parser) -> Option { PIPE => lambda_expr(p), MOVE_KW if la == PIPE => lambda_expr(p), IF_KW => if_expr(p), + MATCH_KW => match_expr(p), UNSAFE_KW if la == L_CURLY => block_expr(p), L_CURLY => block_expr(p), RETURN_KW => return_expr(p), @@ -202,8 +206,7 @@ fn lambda_expr(p: &mut Parser) -> CompletedMarker { fn if_expr(p: &mut Parser) -> CompletedMarker { assert!(p.at(IF_KW)); let m = p.start(); - p.bump(); - expr(p); + if_head(p); block(p); if p.at(ELSE_KW) { p.bump(); @@ -216,6 +219,55 @@ fn if_expr(p: &mut Parser) -> CompletedMarker { m.complete(p, IF_EXPR) } +fn if_head(p: &mut Parser) { + assert!(p.at(IF_KW)); + p.bump(); + expr(p); +} + +// test match_expr +// fn foo() { +// match () { }; +// } +fn match_expr(p: &mut Parser) -> CompletedMarker { + assert!(p.at(MATCH_KW)); + let m = p.start(); + p.bump(); + expr(p); + p.eat(L_CURLY); + while !p.at(EOF) && !p.at(R_CURLY) { + match_arm(p); + if !p.at(R_CURLY) { + p.expect(COMMA); + } + } + p.expect(R_CURLY); + m.complete(p, MATCH_EXPR) +} + +// test match_arm +// fn foo() { +// match () { +// _ => (), +// X | Y if Z => (), +// }; +// } +fn match_arm(p: &mut Parser) { + let m = p.start(); + loop { + patterns::pattern(p); + if !p.eat(PIPE) { + break; + } + } + if p.at(IF_KW) { + if_head(p) + } + p.expect(FAT_ARROW); + expr(p); + m.complete(p, MATCH_ARM); +} + // test block_expr // fn foo() { // {}; diff --git a/src/syntax_kinds/generated.rs b/src/syntax_kinds/generated.rs index 50aa2b580..73b26b274 100644 --- a/src/syntax_kinds/generated.rs +++ b/src/syntax_kinds/generated.rs @@ -132,6 +132,9 @@ pub enum SyntaxKind { IF_EXPR, BLOCK_EXPR, RETURN_EXPR, + MATCH_EXPR, + MATCH_ARM, + MATCH_GUARD, EXTERN_BLOCK_EXPR, ENUM_VARIANT, NAMED_FIELD, @@ -342,6 +345,9 @@ impl SyntaxKind { IF_EXPR => &SyntaxInfo { name: "IF_EXPR" }, BLOCK_EXPR => &SyntaxInfo { name: "BLOCK_EXPR" }, RETURN_EXPR => &SyntaxInfo { name: "RETURN_EXPR" }, + MATCH_EXPR => &SyntaxInfo { name: "MATCH_EXPR" }, + MATCH_ARM => &SyntaxInfo { name: "MATCH_ARM" }, + MATCH_GUARD => &SyntaxInfo { name: "MATCH_GUARD" }, EXTERN_BLOCK_EXPR => &SyntaxInfo { name: "EXTERN_BLOCK_EXPR" }, ENUM_VARIANT => &SyntaxInfo { name: "ENUM_VARIANT" }, NAMED_FIELD => &SyntaxInfo { name: "NAMED_FIELD" }, -- cgit v1.2.3