diff --git a/src/grammar.ron b/src/grammar.ron index 8ce5ebc49c7..9f80b3ebf53 100644 --- a/src/grammar.ron +++ b/src/grammar.ron @@ -135,6 +135,7 @@ Grammar( "PATH_EXPR", "LAMBDA_EXPR", "IF_EXPR", + "WHILE_EXPR", "BLOCK_EXPR", "RETURN_EXPR", "MATCH_EXPR", diff --git a/src/grammar/expressions/atom.rs b/src/grammar/expressions/atom.rs index ad654df9e1a..6a0d47d82ba 100644 --- a/src/grammar/expressions/atom.rs +++ b/src/grammar/expressions/atom.rs @@ -29,7 +29,7 @@ pub(crate) fn literal(p: &mut Parser) -> Option { pub(super) const ATOM_EXPR_FIRST: TokenSet = token_set_union![ LITERAL_FIRST, - token_set![L_PAREN, PIPE, MOVE_KW, IF_KW, MATCH_KW, UNSAFE_KW, L_CURLY, RETURN_KW, + token_set![L_PAREN, PIPE, MOVE_KW, IF_KW, WHILE_KW, MATCH_KW, UNSAFE_KW, L_CURLY, RETURN_KW, IDENT, SELF_KW, SUPER_KW, COLONCOLON ], ]; @@ -47,6 +47,7 @@ pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option lambda_expr(p), MOVE_KW if la == PIPE => lambda_expr(p), IF_KW => if_expr(p), + WHILE_KW => while_expr(p), MATCH_KW => match_expr(p), UNSAFE_KW if la == L_CURLY => block_expr(p), L_CURLY => block_expr(p), @@ -97,7 +98,8 @@ fn lambda_expr(p: &mut Parser) -> CompletedMarker { fn if_expr(p: &mut Parser) -> CompletedMarker { assert!(p.at(IF_KW)); let m = p.start(); - if_head(p); + p.bump(); + cond(p); block(p); if p.at(ELSE_KW) { p.bump(); @@ -110,10 +112,28 @@ fn if_expr(p: &mut Parser) -> CompletedMarker { m.complete(p, IF_EXPR) } -fn if_head(p: &mut Parser) { - assert!(p.at(IF_KW)); +// test while_expr +// fn foo() { +// while true {}; +// while let Some(x) = it.next() {}; +// } +fn while_expr(p: &mut Parser) -> CompletedMarker { + assert!(p.at(WHILE_KW)); + let m = p.start(); p.bump(); - expr_no_struct(p); + cond(p); + block(p); + m.complete(p, WHILE_EXPR) +} + +// test cond +// fn foo() { if let Some(_) = None {} } +fn cond(p: &mut Parser) { + if p.eat(LET_KW) { + patterns::pattern(p); + p.expect(EQ); + } + expr_no_struct(p) } // test match_expr @@ -152,8 +172,8 @@ fn match_arm(p: &mut Parser) { break; } } - if p.at(IF_KW) { - if_head(p) + if p.eat(IF_KW) { + expr_no_struct(p); } p.expect(FAT_ARROW); expr(p); diff --git a/src/syntax_kinds/generated.rs b/src/syntax_kinds/generated.rs index 7bdd0267c92..1d3d3b9c1e1 100644 --- a/src/syntax_kinds/generated.rs +++ b/src/syntax_kinds/generated.rs @@ -125,6 +125,7 @@ pub enum SyntaxKind { PATH_EXPR, LAMBDA_EXPR, IF_EXPR, + WHILE_EXPR, BLOCK_EXPR, RETURN_EXPR, MATCH_EXPR, @@ -343,6 +344,7 @@ impl SyntaxKind { PATH_EXPR => &SyntaxInfo { name: "PATH_EXPR" }, LAMBDA_EXPR => &SyntaxInfo { name: "LAMBDA_EXPR" }, IF_EXPR => &SyntaxInfo { name: "IF_EXPR" }, + WHILE_EXPR => &SyntaxInfo { name: "WHILE_EXPR" }, BLOCK_EXPR => &SyntaxInfo { name: "BLOCK_EXPR" }, RETURN_EXPR => &SyntaxInfo { name: "RETURN_EXPR" }, MATCH_EXPR => &SyntaxInfo { name: "MATCH_EXPR" }, diff --git a/tests/data/parser/inline/0076_cond.rs b/tests/data/parser/inline/0076_cond.rs new file mode 100644 index 00000000000..fdb37ee6f33 --- /dev/null +++ b/tests/data/parser/inline/0076_cond.rs @@ -0,0 +1 @@ +fn foo() { if let Some(_) = None {} } diff --git a/tests/data/parser/inline/0076_cond.txt b/tests/data/parser/inline/0076_cond.txt new file mode 100644 index 00000000000..22eed845823 --- /dev/null +++ b/tests/data/parser/inline/0076_cond.txt @@ -0,0 +1,42 @@ +FILE@[0; 38) + FN_ITEM@[0; 38) + 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; 38) + L_CURLY@[9; 10) + IF_EXPR@[10; 36) + WHITESPACE@[10; 11) + IF_KW@[11; 13) + WHITESPACE@[13; 14) + LET_KW@[14; 17) + TUPLE_PAT@[17; 26) + PATH@[17; 22) + PATH_SEGMENT@[17; 22) + NAME_REF@[17; 22) + WHITESPACE@[17; 18) + IDENT@[18; 22) "Some" + L_PAREN@[22; 23) + PLACEHOLDER_PAT@[23; 24) + UNDERSCORE@[23; 24) + R_PAREN@[24; 25) + WHITESPACE@[25; 26) + EQ@[26; 27) + PATH_EXPR@[27; 33) + PATH@[27; 33) + PATH_SEGMENT@[27; 33) + NAME_REF@[27; 33) + WHITESPACE@[27; 28) + IDENT@[28; 32) "None" + WHITESPACE@[32; 33) + BLOCK_EXPR@[33; 36) + L_CURLY@[33; 34) + R_CURLY@[34; 35) + WHITESPACE@[35; 36) + R_CURLY@[36; 37) + WHITESPACE@[37; 38) diff --git a/tests/data/parser/inline/0077_while_expr.rs b/tests/data/parser/inline/0077_while_expr.rs new file mode 100644 index 00000000000..293046a0494 --- /dev/null +++ b/tests/data/parser/inline/0077_while_expr.rs @@ -0,0 +1,4 @@ +fn foo() { + while true {}; + while let Some(x) = it.next() {}; +} diff --git a/tests/data/parser/inline/0077_while_expr.txt b/tests/data/parser/inline/0077_while_expr.txt new file mode 100644 index 00000000000..447b4b88070 --- /dev/null +++ b/tests/data/parser/inline/0077_while_expr.txt @@ -0,0 +1,64 @@ +FILE@[0; 70) + FN_ITEM@[0; 70) + 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; 70) + L_CURLY@[9; 10) + EXPR_STMT@[10; 34) + WHILE_EXPR@[10; 28) + WHITESPACE@[10; 15) + WHILE_KW@[15; 20) + LITERAL@[20; 26) + WHITESPACE@[20; 21) + TRUE_KW@[21; 25) + WHITESPACE@[25; 26) + BLOCK_EXPR@[26; 28) + L_CURLY@[26; 27) + R_CURLY@[27; 28) + SEMI@[28; 29) + WHITESPACE@[29; 34) + EXPR_STMT@[34; 68) + WHILE_EXPR@[34; 66) + WHILE_KW@[34; 39) + WHITESPACE@[39; 40) + LET_KW@[40; 43) + TUPLE_PAT@[43; 52) + PATH@[43; 48) + PATH_SEGMENT@[43; 48) + NAME_REF@[43; 48) + WHITESPACE@[43; 44) + IDENT@[44; 48) "Some" + L_PAREN@[48; 49) + BIND_PAT@[49; 50) + NAME@[49; 50) + IDENT@[49; 50) "x" + R_PAREN@[50; 51) + WHITESPACE@[51; 52) + EQ@[52; 53) + METHOD_CALL_EXPR@[53; 64) + PATH_EXPR@[53; 56) + PATH@[53; 56) + PATH_SEGMENT@[53; 56) + NAME_REF@[53; 56) + WHITESPACE@[53; 54) + IDENT@[54; 56) "it" + DOT@[56; 57) + NAME_REF@[57; 61) + IDENT@[57; 61) "next" + ARG_LIST@[61; 64) + L_PAREN@[61; 62) + R_PAREN@[62; 63) + WHITESPACE@[63; 64) + BLOCK_EXPR@[64; 66) + L_CURLY@[64; 65) + R_CURLY@[65; 66) + SEMI@[66; 67) + WHITESPACE@[67; 68) + R_CURLY@[68; 69) + WHITESPACE@[69; 70)