diff --git a/src/grammar/expressions/atom.rs b/src/grammar/expressions/atom.rs index 95c81173076..ad654df9e1a 100644 --- a/src/grammar/expressions/atom.rs +++ b/src/grammar/expressions/atom.rs @@ -33,13 +33,13 @@ pub(crate) fn literal(p: &mut Parser) -> Option { IDENT, SELF_KW, SUPER_KW, COLONCOLON ], ]; -pub(super) fn atom_expr(p: &mut Parser) -> Option { +pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option { match literal(p) { Some(m) => return Some(m), None => (), } if paths::is_path_start(p) { - return Some(path_expr(p)); + return Some(path_expr(p, r)); } let la = p.nth(1); let done = match p.current() { @@ -91,7 +91,8 @@ fn lambda_expr(p: &mut Parser) -> CompletedMarker { // fn foo() { // if true {}; // if true {} else {}; -// if true {} else if false {} else {} +// if true {} else if false {} else {}; +// if S {}; // } fn if_expr(p: &mut Parser) -> CompletedMarker { assert!(p.at(IF_KW)); @@ -112,18 +113,19 @@ fn if_expr(p: &mut Parser) -> CompletedMarker { fn if_head(p: &mut Parser) { assert!(p.at(IF_KW)); p.bump(); - expr(p); + expr_no_struct(p); } // test match_expr // fn foo() { // match () { }; +// match S {}; // } fn match_expr(p: &mut Parser) -> CompletedMarker { assert!(p.at(MATCH_KW)); let m = p.start(); p.bump(); - expr(p); + expr_no_struct(p); p.eat(L_CURLY); while !p.at(EOF) && !p.at(R_CURLY) { match_arm(p); diff --git a/src/grammar/expressions/mod.rs b/src/grammar/expressions/mod.rs index f2b0c36f5fd..cedbc235f96 100644 --- a/src/grammar/expressions/mod.rs +++ b/src/grammar/expressions/mod.rs @@ -6,7 +6,13 @@ const EXPR_FIRST: TokenSet = UNARY_EXPR_FIRST; pub(super) fn expr(p: &mut Parser) { - expr_bp(p, 1) + let r = Restrictions { forbid_structs: false }; + expr_bp(p, r, 1) +} + +fn expr_no_struct(p: &mut Parser) { + let r = Restrictions { forbid_structs: true }; + expr_bp(p, r, 1) } // test block @@ -22,6 +28,11 @@ pub(super) fn block(p: &mut Parser) { atom::block_expr(p); } +#[derive(Clone, Copy)] +struct Restrictions { + forbid_structs: bool +} + // test expr_binding_power // fn foo() { // 1 + 2 * 3 == 1 * 2 + 3 @@ -36,8 +47,8 @@ fn bp_of(op: SyntaxKind) -> u8 { } // Parses expression with binding power of at least bp. -fn expr_bp(p: &mut Parser, bp: u8) { - let mut lhs = match unary_expr(p) { +fn expr_bp(p: &mut Parser, r: Restrictions, bp: u8) { + let mut lhs = match unary_expr(p, r) { Some(lhs) => lhs, None => return, }; @@ -47,7 +58,7 @@ fn expr_bp(p: &mut Parser, bp: u8) { if op_bp < bp { break; } - lhs = bin_expr(p, lhs, op_bp); + lhs = bin_expr(p, r, lhs, op_bp); } } @@ -57,17 +68,46 @@ fn expr_bp(p: &mut Parser, bp: u8) { atom::ATOM_EXPR_FIRST, ]; -fn unary_expr(p: &mut Parser) -> Option { - let done = match p.current() { - AMPERSAND => ref_expr(p), - STAR => deref_expr(p), - EXCL => not_expr(p), +fn unary_expr(p: &mut Parser, r: Restrictions) -> Option { + let m; + let kind = match p.current() { + // test ref_expr + // fn foo() { + // let _ = &1; + // let _ = &mut &f(); + // } + AMPERSAND => { + m = p.start(); + p.bump(); + p.eat(MUT_KW); + REF_EXPR + + }, + // test deref_expr + // fn foo() { + // **&1; + // } + STAR => { + m = p.start(); + p.bump(); + DEREF_EXPR + }, + // test not_expr + // fn foo() { + // !!true; + // } + EXCL => { + m = p.start(); + p.bump(); + NOT_EXPR + }, _ => { - let lhs = atom::atom_expr(p)?; - postfix_expr(p, lhs) + let lhs = atom::atom_expr(p, r)?; + return Some(postfix_expr(p, lhs)) } }; - Some(done) + expr(p); + Some(m.complete(p, kind)) } fn postfix_expr(p: &mut Parser, mut lhs: CompletedMarker) -> CompletedMarker { @@ -87,44 +127,6 @@ fn postfix_expr(p: &mut Parser, mut lhs: CompletedMarker) -> CompletedMarker { lhs } -// test ref_expr -// fn foo() { -// let _ = &1; -// let _ = &mut &f(); -// } -fn ref_expr(p: &mut Parser) -> CompletedMarker { - assert!(p.at(AMPERSAND)); - let m = p.start(); - p.bump(); - p.eat(MUT_KW); - expr(p); - m.complete(p, REF_EXPR) -} - -// test deref_expr -// fn foo() { -// **&1; -// } -fn deref_expr(p: &mut Parser) -> CompletedMarker { - assert!(p.at(STAR)); - let m = p.start(); - p.bump(); - expr(p); - m.complete(p, DEREF_EXPR) -} - -// test not_expr -// fn foo() { -// !!true; -// } -fn not_expr(p: &mut Parser) -> CompletedMarker { - assert!(p.at(EXCL)); - let m = p.start(); - p.bump(); - expr(p); - m.complete(p, NOT_EXPR) -} - // test call_expr // fn foo() { // let _ = f(); @@ -199,11 +201,11 @@ fn arg_list(p: &mut Parser) { // let _ = a::b; // let _ = ::a::; // } -fn path_expr(p: &mut Parser) -> CompletedMarker { +fn path_expr(p: &mut Parser, r: Restrictions) -> CompletedMarker { assert!(paths::is_path_start(p)); let m = p.start(); paths::expr_path(p); - if p.at(L_CURLY) { + if p.at(L_CURLY) && !r.forbid_structs { struct_lit(p); m.complete(p, STRUCT_LIT) } else { @@ -243,13 +245,13 @@ fn struct_lit(p: &mut Parser) { p.expect(R_CURLY); } -fn bin_expr(p: &mut Parser, lhs: CompletedMarker, bp: u8) -> CompletedMarker { +fn bin_expr(p: &mut Parser, r: Restrictions, lhs: CompletedMarker, bp: u8) -> CompletedMarker { assert!(match p.current() { MINUS | PLUS | STAR | SLASH | EQEQ | NEQ => true, _ => false, }); let m = lhs.precede(p); p.bump(); - expr_bp(p, bp); + expr_bp(p, r, bp); m.complete(p, BIN_EXPR) } diff --git a/tests/data/parser/inline/0065_if_expr.rs b/tests/data/parser/inline/0065_if_expr.rs index f1691c159bf..4b0d9af8952 100644 --- a/tests/data/parser/inline/0065_if_expr.rs +++ b/tests/data/parser/inline/0065_if_expr.rs @@ -1,5 +1,6 @@ fn foo() { if true {}; if true {} else {}; - if true {} else if false {} else {} + if true {} else if false {} else {}; + if S {}; } diff --git a/tests/data/parser/inline/0065_if_expr.txt b/tests/data/parser/inline/0065_if_expr.txt index dafe536d2ab..8bfbf7d17c8 100644 --- a/tests/data/parser/inline/0065_if_expr.txt +++ b/tests/data/parser/inline/0065_if_expr.txt @@ -1,5 +1,5 @@ -FILE@[0; 93) - FN_ITEM@[0; 93) +FILE@[0; 107) + FN_ITEM@[0; 107) FN_KW@[0; 2) NAME@[2; 6) WHITESPACE@[2; 3) @@ -8,7 +8,7 @@ FILE@[0; 93) L_PAREN@[6; 7) R_PAREN@[7; 8) WHITESPACE@[8; 9) - BLOCK_EXPR@[9; 93) + BLOCK_EXPR@[9; 107) L_CURLY@[9; 10) EXPR_STMT@[10; 31) IF_EXPR@[10; 25) @@ -41,33 +41,50 @@ FILE@[0; 93) R_CURLY@[48; 49) SEMI@[49; 50) WHITESPACE@[50; 55) - IF_EXPR@[55; 91) - IF_KW@[55; 57) - LITERAL@[57; 63) - WHITESPACE@[57; 58) - TRUE_KW@[58; 62) - WHITESPACE@[62; 63) - BLOCK_EXPR@[63; 66) - L_CURLY@[63; 64) - R_CURLY@[64; 65) - WHITESPACE@[65; 66) - ELSE_KW@[66; 70) - IF_EXPR@[70; 91) - WHITESPACE@[70; 71) - IF_KW@[71; 73) - LITERAL@[73; 80) - WHITESPACE@[73; 74) - FALSE_KW@[74; 79) - WHITESPACE@[79; 80) - BLOCK_EXPR@[80; 83) - L_CURLY@[80; 81) - R_CURLY@[81; 82) - WHITESPACE@[82; 83) - ELSE_KW@[83; 87) - BLOCK_EXPR@[87; 91) - WHITESPACE@[87; 88) - L_CURLY@[88; 89) - R_CURLY@[89; 90) - WHITESPACE@[90; 91) - R_CURLY@[91; 92) - WHITESPACE@[92; 93) + EXPR_STMT@[55; 96) + IF_EXPR@[55; 90) + IF_KW@[55; 57) + LITERAL@[57; 63) + WHITESPACE@[57; 58) + TRUE_KW@[58; 62) + WHITESPACE@[62; 63) + BLOCK_EXPR@[63; 66) + L_CURLY@[63; 64) + R_CURLY@[64; 65) + WHITESPACE@[65; 66) + ELSE_KW@[66; 70) + IF_EXPR@[70; 90) + WHITESPACE@[70; 71) + IF_KW@[71; 73) + LITERAL@[73; 80) + WHITESPACE@[73; 74) + FALSE_KW@[74; 79) + WHITESPACE@[79; 80) + BLOCK_EXPR@[80; 83) + L_CURLY@[80; 81) + R_CURLY@[81; 82) + WHITESPACE@[82; 83) + ELSE_KW@[83; 87) + BLOCK_EXPR@[87; 90) + WHITESPACE@[87; 88) + L_CURLY@[88; 89) + R_CURLY@[89; 90) + SEMI@[90; 91) + WHITESPACE@[91; 96) + EXPR_STMT@[96; 105) + IF_EXPR@[96; 103) + IF_KW@[96; 98) + PATH_EXPR@[98; 101) + PATH@[98; 101) + PATH_SEGMENT@[98; 101) + NAME_REF@[98; 101) + WHITESPACE@[98; 99) + IDENT@[99; 100) "S" + WHITESPACE@[100; 101) + BLOCK_EXPR@[101; 103) + L_CURLY@[101; 102) + R_CURLY@[102; 103) + SEMI@[103; 104) + WHITESPACE@[104; 105) + R_CURLY@[105; 106) + WHITESPACE@[106; 107) diff --git a/tests/data/parser/inline/0070_match_expr.rs b/tests/data/parser/inline/0070_match_expr.rs index 40318b35047..c9205dfa30f 100644 --- a/tests/data/parser/inline/0070_match_expr.rs +++ b/tests/data/parser/inline/0070_match_expr.rs @@ -1,3 +1,4 @@ fn foo() { match () { }; + match S {}; } diff --git a/tests/data/parser/inline/0070_match_expr.txt b/tests/data/parser/inline/0070_match_expr.txt index 2dc2f4130cf..6a3ac09a153 100644 --- a/tests/data/parser/inline/0070_match_expr.txt +++ b/tests/data/parser/inline/0070_match_expr.txt @@ -1,5 +1,5 @@ -FILE@[0; 31) - FN_ITEM@[0; 31) +FILE@[0; 47) + FN_ITEM@[0; 47) FN_KW@[0; 2) NAME@[2; 6) WHITESPACE@[2; 3) @@ -8,9 +8,9 @@ FILE@[0; 31) L_PAREN@[6; 7) R_PAREN@[7; 8) WHITESPACE@[8; 9) - BLOCK_EXPR@[9; 31) + BLOCK_EXPR@[9; 47) L_CURLY@[9; 10) - EXPR_STMT@[10; 29) + EXPR_STMT@[10; 33) MATCH_EXPR@[10; 27) WHITESPACE@[10; 15) MATCH_KW@[15; 20) @@ -23,6 +23,20 @@ FILE@[0; 31) WHITESPACE@[25; 26) R_CURLY@[26; 27) SEMI@[27; 28) - WHITESPACE@[28; 29) - R_CURLY@[29; 30) - WHITESPACE@[30; 31) + WHITESPACE@[28; 33) + EXPR_STMT@[33; 45) + MATCH_EXPR@[33; 43) + MATCH_KW@[33; 38) + PATH_EXPR@[38; 41) + PATH@[38; 41) + PATH_SEGMENT@[38; 41) + NAME_REF@[38; 41) + WHITESPACE@[38; 39) + IDENT@[39; 40) "S" + WHITESPACE@[40; 41) + L_CURLY@[41; 42) + R_CURLY@[42; 43) + SEMI@[43; 44) + WHITESPACE@[44; 45) + R_CURLY@[45; 46) + WHITESPACE@[46; 47)