From 89e56c364f3d0a9d5a12ae488185abc1ea69df4a Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 24 Aug 2018 11:45:14 +0300 Subject: Labeled expressions --- crates/libsyntax2/src/grammar.ron | 5 +- crates/libsyntax2/src/grammar/expressions/atom.rs | 61 +++++++++++++++------ crates/libsyntax2/src/grammar/mod.rs | 2 +- crates/libsyntax2/src/syntax_kinds/generated.rs | 10 ++-- .../tests/data/parser/inline/0107_label.rs | 5 ++ .../tests/data/parser/inline/0107_label.txt | 63 ++++++++++++++++++++++ 6 files changed, 123 insertions(+), 23 deletions(-) create mode 100644 crates/libsyntax2/tests/data/parser/inline/0107_label.rs create mode 100644 crates/libsyntax2/tests/data/parser/inline/0107_label.txt (limited to 'crates') diff --git a/crates/libsyntax2/src/grammar.ron b/crates/libsyntax2/src/grammar.ron index dff88cc4a..52764e664 100644 --- a/crates/libsyntax2/src/grammar.ron +++ b/crates/libsyntax2/src/grammar.ron @@ -161,11 +161,12 @@ Grammar( "PATH_EXPR", "LAMBDA_EXPR", "IF_EXPR", - "WHILE_EXPR", "LOOP_EXPR", + "FOR_EXPR", + "WHILE_EXPR", "CONTINUE_EXPR", "BREAK_EXPR", - "FOR_EXPR", + "LABEL", "BLOCK_EXPR", "RETURN_EXPR", "MATCH_EXPR", diff --git a/crates/libsyntax2/src/grammar/expressions/atom.rs b/crates/libsyntax2/src/grammar/expressions/atom.rs index 9f470d561..9d98340af 100644 --- a/crates/libsyntax2/src/grammar/expressions/atom.rs +++ b/crates/libsyntax2/src/grammar/expressions/atom.rs @@ -30,7 +30,7 @@ pub(super) const ATOM_EXPR_FIRST: TokenSet = token_set_union![ LITERAL_FIRST, 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, BREAK_KW, CONTINUE_KW ], + IDENT, SELF_KW, SUPER_KW, COLONCOLON, BREAK_KW, CONTINUE_KW, LIFETIME ], ]; pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option { @@ -48,9 +48,24 @@ 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), - LOOP_KW => loop_expr(p), - FOR_KW => for_expr(p), + + LOOP_KW => loop_expr(p, None), + FOR_KW => for_expr(p, None), + WHILE_KW => while_expr(p, None), + LIFETIME if la == COLON => { + let m = p.start(); + label(p); + match p.current() { + LOOP_KW => loop_expr(p, Some(m)), + FOR_KW => for_expr(p, Some(m)), + WHILE_KW => while_expr(p, Some(m)), + _ => { + p.error("expected a loop"); + return None; + } + } + } + MATCH_KW => match_expr(p), UNSAFE_KW if la == L_CURLY => block_expr(p), L_CURLY => block_expr(p), @@ -164,39 +179,53 @@ fn if_expr(p: &mut Parser) -> CompletedMarker { m.complete(p, IF_EXPR) } -// test while_expr +// test label // fn foo() { -// while true {}; -// while let Some(x) = it.next() {}; +// 'a: loop {} +// 'b: while true {} +// 'c: for x in () {} // } -fn while_expr(p: &mut Parser) -> CompletedMarker { - assert!(p.at(WHILE_KW)); +fn label(p: &mut Parser) { + assert!(p.at(LIFETIME) && p.nth(1) == COLON); let m = p.start(); p.bump(); - cond(p); - block(p); - m.complete(p, WHILE_EXPR) + p.bump(); + m.complete(p, LABEL); } // test loop_expr // fn foo() { // loop {}; // } -fn loop_expr(p: &mut Parser) -> CompletedMarker { +fn loop_expr(p: &mut Parser, m: Option) -> CompletedMarker { assert!(p.at(LOOP_KW)); - let m = p.start(); + let m = m.unwrap_or_else(|| p.start()); p.bump(); block(p); m.complete(p, LOOP_EXPR) } +// test while_expr +// fn foo() { +// while true {}; +// while let Some(x) = it.next() {}; +// } +fn while_expr(p: &mut Parser, m: Option) -> CompletedMarker { + assert!(p.at(WHILE_KW)); + let m = m.unwrap_or_else(|| p.start()); + p.bump(); + cond(p); + block(p); + m.complete(p, WHILE_EXPR) +} + // test for_expr // fn foo() { // for x in [] {}; // } -fn for_expr(p: &mut Parser) -> CompletedMarker { +fn for_expr(p: &mut Parser, m: Option) -> CompletedMarker { assert!(p.at(FOR_KW)); - let m = p.start(); + let m = m.unwrap_or_else(|| p.start()); p.bump(); patterns::pattern(p); p.expect(IN_KW); diff --git a/crates/libsyntax2/src/grammar/mod.rs b/crates/libsyntax2/src/grammar/mod.rs index 0f168eb60..25887921b 100644 --- a/crates/libsyntax2/src/grammar/mod.rs +++ b/crates/libsyntax2/src/grammar/mod.rs @@ -32,7 +32,7 @@ mod type_params; mod types; use { - parser_api::{CompletedMarker, Parser, TokenSet}, + parser_api::{Marker, CompletedMarker, Parser, TokenSet}, SyntaxKind::{self, *}, }; diff --git a/crates/libsyntax2/src/syntax_kinds/generated.rs b/crates/libsyntax2/src/syntax_kinds/generated.rs index 82b6c89cf..61d527f93 100644 --- a/crates/libsyntax2/src/syntax_kinds/generated.rs +++ b/crates/libsyntax2/src/syntax_kinds/generated.rs @@ -157,11 +157,12 @@ pub enum SyntaxKind { PATH_EXPR, LAMBDA_EXPR, IF_EXPR, - WHILE_EXPR, LOOP_EXPR, + FOR_EXPR, + WHILE_EXPR, CONTINUE_EXPR, BREAK_EXPR, - FOR_EXPR, + LABEL, BLOCK_EXPR, RETURN_EXPR, MATCH_EXPR, @@ -406,11 +407,12 @@ 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" }, LOOP_EXPR => &SyntaxInfo { name: "LOOP_EXPR" }, + FOR_EXPR => &SyntaxInfo { name: "FOR_EXPR" }, + WHILE_EXPR => &SyntaxInfo { name: "WHILE_EXPR" }, CONTINUE_EXPR => &SyntaxInfo { name: "CONTINUE_EXPR" }, BREAK_EXPR => &SyntaxInfo { name: "BREAK_EXPR" }, - FOR_EXPR => &SyntaxInfo { name: "FOR_EXPR" }, + LABEL => &SyntaxInfo { name: "LABEL" }, BLOCK_EXPR => &SyntaxInfo { name: "BLOCK_EXPR" }, RETURN_EXPR => &SyntaxInfo { name: "RETURN_EXPR" }, MATCH_EXPR => &SyntaxInfo { name: "MATCH_EXPR" }, diff --git a/crates/libsyntax2/tests/data/parser/inline/0107_label.rs b/crates/libsyntax2/tests/data/parser/inline/0107_label.rs new file mode 100644 index 000000000..48e83f263 --- /dev/null +++ b/crates/libsyntax2/tests/data/parser/inline/0107_label.rs @@ -0,0 +1,5 @@ +fn foo() { + 'a: loop {} + 'b: while true {} + 'c: for x in () {} +} diff --git a/crates/libsyntax2/tests/data/parser/inline/0107_label.txt b/crates/libsyntax2/tests/data/parser/inline/0107_label.txt new file mode 100644 index 000000000..66ba792b8 --- /dev/null +++ b/crates/libsyntax2/tests/data/parser/inline/0107_label.txt @@ -0,0 +1,63 @@ +FILE@[0; 74) + FN_DEF@[0; 73) + FN_KW@[0; 2) + WHITESPACE@[2; 3) + NAME@[3; 6) + IDENT@[3; 6) "foo" + PARAM_LIST@[6; 8) + L_PAREN@[6; 7) + R_PAREN@[7; 8) + WHITESPACE@[8; 9) + BLOCK_EXPR@[9; 73) + L_CURLY@[9; 10) + WHITESPACE@[10; 15) + EXPR_STMT@[15; 26) + LOOP_EXPR@[15; 26) + LABEL@[15; 18) + LIFETIME@[15; 17) "'a" + COLON@[17; 18) + WHITESPACE@[18; 19) + LOOP_KW@[19; 23) + WHITESPACE@[23; 24) + BLOCK_EXPR@[24; 26) + L_CURLY@[24; 25) + R_CURLY@[25; 26) + WHITESPACE@[26; 31) + EXPR_STMT@[31; 48) + WHILE_EXPR@[31; 48) + LABEL@[31; 34) + LIFETIME@[31; 33) "'b" + COLON@[33; 34) + WHITESPACE@[34; 35) + WHILE_KW@[35; 40) + WHITESPACE@[40; 41) + LITERAL@[41; 45) + TRUE_KW@[41; 45) + WHITESPACE@[45; 46) + BLOCK_EXPR@[46; 48) + L_CURLY@[46; 47) + R_CURLY@[47; 48) + WHITESPACE@[48; 53) + FOR_EXPR@[53; 71) + LABEL@[53; 56) + LIFETIME@[53; 55) "'c" + COLON@[55; 56) + WHITESPACE@[56; 57) + FOR_KW@[57; 60) + WHITESPACE@[60; 61) + BIND_PAT@[61; 62) + NAME@[61; 62) + IDENT@[61; 62) "x" + WHITESPACE@[62; 63) + IN_KW@[63; 65) + WHITESPACE@[65; 66) + TUPLE_EXPR@[66; 68) + L_PAREN@[66; 67) + R_PAREN@[67; 68) + WHITESPACE@[68; 69) + BLOCK_EXPR@[69; 71) + L_CURLY@[69; 70) + R_CURLY@[70; 71) + WHITESPACE@[71; 72) + R_CURLY@[72; 73) + WHITESPACE@[73; 74) -- cgit v1.2.3