aboutsummaryrefslogtreecommitdiff
path: root/crates/libsyntax2/src
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2018-08-24 17:27:30 +0100
committerAleksey Kladov <[email protected]>2018-08-24 17:27:30 +0100
commit7edab6ae6b4c5d0c411e88f10e923b91dca31de3 (patch)
tree4c17856285f568c56adb7c02024ef80e821dd367 /crates/libsyntax2/src
parent4d293003964c8f9fabadb1ceb77eab29c0438de3 (diff)
nodes for blocks
Diffstat (limited to 'crates/libsyntax2/src')
-rw-r--r--crates/libsyntax2/src/ast/generated.rs16
-rw-r--r--crates/libsyntax2/src/grammar.ron21
-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
-rw-r--r--crates/libsyntax2/src/lib.rs28
-rw-r--r--crates/libsyntax2/src/syntax_kinds/generated.rs32
12 files changed, 279 insertions, 154 deletions
diff --git a/crates/libsyntax2/src/ast/generated.rs b/crates/libsyntax2/src/ast/generated.rs
index 5edb9faaa..8eb91c1df 100644
--- a/crates/libsyntax2/src/ast/generated.rs
+++ b/crates/libsyntax2/src/ast/generated.rs
@@ -283,25 +283,25 @@ impl<'a> AstNode<'a> for NameRef<'a> {
283 283
284impl<'a> NameRef<'a> {} 284impl<'a> NameRef<'a> {}
285 285
286// NamedField 286// NamedFieldDef
287#[derive(Debug, Clone, Copy)] 287#[derive(Debug, Clone, Copy)]
288pub struct NamedField<'a> { 288pub struct NamedFieldDef<'a> {
289 syntax: SyntaxNodeRef<'a>, 289 syntax: SyntaxNodeRef<'a>,
290} 290}
291 291
292impl<'a> AstNode<'a> for NamedField<'a> { 292impl<'a> AstNode<'a> for NamedFieldDef<'a> {
293 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> { 293 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
294 match syntax.kind() { 294 match syntax.kind() {
295 NAMED_FIELD => Some(NamedField { syntax }), 295 NAMED_FIELD_DEF => Some(NamedFieldDef { syntax }),
296 _ => None, 296 _ => None,
297 } 297 }
298 } 298 }
299 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax } 299 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
300} 300}
301 301
302impl<'a> ast::NameOwner<'a> for NamedField<'a> {} 302impl<'a> ast::NameOwner<'a> for NamedFieldDef<'a> {}
303impl<'a> ast::AttrsOwner<'a> for NamedField<'a> {} 303impl<'a> ast::AttrsOwner<'a> for NamedFieldDef<'a> {}
304impl<'a> NamedField<'a> {} 304impl<'a> NamedFieldDef<'a> {}
305 305
306// NeverType 306// NeverType
307#[derive(Debug, Clone, Copy)] 307#[derive(Debug, Clone, Copy)]
@@ -498,7 +498,7 @@ impl<'a> ast::NameOwner<'a> for StructDef<'a> {}
498impl<'a> ast::TypeParamsOwner<'a> for StructDef<'a> {} 498impl<'a> ast::TypeParamsOwner<'a> for StructDef<'a> {}
499impl<'a> ast::AttrsOwner<'a> for StructDef<'a> {} 499impl<'a> ast::AttrsOwner<'a> for StructDef<'a> {}
500impl<'a> StructDef<'a> { 500impl<'a> StructDef<'a> {
501 pub fn fields(self) -> impl Iterator<Item = NamedField<'a>> + 'a { 501 pub fn fields(self) -> impl Iterator<Item = NamedFieldDef<'a>> + 'a {
502 super::children(self) 502 super::children(self)
503 } 503 }
504} 504}
diff --git a/crates/libsyntax2/src/grammar.ron b/crates/libsyntax2/src/grammar.ron
index 52764e664..f4792df1d 100644
--- a/crates/libsyntax2/src/grammar.ron
+++ b/crates/libsyntax2/src/grammar.ron
@@ -149,6 +149,7 @@ Grammar(
149 "PLACEHOLDER_PAT", 149 "PLACEHOLDER_PAT",
150 "PATH_PAT", 150 "PATH_PAT",
151 "STRUCT_PAT", 151 "STRUCT_PAT",
152 "FIELD_PAT_LIST",
152 "TUPLE_STRUCT_PAT", 153 "TUPLE_STRUCT_PAT",
153 "TUPLE_PAT", 154 "TUPLE_PAT",
154 "SLICE_PAT", 155 "SLICE_PAT",
@@ -170,10 +171,12 @@ Grammar(
170 "BLOCK_EXPR", 171 "BLOCK_EXPR",
171 "RETURN_EXPR", 172 "RETURN_EXPR",
172 "MATCH_EXPR", 173 "MATCH_EXPR",
174 "MATCH_ARM_LIST",
173 "MATCH_ARM", 175 "MATCH_ARM",
174 "MATCH_GUARD", 176 "MATCH_GUARD",
175 "STRUCT_LIT", 177 "STRUCT_LIT",
176 "STRUCT_LIT_FIELD", 178 "NAMED_FIELD_LIST",
179 "NAMED_FIELD",
177 180
178 // postfix 181 // postfix
179 "CALL_EXPR", 182 "CALL_EXPR",
@@ -190,14 +193,20 @@ Grammar(
190 "RANGE_EXPR", // just weird 193 "RANGE_EXPR", // just weird
191 "BIN_EXPR", 194 "BIN_EXPR",
192 195
193 196 "BLOCK",
194 "EXTERN_BLOCK_EXPR", 197 "EXTERN_BLOCK",
198 "EXTERN_ITEM_LIST",
195 "ENUM_VARIANT", 199 "ENUM_VARIANT",
196 "NAMED_FIELD", 200 "NAMED_FIELD_DEF_LIST",
201 "NAMED_FIELD_DEF",
202 "POS_FIELD_LIST",
197 "POS_FIELD", 203 "POS_FIELD",
204 "ENUM_VARIANT_LIST",
205 "ITEM_LIST",
198 "ATTR", 206 "ATTR",
199 "META_ITEM", // not an item actually 207 "META_ITEM", // not an item actually
200 "USE_TREE", 208 "USE_TREE",
209 "USE_TREE_LIST",
201 "PATH", 210 "PATH",
202 "PATH_SEGMENT", 211 "PATH_SEGMENT",
203 "LITERAL", 212 "LITERAL",
@@ -244,10 +253,10 @@ Grammar(
244 "AttrsOwner", 253 "AttrsOwner",
245 ], 254 ],
246 collections: [ 255 collections: [
247 ["fields", "NamedField"] 256 ["fields", "NamedFieldDef"]
248 ] 257 ]
249 ), 258 ),
250 "NamedField": ( traits: ["NameOwner", "AttrsOwner"] ), 259 "NamedFieldDef": ( traits: ["NameOwner", "AttrsOwner"] ),
251 "EnumDef": ( traits: [ 260 "EnumDef": ( traits: [
252 "NameOwner", 261 "NameOwner",
253 "TypeParamsOwner", 262 "TypeParamsOwner",
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
diff --git a/crates/libsyntax2/src/lib.rs b/crates/libsyntax2/src/lib.rs
index 53ae18988..d3ecbe470 100644
--- a/crates/libsyntax2/src/lib.rs
+++ b/crates/libsyntax2/src/lib.rs
@@ -53,5 +53,31 @@ pub use {
53 53
54pub fn parse(text: &str) -> SyntaxNode { 54pub fn parse(text: &str) -> SyntaxNode {
55 let tokens = tokenize(&text); 55 let tokens = tokenize(&text);
56 parser_impl::parse::<yellow::GreenBuilder>(text, &tokens) 56 let res = parser_impl::parse::<yellow::GreenBuilder>(text, &tokens);
57 validate_block_structure(res.borrowed());
58 res
59}
60
61fn validate_block_structure(root: SyntaxNodeRef) {
62 let mut stack = Vec::new();
63 for node in algo::walk::preorder(root) {
64 match node.kind() {
65 SyntaxKind::L_CURLY => {
66 stack.push(node)
67 }
68 SyntaxKind::R_CURLY => {
69 if let Some(pair) = stack.pop() {
70 assert_eq!(node.parent(), pair.parent());
71 assert!(
72 node.next_sibling().is_none() && pair.prev_sibling().is_none(),
73 "floating curlys at {:?}\nfile:\n{}\nerror:\n{}\n",
74 node,
75 root.text(),
76 node.text(),
77 );
78 }
79 }
80 _ => (),
81 }
82 }
57} 83}
diff --git a/crates/libsyntax2/src/syntax_kinds/generated.rs b/crates/libsyntax2/src/syntax_kinds/generated.rs
index 61d527f93..6c7f44aee 100644
--- a/crates/libsyntax2/src/syntax_kinds/generated.rs
+++ b/crates/libsyntax2/src/syntax_kinds/generated.rs
@@ -147,6 +147,7 @@ pub enum SyntaxKind {
147 PLACEHOLDER_PAT, 147 PLACEHOLDER_PAT,
148 PATH_PAT, 148 PATH_PAT,
149 STRUCT_PAT, 149 STRUCT_PAT,
150 FIELD_PAT_LIST,
150 TUPLE_STRUCT_PAT, 151 TUPLE_STRUCT_PAT,
151 TUPLE_PAT, 152 TUPLE_PAT,
152 SLICE_PAT, 153 SLICE_PAT,
@@ -166,10 +167,12 @@ pub enum SyntaxKind {
166 BLOCK_EXPR, 167 BLOCK_EXPR,
167 RETURN_EXPR, 168 RETURN_EXPR,
168 MATCH_EXPR, 169 MATCH_EXPR,
170 MATCH_ARM_LIST,
169 MATCH_ARM, 171 MATCH_ARM,
170 MATCH_GUARD, 172 MATCH_GUARD,
171 STRUCT_LIT, 173 STRUCT_LIT,
172 STRUCT_LIT_FIELD, 174 NAMED_FIELD_LIST,
175 NAMED_FIELD,
173 CALL_EXPR, 176 CALL_EXPR,
174 INDEX_EXPR, 177 INDEX_EXPR,
175 METHOD_CALL_EXPR, 178 METHOD_CALL_EXPR,
@@ -180,13 +183,20 @@ pub enum SyntaxKind {
180 PREFIX_EXPR, 183 PREFIX_EXPR,
181 RANGE_EXPR, 184 RANGE_EXPR,
182 BIN_EXPR, 185 BIN_EXPR,
183 EXTERN_BLOCK_EXPR, 186 BLOCK,
187 EXTERN_BLOCK,
188 EXTERN_ITEM_LIST,
184 ENUM_VARIANT, 189 ENUM_VARIANT,
185 NAMED_FIELD, 190 NAMED_FIELD_DEF_LIST,
191 NAMED_FIELD_DEF,
192 POS_FIELD_LIST,
186 POS_FIELD, 193 POS_FIELD,
194 ENUM_VARIANT_LIST,
195 ITEM_LIST,
187 ATTR, 196 ATTR,
188 META_ITEM, 197 META_ITEM,
189 USE_TREE, 198 USE_TREE,
199 USE_TREE_LIST,
190 PATH, 200 PATH,
191 PATH_SEGMENT, 201 PATH_SEGMENT,
192 LITERAL, 202 LITERAL,
@@ -397,6 +407,7 @@ impl SyntaxKind {
397 PLACEHOLDER_PAT => &SyntaxInfo { name: "PLACEHOLDER_PAT" }, 407 PLACEHOLDER_PAT => &SyntaxInfo { name: "PLACEHOLDER_PAT" },
398 PATH_PAT => &SyntaxInfo { name: "PATH_PAT" }, 408 PATH_PAT => &SyntaxInfo { name: "PATH_PAT" },
399 STRUCT_PAT => &SyntaxInfo { name: "STRUCT_PAT" }, 409 STRUCT_PAT => &SyntaxInfo { name: "STRUCT_PAT" },
410 FIELD_PAT_LIST => &SyntaxInfo { name: "FIELD_PAT_LIST" },
400 TUPLE_STRUCT_PAT => &SyntaxInfo { name: "TUPLE_STRUCT_PAT" }, 411 TUPLE_STRUCT_PAT => &SyntaxInfo { name: "TUPLE_STRUCT_PAT" },
401 TUPLE_PAT => &SyntaxInfo { name: "TUPLE_PAT" }, 412 TUPLE_PAT => &SyntaxInfo { name: "TUPLE_PAT" },
402 SLICE_PAT => &SyntaxInfo { name: "SLICE_PAT" }, 413 SLICE_PAT => &SyntaxInfo { name: "SLICE_PAT" },
@@ -416,10 +427,12 @@ impl SyntaxKind {
416 BLOCK_EXPR => &SyntaxInfo { name: "BLOCK_EXPR" }, 427 BLOCK_EXPR => &SyntaxInfo { name: "BLOCK_EXPR" },
417 RETURN_EXPR => &SyntaxInfo { name: "RETURN_EXPR" }, 428 RETURN_EXPR => &SyntaxInfo { name: "RETURN_EXPR" },
418 MATCH_EXPR => &SyntaxInfo { name: "MATCH_EXPR" }, 429 MATCH_EXPR => &SyntaxInfo { name: "MATCH_EXPR" },
430 MATCH_ARM_LIST => &SyntaxInfo { name: "MATCH_ARM_LIST" },
419 MATCH_ARM => &SyntaxInfo { name: "MATCH_ARM" }, 431 MATCH_ARM => &SyntaxInfo { name: "MATCH_ARM" },
420 MATCH_GUARD => &SyntaxInfo { name: "MATCH_GUARD" }, 432 MATCH_GUARD => &SyntaxInfo { name: "MATCH_GUARD" },
421 STRUCT_LIT => &SyntaxInfo { name: "STRUCT_LIT" }, 433 STRUCT_LIT => &SyntaxInfo { name: "STRUCT_LIT" },
422 STRUCT_LIT_FIELD => &SyntaxInfo { name: "STRUCT_LIT_FIELD" }, 434 NAMED_FIELD_LIST => &SyntaxInfo { name: "NAMED_FIELD_LIST" },
435 NAMED_FIELD => &SyntaxInfo { name: "NAMED_FIELD" },
423 CALL_EXPR => &SyntaxInfo { name: "CALL_EXPR" }, 436 CALL_EXPR => &SyntaxInfo { name: "CALL_EXPR" },
424 INDEX_EXPR => &SyntaxInfo { name: "INDEX_EXPR" }, 437 INDEX_EXPR => &SyntaxInfo { name: "INDEX_EXPR" },
425 METHOD_CALL_EXPR => &SyntaxInfo { name: "METHOD_CALL_EXPR" }, 438 METHOD_CALL_EXPR => &SyntaxInfo { name: "METHOD_CALL_EXPR" },
@@ -430,13 +443,20 @@ impl SyntaxKind {
430 PREFIX_EXPR => &SyntaxInfo { name: "PREFIX_EXPR" }, 443 PREFIX_EXPR => &SyntaxInfo { name: "PREFIX_EXPR" },
431 RANGE_EXPR => &SyntaxInfo { name: "RANGE_EXPR" }, 444 RANGE_EXPR => &SyntaxInfo { name: "RANGE_EXPR" },
432 BIN_EXPR => &SyntaxInfo { name: "BIN_EXPR" }, 445 BIN_EXPR => &SyntaxInfo { name: "BIN_EXPR" },
433 EXTERN_BLOCK_EXPR => &SyntaxInfo { name: "EXTERN_BLOCK_EXPR" }, 446 BLOCK => &SyntaxInfo { name: "BLOCK" },
447 EXTERN_BLOCK => &SyntaxInfo { name: "EXTERN_BLOCK" },
448 EXTERN_ITEM_LIST => &SyntaxInfo { name: "EXTERN_ITEM_LIST" },
434 ENUM_VARIANT => &SyntaxInfo { name: "ENUM_VARIANT" }, 449 ENUM_VARIANT => &SyntaxInfo { name: "ENUM_VARIANT" },
435 NAMED_FIELD => &SyntaxInfo { name: "NAMED_FIELD" }, 450 NAMED_FIELD_DEF_LIST => &SyntaxInfo { name: "NAMED_FIELD_DEF_LIST" },
451 NAMED_FIELD_DEF => &SyntaxInfo { name: "NAMED_FIELD_DEF" },
452 POS_FIELD_LIST => &SyntaxInfo { name: "POS_FIELD_LIST" },
436 POS_FIELD => &SyntaxInfo { name: "POS_FIELD" }, 453 POS_FIELD => &SyntaxInfo { name: "POS_FIELD" },
454 ENUM_VARIANT_LIST => &SyntaxInfo { name: "ENUM_VARIANT_LIST" },
455 ITEM_LIST => &SyntaxInfo { name: "ITEM_LIST" },
437 ATTR => &SyntaxInfo { name: "ATTR" }, 456 ATTR => &SyntaxInfo { name: "ATTR" },
438 META_ITEM => &SyntaxInfo { name: "META_ITEM" }, 457 META_ITEM => &SyntaxInfo { name: "META_ITEM" },
439 USE_TREE => &SyntaxInfo { name: "USE_TREE" }, 458 USE_TREE => &SyntaxInfo { name: "USE_TREE" },
459 USE_TREE_LIST => &SyntaxInfo { name: "USE_TREE_LIST" },
440 PATH => &SyntaxInfo { name: "PATH" }, 460 PATH => &SyntaxInfo { name: "PATH" },
441 PATH_SEGMENT => &SyntaxInfo { name: "PATH_SEGMENT" }, 461 PATH_SEGMENT => &SyntaxInfo { name: "PATH_SEGMENT" },
442 LITERAL => &SyntaxInfo { name: "LITERAL" }, 462 LITERAL => &SyntaxInfo { name: "LITERAL" },