diff options
Diffstat (limited to 'crates/parser')
-rw-r--r-- | crates/parser/src/grammar.rs | 2 | ||||
-rw-r--r-- | crates/parser/src/grammar/expressions/atom.rs | 17 | ||||
-rw-r--r-- | crates/parser/src/grammar/items.rs | 16 | ||||
-rw-r--r-- | crates/parser/src/grammar/params.rs | 17 | ||||
-rw-r--r-- | crates/parser/src/grammar/patterns.rs | 14 | ||||
-rw-r--r-- | crates/parser/src/grammar/type_params.rs | 2 | ||||
-rw-r--r-- | crates/parser/src/grammar/types.rs | 26 | ||||
-rw-r--r-- | crates/parser/src/lib.rs | 2 | ||||
-rw-r--r-- | crates/parser/src/syntax_kind/generated.rs | 1 |
9 files changed, 70 insertions, 27 deletions
diff --git a/crates/parser/src/grammar.rs b/crates/parser/src/grammar.rs index 1a078f6b4..f08c8bab7 100644 --- a/crates/parser/src/grammar.rs +++ b/crates/parser/src/grammar.rs | |||
@@ -55,7 +55,7 @@ pub(crate) mod fragments { | |||
55 | use super::*; | 55 | use super::*; |
56 | 56 | ||
57 | pub(crate) use super::{ | 57 | pub(crate) use super::{ |
58 | expressions::block_expr, paths::type_path as path, patterns::pattern, types::type_, | 58 | expressions::block_expr, paths::type_path as path, patterns::pattern_single, types::type_, |
59 | }; | 59 | }; |
60 | 60 | ||
61 | pub(crate) fn expr(p: &mut Parser) { | 61 | pub(crate) fn expr(p: &mut Parser) { |
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 | ||
78 | struct Variadic(bool); | 81 | struct Variadic(bool); |
79 | 82 | ||
80 | fn param(p: &mut Parser, flavor: Flavor) -> Variadic { | 83 | fn 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 | // } |
154 | fn opt_self_param(p: &mut Parser) { | 156 | fn 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 | // } | ||
396 | fn 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>; |
230 | pub(super) fn for_type(p: &mut Parser) { | 230 | pub(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 |
313 | fn opt_path_type_bounds_as_dyn_trait_type(p: &mut Parser, path_type_marker: CompletedMarker) { | 319 | fn 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); |
diff --git a/crates/parser/src/lib.rs b/crates/parser/src/lib.rs index ab8e4c70e..811e740f9 100644 --- a/crates/parser/src/lib.rs +++ b/crates/parser/src/lib.rs | |||
@@ -112,7 +112,7 @@ pub fn parse_fragment( | |||
112 | FragmentKind::Path => grammar::fragments::path, | 112 | FragmentKind::Path => grammar::fragments::path, |
113 | FragmentKind::Expr => grammar::fragments::expr, | 113 | FragmentKind::Expr => grammar::fragments::expr, |
114 | FragmentKind::Type => grammar::fragments::type_, | 114 | FragmentKind::Type => grammar::fragments::type_, |
115 | FragmentKind::Pattern => grammar::fragments::pattern, | 115 | FragmentKind::Pattern => grammar::fragments::pattern_single, |
116 | FragmentKind::Item => grammar::fragments::item, | 116 | FragmentKind::Item => grammar::fragments::item, |
117 | FragmentKind::Block => grammar::fragments::block_expr, | 117 | FragmentKind::Block => grammar::fragments::block_expr, |
118 | FragmentKind::Visibility => grammar::fragments::opt_visibility, | 118 | FragmentKind::Visibility => grammar::fragments::opt_visibility, |
diff --git a/crates/parser/src/syntax_kind/generated.rs b/crates/parser/src/syntax_kind/generated.rs index 980aa5979..f69e71bdb 100644 --- a/crates/parser/src/syntax_kind/generated.rs +++ b/crates/parser/src/syntax_kind/generated.rs | |||
@@ -170,6 +170,7 @@ pub enum SyntaxKind { | |||
170 | RANGE_PAT, | 170 | RANGE_PAT, |
171 | LITERAL_PAT, | 171 | LITERAL_PAT, |
172 | MACRO_PAT, | 172 | MACRO_PAT, |
173 | CONST_BLOCK_PAT, | ||
173 | TUPLE_EXPR, | 174 | TUPLE_EXPR, |
174 | ARRAY_EXPR, | 175 | ARRAY_EXPR, |
175 | PAREN_EXPR, | 176 | PAREN_EXPR, |