]> git.lizzy.rs Git - rust.git/blob - crates/parser/src/grammar/expressions.rs
Apply a few clippy suggestions
[rust.git] / crates / parser / src / grammar / expressions.rs
1 mod atom;
2
3 pub(crate) use self::atom::{block_expr, match_arm_list};
4 pub(super) use self::atom::{literal, LITERAL_FIRST};
5 use super::*;
6
7 pub(super) enum StmtWithSemi {
8     Yes,
9     No,
10     Optional,
11 }
12
13 const EXPR_FIRST: TokenSet = LHS_FIRST;
14
15 pub(super) fn expr(p: &mut Parser) -> (Option<CompletedMarker>, BlockLike) {
16     let r = Restrictions { forbid_structs: false, prefer_stmt: false };
17     expr_bp(p, r, 1)
18 }
19
20 pub(super) fn expr_with_attrs(p: &mut Parser) -> bool {
21     let m = p.start();
22     let has_attrs = p.at(T![#]);
23     attributes::outer_attrs(p);
24
25     let (cm, _block_like) = expr(p);
26     let success = cm.is_some();
27
28     match (has_attrs, cm) {
29         (true, Some(cm)) => {
30             let kind = cm.kind();
31             cm.undo_completion(p).abandon(p);
32             m.complete(p, kind);
33         }
34         _ => m.abandon(p),
35     }
36
37     success
38 }
39
40 pub(super) fn expr_stmt(p: &mut Parser) -> (Option<CompletedMarker>, BlockLike) {
41     let r = Restrictions { forbid_structs: false, prefer_stmt: true };
42     expr_bp(p, r, 1)
43 }
44
45 fn expr_no_struct(p: &mut Parser) {
46     let r = Restrictions { forbid_structs: true, prefer_stmt: false };
47     expr_bp(p, r, 1);
48 }
49
50 fn is_expr_stmt_attr_allowed(kind: SyntaxKind) -> bool {
51     let forbid = matches!(kind, BIN_EXPR | RANGE_EXPR);
52     !forbid
53 }
54
55 pub(super) fn stmt(p: &mut Parser, with_semi: StmtWithSemi, prefer_expr: bool) {
56     let m = p.start();
57     // test attr_on_expr_stmt
58     // fn foo() {
59     //     #[A] foo();
60     //     #[B] bar!{}
61     //     #[C] #[D] {}
62     //     #[D] return ();
63     // }
64     let has_attrs = p.at(T![#]);
65     attributes::outer_attrs(p);
66
67     if p.at(T![let]) {
68         let_stmt(p, m, with_semi);
69         return;
70     }
71
72     // test block_items
73     // fn a() { fn b() {} }
74     let m = match items::maybe_item(p, m) {
75         Ok(()) => return,
76         Err(m) => m,
77     };
78
79     let (cm, blocklike) = expr_stmt(p);
80     let kind = cm.as_ref().map(|cm| cm.kind()).unwrap_or(ERROR);
81
82     if has_attrs && !is_expr_stmt_attr_allowed(kind) {
83         // test_err attr_on_expr_not_allowed
84         // fn foo() {
85         //    #[A] 1 + 2;
86         //    #[B] if true {};
87         // }
88         p.error(format!("attributes are not allowed on {:?}", kind));
89     }
90
91     if p.at(T!['}']) || (prefer_expr && p.at(EOF)) {
92         // test attr_on_last_expr_in_block
93         // fn foo() {
94         //     { #[A] bar!()? }
95         //     #[B] &()
96         // }
97         if let Some(cm) = cm {
98             cm.undo_completion(p).abandon(p);
99             m.complete(p, kind);
100         } else {
101             m.abandon(p);
102         }
103     } else {
104         // test no_semi_after_block
105         // fn foo() {
106         //     if true {}
107         //     loop {}
108         //     match () {}
109         //     while true {}
110         //     for _ in () {}
111         //     {}
112         //     {}
113         //     macro_rules! test {
114         //          () => {}
115         //     }
116         //     test!{}
117         // }
118
119         match with_semi {
120             StmtWithSemi::Yes => {
121                 if blocklike.is_block() {
122                     p.eat(T![;]);
123                 } else {
124                     p.expect(T![;]);
125                 }
126             }
127             StmtWithSemi::No => {}
128             StmtWithSemi::Optional => {
129                 if p.at(T![;]) {
130                     p.eat(T![;]);
131                 }
132             }
133         }
134
135         m.complete(p, EXPR_STMT);
136     }
137
138     // test let_stmt
139     // fn foo() {
140     //     let a;
141     //     let b: i32;
142     //     let c = 92;
143     //     let d: i32 = 92;
144     //     let e: !;
145     //     let _: ! = {};
146     //     let f = #[attr]||{};
147     // }
148     fn let_stmt(p: &mut Parser, m: Marker, with_semi: StmtWithSemi) {
149         assert!(p.at(T![let]));
150         p.bump(T![let]);
151         patterns::pattern(p);
152         if p.at(T![:]) {
153             types::ascription(p);
154         }
155         if p.eat(T![=]) {
156             expressions::expr_with_attrs(p);
157         }
158
159         match with_semi {
160             StmtWithSemi::Yes => {
161                 p.expect(T![;]);
162             }
163             StmtWithSemi::No => {}
164             StmtWithSemi::Optional => {
165                 if p.at(T![;]) {
166                     p.eat(T![;]);
167                 }
168             }
169         }
170         m.complete(p, LET_STMT);
171     }
172 }
173
174 pub(super) fn expr_block_contents(p: &mut Parser) {
175     // This is checked by a validator
176     attributes::inner_attrs(p);
177
178     while !p.at(EOF) && !p.at(T!['}']) {
179         // test nocontentexpr
180         // fn foo(){
181         //     ;;;some_expr();;;;{;;;};;;;Ok(())
182         // }
183
184         // test nocontentexpr_after_item
185         // fn simple_function() {
186         //     enum LocalEnum {
187         //         One,
188         //         Two,
189         //     };
190         //     fn f() {};
191         //     struct S {};
192         // }
193
194         if p.at(T![;]) {
195             p.bump(T![;]);
196             continue;
197         }
198
199         stmt(p, StmtWithSemi::Yes, false)
200     }
201 }
202
203 #[derive(Clone, Copy)]
204 struct Restrictions {
205     forbid_structs: bool,
206     prefer_stmt: bool,
207 }
208
209 /// Binding powers of operators for a Pratt parser.
210 ///
211 /// See https://www.oilshell.org/blog/2016/11/03.html
212 #[rustfmt::skip]
213 fn current_op(p: &Parser) -> (u8, SyntaxKind) {
214     const NOT_AN_OP: (u8, SyntaxKind) = (0, T![@]);
215     match p.current() {
216         T![|] if p.at(T![||])  => (3,  T![||]),
217         T![|] if p.at(T![|=])  => (1,  T![|=]),
218         T![|]                  => (6,  T![|]),
219         T![>] if p.at(T![>>=]) => (1,  T![>>=]),
220         T![>] if p.at(T![>>])  => (9,  T![>>]),
221         T![>] if p.at(T![>=])  => (5,  T![>=]),
222         T![>]                  => (5,  T![>]),
223         T![=] if p.at(T![=>])  => NOT_AN_OP,
224         T![=] if p.at(T![==])  => (5,  T![==]),
225         T![=]                  => (1,  T![=]),
226         T![<] if p.at(T![<=])  => (5,  T![<=]),
227         T![<] if p.at(T![<<=]) => (1,  T![<<=]),
228         T![<] if p.at(T![<<])  => (9,  T![<<]),
229         T![<]                  => (5,  T![<]),
230         T![+] if p.at(T![+=])  => (1,  T![+=]),
231         T![+]                  => (10, T![+]),
232         T![^] if p.at(T![^=])  => (1,  T![^=]),
233         T![^]                  => (7,  T![^]),
234         T![%] if p.at(T![%=])  => (1,  T![%=]),
235         T![%]                  => (11, T![%]),
236         T![&] if p.at(T![&=])  => (1,  T![&=]),
237         T![&] if p.at(T![&&])  => (4,  T![&&]),
238         T![&]                  => (8,  T![&]),
239         T![/] if p.at(T![/=])  => (1,  T![/=]),
240         T![/]                  => (11, T![/]),
241         T![*] if p.at(T![*=])  => (1,  T![*=]),
242         T![*]                  => (11, T![*]),
243         T![.] if p.at(T![..=]) => (2,  T![..=]),
244         T![.] if p.at(T![..])  => (2,  T![..]),
245         T![!] if p.at(T![!=])  => (5,  T![!=]),
246         T![-] if p.at(T![-=])  => (1,  T![-=]),
247         T![-]                  => (10, T![-]),
248         T![as]                 => (12, T![as]),
249
250         _                      => NOT_AN_OP
251     }
252 }
253
254 // Parses expression with binding power of at least bp.
255 fn expr_bp(p: &mut Parser, mut r: Restrictions, bp: u8) -> (Option<CompletedMarker>, BlockLike) {
256     let mut lhs = match lhs(p, r) {
257         Some((lhs, blocklike)) => {
258             // test stmt_bin_expr_ambiguity
259             // fn foo() {
260             //     let _ = {1} & 2;
261             //     {1} &2;
262             // }
263             if r.prefer_stmt && blocklike.is_block() {
264                 return (Some(lhs), BlockLike::Block);
265             }
266             lhs
267         }
268         None => return (None, BlockLike::NotBlock),
269     };
270
271     loop {
272         let is_range = p.at(T![..]) || p.at(T![..=]);
273         let (op_bp, op) = current_op(p);
274         if op_bp < bp {
275             break;
276         }
277         // test as_precedence
278         // fn foo() {
279         //     let _ = &1 as *const i32;
280         // }
281         if p.at(T![as]) {
282             lhs = cast_expr(p, lhs);
283             continue;
284         }
285         let m = lhs.precede(p);
286         p.bump(op);
287
288         // test binop_resets_statementness
289         // fn foo() {
290         //     v = {1}&2;
291         // }
292         r = Restrictions { prefer_stmt: false, ..r };
293
294         if is_range {
295             // test postfix_range
296             // fn foo() {
297             //     let x = 1..;
298             //     match 1.. { _ => () };
299             //     match a.b()..S { _ => () };
300             // }
301             let has_trailing_expression =
302                 p.at_ts(EXPR_FIRST) && !(r.forbid_structs && p.at(T!['{']));
303             if !has_trailing_expression {
304                 // no RHS
305                 lhs = m.complete(p, RANGE_EXPR);
306                 break;
307             }
308         }
309
310         expr_bp(p, Restrictions { prefer_stmt: false, ..r }, op_bp + 1);
311         lhs = m.complete(p, if is_range { RANGE_EXPR } else { BIN_EXPR });
312     }
313     (Some(lhs), BlockLike::NotBlock)
314 }
315
316 const LHS_FIRST: TokenSet =
317     atom::ATOM_EXPR_FIRST.union(TokenSet::new(&[T![&], T![*], T![!], T![.], T![-]]));
318
319 fn lhs(p: &mut Parser, r: Restrictions) -> Option<(CompletedMarker, BlockLike)> {
320     let m;
321     let kind = match p.current() {
322         // test ref_expr
323         // fn foo() {
324         //     // reference operator
325         //     let _ = &1;
326         //     let _ = &mut &f();
327         //     let _ = &raw;
328         //     let _ = &raw.0;
329         //     // raw reference operator
330         //     let _ = &raw mut foo;
331         //     let _ = &raw const foo;
332         // }
333         T![&] => {
334             m = p.start();
335             p.bump(T![&]);
336             if p.at(IDENT)
337                 && p.at_contextual_kw("raw")
338                 && (p.nth_at(1, T![mut]) || p.nth_at(1, T![const]))
339             {
340                 p.bump_remap(T![raw]);
341                 p.bump_any();
342             } else {
343                 p.eat(T![mut]);
344             }
345             REF_EXPR
346         }
347         // test unary_expr
348         // fn foo() {
349         //     **&1;
350         //     !!true;
351         //     --1;
352         // }
353         T![*] | T![!] | T![-] => {
354             m = p.start();
355             p.bump_any();
356             PREFIX_EXPR
357         }
358         _ => {
359             // test full_range_expr
360             // fn foo() { xs[..]; }
361             for &op in [T![..=], T![..]].iter() {
362                 if p.at(op) {
363                     m = p.start();
364                     p.bump(op);
365                     if p.at_ts(EXPR_FIRST) && !(r.forbid_structs && p.at(T!['{'])) {
366                         expr_bp(p, r, 2);
367                     }
368                     return Some((m.complete(p, RANGE_EXPR), BlockLike::NotBlock));
369                 }
370             }
371
372             // test expression_after_block
373             // fn foo() {
374             //    let mut p = F{x: 5};
375             //    {p}.x = 10;
376             // }
377             //
378             let (lhs, blocklike) = atom::atom_expr(p, r)?;
379             return Some(postfix_expr(p, lhs, blocklike, !(r.prefer_stmt && blocklike.is_block())));
380         }
381     };
382     // parse the interior of the unary expression
383     expr_bp(p, r, 255);
384     Some((m.complete(p, kind), BlockLike::NotBlock))
385 }
386
387 fn postfix_expr(
388     p: &mut Parser,
389     mut lhs: CompletedMarker,
390     // Calls are disallowed if the type is a block and we prefer statements because the call cannot be disambiguated from a tuple
391     // E.g. `while true {break}();` is parsed as
392     // `while true {break}; ();`
393     mut block_like: BlockLike,
394     mut allow_calls: bool,
395 ) -> (CompletedMarker, BlockLike) {
396     loop {
397         lhs = match p.current() {
398             // test stmt_postfix_expr_ambiguity
399             // fn foo() {
400             //     match () {
401             //         _ => {}
402             //         () => {}
403             //         [] => {}
404             //     }
405             // }
406             T!['('] if allow_calls => call_expr(p, lhs),
407             T!['['] if allow_calls => index_expr(p, lhs),
408             T![.] => match postfix_dot_expr(p, lhs) {
409                 Ok(it) => it,
410                 Err(it) => {
411                     lhs = it;
412                     break;
413                 }
414             },
415             T![?] => try_expr(p, lhs),
416             _ => break,
417         };
418         allow_calls = true;
419         block_like = BlockLike::NotBlock;
420     }
421     return (lhs, block_like);
422
423     fn postfix_dot_expr(
424         p: &mut Parser,
425         lhs: CompletedMarker,
426     ) -> Result<CompletedMarker, CompletedMarker> {
427         assert!(p.at(T![.]));
428         if p.nth(1) == IDENT && (p.nth(2) == T!['('] || p.nth_at(2, T![::])) {
429             return Ok(method_call_expr(p, lhs));
430         }
431
432         // test await_expr
433         // fn foo() {
434         //     x.await;
435         //     x.0.await;
436         //     x.0().await?.hello();
437         // }
438         if p.nth(1) == T![await] {
439             let m = lhs.precede(p);
440             p.bump(T![.]);
441             p.bump(T![await]);
442             return Ok(m.complete(p, AWAIT_EXPR));
443         }
444
445         if p.at(T![..=]) || p.at(T![..]) {
446             return Err(lhs);
447         }
448
449         Ok(field_expr(p, lhs))
450     }
451 }
452
453 // test call_expr
454 // fn foo() {
455 //     let _ = f();
456 //     let _ = f()(1)(1, 2,);
457 //     let _ = f(<Foo>::func());
458 //     f(<Foo as Trait>::func());
459 // }
460 fn call_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
461     assert!(p.at(T!['(']));
462     let m = lhs.precede(p);
463     arg_list(p);
464     m.complete(p, CALL_EXPR)
465 }
466
467 // test index_expr
468 // fn foo() {
469 //     x[1][2];
470 // }
471 fn index_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
472     assert!(p.at(T!['[']));
473     let m = lhs.precede(p);
474     p.bump(T!['[']);
475     expr(p);
476     p.expect(T![']']);
477     m.complete(p, INDEX_EXPR)
478 }
479
480 // test method_call_expr
481 // fn foo() {
482 //     x.foo();
483 //     y.bar::<T>(1, 2,);
484 // }
485 fn method_call_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
486     assert!(p.at(T![.]) && p.nth(1) == IDENT && (p.nth(2) == T!['('] || p.nth_at(2, T![::])));
487     let m = lhs.precede(p);
488     p.bump_any();
489     name_ref(p);
490     type_args::opt_generic_arg_list(p, true);
491     if p.at(T!['(']) {
492         arg_list(p);
493     }
494     m.complete(p, METHOD_CALL_EXPR)
495 }
496
497 // test field_expr
498 // fn foo() {
499 //     x.foo;
500 //     x.0.bar;
501 //     x.0();
502 // }
503
504 // test_err bad_tuple_index_expr
505 // fn foo() {
506 //     x.0.;
507 //     x.1i32;
508 //     x.0x01;
509 // }
510 fn field_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
511     assert!(p.at(T![.]));
512     let m = lhs.precede(p);
513     p.bump(T![.]);
514     if p.at(IDENT) || p.at(INT_NUMBER) {
515         name_ref_or_index(p)
516     } else if p.at(FLOAT_NUMBER) {
517         // FIXME: How to recover and instead parse INT + T![.]?
518         p.bump_any();
519     } else {
520         p.error("expected field name or number")
521     }
522     m.complete(p, FIELD_EXPR)
523 }
524
525 // test try_expr
526 // fn foo() {
527 //     x?;
528 // }
529 fn try_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
530     assert!(p.at(T![?]));
531     let m = lhs.precede(p);
532     p.bump(T![?]);
533     m.complete(p, TRY_EXPR)
534 }
535
536 // test cast_expr
537 // fn foo() {
538 //     82 as i32;
539 //     81 as i8 + 1;
540 //     79 as i16 - 1;
541 //     0x36 as u8 <= 0x37;
542 // }
543 fn cast_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
544     assert!(p.at(T![as]));
545     let m = lhs.precede(p);
546     p.bump(T![as]);
547     // Use type_no_bounds(), because cast expressions are not
548     // allowed to have bounds.
549     types::type_no_bounds(p);
550     m.complete(p, CAST_EXPR)
551 }
552
553 fn arg_list(p: &mut Parser) {
554     assert!(p.at(T!['(']));
555     let m = p.start();
556     p.bump(T!['(']);
557     while !p.at(T![')']) && !p.at(EOF) {
558         // test arg_with_attr
559         // fn main() {
560         //     foo(#[attr] 92)
561         // }
562         if !expr_with_attrs(p) {
563             break;
564         }
565         if !p.at(T![')']) && !p.expect(T![,]) {
566             break;
567         }
568     }
569     p.eat(T![')']);
570     m.complete(p, ARG_LIST);
571 }
572
573 // test path_expr
574 // fn foo() {
575 //     let _ = a;
576 //     let _ = a::b;
577 //     let _ = ::a::<b>;
578 //     let _ = format!();
579 // }
580 fn path_expr(p: &mut Parser, r: Restrictions) -> (CompletedMarker, BlockLike) {
581     assert!(paths::is_path_start(p));
582     let m = p.start();
583     paths::expr_path(p);
584     match p.current() {
585         T!['{'] if !r.forbid_structs => {
586             record_expr_field_list(p);
587             (m.complete(p, RECORD_EXPR), BlockLike::NotBlock)
588         }
589         T![!] if !p.at(T![!=]) => {
590             let block_like = items::macro_call_after_excl(p);
591             (m.complete(p, MACRO_CALL), block_like)
592         }
593         _ => (m.complete(p, PATH_EXPR), BlockLike::NotBlock),
594     }
595 }
596
597 // test record_lit
598 // fn foo() {
599 //     S {};
600 //     S { x, y: 32, };
601 //     S { x, y: 32, ..Default::default() };
602 //     TupleStruct { 0: 1 };
603 // }
604 pub(crate) fn record_expr_field_list(p: &mut Parser) {
605     assert!(p.at(T!['{']));
606     let m = p.start();
607     p.bump(T!['{']);
608     while !p.at(EOF) && !p.at(T!['}']) {
609         let m = p.start();
610         // test record_literal_field_with_attr
611         // fn main() {
612         //     S { #[cfg(test)] field: 1 }
613         // }
614         attributes::outer_attrs(p);
615
616         match p.current() {
617             IDENT | INT_NUMBER => {
618                 // test_err record_literal_before_ellipsis_recovery
619                 // fn main() {
620                 //     S { field ..S::default() }
621                 // }
622                 if p.nth_at(1, T![:]) || p.nth_at(1, T![..]) {
623                     name_ref_or_index(p);
624                     p.expect(T![:]);
625                 }
626                 expr(p);
627                 m.complete(p, RECORD_EXPR_FIELD);
628             }
629             T![.] if p.at(T![..]) => {
630                 m.abandon(p);
631                 p.bump(T![..]);
632                 expr(p);
633             }
634             T!['{'] => {
635                 error_block(p, "expected a field");
636                 m.abandon(p);
637             }
638             _ => {
639                 p.err_and_bump("expected identifier");
640                 m.abandon(p);
641             }
642         }
643         if !p.at(T!['}']) {
644             p.expect(T![,]);
645         }
646     }
647     p.expect(T!['}']);
648     m.complete(p, RECORD_EXPR_FIELD_LIST);
649 }