diff options
-rw-r--r-- | src/grammar/expressions/atom.rs | 12 | ||||
-rw-r--r-- | src/grammar/expressions/mod.rs | 110 | ||||
-rw-r--r-- | tests/data/parser/inline/0065_if_expr.rs | 3 | ||||
-rw-r--r-- | tests/data/parser/inline/0065_if_expr.txt | 83 | ||||
-rw-r--r-- | tests/data/parser/inline/0070_match_expr.rs | 1 | ||||
-rw-r--r-- | tests/data/parser/inline/0070_match_expr.txt | 28 |
6 files changed, 137 insertions, 100 deletions
diff --git a/src/grammar/expressions/atom.rs b/src/grammar/expressions/atom.rs index 95c811730..ad654df9e 100644 --- a/src/grammar/expressions/atom.rs +++ b/src/grammar/expressions/atom.rs | |||
@@ -33,13 +33,13 @@ pub(super) const ATOM_EXPR_FIRST: TokenSet = | |||
33 | IDENT, SELF_KW, SUPER_KW, COLONCOLON ], | 33 | IDENT, SELF_KW, SUPER_KW, COLONCOLON ], |
34 | ]; | 34 | ]; |
35 | 35 | ||
36 | pub(super) fn atom_expr(p: &mut Parser) -> Option<CompletedMarker> { | 36 | pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<CompletedMarker> { |
37 | match literal(p) { | 37 | match literal(p) { |
38 | Some(m) => return Some(m), | 38 | Some(m) => return Some(m), |
39 | None => (), | 39 | None => (), |
40 | } | 40 | } |
41 | if paths::is_path_start(p) { | 41 | if paths::is_path_start(p) { |
42 | return Some(path_expr(p)); | 42 | return Some(path_expr(p, r)); |
43 | } | 43 | } |
44 | let la = p.nth(1); | 44 | let la = p.nth(1); |
45 | let done = match p.current() { | 45 | let done = match p.current() { |
@@ -91,7 +91,8 @@ fn lambda_expr(p: &mut Parser) -> CompletedMarker { | |||
91 | // fn foo() { | 91 | // fn foo() { |
92 | // if true {}; | 92 | // if true {}; |
93 | // if true {} else {}; | 93 | // if true {} else {}; |
94 | // if true {} else if false {} else {} | 94 | // if true {} else if false {} else {}; |
95 | // if S {}; | ||
95 | // } | 96 | // } |
96 | fn if_expr(p: &mut Parser) -> CompletedMarker { | 97 | fn if_expr(p: &mut Parser) -> CompletedMarker { |
97 | assert!(p.at(IF_KW)); | 98 | assert!(p.at(IF_KW)); |
@@ -112,18 +113,19 @@ fn if_expr(p: &mut Parser) -> CompletedMarker { | |||
112 | fn if_head(p: &mut Parser) { | 113 | fn if_head(p: &mut Parser) { |
113 | assert!(p.at(IF_KW)); | 114 | assert!(p.at(IF_KW)); |
114 | p.bump(); | 115 | p.bump(); |
115 | expr(p); | 116 | expr_no_struct(p); |
116 | } | 117 | } |
117 | 118 | ||
118 | // test match_expr | 119 | // test match_expr |
119 | // fn foo() { | 120 | // fn foo() { |
120 | // match () { }; | 121 | // match () { }; |
122 | // match S {}; | ||
121 | // } | 123 | // } |
122 | fn match_expr(p: &mut Parser) -> CompletedMarker { | 124 | fn match_expr(p: &mut Parser) -> CompletedMarker { |
123 | assert!(p.at(MATCH_KW)); | 125 | assert!(p.at(MATCH_KW)); |
124 | let m = p.start(); | 126 | let m = p.start(); |
125 | p.bump(); | 127 | p.bump(); |
126 | expr(p); | 128 | expr_no_struct(p); |
127 | p.eat(L_CURLY); | 129 | p.eat(L_CURLY); |
128 | while !p.at(EOF) && !p.at(R_CURLY) { | 130 | while !p.at(EOF) && !p.at(R_CURLY) { |
129 | match_arm(p); | 131 | match_arm(p); |
diff --git a/src/grammar/expressions/mod.rs b/src/grammar/expressions/mod.rs index f2b0c36f5..cedbc235f 100644 --- a/src/grammar/expressions/mod.rs +++ b/src/grammar/expressions/mod.rs | |||
@@ -6,7 +6,13 @@ pub(super) use self::atom::literal; | |||
6 | const EXPR_FIRST: TokenSet = UNARY_EXPR_FIRST; | 6 | const EXPR_FIRST: TokenSet = UNARY_EXPR_FIRST; |
7 | 7 | ||
8 | pub(super) fn expr(p: &mut Parser) { | 8 | pub(super) fn expr(p: &mut Parser) { |
9 | expr_bp(p, 1) | 9 | let r = Restrictions { forbid_structs: false }; |
10 | expr_bp(p, r, 1) | ||
11 | } | ||
12 | |||
13 | fn expr_no_struct(p: &mut Parser) { | ||
14 | let r = Restrictions { forbid_structs: true }; | ||
15 | expr_bp(p, r, 1) | ||
10 | } | 16 | } |
11 | 17 | ||
12 | // test block | 18 | // test block |
@@ -22,6 +28,11 @@ pub(super) fn block(p: &mut Parser) { | |||
22 | atom::block_expr(p); | 28 | atom::block_expr(p); |
23 | } | 29 | } |
24 | 30 | ||
31 | #[derive(Clone, Copy)] | ||
32 | struct Restrictions { | ||
33 | forbid_structs: bool | ||
34 | } | ||
35 | |||
25 | // test expr_binding_power | 36 | // test expr_binding_power |
26 | // fn foo() { | 37 | // fn foo() { |
27 | // 1 + 2 * 3 == 1 * 2 + 3 | 38 | // 1 + 2 * 3 == 1 * 2 + 3 |
@@ -36,8 +47,8 @@ fn bp_of(op: SyntaxKind) -> u8 { | |||
36 | } | 47 | } |
37 | 48 | ||
38 | // Parses expression with binding power of at least bp. | 49 | // Parses expression with binding power of at least bp. |
39 | fn expr_bp(p: &mut Parser, bp: u8) { | 50 | fn expr_bp(p: &mut Parser, r: Restrictions, bp: u8) { |
40 | let mut lhs = match unary_expr(p) { | 51 | let mut lhs = match unary_expr(p, r) { |
41 | Some(lhs) => lhs, | 52 | Some(lhs) => lhs, |
42 | None => return, | 53 | None => return, |
43 | }; | 54 | }; |
@@ -47,7 +58,7 @@ fn expr_bp(p: &mut Parser, bp: u8) { | |||
47 | if op_bp < bp { | 58 | if op_bp < bp { |
48 | break; | 59 | break; |
49 | } | 60 | } |
50 | lhs = bin_expr(p, lhs, op_bp); | 61 | lhs = bin_expr(p, r, lhs, op_bp); |
51 | } | 62 | } |
52 | } | 63 | } |
53 | 64 | ||
@@ -57,17 +68,46 @@ const UNARY_EXPR_FIRST: TokenSet = | |||
57 | atom::ATOM_EXPR_FIRST, | 68 | atom::ATOM_EXPR_FIRST, |
58 | ]; | 69 | ]; |
59 | 70 | ||
60 | fn unary_expr(p: &mut Parser) -> Option<CompletedMarker> { | 71 | fn unary_expr(p: &mut Parser, r: Restrictions) -> Option<CompletedMarker> { |
61 | let done = match p.current() { | 72 | let m; |
62 | AMPERSAND => ref_expr(p), | 73 | let kind = match p.current() { |
63 | STAR => deref_expr(p), | 74 | // test ref_expr |
64 | EXCL => not_expr(p), | 75 | // fn foo() { |
76 | // let _ = &1; | ||
77 | // let _ = &mut &f(); | ||
78 | // } | ||
79 | AMPERSAND => { | ||
80 | m = p.start(); | ||
81 | p.bump(); | ||
82 | p.eat(MUT_KW); | ||
83 | REF_EXPR | ||
84 | |||
85 | }, | ||
86 | // test deref_expr | ||
87 | // fn foo() { | ||
88 | // **&1; | ||
89 | // } | ||
90 | STAR => { | ||
91 | m = p.start(); | ||
92 | p.bump(); | ||
93 | DEREF_EXPR | ||
94 | }, | ||
95 | // test not_expr | ||
96 | // fn foo() { | ||
97 | // !!true; | ||
98 | // } | ||
99 | EXCL => { | ||
100 | m = p.start(); | ||
101 | p.bump(); | ||
102 | NOT_EXPR | ||
103 | }, | ||
65 | _ => { | 104 | _ => { |
66 | let lhs = atom::atom_expr(p)?; | 105 | let lhs = atom::atom_expr(p, r)?; |
67 | postfix_expr(p, lhs) | 106 | return Some(postfix_expr(p, lhs)) |
68 | } | 107 | } |
69 | }; | 108 | }; |
70 | Some(done) | 109 | expr(p); |
110 | Some(m.complete(p, kind)) | ||
71 | } | 111 | } |
72 | 112 | ||
73 | fn postfix_expr(p: &mut Parser, mut lhs: CompletedMarker) -> CompletedMarker { | 113 | fn postfix_expr(p: &mut Parser, mut lhs: CompletedMarker) -> CompletedMarker { |
@@ -87,44 +127,6 @@ fn postfix_expr(p: &mut Parser, mut lhs: CompletedMarker) -> CompletedMarker { | |||
87 | lhs | 127 | lhs |
88 | } | 128 | } |
89 | 129 | ||
90 | // test ref_expr | ||
91 | // fn foo() { | ||
92 | // let _ = &1; | ||
93 | // let _ = &mut &f(); | ||
94 | // } | ||
95 | fn ref_expr(p: &mut Parser) -> CompletedMarker { | ||
96 | assert!(p.at(AMPERSAND)); | ||
97 | let m = p.start(); | ||
98 | p.bump(); | ||
99 | p.eat(MUT_KW); | ||
100 | expr(p); | ||
101 | m.complete(p, REF_EXPR) | ||
102 | } | ||
103 | |||
104 | // test deref_expr | ||
105 | // fn foo() { | ||
106 | // **&1; | ||
107 | // } | ||
108 | fn deref_expr(p: &mut Parser) -> CompletedMarker { | ||
109 | assert!(p.at(STAR)); | ||
110 | let m = p.start(); | ||
111 | p.bump(); | ||
112 | expr(p); | ||
113 | m.complete(p, DEREF_EXPR) | ||
114 | } | ||
115 | |||
116 | // test not_expr | ||
117 | // fn foo() { | ||
118 | // !!true; | ||
119 | // } | ||
120 | fn not_expr(p: &mut Parser) -> CompletedMarker { | ||
121 | assert!(p.at(EXCL)); | ||
122 | let m = p.start(); | ||
123 | p.bump(); | ||
124 | expr(p); | ||
125 | m.complete(p, NOT_EXPR) | ||
126 | } | ||
127 | |||
128 | // test call_expr | 130 | // test call_expr |
129 | // fn foo() { | 131 | // fn foo() { |
130 | // let _ = f(); | 132 | // let _ = f(); |
@@ -199,11 +201,11 @@ fn arg_list(p: &mut Parser) { | |||
199 | // let _ = a::b; | 201 | // let _ = a::b; |
200 | // let _ = ::a::<b>; | 202 | // let _ = ::a::<b>; |
201 | // } | 203 | // } |
202 | fn path_expr(p: &mut Parser) -> CompletedMarker { | 204 | fn path_expr(p: &mut Parser, r: Restrictions) -> CompletedMarker { |
203 | assert!(paths::is_path_start(p)); | 205 | assert!(paths::is_path_start(p)); |
204 | let m = p.start(); | 206 | let m = p.start(); |
205 | paths::expr_path(p); | 207 | paths::expr_path(p); |
206 | if p.at(L_CURLY) { | 208 | if p.at(L_CURLY) && !r.forbid_structs { |
207 | struct_lit(p); | 209 | struct_lit(p); |
208 | m.complete(p, STRUCT_LIT) | 210 | m.complete(p, STRUCT_LIT) |
209 | } else { | 211 | } else { |
@@ -243,13 +245,13 @@ fn struct_lit(p: &mut Parser) { | |||
243 | p.expect(R_CURLY); | 245 | p.expect(R_CURLY); |
244 | } | 246 | } |
245 | 247 | ||
246 | fn bin_expr(p: &mut Parser, lhs: CompletedMarker, bp: u8) -> CompletedMarker { | 248 | fn bin_expr(p: &mut Parser, r: Restrictions, lhs: CompletedMarker, bp: u8) -> CompletedMarker { |
247 | assert!(match p.current() { | 249 | assert!(match p.current() { |
248 | MINUS | PLUS | STAR | SLASH | EQEQ | NEQ => true, | 250 | MINUS | PLUS | STAR | SLASH | EQEQ | NEQ => true, |
249 | _ => false, | 251 | _ => false, |
250 | }); | 252 | }); |
251 | let m = lhs.precede(p); | 253 | let m = lhs.precede(p); |
252 | p.bump(); | 254 | p.bump(); |
253 | expr_bp(p, bp); | 255 | expr_bp(p, r, bp); |
254 | m.complete(p, BIN_EXPR) | 256 | m.complete(p, BIN_EXPR) |
255 | } | 257 | } |
diff --git a/tests/data/parser/inline/0065_if_expr.rs b/tests/data/parser/inline/0065_if_expr.rs index f1691c159..4b0d9af89 100644 --- a/tests/data/parser/inline/0065_if_expr.rs +++ b/tests/data/parser/inline/0065_if_expr.rs | |||
@@ -1,5 +1,6 @@ | |||
1 | fn foo() { | 1 | fn foo() { |
2 | if true {}; | 2 | if true {}; |
3 | if true {} else {}; | 3 | if true {} else {}; |
4 | if true {} else if false {} else {} | 4 | if true {} else if false {} else {}; |
5 | if S {}; | ||
5 | } | 6 | } |
diff --git a/tests/data/parser/inline/0065_if_expr.txt b/tests/data/parser/inline/0065_if_expr.txt index dafe536d2..8bfbf7d17 100644 --- a/tests/data/parser/inline/0065_if_expr.txt +++ b/tests/data/parser/inline/0065_if_expr.txt | |||
@@ -1,5 +1,5 @@ | |||
1 | FILE@[0; 93) | 1 | FILE@[0; 107) |
2 | FN_ITEM@[0; 93) | 2 | FN_ITEM@[0; 107) |
3 | FN_KW@[0; 2) | 3 | FN_KW@[0; 2) |
4 | NAME@[2; 6) | 4 | NAME@[2; 6) |
5 | WHITESPACE@[2; 3) | 5 | WHITESPACE@[2; 3) |
@@ -8,7 +8,7 @@ FILE@[0; 93) | |||
8 | L_PAREN@[6; 7) | 8 | L_PAREN@[6; 7) |
9 | R_PAREN@[7; 8) | 9 | R_PAREN@[7; 8) |
10 | WHITESPACE@[8; 9) | 10 | WHITESPACE@[8; 9) |
11 | BLOCK_EXPR@[9; 93) | 11 | BLOCK_EXPR@[9; 107) |
12 | L_CURLY@[9; 10) | 12 | L_CURLY@[9; 10) |
13 | EXPR_STMT@[10; 31) | 13 | EXPR_STMT@[10; 31) |
14 | IF_EXPR@[10; 25) | 14 | IF_EXPR@[10; 25) |
@@ -41,33 +41,50 @@ FILE@[0; 93) | |||
41 | R_CURLY@[48; 49) | 41 | R_CURLY@[48; 49) |
42 | SEMI@[49; 50) | 42 | SEMI@[49; 50) |
43 | WHITESPACE@[50; 55) | 43 | WHITESPACE@[50; 55) |
44 | IF_EXPR@[55; 91) | 44 | EXPR_STMT@[55; 96) |
45 | IF_KW@[55; 57) | 45 | IF_EXPR@[55; 90) |
46 | LITERAL@[57; 63) | 46 | IF_KW@[55; 57) |
47 | WHITESPACE@[57; 58) | 47 | LITERAL@[57; 63) |
48 | TRUE_KW@[58; 62) | 48 | WHITESPACE@[57; 58) |
49 | WHITESPACE@[62; 63) | 49 | TRUE_KW@[58; 62) |
50 | BLOCK_EXPR@[63; 66) | 50 | WHITESPACE@[62; 63) |
51 | L_CURLY@[63; 64) | 51 | BLOCK_EXPR@[63; 66) |
52 | R_CURLY@[64; 65) | 52 | L_CURLY@[63; 64) |
53 | WHITESPACE@[65; 66) | 53 | R_CURLY@[64; 65) |
54 | ELSE_KW@[66; 70) | 54 | WHITESPACE@[65; 66) |
55 | IF_EXPR@[70; 91) | 55 | ELSE_KW@[66; 70) |
56 | WHITESPACE@[70; 71) | 56 | IF_EXPR@[70; 90) |
57 | IF_KW@[71; 73) | 57 | WHITESPACE@[70; 71) |
58 | LITERAL@[73; 80) | 58 | IF_KW@[71; 73) |
59 | WHITESPACE@[73; 74) | 59 | LITERAL@[73; 80) |
60 | FALSE_KW@[74; 79) | 60 | WHITESPACE@[73; 74) |
61 | WHITESPACE@[79; 80) | 61 | FALSE_KW@[74; 79) |
62 | BLOCK_EXPR@[80; 83) | 62 | WHITESPACE@[79; 80) |
63 | L_CURLY@[80; 81) | 63 | BLOCK_EXPR@[80; 83) |
64 | R_CURLY@[81; 82) | 64 | L_CURLY@[80; 81) |
65 | WHITESPACE@[82; 83) | 65 | R_CURLY@[81; 82) |
66 | ELSE_KW@[83; 87) | 66 | WHITESPACE@[82; 83) |
67 | BLOCK_EXPR@[87; 91) | 67 | ELSE_KW@[83; 87) |
68 | WHITESPACE@[87; 88) | 68 | BLOCK_EXPR@[87; 90) |
69 | L_CURLY@[88; 89) | 69 | WHITESPACE@[87; 88) |
70 | R_CURLY@[89; 90) | 70 | L_CURLY@[88; 89) |
71 | WHITESPACE@[90; 91) | 71 | R_CURLY@[89; 90) |
72 | R_CURLY@[91; 92) | 72 | SEMI@[90; 91) |
73 | WHITESPACE@[92; 93) | 73 | WHITESPACE@[91; 96) |
74 | EXPR_STMT@[96; 105) | ||
75 | IF_EXPR@[96; 103) | ||
76 | IF_KW@[96; 98) | ||
77 | PATH_EXPR@[98; 101) | ||
78 | PATH@[98; 101) | ||
79 | PATH_SEGMENT@[98; 101) | ||
80 | NAME_REF@[98; 101) | ||
81 | WHITESPACE@[98; 99) | ||
82 | IDENT@[99; 100) "S" | ||
83 | WHITESPACE@[100; 101) | ||
84 | BLOCK_EXPR@[101; 103) | ||
85 | L_CURLY@[101; 102) | ||
86 | R_CURLY@[102; 103) | ||
87 | SEMI@[103; 104) | ||
88 | WHITESPACE@[104; 105) | ||
89 | R_CURLY@[105; 106) | ||
90 | WHITESPACE@[106; 107) | ||
diff --git a/tests/data/parser/inline/0070_match_expr.rs b/tests/data/parser/inline/0070_match_expr.rs index 40318b350..c9205dfa3 100644 --- a/tests/data/parser/inline/0070_match_expr.rs +++ b/tests/data/parser/inline/0070_match_expr.rs | |||
@@ -1,3 +1,4 @@ | |||
1 | fn foo() { | 1 | fn foo() { |
2 | match () { }; | 2 | match () { }; |
3 | match S {}; | ||
3 | } | 4 | } |
diff --git a/tests/data/parser/inline/0070_match_expr.txt b/tests/data/parser/inline/0070_match_expr.txt index 2dc2f4130..6a3ac09a1 100644 --- a/tests/data/parser/inline/0070_match_expr.txt +++ b/tests/data/parser/inline/0070_match_expr.txt | |||
@@ -1,5 +1,5 @@ | |||
1 | FILE@[0; 31) | 1 | FILE@[0; 47) |
2 | FN_ITEM@[0; 31) | 2 | FN_ITEM@[0; 47) |
3 | FN_KW@[0; 2) | 3 | FN_KW@[0; 2) |
4 | NAME@[2; 6) | 4 | NAME@[2; 6) |
5 | WHITESPACE@[2; 3) | 5 | WHITESPACE@[2; 3) |
@@ -8,9 +8,9 @@ FILE@[0; 31) | |||
8 | L_PAREN@[6; 7) | 8 | L_PAREN@[6; 7) |
9 | R_PAREN@[7; 8) | 9 | R_PAREN@[7; 8) |
10 | WHITESPACE@[8; 9) | 10 | WHITESPACE@[8; 9) |
11 | BLOCK_EXPR@[9; 31) | 11 | BLOCK_EXPR@[9; 47) |
12 | L_CURLY@[9; 10) | 12 | L_CURLY@[9; 10) |
13 | EXPR_STMT@[10; 29) | 13 | EXPR_STMT@[10; 33) |
14 | MATCH_EXPR@[10; 27) | 14 | MATCH_EXPR@[10; 27) |
15 | WHITESPACE@[10; 15) | 15 | WHITESPACE@[10; 15) |
16 | MATCH_KW@[15; 20) | 16 | MATCH_KW@[15; 20) |
@@ -23,6 +23,20 @@ FILE@[0; 31) | |||
23 | WHITESPACE@[25; 26) | 23 | WHITESPACE@[25; 26) |
24 | R_CURLY@[26; 27) | 24 | R_CURLY@[26; 27) |
25 | SEMI@[27; 28) | 25 | SEMI@[27; 28) |
26 | WHITESPACE@[28; 29) | 26 | WHITESPACE@[28; 33) |
27 | R_CURLY@[29; 30) | 27 | EXPR_STMT@[33; 45) |
28 | WHITESPACE@[30; 31) | 28 | MATCH_EXPR@[33; 43) |
29 | MATCH_KW@[33; 38) | ||
30 | PATH_EXPR@[38; 41) | ||
31 | PATH@[38; 41) | ||
32 | PATH_SEGMENT@[38; 41) | ||
33 | NAME_REF@[38; 41) | ||
34 | WHITESPACE@[38; 39) | ||
35 | IDENT@[39; 40) "S" | ||
36 | WHITESPACE@[40; 41) | ||
37 | L_CURLY@[41; 42) | ||
38 | R_CURLY@[42; 43) | ||
39 | SEMI@[43; 44) | ||
40 | WHITESPACE@[44; 45) | ||
41 | R_CURLY@[45; 46) | ||
42 | WHITESPACE@[46; 47) | ||