aboutsummaryrefslogtreecommitdiff
path: root/crates/libsyntax2/src/grammar
diff options
context:
space:
mode:
Diffstat (limited to 'crates/libsyntax2/src/grammar')
-rw-r--r--crates/libsyntax2/src/grammar/expressions/atom.rs73
-rw-r--r--crates/libsyntax2/src/grammar/expressions/mod.rs67
-rw-r--r--crates/libsyntax2/src/grammar/items/mod.rs26
-rw-r--r--crates/libsyntax2/src/grammar/items/structs.rs75
-rw-r--r--crates/libsyntax2/src/grammar/items/traits.rs54
-rw-r--r--crates/libsyntax2/src/grammar/items/use_item.rs8
-rw-r--r--crates/libsyntax2/src/grammar/mod.rs25
-rw-r--r--crates/libsyntax2/src/grammar/patterns.rs8
8 files changed, 203 insertions, 133 deletions
diff --git a/crates/libsyntax2/src/grammar/expressions/atom.rs b/crates/libsyntax2/src/grammar/expressions/atom.rs
index 9d98340af..417366026 100644
--- a/crates/libsyntax2/src/grammar/expressions/atom.rs
+++ b/crates/libsyntax2/src/grammar/expressions/atom.rs
@@ -148,7 +148,11 @@ fn lambda_expr(p: &mut Parser) -> CompletedMarker {
148 p.eat(MOVE_KW); 148 p.eat(MOVE_KW);
149 params::param_list_opt_types(p); 149 params::param_list_opt_types(p);
150 if opt_fn_ret_type(p) { 150 if opt_fn_ret_type(p) {
151 block(p); 151 if p.at(L_CURLY) {
152 block(p);
153 } else {
154 p.error("expected a block");
155 }
152 } else { 156 } else {
153 expr(p); 157 expr(p);
154 } 158 }
@@ -254,6 +258,17 @@ fn match_expr(p: &mut Parser) -> CompletedMarker {
254 let m = p.start(); 258 let m = p.start();
255 p.bump(); 259 p.bump();
256 expr_no_struct(p); 260 expr_no_struct(p);
261 if p.at(L_CURLY) {
262 match_arm_list(p);
263 } else {
264 p.error("expected `{`")
265 }
266 m.complete(p, MATCH_EXPR)
267}
268
269fn match_arm_list(p: &mut Parser) {
270 assert!(p.at(L_CURLY));
271 let m = p.start();
257 p.eat(L_CURLY); 272 p.eat(L_CURLY);
258 while !p.at(EOF) && !p.at(R_CURLY) { 273 while !p.at(EOF) && !p.at(R_CURLY) {
259 // test match_arms_commas 274 // test match_arms_commas
@@ -271,7 +286,7 @@ fn match_expr(p: &mut Parser) -> CompletedMarker {
271 } 286 }
272 } 287 }
273 p.expect(R_CURLY); 288 p.expect(R_CURLY);
274 m.complete(p, MATCH_EXPR) 289 m.complete(p, MATCH_ARM_LIST);
275} 290}
276 291
277// test match_arm 292// test match_arm
@@ -307,62 +322,10 @@ pub(super) fn block_expr(p: &mut Parser) -> CompletedMarker {
307 assert!(p.at(L_CURLY) || p.at(UNSAFE_KW) && p.nth(1) == L_CURLY); 322 assert!(p.at(L_CURLY) || p.at(UNSAFE_KW) && p.nth(1) == L_CURLY);
308 let m = p.start(); 323 let m = p.start();
309 p.eat(UNSAFE_KW); 324 p.eat(UNSAFE_KW);
310 p.bump(); 325 block(p);
311 while !p.at(EOF) && !p.at(R_CURLY) {
312 match p.current() {
313 LET_KW => let_stmt(p),
314 _ => {
315 // test block_items
316 // fn a() { fn b() {} }
317 let m = p.start();
318 match items::maybe_item(p, items::ItemFlavor::Mod) {
319 items::MaybeItem::Item(kind) => {
320 m.complete(p, kind);
321 }
322 items::MaybeItem::Modifiers => {
323 m.abandon(p);
324 p.error("expected an item");
325 }
326 // test pub_expr
327 // fn foo() { pub 92; } //FIXME
328 items::MaybeItem::None => {
329 let is_blocklike = expressions::expr_stmt(p) == BlockLike::Block;
330 if p.eat(SEMI) || (is_blocklike && !p.at(R_CURLY)) {
331 m.complete(p, EXPR_STMT);
332 } else {
333 m.abandon(p);
334 }
335 }
336 }
337 }
338 }
339 }
340 p.expect(R_CURLY);
341 m.complete(p, BLOCK_EXPR) 326 m.complete(p, BLOCK_EXPR)
342} 327}
343 328
344// test let_stmt;
345// fn foo() {
346// let a;
347// let b: i32;
348// let c = 92;
349// let d: i32 = 92;
350// }
351fn let_stmt(p: &mut Parser) {
352 assert!(p.at(LET_KW));
353 let m = p.start();
354 p.bump();
355 patterns::pattern(p);
356 if p.at(COLON) {
357 types::ascription(p);
358 }
359 if p.eat(EQ) {
360 expressions::expr(p);
361 }
362 p.expect(SEMI);
363 m.complete(p, LET_STMT);
364}
365
366// test return_expr 329// test return_expr
367// fn foo() { 330// fn foo() {
368// return; 331// return;
diff --git a/crates/libsyntax2/src/grammar/expressions/mod.rs b/crates/libsyntax2/src/grammar/expressions/mod.rs
index 9ce0c1f8f..e133c1d9b 100644
--- a/crates/libsyntax2/src/grammar/expressions/mod.rs
+++ b/crates/libsyntax2/src/grammar/expressions/mod.rs
@@ -26,11 +26,62 @@ fn expr_no_struct(p: &mut Parser) {
26// fn c() { 1; 2; } 26// fn c() { 1; 2; }
27// fn d() { 1; 2 } 27// fn d() { 1; 2 }
28pub(super) fn block(p: &mut Parser) { 28pub(super) fn block(p: &mut Parser) {
29 if !p.at(L_CURLY) { 29 assert!(p.at(L_CURLY));
30 p.error("expected block"); 30 let m = p.start();
31 return; 31 p.bump();
32 while !p.at(EOF) && !p.at(R_CURLY) {
33 match p.current() {
34 LET_KW => let_stmt(p),
35 _ => {
36 // test block_items
37 // fn a() { fn b() {} }
38 let m = p.start();
39 match items::maybe_item(p, items::ItemFlavor::Mod) {
40 items::MaybeItem::Item(kind) => {
41 m.complete(p, kind);
42 }
43 items::MaybeItem::Modifiers => {
44 m.abandon(p);
45 p.error("expected an item");
46 }
47 // test pub_expr
48 // fn foo() { pub 92; } //FIXME
49 items::MaybeItem::None => {
50 let is_blocklike = expressions::expr_stmt(p) == BlockLike::Block;
51 if p.eat(SEMI) || (is_blocklike && !p.at(R_CURLY)) {
52 m.complete(p, EXPR_STMT);
53 } else {
54 m.abandon(p);
55 }
56 }
57 }
58 }
59 }
60 }
61 p.expect(R_CURLY);
62 m.complete(p, BLOCK);
63
64 // test let_stmt;
65 // fn foo() {
66 // let a;
67 // let b: i32;
68 // let c = 92;
69 // let d: i32 = 92;
70 // }
71 fn let_stmt(p: &mut Parser) {
72 assert!(p.at(LET_KW));
73 let m = p.start();
74 p.bump();
75 patterns::pattern(p);
76 if p.at(COLON) {
77 types::ascription(p);
78 }
79 if p.eat(EQ) {
80 expressions::expr(p);
81 }
82 p.expect(SEMI);
83 m.complete(p, LET_STMT);
32 } 84 }
33 atom::block_expr(p);
34} 85}
35 86
36#[derive(Clone, Copy)] 87#[derive(Clone, Copy)]
@@ -339,7 +390,7 @@ fn path_expr(p: &mut Parser, r: Restrictions) -> CompletedMarker {
339 paths::expr_path(p); 390 paths::expr_path(p);
340 match p.current() { 391 match p.current() {
341 L_CURLY if !r.forbid_structs => { 392 L_CURLY if !r.forbid_structs => {
342 struct_lit(p); 393 named_field_list(p);
343 m.complete(p, STRUCT_LIT) 394 m.complete(p, STRUCT_LIT)
344 } 395 }
345 EXCL => { 396 EXCL => {
@@ -356,8 +407,9 @@ fn path_expr(p: &mut Parser, r: Restrictions) -> CompletedMarker {
356// S { x, y: 32, }; 407// S { x, y: 32, };
357// S { x, y: 32, ..Default::default() }; 408// S { x, y: 32, ..Default::default() };
358// } 409// }
359fn struct_lit(p: &mut Parser) { 410fn named_field_list(p: &mut Parser) {
360 assert!(p.at(L_CURLY)); 411 assert!(p.at(L_CURLY));
412 let m = p.start();
361 p.bump(); 413 p.bump();
362 while !p.at(EOF) && !p.at(R_CURLY) { 414 while !p.at(EOF) && !p.at(R_CURLY) {
363 match p.current() { 415 match p.current() {
@@ -367,7 +419,7 @@ fn struct_lit(p: &mut Parser) {
367 if p.eat(COLON) { 419 if p.eat(COLON) {
368 expr(p); 420 expr(p);
369 } 421 }
370 m.complete(p, STRUCT_LIT_FIELD); 422 m.complete(p, NAMED_FIELD);
371 } 423 }
372 DOTDOT => { 424 DOTDOT => {
373 p.bump(); 425 p.bump();
@@ -380,4 +432,5 @@ fn struct_lit(p: &mut Parser) {
380 } 432 }
381 } 433 }
382 p.expect(R_CURLY); 434 p.expect(R_CURLY);
435 m.complete(p, NAMED_FIELD_LIST);
383} 436}
diff --git a/crates/libsyntax2/src/grammar/items/mod.rs b/crates/libsyntax2/src/grammar/items/mod.rs
index 18b681ee2..d236fb506 100644
--- a/crates/libsyntax2/src/grammar/items/mod.rs
+++ b/crates/libsyntax2/src/grammar/items/mod.rs
@@ -194,8 +194,8 @@ fn items_without_modifiers(p: &mut Parser) -> Option<SyntaxKind> {
194 // extern {} 194 // extern {}
195 EXTERN_KW if la == L_CURLY || ((la == STRING || la == RAW_STRING) && p.nth(2) == L_CURLY) => { 195 EXTERN_KW if la == L_CURLY || ((la == STRING || la == RAW_STRING) && p.nth(2) == L_CURLY) => {
196 abi(p); 196 abi(p);
197 extern_block(p); 197 extern_item_list(p);
198 EXTERN_BLOCK_EXPR 198 EXTERN_BLOCK
199 } 199 }
200 _ => return None, 200 _ => return None,
201 }; 201 };
@@ -212,10 +212,12 @@ fn extern_crate_item(p: &mut Parser) {
212 p.expect(SEMI); 212 p.expect(SEMI);
213} 213}
214 214
215fn extern_block(p: &mut Parser) { 215fn extern_item_list(p: &mut Parser) {
216 assert!(p.at(L_CURLY)); 216 assert!(p.at(L_CURLY));
217 let m = p.start();
217 p.bump(); 218 p.bump();
218 p.expect(R_CURLY); 219 p.expect(R_CURLY);
220 m.complete(p, EXTERN_ITEM_LIST);
219} 221}
220 222
221fn function(p: &mut Parser, flavor: ItemFlavor) { 223fn function(p: &mut Parser, flavor: ItemFlavor) {
@@ -284,14 +286,22 @@ fn mod_item(p: &mut Parser) {
284 p.bump(); 286 p.bump();
285 287
286 name(p); 288 name(p);
287 if !p.eat(SEMI) { 289 if p.at(L_CURLY) {
288 if p.expect(L_CURLY) { 290 mod_item_list(p);
289 mod_contents(p, true); 291 } else if !p.eat(SEMI) {
290 p.expect(R_CURLY); 292 p.error("expected `;` or `{`");
291 }
292 } 293 }
293} 294}
294 295
296fn mod_item_list(p: &mut Parser) {
297 assert!(p.at(L_CURLY));
298 let m = p.start();
299 p.bump();
300 mod_contents(p, true);
301 p.expect(R_CURLY);
302 m.complete(p, ITEM_LIST);
303}
304
295fn macro_call(p: &mut Parser) -> BlockLike { 305fn macro_call(p: &mut Parser) -> BlockLike {
296 assert!(paths::is_path_start(p)); 306 assert!(paths::is_path_start(p));
297 paths::use_path(p); 307 paths::use_path(p);
diff --git a/crates/libsyntax2/src/grammar/items/structs.rs b/crates/libsyntax2/src/grammar/items/structs.rs
index cde9d0ae6..ca027d718 100644
--- a/crates/libsyntax2/src/grammar/items/structs.rs
+++ b/crates/libsyntax2/src/grammar/items/structs.rs
@@ -14,7 +14,7 @@ pub(super) fn struct_def(p: &mut Parser) {
14 p.bump(); 14 p.bump();
15 return; 15 return;
16 } 16 }
17 L_CURLY => named_fields(p), 17 L_CURLY => named_field_def_list(p),
18 _ => { 18 _ => {
19 //TODO: special case `(` error message 19 //TODO: special case `(` error message
20 p.error("expected `;` or `{`"); 20 p.error("expected `;` or `{`");
@@ -26,9 +26,9 @@ pub(super) fn struct_def(p: &mut Parser) {
26 p.bump(); 26 p.bump();
27 return; 27 return;
28 } 28 }
29 L_CURLY => named_fields(p), 29 L_CURLY => named_field_def_list(p),
30 L_PAREN => { 30 L_PAREN => {
31 pos_fields(p); 31 pos_field_list(p);
32 p.expect(SEMI); 32 p.expect(SEMI);
33 } 33 }
34 _ => { 34 _ => {
@@ -44,46 +44,58 @@ pub(super) fn enum_def(p: &mut Parser) {
44 name(p); 44 name(p);
45 type_params::opt_type_param_list(p); 45 type_params::opt_type_param_list(p);
46 type_params::opt_where_clause(p); 46 type_params::opt_where_clause(p);
47 if p.expect(L_CURLY) { 47 if p.at(L_CURLY) {
48 while !p.at(EOF) && !p.at(R_CURLY) { 48 enum_variant_list(p);
49 let var = p.start(); 49 } else {
50 attributes::outer_attributes(p); 50 p.error("expected `{`")
51 if p.at(IDENT) { 51 }
52 name(p); 52}
53 match p.current() { 53
54 L_CURLY => named_fields(p), 54fn enum_variant_list(p: &mut Parser) {
55 L_PAREN => pos_fields(p), 55 assert!(p.at(L_CURLY));
56 EQ => { 56 let m = p.start();
57 p.bump(); 57 p.bump();
58 expressions::expr(p); 58 while !p.at(EOF) && !p.at(R_CURLY) {
59 } 59 let var = p.start();
60 _ => (), 60 attributes::outer_attributes(p);
61 if p.at(IDENT) {
62 name(p);
63 match p.current() {
64 L_CURLY => named_field_def_list(p),
65 L_PAREN => pos_field_list(p),
66 EQ => {
67 p.bump();
68 expressions::expr(p);
61 } 69 }
62 var.complete(p, ENUM_VARIANT); 70 _ => (),
63 } else {
64 var.abandon(p);
65 p.err_and_bump("expected enum variant");
66 }
67 if !p.at(R_CURLY) {
68 p.expect(COMMA);
69 } 71 }
72 var.complete(p, ENUM_VARIANT);
73 } else {
74 var.abandon(p);
75 p.err_and_bump("expected enum variant");
76 }
77 if !p.at(R_CURLY) {
78 p.expect(COMMA);
70 } 79 }
71 p.expect(R_CURLY);
72 } 80 }
81 p.expect(R_CURLY);
82 m.complete(p, ENUM_VARIANT_LIST);
73} 83}
74 84
75fn named_fields(p: &mut Parser) { 85fn named_field_def_list(p: &mut Parser) {
76 assert!(p.at(L_CURLY)); 86 assert!(p.at(L_CURLY));
87 let m = p.start();
77 p.bump(); 88 p.bump();
78 while !p.at(R_CURLY) && !p.at(EOF) { 89 while !p.at(R_CURLY) && !p.at(EOF) {
79 named_field(p); 90 named_field_def(p);
80 if !p.at(R_CURLY) { 91 if !p.at(R_CURLY) {
81 p.expect(COMMA); 92 p.expect(COMMA);
82 } 93 }
83 } 94 }
84 p.expect(R_CURLY); 95 p.expect(R_CURLY);
96 m.complete(p, NAMED_FIELD_DEF_LIST);
85 97
86 fn named_field(p: &mut Parser) { 98 fn named_field_def(p: &mut Parser) {
87 let m = p.start(); 99 let m = p.start();
88 // test field_attrs 100 // test field_attrs
89 // struct S { 101 // struct S {
@@ -96,7 +108,7 @@ fn named_fields(p: &mut Parser) {
96 name(p); 108 name(p);
97 p.expect(COLON); 109 p.expect(COLON);
98 types::type_(p); 110 types::type_(p);
99 m.complete(p, NAMED_FIELD); 111 m.complete(p, NAMED_FIELD_DEF);
100 } else { 112 } else {
101 m.abandon(p); 113 m.abandon(p);
102 p.err_and_bump("expected field declaration"); 114 p.err_and_bump("expected field declaration");
@@ -104,7 +116,9 @@ fn named_fields(p: &mut Parser) {
104 } 116 }
105} 117}
106 118
107fn pos_fields(p: &mut Parser) { 119fn pos_field_list(p: &mut Parser) {
120 assert!(p.at(L_PAREN));
121 let m = p.start();
108 if !p.expect(L_PAREN) { 122 if !p.expect(L_PAREN) {
109 return; 123 return;
110 } 124 }
@@ -119,4 +133,5 @@ fn pos_fields(p: &mut Parser) {
119 } 133 }
120 } 134 }
121 p.expect(R_PAREN); 135 p.expect(R_PAREN);
136 m.complete(p, POS_FIELD_LIST);
122} 137}
diff --git a/crates/libsyntax2/src/grammar/items/traits.rs b/crates/libsyntax2/src/grammar/items/traits.rs
index 73ecd4bef..3853ccaab 100644
--- a/crates/libsyntax2/src/grammar/items/traits.rs
+++ b/crates/libsyntax2/src/grammar/items/traits.rs
@@ -11,18 +11,29 @@ pub(super) fn trait_def(p: &mut Parser) {
11 type_params::bounds(p); 11 type_params::bounds(p);
12 } 12 }
13 type_params::opt_where_clause(p); 13 type_params::opt_where_clause(p);
14 p.expect(L_CURLY); 14 if p.at(L_CURLY) {
15 // test trait_item_items 15 trait_item_list(p);
16 // impl F { 16 } else {
17 // type A: Clone; 17 p.error("expected `{`");
18 // const B: i32; 18 }
19 // fn foo() {} 19}
20 // fn bar(&self); 20
21 // } 21// test trait_item_list
22// impl F {
23// type A: Clone;
24// const B: i32;
25// fn foo() {}
26// fn bar(&self);
27// }
28fn trait_item_list(p: &mut Parser) {
29 assert!(p.at(L_CURLY));
30 let m = p.start();
31 p.bump();
22 while !p.at(EOF) && !p.at(R_CURLY) { 32 while !p.at(EOF) && !p.at(R_CURLY) {
23 item_or_macro(p, true, ItemFlavor::Trait); 33 item_or_macro(p, true, ItemFlavor::Trait);
24 } 34 }
25 p.expect(R_CURLY); 35 p.expect(R_CURLY);
36 m.complete(p, ITEM_LIST);
26} 37}
27 38
28// test impl_item 39// test impl_item
@@ -45,19 +56,30 @@ pub(super) fn impl_item(p: &mut Parser) {
45 types::type_(p); 56 types::type_(p);
46 } 57 }
47 type_params::opt_where_clause(p); 58 type_params::opt_where_clause(p);
48 p.expect(L_CURLY); 59 if p.at(L_CURLY) {
60 impl_item_list(p);
61 } else {
62 p.error("expected `{`");
63 }
64}
65
66// test impl_item_list
67// impl F {
68// type A = i32;
69// const B: i32 = 92;
70// fn foo() {}
71// fn bar(&self) {}
72// }
73fn impl_item_list(p: &mut Parser) {
74 assert!(p.at(L_CURLY));
75 let m = p.start();
76 p.bump();
49 77
50 // test impl_item_items
51 // impl F {
52 // type A = i32;
53 // const B: i32 = 92;
54 // fn foo() {}
55 // fn bar(&self) {}
56 // }
57 while !p.at(EOF) && !p.at(R_CURLY) { 78 while !p.at(EOF) && !p.at(R_CURLY) {
58 item_or_macro(p, true, ItemFlavor::Mod); 79 item_or_macro(p, true, ItemFlavor::Mod);
59 } 80 }
60 p.expect(R_CURLY); 81 p.expect(R_CURLY);
82 m.complete(p, ITEM_LIST);
61} 83}
62 84
63fn choose_type_params_over_qpath(p: &Parser) -> bool { 85fn choose_type_params_over_qpath(p: &Parser) -> bool {
diff --git a/crates/libsyntax2/src/grammar/items/use_item.rs b/crates/libsyntax2/src/grammar/items/use_item.rs
index 3da40a629..2fbf2234a 100644
--- a/crates/libsyntax2/src/grammar/items/use_item.rs
+++ b/crates/libsyntax2/src/grammar/items/use_item.rs
@@ -20,7 +20,7 @@ fn use_tree(p: &mut Parser) {
20 if p.at(COLONCOLON) { 20 if p.at(COLONCOLON) {
21 p.bump(); 21 p.bump();
22 } 22 }
23 nested_trees(p); 23 use_tree_list(p);
24 } 24 }
25 _ if paths::is_path_start(p) => { 25 _ if paths::is_path_start(p) => {
26 paths::use_path(p); 26 paths::use_path(p);
@@ -34,7 +34,7 @@ fn use_tree(p: &mut Parser) {
34 STAR => { 34 STAR => {
35 p.bump(); 35 p.bump();
36 } 36 }
37 L_CURLY => nested_trees(p), 37 L_CURLY => use_tree_list(p),
38 _ => { 38 _ => {
39 // is this unreachable? 39 // is this unreachable?
40 p.error("expected `{` or `*`"); 40 p.error("expected `{` or `*`");
@@ -53,8 +53,9 @@ fn use_tree(p: &mut Parser) {
53 m.complete(p, USE_TREE); 53 m.complete(p, USE_TREE);
54} 54}
55 55
56fn nested_trees(p: &mut Parser) { 56fn use_tree_list(p: &mut Parser) {
57 assert!(p.at(L_CURLY)); 57 assert!(p.at(L_CURLY));
58 let m = p.start();
58 p.bump(); 59 p.bump();
59 while !p.at(EOF) && !p.at(R_CURLY) { 60 while !p.at(EOF) && !p.at(R_CURLY) {
60 use_tree(p); 61 use_tree(p);
@@ -63,4 +64,5 @@ fn nested_trees(p: &mut Parser) {
63 } 64 }
64 } 65 }
65 p.expect(R_CURLY); 66 p.expect(R_CURLY);
67 m.complete(p, USE_TREE_LIST);
66} 68}
diff --git a/crates/libsyntax2/src/grammar/mod.rs b/crates/libsyntax2/src/grammar/mod.rs
index 25887921b..0f118f12d 100644
--- a/crates/libsyntax2/src/grammar/mod.rs
+++ b/crates/libsyntax2/src/grammar/mod.rs
@@ -144,18 +144,21 @@ fn name_ref(p: &mut Parser) {
144} 144}
145 145
146fn error_block(p: &mut Parser, message: &str) { 146fn error_block(p: &mut Parser, message: &str) {
147 assert!(p.at(L_CURLY)); 147 go(p, Some(message));
148 let err = p.start(); 148 fn go(p: &mut Parser, message: Option<&str>) {
149 p.error(message); 149 assert!(p.at(L_CURLY));
150 p.bump(); 150 let m = p.start();
151 let mut level: u32 = 1; 151 if let Some(message) = message {
152 while level > 0 && !p.at(EOF) { 152 p.error(message);
153 match p.current() {
154 L_CURLY => level += 1,
155 R_CURLY => level -= 1,
156 _ => (),
157 } 153 }
158 p.bump(); 154 p.bump();
155 while !p.at(EOF) && !p.at(R_CURLY) {
156 match p.current() {
157 L_CURLY => go(p, None),
158 _ => p.bump(),
159 }
160 }
161 p.eat(R_CURLY);
162 m.complete(p, ERROR);
159 } 163 }
160 err.complete(p, ERROR);
161} 164}
diff --git a/crates/libsyntax2/src/grammar/patterns.rs b/crates/libsyntax2/src/grammar/patterns.rs
index 71a1d5445..7ddbfa318 100644
--- a/crates/libsyntax2/src/grammar/patterns.rs
+++ b/crates/libsyntax2/src/grammar/patterns.rs
@@ -69,7 +69,7 @@ fn path_pat(p: &mut Parser) -> CompletedMarker {
69 TUPLE_STRUCT_PAT 69 TUPLE_STRUCT_PAT
70 } 70 }
71 L_CURLY => { 71 L_CURLY => {
72 struct_pat_fields(p); 72 field_pat_list(p);
73 STRUCT_PAT 73 STRUCT_PAT
74 } 74 }
75 _ => PATH_PAT 75 _ => PATH_PAT
@@ -99,15 +99,16 @@ fn tuple_pat_fields(p: &mut Parser) {
99 p.expect(R_PAREN); 99 p.expect(R_PAREN);
100} 100}
101 101
102// test struct_pat_fields 102// test field_pat_list
103// fn foo() { 103// fn foo() {
104// let S {} = (); 104// let S {} = ();
105// let S { f, ref mut g } = (); 105// let S { f, ref mut g } = ();
106// let S { h: _, ..} = (); 106// let S { h: _, ..} = ();
107// let S { h: _, } = (); 107// let S { h: _, } = ();
108// } 108// }
109fn struct_pat_fields(p: &mut Parser) { 109fn field_pat_list(p: &mut Parser) {
110 assert!(p.at(L_CURLY)); 110 assert!(p.at(L_CURLY));
111 let m = p.start();
111 p.bump(); 112 p.bump();
112 while !p.at(EOF) && !p.at(R_CURLY) { 113 while !p.at(EOF) && !p.at(R_CURLY) {
113 match p.current() { 114 match p.current() {
@@ -126,6 +127,7 @@ fn struct_pat_fields(p: &mut Parser) {
126 } 127 }
127 } 128 }
128 p.expect(R_CURLY); 129 p.expect(R_CURLY);
130 m.complete(p, FIELD_PAT_LIST);
129} 131}
130 132
131// test placeholder_pat 133// test placeholder_pat