diff options
Diffstat (limited to 'crates/ra_parser/src/grammar/expressions.rs')
-rw-r--r-- | crates/ra_parser/src/grammar/expressions.rs | 156 |
1 files changed, 78 insertions, 78 deletions
diff --git a/crates/ra_parser/src/grammar/expressions.rs b/crates/ra_parser/src/grammar/expressions.rs index 9fe529f53..bb6c78b5f 100644 --- a/crates/ra_parser/src/grammar/expressions.rs +++ b/crates/ra_parser/src/grammar/expressions.rs | |||
@@ -36,14 +36,14 @@ fn expr_no_struct(p: &mut Parser) { | |||
36 | // fn c() { 1; 2; } | 36 | // fn c() { 1; 2; } |
37 | // fn d() { 1; 2 } | 37 | // fn d() { 1; 2 } |
38 | pub(crate) fn block(p: &mut Parser) { | 38 | pub(crate) fn block(p: &mut Parser) { |
39 | if !p.at(L_CURLY) { | 39 | if !p.at(T!['{']) { |
40 | p.error("expected a block"); | 40 | p.error("expected a block"); |
41 | return; | 41 | return; |
42 | } | 42 | } |
43 | let m = p.start(); | 43 | let m = p.start(); |
44 | p.bump(); | 44 | p.bump(); |
45 | expr_block_contents(p); | 45 | expr_block_contents(p); |
46 | p.expect(R_CURLY); | 46 | p.expect(T!['}']); |
47 | m.complete(p, BLOCK); | 47 | m.complete(p, BLOCK); |
48 | } | 48 | } |
49 | 49 | ||
@@ -65,10 +65,10 @@ pub(super) fn stmt(p: &mut Parser, with_semi: StmtWithSemi) { | |||
65 | // #[C] #[D] {} | 65 | // #[C] #[D] {} |
66 | // #[D] return (); | 66 | // #[D] return (); |
67 | // } | 67 | // } |
68 | let has_attrs = p.at(POUND); | 68 | let has_attrs = p.at(T![#]); |
69 | attributes::outer_attributes(p); | 69 | attributes::outer_attributes(p); |
70 | 70 | ||
71 | if p.at(LET_KW) { | 71 | if p.at(T![let]) { |
72 | let_stmt(p, m, with_semi); | 72 | let_stmt(p, m, with_semi); |
73 | return; | 73 | return; |
74 | } | 74 | } |
@@ -90,7 +90,7 @@ pub(super) fn stmt(p: &mut Parser, with_semi: StmtWithSemi) { | |||
90 | p.error(format!("attributes are not allowed on {:?}", kind)); | 90 | p.error(format!("attributes are not allowed on {:?}", kind)); |
91 | } | 91 | } |
92 | 92 | ||
93 | if p.at(R_CURLY) { | 93 | if p.at(T!['}']) { |
94 | // test attr_on_last_expr_in_block | 94 | // test attr_on_last_expr_in_block |
95 | // fn foo() { | 95 | // fn foo() { |
96 | // { #[A] bar!()? } | 96 | // { #[A] bar!()? } |
@@ -121,15 +121,15 @@ pub(super) fn stmt(p: &mut Parser, with_semi: StmtWithSemi) { | |||
121 | match with_semi { | 121 | match with_semi { |
122 | StmtWithSemi::Yes => { | 122 | StmtWithSemi::Yes => { |
123 | if blocklike.is_block() { | 123 | if blocklike.is_block() { |
124 | p.eat(SEMI); | 124 | p.eat(T![;]); |
125 | } else { | 125 | } else { |
126 | p.expect(SEMI); | 126 | p.expect(T![;]); |
127 | } | 127 | } |
128 | } | 128 | } |
129 | StmtWithSemi::No => {} | 129 | StmtWithSemi::No => {} |
130 | StmtWithSemi::Optional => { | 130 | StmtWithSemi::Optional => { |
131 | if p.at(SEMI) { | 131 | if p.at(T![;]) { |
132 | p.eat(SEMI); | 132 | p.eat(T![;]); |
133 | } | 133 | } |
134 | } | 134 | } |
135 | } | 135 | } |
@@ -145,24 +145,24 @@ pub(super) fn stmt(p: &mut Parser, with_semi: StmtWithSemi) { | |||
145 | // let d: i32 = 92; | 145 | // let d: i32 = 92; |
146 | // } | 146 | // } |
147 | fn let_stmt(p: &mut Parser, m: Marker, with_semi: StmtWithSemi) { | 147 | fn let_stmt(p: &mut Parser, m: Marker, with_semi: StmtWithSemi) { |
148 | assert!(p.at(LET_KW)); | 148 | assert!(p.at(T![let])); |
149 | p.bump(); | 149 | p.bump(); |
150 | patterns::pattern(p); | 150 | patterns::pattern(p); |
151 | if p.at(COLON) { | 151 | if p.at(T![:]) { |
152 | types::ascription(p); | 152 | types::ascription(p); |
153 | } | 153 | } |
154 | if p.eat(EQ) { | 154 | if p.eat(T![=]) { |
155 | expressions::expr(p); | 155 | expressions::expr(p); |
156 | } | 156 | } |
157 | 157 | ||
158 | match with_semi { | 158 | match with_semi { |
159 | StmtWithSemi::Yes => { | 159 | StmtWithSemi::Yes => { |
160 | p.expect(SEMI); | 160 | p.expect(T![;]); |
161 | } | 161 | } |
162 | StmtWithSemi::No => {} | 162 | StmtWithSemi::No => {} |
163 | StmtWithSemi::Optional => { | 163 | StmtWithSemi::Optional => { |
164 | if p.at(SEMI) { | 164 | if p.at(T![;]) { |
165 | p.eat(SEMI); | 165 | p.eat(T![;]); |
166 | } | 166 | } |
167 | } | 167 | } |
168 | } | 168 | } |
@@ -174,12 +174,12 @@ pub(crate) fn expr_block_contents(p: &mut Parser) { | |||
174 | // This is checked by a validator | 174 | // This is checked by a validator |
175 | attributes::inner_attributes(p); | 175 | attributes::inner_attributes(p); |
176 | 176 | ||
177 | while !p.at(EOF) && !p.at(R_CURLY) { | 177 | while !p.at(EOF) && !p.at(T!['}']) { |
178 | // test nocontentexpr | 178 | // test nocontentexpr |
179 | // fn foo(){ | 179 | // fn foo(){ |
180 | // ;;;some_expr();;;;{;;;};;;;Ok(()) | 180 | // ;;;some_expr();;;;{;;;};;;;Ok(()) |
181 | // } | 181 | // } |
182 | if p.current() == SEMI { | 182 | if p.current() == T![;] { |
183 | p.bump(); | 183 | p.bump(); |
184 | continue; | 184 | continue; |
185 | } | 185 | } |
@@ -202,41 +202,41 @@ enum Op { | |||
202 | fn current_op(p: &Parser) -> (u8, Op) { | 202 | fn current_op(p: &Parser) -> (u8, Op) { |
203 | if let Some(t) = p.current3() { | 203 | if let Some(t) = p.current3() { |
204 | match t { | 204 | match t { |
205 | (L_ANGLE, L_ANGLE, EQ) => return (1, Op::Composite(SHLEQ, 3)), | 205 | (T![<], T![<], T![=]) => return (1, Op::Composite(T![<<=], 3)), |
206 | (R_ANGLE, R_ANGLE, EQ) => return (1, Op::Composite(SHREQ, 3)), | 206 | (T![>], T![>], T![=]) => return (1, Op::Composite(T![>>=], 3)), |
207 | _ => (), | 207 | _ => (), |
208 | } | 208 | } |
209 | } | 209 | } |
210 | 210 | ||
211 | if let Some(t) = p.current2() { | 211 | if let Some(t) = p.current2() { |
212 | match t { | 212 | match t { |
213 | (PLUS, EQ) => return (1, Op::Composite(PLUSEQ, 2)), | 213 | (T![+], T![=]) => return (1, Op::Composite(T![+=], 2)), |
214 | (MINUS, EQ) => return (1, Op::Composite(MINUSEQ, 2)), | 214 | (T![-], T![=]) => return (1, Op::Composite(T![-=], 2)), |
215 | (STAR, EQ) => return (1, Op::Composite(STAREQ, 2)), | 215 | (T![*], T![=]) => return (1, Op::Composite(T![*=], 2)), |
216 | (PERCENT, EQ) => return (1, Op::Composite(PERCENTEQ, 2)), | 216 | (T![%], T![=]) => return (1, Op::Composite(T![%=], 2)), |
217 | (SLASH, EQ) => return (1, Op::Composite(SLASHEQ, 2)), | 217 | (T![/], T![=]) => return (1, Op::Composite(T![/=], 2)), |
218 | (PIPE, EQ) => return (1, Op::Composite(PIPEEQ, 2)), | 218 | (T![|], T![=]) => return (1, Op::Composite(T![|=], 2)), |
219 | (AMP, EQ) => return (1, Op::Composite(AMPEQ, 2)), | 219 | (T![&], T![=]) => return (1, Op::Composite(T![&=], 2)), |
220 | (CARET, EQ) => return (1, Op::Composite(CARETEQ, 2)), | 220 | (T![^], T![=]) => return (1, Op::Composite(T![^=], 2)), |
221 | (PIPE, PIPE) => return (3, Op::Composite(PIPEPIPE, 2)), | 221 | (T![|], T![|]) => return (3, Op::Composite(T![||], 2)), |
222 | (AMP, AMP) => return (4, Op::Composite(AMPAMP, 2)), | 222 | (T![&], T![&]) => return (4, Op::Composite(T![&&], 2)), |
223 | (L_ANGLE, EQ) => return (5, Op::Composite(LTEQ, 2)), | 223 | (T![<], T![=]) => return (5, Op::Composite(T![<=], 2)), |
224 | (R_ANGLE, EQ) => return (5, Op::Composite(GTEQ, 2)), | 224 | (T![>], T![=]) => return (5, Op::Composite(T![>=], 2)), |
225 | (L_ANGLE, L_ANGLE) => return (9, Op::Composite(SHL, 2)), | 225 | (T![<], T![<]) => return (9, Op::Composite(T![<<], 2)), |
226 | (R_ANGLE, R_ANGLE) => return (9, Op::Composite(SHR, 2)), | 226 | (T![>], T![>]) => return (9, Op::Composite(T![>>], 2)), |
227 | _ => (), | 227 | _ => (), |
228 | } | 228 | } |
229 | } | 229 | } |
230 | 230 | ||
231 | let bp = match p.current() { | 231 | let bp = match p.current() { |
232 | EQ => 1, | 232 | T![=] => 1, |
233 | DOTDOT | DOTDOTEQ => 2, | 233 | T![..] | T![..=] => 2, |
234 | EQEQ | NEQ | L_ANGLE | R_ANGLE => 5, | 234 | T![==] | T![!=] | T![<] | T![>] => 5, |
235 | PIPE => 6, | 235 | T![|] => 6, |
236 | CARET => 7, | 236 | T![^] => 7, |
237 | AMP => 8, | 237 | T![&] => 8, |
238 | MINUS | PLUS => 10, | 238 | T![-] | T![+] => 10, |
239 | STAR | SLASH | PERCENT => 11, | 239 | T![*] | T![/] | T![%] => 11, |
240 | _ => 0, | 240 | _ => 0, |
241 | }; | 241 | }; |
242 | (bp, Op::Simple) | 242 | (bp, Op::Simple) |
@@ -284,7 +284,7 @@ fn expr_bp( | |||
284 | newly_dollar_open = false; | 284 | newly_dollar_open = false; |
285 | } | 285 | } |
286 | 286 | ||
287 | let is_range = p.current() == DOTDOT || p.current() == DOTDOTEQ; | 287 | let is_range = p.current() == T![..] || p.current() == T![..=]; |
288 | let (op_bp, op) = current_op(p); | 288 | let (op_bp, op) = current_op(p); |
289 | if op_bp < bp { | 289 | if op_bp < bp { |
290 | break; | 290 | break; |
@@ -318,10 +318,10 @@ fn lhs( | |||
318 | // let _ = &1; | 318 | // let _ = &1; |
319 | // let _ = &mut &f(); | 319 | // let _ = &mut &f(); |
320 | // } | 320 | // } |
321 | AMP => { | 321 | T![&] => { |
322 | m = p.start(); | 322 | m = p.start(); |
323 | p.bump(); | 323 | p.bump(); |
324 | p.eat(MUT_KW); | 324 | p.eat(T![mut]); |
325 | REF_EXPR | 325 | REF_EXPR |
326 | } | 326 | } |
327 | // test unary_expr | 327 | // test unary_expr |
@@ -330,14 +330,14 @@ fn lhs( | |||
330 | // !!true; | 330 | // !!true; |
331 | // --1; | 331 | // --1; |
332 | // } | 332 | // } |
333 | STAR | EXCL | MINUS => { | 333 | T![*] | T![!] | T![-] => { |
334 | m = p.start(); | 334 | m = p.start(); |
335 | p.bump(); | 335 | p.bump(); |
336 | PREFIX_EXPR | 336 | PREFIX_EXPR |
337 | } | 337 | } |
338 | // test full_range_expr | 338 | // test full_range_expr |
339 | // fn foo() { xs[..]; } | 339 | // fn foo() { xs[..]; } |
340 | DOTDOT | DOTDOTEQ => { | 340 | T![..] | T![..=] => { |
341 | m = p.start(); | 341 | m = p.start(); |
342 | p.bump(); | 342 | p.bump(); |
343 | if p.at_ts(EXPR_FIRST) { | 343 | if p.at_ts(EXPR_FIRST) { |
@@ -375,21 +375,21 @@ fn postfix_expr( | |||
375 | // [] => {} | 375 | // [] => {} |
376 | // } | 376 | // } |
377 | // } | 377 | // } |
378 | L_PAREN if allow_calls => call_expr(p, lhs), | 378 | T!['('] if allow_calls => call_expr(p, lhs), |
379 | L_BRACK if allow_calls => index_expr(p, lhs), | 379 | T!['['] if allow_calls => index_expr(p, lhs), |
380 | DOT if p.nth(1) == IDENT && (p.nth(2) == L_PAREN || p.nth(2) == COLONCOLON) => { | 380 | T![.] if p.nth(1) == IDENT && (p.nth(2) == T!['('] || p.nth(2) == T![::]) => { |
381 | method_call_expr(p, lhs) | 381 | method_call_expr(p, lhs) |
382 | } | 382 | } |
383 | DOT => field_expr(p, lhs), | 383 | T![.] => field_expr(p, lhs), |
384 | // test postfix_range | 384 | // test postfix_range |
385 | // fn foo() { let x = 1..; } | 385 | // fn foo() { let x = 1..; } |
386 | DOTDOT | DOTDOTEQ if !EXPR_FIRST.contains(p.nth(1)) => { | 386 | T![..] | T![..=] if !EXPR_FIRST.contains(p.nth(1)) => { |
387 | let m = lhs.precede(p); | 387 | let m = lhs.precede(p); |
388 | p.bump(); | 388 | p.bump(); |
389 | m.complete(p, RANGE_EXPR) | 389 | m.complete(p, RANGE_EXPR) |
390 | } | 390 | } |
391 | QUESTION => try_expr(p, lhs), | 391 | T![?] => try_expr(p, lhs), |
392 | AS_KW => cast_expr(p, lhs), | 392 | T![as] => cast_expr(p, lhs), |
393 | _ => break, | 393 | _ => break, |
394 | }; | 394 | }; |
395 | allow_calls = true | 395 | allow_calls = true |
@@ -405,7 +405,7 @@ fn postfix_expr( | |||
405 | // f(<Foo as Trait>::func()); | 405 | // f(<Foo as Trait>::func()); |
406 | // } | 406 | // } |
407 | fn call_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker { | 407 | fn call_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker { |
408 | assert!(p.at(L_PAREN)); | 408 | assert!(p.at(T!['('])); |
409 | let m = lhs.precede(p); | 409 | let m = lhs.precede(p); |
410 | arg_list(p); | 410 | arg_list(p); |
411 | m.complete(p, CALL_EXPR) | 411 | m.complete(p, CALL_EXPR) |
@@ -416,11 +416,11 @@ fn call_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker { | |||
416 | // x[1][2]; | 416 | // x[1][2]; |
417 | // } | 417 | // } |
418 | fn index_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker { | 418 | fn index_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker { |
419 | assert!(p.at(L_BRACK)); | 419 | assert!(p.at(T!['['])); |
420 | let m = lhs.precede(p); | 420 | let m = lhs.precede(p); |
421 | p.bump(); | 421 | p.bump(); |
422 | expr(p); | 422 | expr(p); |
423 | p.expect(R_BRACK); | 423 | p.expect(T![']']); |
424 | m.complete(p, INDEX_EXPR) | 424 | m.complete(p, INDEX_EXPR) |
425 | } | 425 | } |
426 | 426 | ||
@@ -430,12 +430,12 @@ fn index_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker { | |||
430 | // y.bar::<T>(1, 2,); | 430 | // y.bar::<T>(1, 2,); |
431 | // } | 431 | // } |
432 | fn method_call_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker { | 432 | fn method_call_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker { |
433 | assert!(p.at(DOT) && p.nth(1) == IDENT && (p.nth(2) == L_PAREN || p.nth(2) == COLONCOLON)); | 433 | assert!(p.at(T![.]) && p.nth(1) == IDENT && (p.nth(2) == T!['('] || p.nth(2) == T![::])); |
434 | let m = lhs.precede(p); | 434 | let m = lhs.precede(p); |
435 | p.bump(); | 435 | p.bump(); |
436 | name_ref(p); | 436 | name_ref(p); |
437 | type_args::opt_type_arg_list(p, true); | 437 | type_args::opt_type_arg_list(p, true); |
438 | if p.at(L_PAREN) { | 438 | if p.at(T!['(']) { |
439 | arg_list(p); | 439 | arg_list(p); |
440 | } | 440 | } |
441 | m.complete(p, METHOD_CALL_EXPR) | 441 | m.complete(p, METHOD_CALL_EXPR) |
@@ -455,7 +455,7 @@ fn method_call_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker { | |||
455 | // x.0x01; | 455 | // x.0x01; |
456 | // } | 456 | // } |
457 | fn field_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker { | 457 | fn field_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker { |
458 | assert!(p.at(DOT)); | 458 | assert!(p.at(T![.])); |
459 | let m = lhs.precede(p); | 459 | let m = lhs.precede(p); |
460 | p.bump(); | 460 | p.bump(); |
461 | if p.at(IDENT) { | 461 | if p.at(IDENT) { |
@@ -463,7 +463,7 @@ fn field_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker { | |||
463 | } else if p.at(INT_NUMBER) { | 463 | } else if p.at(INT_NUMBER) { |
464 | p.bump(); | 464 | p.bump(); |
465 | } else if p.at(FLOAT_NUMBER) { | 465 | } else if p.at(FLOAT_NUMBER) { |
466 | // FIXME: How to recover and instead parse INT + DOT? | 466 | // FIXME: How to recover and instead parse INT + T![.]? |
467 | p.bump(); | 467 | p.bump(); |
468 | } else { | 468 | } else { |
469 | p.error("expected field name or number") | 469 | p.error("expected field name or number") |
@@ -476,7 +476,7 @@ fn field_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker { | |||
476 | // x?; | 476 | // x?; |
477 | // } | 477 | // } |
478 | fn try_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker { | 478 | fn try_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker { |
479 | assert!(p.at(QUESTION)); | 479 | assert!(p.at(T![?])); |
480 | let m = lhs.precede(p); | 480 | let m = lhs.precede(p); |
481 | p.bump(); | 481 | p.bump(); |
482 | m.complete(p, TRY_EXPR) | 482 | m.complete(p, TRY_EXPR) |
@@ -490,7 +490,7 @@ fn try_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker { | |||
490 | // 0x36 as u8 <= 0x37; | 490 | // 0x36 as u8 <= 0x37; |
491 | // } | 491 | // } |
492 | fn cast_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker { | 492 | fn cast_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker { |
493 | assert!(p.at(AS_KW)); | 493 | assert!(p.at(T![as])); |
494 | let m = lhs.precede(p); | 494 | let m = lhs.precede(p); |
495 | p.bump(); | 495 | p.bump(); |
496 | // Use type_no_bounds(), because cast expressions are not | 496 | // Use type_no_bounds(), because cast expressions are not |
@@ -500,20 +500,20 @@ fn cast_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker { | |||
500 | } | 500 | } |
501 | 501 | ||
502 | fn arg_list(p: &mut Parser) { | 502 | fn arg_list(p: &mut Parser) { |
503 | assert!(p.at(L_PAREN)); | 503 | assert!(p.at(T!['('])); |
504 | let m = p.start(); | 504 | let m = p.start(); |
505 | p.bump(); | 505 | p.bump(); |
506 | while !p.at(R_PAREN) && !p.at(EOF) { | 506 | while !p.at(T![')']) && !p.at(EOF) { |
507 | if !p.at_ts(EXPR_FIRST) { | 507 | if !p.at_ts(EXPR_FIRST) { |
508 | p.error("expected expression"); | 508 | p.error("expected expression"); |
509 | break; | 509 | break; |
510 | } | 510 | } |
511 | expr(p); | 511 | expr(p); |
512 | if !p.at(R_PAREN) && !p.expect(COMMA) { | 512 | if !p.at(T![')']) && !p.expect(T![,]) { |
513 | break; | 513 | break; |
514 | } | 514 | } |
515 | } | 515 | } |
516 | p.eat(R_PAREN); | 516 | p.eat(T![')']); |
517 | m.complete(p, ARG_LIST); | 517 | m.complete(p, ARG_LIST); |
518 | } | 518 | } |
519 | 519 | ||
@@ -525,15 +525,15 @@ fn arg_list(p: &mut Parser) { | |||
525 | // let _ = format!(); | 525 | // let _ = format!(); |
526 | // } | 526 | // } |
527 | fn path_expr(p: &mut Parser, r: Restrictions) -> (CompletedMarker, BlockLike) { | 527 | fn path_expr(p: &mut Parser, r: Restrictions) -> (CompletedMarker, BlockLike) { |
528 | assert!(paths::is_path_start(p) || p.at(L_ANGLE)); | 528 | assert!(paths::is_path_start(p) || p.at(T![<])); |
529 | let m = p.start(); | 529 | let m = p.start(); |
530 | paths::expr_path(p); | 530 | paths::expr_path(p); |
531 | match p.current() { | 531 | match p.current() { |
532 | L_CURLY if !r.forbid_structs => { | 532 | T!['{'] if !r.forbid_structs => { |
533 | named_field_list(p); | 533 | named_field_list(p); |
534 | (m.complete(p, STRUCT_LIT), BlockLike::NotBlock) | 534 | (m.complete(p, STRUCT_LIT), BlockLike::NotBlock) |
535 | } | 535 | } |
536 | EXCL => { | 536 | T![!] => { |
537 | let block_like = items::macro_call_after_excl(p); | 537 | let block_like = items::macro_call_after_excl(p); |
538 | (m.complete(p, MACRO_CALL), block_like) | 538 | (m.complete(p, MACRO_CALL), block_like) |
539 | } | 539 | } |
@@ -548,35 +548,35 @@ fn path_expr(p: &mut Parser, r: Restrictions) -> (CompletedMarker, BlockLike) { | |||
548 | // S { x, y: 32, ..Default::default() }; | 548 | // S { x, y: 32, ..Default::default() }; |
549 | // } | 549 | // } |
550 | pub(crate) fn named_field_list(p: &mut Parser) { | 550 | pub(crate) fn named_field_list(p: &mut Parser) { |
551 | assert!(p.at(L_CURLY)); | 551 | assert!(p.at(T!['{'])); |
552 | let m = p.start(); | 552 | let m = p.start(); |
553 | p.bump(); | 553 | p.bump(); |
554 | while !p.at(EOF) && !p.at(R_CURLY) { | 554 | while !p.at(EOF) && !p.at(T!['}']) { |
555 | match p.current() { | 555 | match p.current() { |
556 | // test struct_literal_field_with_attr | 556 | // test struct_literal_field_with_attr |
557 | // fn main() { | 557 | // fn main() { |
558 | // S { #[cfg(test)] field: 1 } | 558 | // S { #[cfg(test)] field: 1 } |
559 | // } | 559 | // } |
560 | IDENT | POUND => { | 560 | IDENT | T![#] => { |
561 | let m = p.start(); | 561 | let m = p.start(); |
562 | attributes::outer_attributes(p); | 562 | attributes::outer_attributes(p); |
563 | name_ref(p); | 563 | name_ref(p); |
564 | if p.eat(COLON) { | 564 | if p.eat(T![:]) { |
565 | expr(p); | 565 | expr(p); |
566 | } | 566 | } |
567 | m.complete(p, NAMED_FIELD); | 567 | m.complete(p, NAMED_FIELD); |
568 | } | 568 | } |
569 | DOTDOT => { | 569 | T![..] => { |
570 | p.bump(); | 570 | p.bump(); |
571 | expr(p); | 571 | expr(p); |
572 | } | 572 | } |
573 | L_CURLY => error_block(p, "expected a field"), | 573 | T!['{'] => error_block(p, "expected a field"), |
574 | _ => p.err_and_bump("expected identifier"), | 574 | _ => p.err_and_bump("expected identifier"), |
575 | } | 575 | } |
576 | if !p.at(R_CURLY) { | 576 | if !p.at(T!['}']) { |
577 | p.expect(COMMA); | 577 | p.expect(T![,]); |
578 | } | 578 | } |
579 | } | 579 | } |
580 | p.expect(R_CURLY); | 580 | p.expect(T!['}']); |
581 | m.complete(p, NAMED_FIELD_LIST); | 581 | m.complete(p, NAMED_FIELD_LIST); |
582 | } | 582 | } |