From 8f1c64505574f60c805c5b4a32e55e818b9e0eee Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 4 Aug 2018 13:39:03 +0300 Subject: [PATCH] Match expr --- src/grammar.ron | 3 + src/grammar/expressions.rs | 56 ++++++++++++++++- src/syntax_kinds/generated.rs | 6 ++ tests/data/parser/inline/0069_match_arm.rs | 6 ++ tests/data/parser/inline/0069_match_arm.txt | 65 ++++++++++++++++++++ tests/data/parser/inline/0070_match_expr.rs | 3 + tests/data/parser/inline/0070_match_expr.txt | 28 +++++++++ 7 files changed, 165 insertions(+), 2 deletions(-) create mode 100644 tests/data/parser/inline/0069_match_arm.rs create mode 100644 tests/data/parser/inline/0069_match_arm.txt create mode 100644 tests/data/parser/inline/0070_match_expr.rs create mode 100644 tests/data/parser/inline/0070_match_expr.txt diff --git a/src/grammar.ron b/src/grammar.ron index 8e8a7101020..0239a3c1dcf 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 c6841992939..6506892e15e 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 50aa2b580b3..73b26b274a9 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" }, diff --git a/tests/data/parser/inline/0069_match_arm.rs b/tests/data/parser/inline/0069_match_arm.rs new file mode 100644 index 00000000000..2c0e8841451 --- /dev/null +++ b/tests/data/parser/inline/0069_match_arm.rs @@ -0,0 +1,6 @@ +fn foo() { + match () { + _ => (), + X | Y if Z => (), + }; +} diff --git a/tests/data/parser/inline/0069_match_arm.txt b/tests/data/parser/inline/0069_match_arm.txt new file mode 100644 index 00000000000..efdee2568a9 --- /dev/null +++ b/tests/data/parser/inline/0069_match_arm.txt @@ -0,0 +1,65 @@ +FILE@[0; 78) + FN_ITEM@[0; 78) + FN_KW@[0; 2) + NAME@[2; 6) + WHITESPACE@[2; 3) + IDENT@[3; 6) "foo" + PARAM_LIST@[6; 9) + L_PAREN@[6; 7) + R_PAREN@[7; 8) + WHITESPACE@[8; 9) + BLOCK_EXPR@[9; 78) + L_CURLY@[9; 10) + EXPR_STMT@[10; 76) + MATCH_EXPR@[10; 74) + WHITESPACE@[10; 15) + MATCH_KW@[15; 20) + TUPLE_EXPR@[20; 24) + WHITESPACE@[20; 21) + L_PAREN@[21; 22) + R_PAREN@[22; 23) + WHITESPACE@[23; 24) + L_CURLY@[24; 25) + MATCH_ARM@[25; 41) + PLACEHOLDER_PAT@[25; 36) + WHITESPACE@[25; 34) + UNDERSCORE@[34; 35) + WHITESPACE@[35; 36) + FAT_ARROW@[36; 38) + TUPLE_EXPR@[38; 41) + WHITESPACE@[38; 39) + L_PAREN@[39; 40) + R_PAREN@[40; 41) + COMMA@[41; 42) + MATCH_ARM@[42; 67) + BIND_PAT@[42; 53) + NAME@[42; 53) + WHITESPACE@[42; 51) + IDENT@[51; 52) "X" + WHITESPACE@[52; 53) + PIPE@[53; 54) + BIND_PAT@[54; 57) + NAME@[54; 57) + WHITESPACE@[54; 55) + IDENT@[55; 56) "Y" + WHITESPACE@[56; 57) + IF_KW@[57; 59) + PATH_EXPR@[59; 62) + PATH@[59; 62) + PATH_SEGMENT@[59; 62) + NAME_REF@[59; 62) + WHITESPACE@[59; 60) + IDENT@[60; 61) "Z" + WHITESPACE@[61; 62) + FAT_ARROW@[62; 64) + TUPLE_EXPR@[64; 67) + WHITESPACE@[64; 65) + L_PAREN@[65; 66) + R_PAREN@[66; 67) + COMMA@[67; 68) + WHITESPACE@[68; 73) + R_CURLY@[73; 74) + SEMI@[74; 75) + WHITESPACE@[75; 76) + R_CURLY@[76; 77) + WHITESPACE@[77; 78) diff --git a/tests/data/parser/inline/0070_match_expr.rs b/tests/data/parser/inline/0070_match_expr.rs new file mode 100644 index 00000000000..40318b35047 --- /dev/null +++ b/tests/data/parser/inline/0070_match_expr.rs @@ -0,0 +1,3 @@ +fn foo() { + match () { }; +} diff --git a/tests/data/parser/inline/0070_match_expr.txt b/tests/data/parser/inline/0070_match_expr.txt new file mode 100644 index 00000000000..2dc2f4130cf --- /dev/null +++ b/tests/data/parser/inline/0070_match_expr.txt @@ -0,0 +1,28 @@ +FILE@[0; 31) + FN_ITEM@[0; 31) + FN_KW@[0; 2) + NAME@[2; 6) + WHITESPACE@[2; 3) + IDENT@[3; 6) "foo" + PARAM_LIST@[6; 9) + L_PAREN@[6; 7) + R_PAREN@[7; 8) + WHITESPACE@[8; 9) + BLOCK_EXPR@[9; 31) + L_CURLY@[9; 10) + EXPR_STMT@[10; 29) + MATCH_EXPR@[10; 27) + WHITESPACE@[10; 15) + MATCH_KW@[15; 20) + TUPLE_EXPR@[20; 24) + WHITESPACE@[20; 21) + L_PAREN@[21; 22) + R_PAREN@[22; 23) + WHITESPACE@[23; 24) + L_CURLY@[24; 25) + WHITESPACE@[25; 26) + R_CURLY@[26; 27) + SEMI@[27; 28) + WHITESPACE@[28; 29) + R_CURLY@[29; 30) + WHITESPACE@[30; 31)