diff options
author | Aleksey Kladov <[email protected]> | 2018-08-24 09:45:14 +0100 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2018-08-24 09:45:50 +0100 |
commit | 89e56c364f3d0a9d5a12ae488185abc1ea69df4a (patch) | |
tree | fd619bd07dbb2ec351a0c23549dc31dad64e7641 | |
parent | 719710a13256a32b9fcbf06c1ff43f8961b9b2e6 (diff) |
Labeled expressions
-rw-r--r-- | crates/libsyntax2/src/grammar.ron | 5 | ||||
-rw-r--r-- | crates/libsyntax2/src/grammar/expressions/atom.rs | 61 | ||||
-rw-r--r-- | crates/libsyntax2/src/grammar/mod.rs | 2 | ||||
-rw-r--r-- | crates/libsyntax2/src/syntax_kinds/generated.rs | 10 | ||||
-rw-r--r-- | crates/libsyntax2/tests/data/parser/inline/0107_label.rs | 5 | ||||
-rw-r--r-- | crates/libsyntax2/tests/data/parser/inline/0107_label.txt | 63 |
6 files changed, 123 insertions, 23 deletions
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( | |||
161 | "PATH_EXPR", | 161 | "PATH_EXPR", |
162 | "LAMBDA_EXPR", | 162 | "LAMBDA_EXPR", |
163 | "IF_EXPR", | 163 | "IF_EXPR", |
164 | "WHILE_EXPR", | ||
165 | "LOOP_EXPR", | 164 | "LOOP_EXPR", |
165 | "FOR_EXPR", | ||
166 | "WHILE_EXPR", | ||
166 | "CONTINUE_EXPR", | 167 | "CONTINUE_EXPR", |
167 | "BREAK_EXPR", | 168 | "BREAK_EXPR", |
168 | "FOR_EXPR", | 169 | "LABEL", |
169 | "BLOCK_EXPR", | 170 | "BLOCK_EXPR", |
170 | "RETURN_EXPR", | 171 | "RETURN_EXPR", |
171 | "MATCH_EXPR", | 172 | "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 = | |||
30 | token_set_union![ | 30 | token_set_union![ |
31 | LITERAL_FIRST, | 31 | LITERAL_FIRST, |
32 | token_set![L_PAREN, PIPE, MOVE_KW, IF_KW, WHILE_KW, MATCH_KW, UNSAFE_KW, L_CURLY, RETURN_KW, | 32 | token_set![L_PAREN, PIPE, MOVE_KW, IF_KW, WHILE_KW, MATCH_KW, UNSAFE_KW, L_CURLY, RETURN_KW, |
33 | IDENT, SELF_KW, SUPER_KW, COLONCOLON, BREAK_KW, CONTINUE_KW ], | 33 | IDENT, SELF_KW, SUPER_KW, COLONCOLON, BREAK_KW, CONTINUE_KW, LIFETIME ], |
34 | ]; | 34 | ]; |
35 | 35 | ||
36 | pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<CompletedMarker> { | 36 | pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<CompletedMarker> { |
@@ -48,9 +48,24 @@ pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<CompletedMark | |||
48 | PIPE => lambda_expr(p), | 48 | PIPE => lambda_expr(p), |
49 | MOVE_KW if la == PIPE => lambda_expr(p), | 49 | MOVE_KW if la == PIPE => lambda_expr(p), |
50 | IF_KW => if_expr(p), | 50 | IF_KW => if_expr(p), |
51 | WHILE_KW => while_expr(p), | 51 | |
52 | LOOP_KW => loop_expr(p), | 52 | LOOP_KW => loop_expr(p, None), |
53 | FOR_KW => for_expr(p), | 53 | FOR_KW => for_expr(p, None), |
54 | WHILE_KW => while_expr(p, None), | ||
55 | LIFETIME if la == COLON => { | ||
56 | let m = p.start(); | ||
57 | label(p); | ||
58 | match p.current() { | ||
59 | LOOP_KW => loop_expr(p, Some(m)), | ||
60 | FOR_KW => for_expr(p, Some(m)), | ||
61 | WHILE_KW => while_expr(p, Some(m)), | ||
62 | _ => { | ||
63 | p.error("expected a loop"); | ||
64 | return None; | ||
65 | } | ||
66 | } | ||
67 | } | ||
68 | |||
54 | MATCH_KW => match_expr(p), | 69 | MATCH_KW => match_expr(p), |
55 | UNSAFE_KW if la == L_CURLY => block_expr(p), | 70 | UNSAFE_KW if la == L_CURLY => block_expr(p), |
56 | L_CURLY => block_expr(p), | 71 | L_CURLY => block_expr(p), |
@@ -164,39 +179,53 @@ fn if_expr(p: &mut Parser) -> CompletedMarker { | |||
164 | m.complete(p, IF_EXPR) | 179 | m.complete(p, IF_EXPR) |
165 | } | 180 | } |
166 | 181 | ||
167 | // test while_expr | 182 | // test label |
168 | // fn foo() { | 183 | // fn foo() { |
169 | // while true {}; | 184 | // 'a: loop {} |
170 | // while let Some(x) = it.next() {}; | 185 | // 'b: while true {} |
186 | // 'c: for x in () {} | ||
171 | // } | 187 | // } |
172 | fn while_expr(p: &mut Parser) -> CompletedMarker { | 188 | fn label(p: &mut Parser) { |
173 | assert!(p.at(WHILE_KW)); | 189 | assert!(p.at(LIFETIME) && p.nth(1) == COLON); |
174 | let m = p.start(); | 190 | let m = p.start(); |
175 | p.bump(); | 191 | p.bump(); |
176 | cond(p); | 192 | p.bump(); |
177 | block(p); | 193 | m.complete(p, LABEL); |
178 | m.complete(p, WHILE_EXPR) | ||
179 | } | 194 | } |
180 | 195 | ||
181 | // test loop_expr | 196 | // test loop_expr |
182 | // fn foo() { | 197 | // fn foo() { |
183 | // loop {}; | 198 | // loop {}; |
184 | // } | 199 | // } |
185 | fn loop_expr(p: &mut Parser) -> CompletedMarker { | 200 | fn loop_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker { |
186 | assert!(p.at(LOOP_KW)); | 201 | assert!(p.at(LOOP_KW)); |
187 | let m = p.start(); | 202 | let m = m.unwrap_or_else(|| p.start()); |
188 | p.bump(); | 203 | p.bump(); |
189 | block(p); | 204 | block(p); |
190 | m.complete(p, LOOP_EXPR) | 205 | m.complete(p, LOOP_EXPR) |
191 | } | 206 | } |
192 | 207 | ||
208 | // test while_expr | ||
209 | // fn foo() { | ||
210 | // while true {}; | ||
211 | // while let Some(x) = it.next() {}; | ||
212 | // } | ||
213 | fn while_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker { | ||
214 | assert!(p.at(WHILE_KW)); | ||
215 | let m = m.unwrap_or_else(|| p.start()); | ||
216 | p.bump(); | ||
217 | cond(p); | ||
218 | block(p); | ||
219 | m.complete(p, WHILE_EXPR) | ||
220 | } | ||
221 | |||
193 | // test for_expr | 222 | // test for_expr |
194 | // fn foo() { | 223 | // fn foo() { |
195 | // for x in [] {}; | 224 | // for x in [] {}; |
196 | // } | 225 | // } |
197 | fn for_expr(p: &mut Parser) -> CompletedMarker { | 226 | fn for_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker { |
198 | assert!(p.at(FOR_KW)); | 227 | assert!(p.at(FOR_KW)); |
199 | let m = p.start(); | 228 | let m = m.unwrap_or_else(|| p.start()); |
200 | p.bump(); | 229 | p.bump(); |
201 | patterns::pattern(p); | 230 | patterns::pattern(p); |
202 | p.expect(IN_KW); | 231 | 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; | |||
32 | mod types; | 32 | mod types; |
33 | 33 | ||
34 | use { | 34 | use { |
35 | parser_api::{CompletedMarker, Parser, TokenSet}, | 35 | parser_api::{Marker, CompletedMarker, Parser, TokenSet}, |
36 | SyntaxKind::{self, *}, | 36 | SyntaxKind::{self, *}, |
37 | }; | 37 | }; |
38 | 38 | ||
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 { | |||
157 | PATH_EXPR, | 157 | PATH_EXPR, |
158 | LAMBDA_EXPR, | 158 | LAMBDA_EXPR, |
159 | IF_EXPR, | 159 | IF_EXPR, |
160 | WHILE_EXPR, | ||
161 | LOOP_EXPR, | 160 | LOOP_EXPR, |
161 | FOR_EXPR, | ||
162 | WHILE_EXPR, | ||
162 | CONTINUE_EXPR, | 163 | CONTINUE_EXPR, |
163 | BREAK_EXPR, | 164 | BREAK_EXPR, |
164 | FOR_EXPR, | 165 | LABEL, |
165 | BLOCK_EXPR, | 166 | BLOCK_EXPR, |
166 | RETURN_EXPR, | 167 | RETURN_EXPR, |
167 | MATCH_EXPR, | 168 | MATCH_EXPR, |
@@ -406,11 +407,12 @@ impl SyntaxKind { | |||
406 | PATH_EXPR => &SyntaxInfo { name: "PATH_EXPR" }, | 407 | PATH_EXPR => &SyntaxInfo { name: "PATH_EXPR" }, |
407 | LAMBDA_EXPR => &SyntaxInfo { name: "LAMBDA_EXPR" }, | 408 | LAMBDA_EXPR => &SyntaxInfo { name: "LAMBDA_EXPR" }, |
408 | IF_EXPR => &SyntaxInfo { name: "IF_EXPR" }, | 409 | IF_EXPR => &SyntaxInfo { name: "IF_EXPR" }, |
409 | WHILE_EXPR => &SyntaxInfo { name: "WHILE_EXPR" }, | ||
410 | LOOP_EXPR => &SyntaxInfo { name: "LOOP_EXPR" }, | 410 | LOOP_EXPR => &SyntaxInfo { name: "LOOP_EXPR" }, |
411 | FOR_EXPR => &SyntaxInfo { name: "FOR_EXPR" }, | ||
412 | WHILE_EXPR => &SyntaxInfo { name: "WHILE_EXPR" }, | ||
411 | CONTINUE_EXPR => &SyntaxInfo { name: "CONTINUE_EXPR" }, | 413 | CONTINUE_EXPR => &SyntaxInfo { name: "CONTINUE_EXPR" }, |
412 | BREAK_EXPR => &SyntaxInfo { name: "BREAK_EXPR" }, | 414 | BREAK_EXPR => &SyntaxInfo { name: "BREAK_EXPR" }, |
413 | FOR_EXPR => &SyntaxInfo { name: "FOR_EXPR" }, | 415 | LABEL => &SyntaxInfo { name: "LABEL" }, |
414 | BLOCK_EXPR => &SyntaxInfo { name: "BLOCK_EXPR" }, | 416 | BLOCK_EXPR => &SyntaxInfo { name: "BLOCK_EXPR" }, |
415 | RETURN_EXPR => &SyntaxInfo { name: "RETURN_EXPR" }, | 417 | RETURN_EXPR => &SyntaxInfo { name: "RETURN_EXPR" }, |
416 | MATCH_EXPR => &SyntaxInfo { name: "MATCH_EXPR" }, | 418 | 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 @@ | |||
1 | fn foo() { | ||
2 | 'a: loop {} | ||
3 | 'b: while true {} | ||
4 | 'c: for x in () {} | ||
5 | } | ||
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 @@ | |||
1 | FILE@[0; 74) | ||
2 | FN_DEF@[0; 73) | ||
3 | FN_KW@[0; 2) | ||
4 | WHITESPACE@[2; 3) | ||
5 | NAME@[3; 6) | ||
6 | IDENT@[3; 6) "foo" | ||
7 | PARAM_LIST@[6; 8) | ||
8 | L_PAREN@[6; 7) | ||
9 | R_PAREN@[7; 8) | ||
10 | WHITESPACE@[8; 9) | ||
11 | BLOCK_EXPR@[9; 73) | ||
12 | L_CURLY@[9; 10) | ||
13 | WHITESPACE@[10; 15) | ||
14 | EXPR_STMT@[15; 26) | ||
15 | LOOP_EXPR@[15; 26) | ||
16 | LABEL@[15; 18) | ||
17 | LIFETIME@[15; 17) "'a" | ||
18 | COLON@[17; 18) | ||
19 | WHITESPACE@[18; 19) | ||
20 | LOOP_KW@[19; 23) | ||
21 | WHITESPACE@[23; 24) | ||
22 | BLOCK_EXPR@[24; 26) | ||
23 | L_CURLY@[24; 25) | ||
24 | R_CURLY@[25; 26) | ||
25 | WHITESPACE@[26; 31) | ||
26 | EXPR_STMT@[31; 48) | ||
27 | WHILE_EXPR@[31; 48) | ||
28 | LABEL@[31; 34) | ||
29 | LIFETIME@[31; 33) "'b" | ||
30 | COLON@[33; 34) | ||
31 | WHITESPACE@[34; 35) | ||
32 | WHILE_KW@[35; 40) | ||
33 | WHITESPACE@[40; 41) | ||
34 | LITERAL@[41; 45) | ||
35 | TRUE_KW@[41; 45) | ||
36 | WHITESPACE@[45; 46) | ||
37 | BLOCK_EXPR@[46; 48) | ||
38 | L_CURLY@[46; 47) | ||
39 | R_CURLY@[47; 48) | ||
40 | WHITESPACE@[48; 53) | ||
41 | FOR_EXPR@[53; 71) | ||
42 | LABEL@[53; 56) | ||
43 | LIFETIME@[53; 55) "'c" | ||
44 | COLON@[55; 56) | ||
45 | WHITESPACE@[56; 57) | ||
46 | FOR_KW@[57; 60) | ||
47 | WHITESPACE@[60; 61) | ||
48 | BIND_PAT@[61; 62) | ||
49 | NAME@[61; 62) | ||
50 | IDENT@[61; 62) "x" | ||
51 | WHITESPACE@[62; 63) | ||
52 | IN_KW@[63; 65) | ||
53 | WHITESPACE@[65; 66) | ||
54 | TUPLE_EXPR@[66; 68) | ||
55 | L_PAREN@[66; 67) | ||
56 | R_PAREN@[67; 68) | ||
57 | WHITESPACE@[68; 69) | ||
58 | BLOCK_EXPR@[69; 71) | ||
59 | L_CURLY@[69; 70) | ||
60 | R_CURLY@[70; 71) | ||
61 | WHITESPACE@[71; 72) | ||
62 | R_CURLY@[72; 73) | ||
63 | WHITESPACE@[73; 74) | ||