aboutsummaryrefslogtreecommitdiff
path: root/crates/parser/src/grammar
diff options
context:
space:
mode:
Diffstat (limited to 'crates/parser/src/grammar')
-rw-r--r--crates/parser/src/grammar/expressions/atom.rs17
-rw-r--r--crates/parser/src/grammar/items.rs16
-rw-r--r--crates/parser/src/grammar/params.rs17
-rw-r--r--crates/parser/src/grammar/patterns.rs14
-rw-r--r--crates/parser/src/grammar/type_params.rs2
-rw-r--r--crates/parser/src/grammar/types.rs26
6 files changed, 67 insertions, 25 deletions
diff --git a/crates/parser/src/grammar/expressions/atom.rs b/crates/parser/src/grammar/expressions/atom.rs
index 18b63feb7..c7a3556a7 100644
--- a/crates/parser/src/grammar/expressions/atom.rs
+++ b/crates/parser/src/grammar/expressions/atom.rs
@@ -46,6 +46,7 @@ pub(super) const ATOM_EXPR_FIRST: TokenSet =
46 T![continue], 46 T![continue],
47 T![async], 47 T![async],
48 T![try], 48 T![try],
49 T![const],
49 T![loop], 50 T![loop],
50 T![for], 51 T![for],
51 LIFETIME_IDENT, 52 LIFETIME_IDENT,
@@ -115,6 +116,14 @@ pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<(CompletedMar
115 block_expr(p); 116 block_expr(p);
116 m.complete(p, EFFECT_EXPR) 117 m.complete(p, EFFECT_EXPR)
117 } 118 }
119 // test const_block
120 // fn f() { const { } }
121 T![const] if la == T!['{'] => {
122 let m = p.start();
123 p.bump(T![const]);
124 block_expr(p);
125 m.complete(p, EFFECT_EXPR)
126 }
118 T!['{'] => { 127 T!['{'] => {
119 // test for_range_from 128 // test for_range_from
120 // fn foo() { 129 // fn foo() {
@@ -156,11 +165,13 @@ fn tuple_expr(p: &mut Parser) -> CompletedMarker {
156 let mut saw_expr = false; 165 let mut saw_expr = false;
157 while !p.at(EOF) && !p.at(T![')']) { 166 while !p.at(EOF) && !p.at(T![')']) {
158 saw_expr = true; 167 saw_expr = true;
159 if !p.at_ts(EXPR_FIRST) { 168
160 p.error("expected expression"); 169 // test tuple_attrs
170 // const A: (i64, i64) = (1, #[cfg(test)] 2);
171 if !expr_with_attrs(p) {
161 break; 172 break;
162 } 173 }
163 expr(p); 174
164 if !p.at(T![')']) { 175 if !p.at(T![')']) {
165 saw_comma = true; 176 saw_comma = true;
166 p.expect(T![,]); 177 p.expect(T![,]);
diff --git a/crates/parser/src/grammar/items.rs b/crates/parser/src/grammar/items.rs
index 8999829b4..cf4168d32 100644
--- a/crates/parser/src/grammar/items.rs
+++ b/crates/parser/src/grammar/items.rs
@@ -96,7 +96,10 @@ pub(super) fn maybe_item(p: &mut Parser, m: Marker) -> Result<(), Marker> {
96 let mut has_mods = false; 96 let mut has_mods = false;
97 97
98 // modifiers 98 // modifiers
99 has_mods |= p.eat(T![const]); 99 if p.at(T![const]) && p.nth(1) != T!['{'] {
100 p.eat(T![const]);
101 has_mods = true;
102 }
100 103
101 // test_err async_without_semicolon 104 // test_err async_without_semicolon
102 // fn foo() { let _ = async {} } 105 // fn foo() { let _ = async {} }
@@ -167,7 +170,7 @@ pub(super) fn maybe_item(p: &mut Parser, m: Marker) -> Result<(), Marker> {
167 m.complete(p, TRAIT); 170 m.complete(p, TRAIT);
168 } 171 }
169 172
170 T![const] => { 173 T![const] if p.nth(1) != T!['{'] => {
171 consts::konst(p, m); 174 consts::konst(p, m);
172 } 175 }
173 176
@@ -386,10 +389,15 @@ fn macro_rules(p: &mut Parser, m: Marker) {
386 } 389 }
387 390
388 match p.current() { 391 match p.current() {
389 T!['{'] => { 392 // test macro_rules_non_brace
393 // macro_rules! m ( ($i:ident) => {} );
394 // macro_rules! m [ ($i:ident) => {} ];
395 T!['['] | T!['('] => {
390 token_tree(p); 396 token_tree(p);
397 p.expect(T![;]);
391 } 398 }
392 _ => p.error("expected `{`"), 399 T!['{'] => token_tree(p),
400 _ => p.error("expected `{`, `[`, `(`"),
393 } 401 }
394 m.complete(p, MACRO_RULES); 402 m.complete(p, MACRO_RULES);
395} 403}
diff --git a/crates/parser/src/grammar/params.rs b/crates/parser/src/grammar/params.rs
index 3ee4e4fca..2d006a1d5 100644
--- a/crates/parser/src/grammar/params.rs
+++ b/crates/parser/src/grammar/params.rs
@@ -47,20 +47,23 @@ fn list_(p: &mut Parser, flavor: Flavor) {
47 if let FnDef = flavor { 47 if let FnDef = flavor {
48 // test self_param_outer_attr 48 // test self_param_outer_attr
49 // fn f(#[must_use] self) {} 49 // fn f(#[must_use] self) {}
50 let m = p.start();
50 attributes::outer_attrs(p); 51 attributes::outer_attrs(p);
51 opt_self_param(p); 52 opt_self_param(p, m);
52 } 53 }
53 54
54 while !p.at(EOF) && !p.at(ket) { 55 while !p.at(EOF) && !p.at(ket) {
55 // test param_outer_arg 56 // test param_outer_arg
56 // fn f(#[attr1] pat: Type) {} 57 // fn f(#[attr1] pat: Type) {}
58 let m = p.start();
57 attributes::outer_attrs(p); 59 attributes::outer_attrs(p);
58 60
59 if !p.at_ts(PARAM_FIRST) { 61 if !p.at_ts(PARAM_FIRST) {
60 p.error("expected value parameter"); 62 p.error("expected value parameter");
63 m.abandon(p);
61 break; 64 break;
62 } 65 }
63 let param = param(p, flavor); 66 let param = param(p, m, flavor);
64 if !p.at(ket) { 67 if !p.at(ket) {
65 p.expect(T![,]); 68 p.expect(T![,]);
66 } 69 }
@@ -77,9 +80,8 @@ const PARAM_FIRST: TokenSet = patterns::PATTERN_FIRST.union(types::TYPE_FIRST);
77 80
78struct Variadic(bool); 81struct Variadic(bool);
79 82
80fn param(p: &mut Parser, flavor: Flavor) -> Variadic { 83fn param(p: &mut Parser, m: Marker, flavor: Flavor) -> Variadic {
81 let mut res = Variadic(false); 84 let mut res = Variadic(false);
82 let m = p.start();
83 match flavor { 85 match flavor {
84 // test param_list_vararg 86 // test param_list_vararg
85 // extern "C" { fn printf(format: *const i8, ...) -> i32; } 87 // extern "C" { fn printf(format: *const i8, ...) -> i32; }
@@ -151,10 +153,8 @@ fn variadic_param(p: &mut Parser) -> bool {
151// fn d(&'a mut self, x: i32) {} 153// fn d(&'a mut self, x: i32) {}
152// fn e(mut self) {} 154// fn e(mut self) {}
153// } 155// }
154fn opt_self_param(p: &mut Parser) { 156fn opt_self_param(p: &mut Parser, m: Marker) {
155 let m;
156 if p.at(T![self]) || p.at(T![mut]) && p.nth(1) == T![self] { 157 if p.at(T![self]) || p.at(T![mut]) && p.nth(1) == T![self] {
157 m = p.start();
158 p.eat(T![mut]); 158 p.eat(T![mut]);
159 p.eat(T![self]); 159 p.eat(T![self]);
160 // test arb_self_types 160 // test arb_self_types
@@ -174,9 +174,8 @@ fn opt_self_param(p: &mut Parser) {
174 (T![&], T![mut], T![self], _) => 3, 174 (T![&], T![mut], T![self], _) => 3,
175 (T![&], LIFETIME_IDENT, T![self], _) => 3, 175 (T![&], LIFETIME_IDENT, T![self], _) => 3,
176 (T![&], LIFETIME_IDENT, T![mut], T![self]) => 4, 176 (T![&], LIFETIME_IDENT, T![mut], T![self]) => 4,
177 _ => return, 177 _ => return m.abandon(p),
178 }; 178 };
179 m = p.start();
180 p.bump_any(); 179 p.bump_any();
181 if p.at(LIFETIME_IDENT) { 180 if p.at(LIFETIME_IDENT) {
182 lifetime(p); 181 lifetime(p);
diff --git a/crates/parser/src/grammar/patterns.rs b/crates/parser/src/grammar/patterns.rs
index 7e7f73dee..b53d5749f 100644
--- a/crates/parser/src/grammar/patterns.rs
+++ b/crates/parser/src/grammar/patterns.rs
@@ -89,6 +89,7 @@ fn atom_pat(p: &mut Parser, recovery_set: TokenSet) -> Option<CompletedMarker> {
89 let m = match p.nth(0) { 89 let m = match p.nth(0) {
90 T![box] => box_pat(p), 90 T![box] => box_pat(p),
91 T![ref] | T![mut] => ident_pat(p, true), 91 T![ref] | T![mut] => ident_pat(p, true),
92 T![const] => const_block_pat(p),
92 IDENT => match p.nth(1) { 93 IDENT => match p.nth(1) {
93 // Checks the token after an IDENT to see if a pattern is a path (Struct { .. }) or macro 94 // Checks the token after an IDENT to see if a pattern is a path (Struct { .. }) or macro
94 // (T![x]). 95 // (T![x]).
@@ -386,3 +387,16 @@ fn box_pat(p: &mut Parser) -> CompletedMarker {
386 pattern_single(p); 387 pattern_single(p);
387 m.complete(p, BOX_PAT) 388 m.complete(p, BOX_PAT)
388} 389}
390
391// test const_block_pat
392// fn main() {
393// let const { 15 } = ();
394// let const { foo(); bar() } = ();
395// }
396fn const_block_pat(p: &mut Parser) -> CompletedMarker {
397 assert!(p.at(T![const]));
398 let m = p.start();
399 p.bump(T![const]);
400 expressions::block_expr(p);
401 m.complete(p, CONST_BLOCK_PAT)
402}
diff --git a/crates/parser/src/grammar/type_params.rs b/crates/parser/src/grammar/type_params.rs
index 9c3f7c28a..4aeccd193 100644
--- a/crates/parser/src/grammar/type_params.rs
+++ b/crates/parser/src/grammar/type_params.rs
@@ -113,7 +113,7 @@ fn type_bound(p: &mut Parser) -> bool {
113 p.eat(T![?]); 113 p.eat(T![?]);
114 match p.current() { 114 match p.current() {
115 LIFETIME_IDENT => lifetime(p), 115 LIFETIME_IDENT => lifetime(p),
116 T![for] => types::for_type(p), 116 T![for] => types::for_type(p, false),
117 _ if paths::is_use_path_start(p) => types::path_type_(p, false), 117 _ if paths::is_use_path_start(p) => types::path_type_(p, false),
118 _ => { 118 _ => {
119 m.abandon(p); 119 m.abandon(p);
diff --git a/crates/parser/src/grammar/types.rs b/crates/parser/src/grammar/types.rs
index 36a15eace..94cbf7d85 100644
--- a/crates/parser/src/grammar/types.rs
+++ b/crates/parser/src/grammar/types.rs
@@ -44,7 +44,7 @@ fn type_with_bounds_cond(p: &mut Parser, allow_bounds: bool) {
44 T![&] => ref_type(p), 44 T![&] => ref_type(p),
45 T![_] => infer_type(p), 45 T![_] => infer_type(p),
46 T![fn] | T![unsafe] | T![extern] => fn_ptr_type(p), 46 T![fn] | T![unsafe] | T![extern] => fn_ptr_type(p),
47 T![for] => for_type(p), 47 T![for] => for_type(p, allow_bounds),
48 T![impl] => impl_trait_type(p), 48 T![impl] => impl_trait_type(p),
49 T![dyn] => dyn_trait_type(p), 49 T![dyn] => dyn_trait_type(p),
50 // Some path types are not allowed to have bounds (no plus) 50 // Some path types are not allowed to have bounds (no plus)
@@ -227,7 +227,7 @@ pub(super) fn for_binder(p: &mut Parser) {
227// type A = for<'a> fn() -> (); 227// type A = for<'a> fn() -> ();
228// type B = for<'a> unsafe extern "C" fn(&'a ()) -> (); 228// type B = for<'a> unsafe extern "C" fn(&'a ()) -> ();
229// type Obj = for<'a> PartialEq<&'a i32>; 229// type Obj = for<'a> PartialEq<&'a i32>;
230pub(super) fn for_type(p: &mut Parser) { 230pub(super) fn for_type(p: &mut Parser, allow_bounds: bool) {
231 assert!(p.at(T![for])); 231 assert!(p.at(T![for]));
232 let m = p.start(); 232 let m = p.start();
233 for_binder(p); 233 for_binder(p);
@@ -240,7 +240,13 @@ pub(super) fn for_type(p: &mut Parser) {
240 } 240 }
241 } 241 }
242 type_no_bounds(p); 242 type_no_bounds(p);
243 m.complete(p, FOR_TYPE); 243 let completed = m.complete(p, FOR_TYPE);
244
245 // test no_dyn_trait_leading_for
246 // type A = for<'a> Test<'a> + Send;
247 if allow_bounds {
248 opt_type_bounds_as_dyn_trait_type(p, completed);
249 }
244} 250}
245 251
246// test impl_trait_type 252// test impl_trait_type
@@ -290,7 +296,7 @@ fn path_or_macro_type_(p: &mut Parser, allow_bounds: bool) {
290 let path = m.complete(p, kind); 296 let path = m.complete(p, kind);
291 297
292 if allow_bounds { 298 if allow_bounds {
293 opt_path_type_bounds_as_dyn_trait_type(p, path); 299 opt_type_bounds_as_dyn_trait_type(p, path);
294 } 300 }
295} 301}
296 302
@@ -304,19 +310,23 @@ pub(super) fn path_type_(p: &mut Parser, allow_bounds: bool) {
304 // fn foo() -> Box<dyn T + 'f> {} 310 // fn foo() -> Box<dyn T + 'f> {}
305 let path = m.complete(p, PATH_TYPE); 311 let path = m.complete(p, PATH_TYPE);
306 if allow_bounds { 312 if allow_bounds {
307 opt_path_type_bounds_as_dyn_trait_type(p, path); 313 opt_type_bounds_as_dyn_trait_type(p, path);
308 } 314 }
309} 315}
310 316
311/// This turns a parsed PATH_TYPE optionally into a DYN_TRAIT_TYPE 317/// This turns a parsed PATH_TYPE or FOR_TYPE optionally into a DYN_TRAIT_TYPE
312/// with a TYPE_BOUND_LIST 318/// with a TYPE_BOUND_LIST
313fn opt_path_type_bounds_as_dyn_trait_type(p: &mut Parser, path_type_marker: CompletedMarker) { 319fn opt_type_bounds_as_dyn_trait_type(p: &mut Parser, type_marker: CompletedMarker) {
320 assert!(matches!(
321 type_marker.kind(),
322 SyntaxKind::PATH_TYPE | SyntaxKind::FOR_TYPE | SyntaxKind::MACRO_CALL
323 ));
314 if !p.at(T![+]) { 324 if !p.at(T![+]) {
315 return; 325 return;
316 } 326 }
317 327
318 // First create a TYPE_BOUND from the completed PATH_TYPE 328 // First create a TYPE_BOUND from the completed PATH_TYPE
319 let m = path_type_marker.precede(p).complete(p, TYPE_BOUND); 329 let m = type_marker.precede(p).complete(p, TYPE_BOUND);
320 330
321 // Next setup a marker for the TYPE_BOUND_LIST 331 // Next setup a marker for the TYPE_BOUND_LIST
322 let m = m.precede(p); 332 let m = m.precede(p);