5 pub(crate) use self::atom::{block_expr, match_arm_list};
6 pub(super) use self::atom::{literal, LITERAL_FIRST};
8 #[derive(PartialEq, Eq)]
9 pub(super) enum Semicolon {
15 const EXPR_FIRST: TokenSet = LHS_FIRST;
17 pub(super) fn expr(p: &mut Parser) -> bool {
18 let r = Restrictions { forbid_structs: false, prefer_stmt: false };
19 expr_bp(p, None, r, 1).is_some()
22 pub(super) fn expr_stmt(p: &mut Parser, m: Option<Marker>) -> Option<(CompletedMarker, BlockLike)> {
23 let r = Restrictions { forbid_structs: false, prefer_stmt: true };
27 fn expr_no_struct(p: &mut Parser) {
28 let r = Restrictions { forbid_structs: true, prefer_stmt: false };
29 expr_bp(p, None, r, 1);
32 pub(super) fn stmt(p: &mut Parser, semicolon: Semicolon) {
38 // test attr_on_expr_stmt
45 attributes::outer_attrs(p);
48 let_stmt(p, m, semicolon);
53 // fn a() { fn b() {} }
54 let m = match items::opt_item(p, m) {
59 if let Some((cm, blocklike)) = expr_stmt(p, Some(m)) {
60 if !(p.at(T!['}']) || (semicolon != Semicolon::Required && p.at(EOF))) {
61 // test no_semi_after_block
70 // macro_rules! test {
75 let m = cm.precede(p);
77 Semicolon::Required => {
78 if blocklike.is_block() {
84 Semicolon::Optional => {
87 Semicolon::Forbidden => (),
89 m.complete(p, EXPR_STMT);
94 // fn f() { let x: i32 = 92; }
95 fn let_stmt(p: &mut Parser, m: Marker, with_semi: Semicolon) {
99 // test let_stmt_ascription
100 // fn f() { let x: i32; }
101 types::ascription(p);
104 // test let_stmt_init
105 // fn f() { let x = 92; }
106 expressions::expr(p);
111 // fn f() { let Some(x) = opt else { return }; }
116 m.complete(p, LET_ELSE);
120 Semicolon::Forbidden => (),
121 Semicolon::Optional => {
124 Semicolon::Required => {
128 m.complete(p, LET_STMT);
132 pub(super) fn expr_block_contents(p: &mut Parser) {
133 attributes::inner_attrs(p);
135 while !p.at(EOF) && !p.at(T!['}']) {
136 // test nocontentexpr
138 // ;;;some_expr();;;;{;;;};;;;Ok(())
141 // test nocontentexpr_after_item
142 // fn simple_function() {
150 stmt(p, Semicolon::Required);
154 #[derive(Clone, Copy)]
155 struct Restrictions {
156 forbid_structs: bool,
160 /// Binding powers of operators for a Pratt parser.
162 /// See <https://matklad.github.io/2020/04/13/simple-but-powerful-pratt-parsing.html>
164 fn current_op(p: &Parser) -> (u8, SyntaxKind) {
165 const NOT_AN_OP: (u8, SyntaxKind) = (0, T![@]);
167 T![|] if p.at(T![||]) => (3, T![||]),
168 T![|] if p.at(T![|=]) => (1, T![|=]),
170 T![>] if p.at(T![>>=]) => (1, T![>>=]),
171 T![>] if p.at(T![>>]) => (9, T![>>]),
172 T![>] if p.at(T![>=]) => (5, T![>=]),
174 T![=] if p.at(T![=>]) => NOT_AN_OP,
175 T![=] if p.at(T![==]) => (5, T![==]),
177 T![<] if p.at(T![<=]) => (5, T![<=]),
178 T![<] if p.at(T![<<=]) => (1, T![<<=]),
179 T![<] if p.at(T![<<]) => (9, T![<<]),
181 T![+] if p.at(T![+=]) => (1, T![+=]),
182 T![+] => (10, T![+]),
183 T![^] if p.at(T![^=]) => (1, T![^=]),
185 T![%] if p.at(T![%=]) => (1, T![%=]),
186 T![%] => (11, T![%]),
187 T![&] if p.at(T![&=]) => (1, T![&=]),
188 T![&] if p.at(T![&&]) => (4, T![&&]),
190 T![/] if p.at(T![/=]) => (1, T![/=]),
191 T![/] => (11, T![/]),
192 T![*] if p.at(T![*=]) => (1, T![*=]),
193 T![*] => (11, T![*]),
194 T![.] if p.at(T![..=]) => (2, T![..=]),
195 T![.] if p.at(T![..]) => (2, T![..]),
196 T![!] if p.at(T![!=]) => (5, T![!=]),
197 T![-] if p.at(T![-=]) => (1, T![-=]),
198 T![-] => (10, T![-]),
199 T![as] => (12, T![as]),
205 // Parses expression with binding power of at least bp.
211 ) -> Option<(CompletedMarker, BlockLike)> {
212 let m = m.unwrap_or_else(|| {
214 attributes::outer_attrs(p);
217 let mut lhs = match lhs(p, r) {
218 Some((lhs, blocklike)) => {
219 let lhs = lhs.extend_to(p, m);
220 if r.prefer_stmt && blocklike.is_block() {
221 // test stmt_bin_expr_ambiguity
226 return Some((lhs, BlockLike::Block));
237 let is_range = p.at(T![..]) || p.at(T![..=]);
238 let (op_bp, op) = current_op(p);
242 // test as_precedence
243 // fn f() { let _ = &1 as *const i32; }
245 lhs = cast_expr(p, lhs);
248 let m = lhs.precede(p);
251 // test binop_resets_statementness
252 // fn f() { v = {1}&2; }
253 r = Restrictions { prefer_stmt: false, ..r };
256 // test postfix_range
259 // match 1.. { _ => () };
260 // match a.b()..S { _ => () };
262 let has_trailing_expression =
263 p.at_ts(EXPR_FIRST) && !(r.forbid_structs && p.at(T!['{']));
264 if !has_trailing_expression {
266 lhs = m.complete(p, RANGE_EXPR);
271 expr_bp(p, None, Restrictions { prefer_stmt: false, ..r }, op_bp + 1);
272 lhs = m.complete(p, if is_range { RANGE_EXPR } else { BIN_EXPR });
274 Some((lhs, BlockLike::NotBlock))
277 const LHS_FIRST: TokenSet =
278 atom::ATOM_EXPR_FIRST.union(TokenSet::new(&[T![&], T![*], T![!], T![.], T![-]]));
280 fn lhs(p: &mut Parser, r: Restrictions) -> Option<(CompletedMarker, BlockLike)> {
282 let kind = match p.current() {
285 // // reference operator
287 // let _ = &mut &f();
290 // // raw reference operator
291 // let _ = &raw mut foo;
292 // let _ = &raw const foo;
297 if p.at_contextual_kw(T![raw]) && (p.nth_at(1, T![mut]) || p.nth_at(1, T![const])) {
298 p.bump_remap(T![raw]);
311 T![*] | T![!] | T![-] => {
317 // test full_range_expr
318 // fn foo() { xs[..]; }
319 for op in [T![..=], T![..]] {
323 if p.at_ts(EXPR_FIRST) && !(r.forbid_structs && p.at(T!['{'])) {
324 expr_bp(p, None, r, 2);
326 let cm = m.complete(p, RANGE_EXPR);
327 return Some((cm, BlockLike::NotBlock));
331 // test expression_after_block
333 // let mut p = F{x: 5};
336 let (lhs, blocklike) = atom::atom_expr(p, r)?;
337 let (cm, block_like) =
338 postfix_expr(p, lhs, blocklike, !(r.prefer_stmt && blocklike.is_block()));
339 return Some((cm, block_like));
342 // parse the interior of the unary expression
343 expr_bp(p, None, r, 255);
344 let cm = m.complete(p, kind);
345 Some((cm, BlockLike::NotBlock))
350 mut lhs: CompletedMarker,
351 // Calls are disallowed if the type is a block and we prefer statements because the call cannot be disambiguated from a tuple
352 // E.g. `while true {break}();` is parsed as
353 // `while true {break}; ();`
354 mut block_like: BlockLike,
355 mut allow_calls: bool,
356 ) -> (CompletedMarker, BlockLike) {
358 lhs = match p.current() {
359 // test stmt_postfix_expr_ambiguity
367 T!['('] if allow_calls => call_expr(p, lhs),
368 T!['['] if allow_calls => index_expr(p, lhs),
369 T![.] => match postfix_dot_expr(p, lhs) {
376 T![?] => try_expr(p, lhs),
380 block_like = BlockLike::NotBlock;
382 return (lhs, block_like);
386 lhs: CompletedMarker,
387 ) -> Result<CompletedMarker, CompletedMarker> {
388 assert!(p.at(T![.]));
389 if p.nth(1) == IDENT && (p.nth(2) == T!['('] || p.nth_at(2, T![::])) {
390 return Ok(method_call_expr(p, lhs));
397 // x.0().await?.hello();
399 if p.nth(1) == T![await] {
400 let m = lhs.precede(p);
403 return Ok(m.complete(p, AWAIT_EXPR));
406 if p.at(T![..=]) || p.at(T![..]) {
410 Ok(field_expr(p, lhs))
417 // let _ = f()(1)(1, 2,);
418 // let _ = f(<Foo>::func());
419 // f(<Foo as Trait>::func());
421 fn call_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
422 assert!(p.at(T!['(']));
423 let m = lhs.precede(p);
425 m.complete(p, CALL_EXPR)
432 fn index_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
433 assert!(p.at(T!['[']));
434 let m = lhs.precede(p);
438 m.complete(p, INDEX_EXPR)
441 // test method_call_expr
444 // y.bar::<T>(1, 2,);
446 fn method_call_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
447 assert!(p.at(T![.]) && p.nth(1) == IDENT && (p.nth(2) == T!['('] || p.nth_at(2, T![::])));
448 let m = lhs.precede(p);
451 generic_args::opt_generic_arg_list(p, true);
455 m.complete(p, METHOD_CALL_EXPR)
464 fn field_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
465 assert!(p.at(T![.]));
466 let m = lhs.precede(p);
468 if p.at(IDENT) || p.at(INT_NUMBER) {
469 name_ref_or_index(p);
470 } else if p.at(FLOAT_NUMBER) {
471 // FIXME: How to recover and instead parse INT + T![.]?
474 p.error("expected field name or number");
476 m.complete(p, FIELD_EXPR)
483 fn try_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
484 assert!(p.at(T![?]));
485 let m = lhs.precede(p);
487 m.complete(p, TRY_EXPR)
495 // 0x36 as u8 <= 0x37;
497 fn cast_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
498 assert!(p.at(T![as]));
499 let m = lhs.precede(p);
501 // Use type_no_bounds(), because cast expressions are not
502 // allowed to have bounds.
503 types::type_no_bounds(p);
504 m.complete(p, CAST_EXPR)
507 fn arg_list(p: &mut Parser) {
508 assert!(p.at(T!['(']));
511 while !p.at(T![')']) && !p.at(EOF) {
512 // test arg_with_attr
519 if !p.at(T![')']) && !p.expect(T![,]) {
524 m.complete(p, ARG_LIST);
532 // let _ = format!();
534 fn path_expr(p: &mut Parser, r: Restrictions) -> (CompletedMarker, BlockLike) {
535 assert!(paths::is_path_start(p));
539 T!['{'] if !r.forbid_structs => {
540 record_expr_field_list(p);
541 (m.complete(p, RECORD_EXPR), BlockLike::NotBlock)
543 T![!] if !p.at(T![!=]) => {
544 let block_like = items::macro_call_after_excl(p);
545 (m.complete(p, MACRO_CALL), block_like)
547 _ => (m.complete(p, PATH_EXPR), BlockLike::NotBlock),
555 // S { x, y: 32, ..Default::default() };
556 // TupleStruct { 0: 1 };
558 pub(crate) fn record_expr_field_list(p: &mut Parser) {
559 assert!(p.at(T!['{']));
562 while !p.at(EOF) && !p.at(T!['}']) {
564 // test record_literal_field_with_attr
566 // S { #[cfg(test)] field: 1 }
568 attributes::outer_attrs(p);
571 IDENT | INT_NUMBER => {
572 // test_err record_literal_before_ellipsis_recovery
574 // S { field ..S::default() }
576 if p.nth_at(1, T![:]) || p.nth_at(1, T![..]) {
577 name_ref_or_index(p);
581 m.complete(p, RECORD_EXPR_FIELD);
583 T![.] if p.at(T![..]) => {
589 error_block(p, "expected a field");
593 p.err_and_bump("expected identifier");
602 m.complete(p, RECORD_EXPR_FIELD_LIST);