diff options
-rw-r--r-- | src/grammar.ron | 2 | ||||
-rw-r--r-- | src/grammar/items/mod.rs | 78 | ||||
-rw-r--r-- | src/grammar/items/traits.rs | 2 | ||||
-rw-r--r-- | src/syntax_kinds/generated.rs | 4 | ||||
-rw-r--r-- | tests/data/parser/err/0008_item_block_recovery.txt | 14 | ||||
-rw-r--r-- | tests/data/parser/inline/0078_mod_contents.rs | 5 | ||||
-rw-r--r-- | tests/data/parser/inline/0078_mod_contents.txt | 62 |
7 files changed, 151 insertions, 16 deletions
diff --git a/src/grammar.ron b/src/grammar.ron index 9f80b3ebf..0a79eeb95 100644 --- a/src/grammar.ron +++ b/src/grammar.ron | |||
@@ -109,6 +109,8 @@ Grammar( | |||
109 | "TRAIT_ITEM", | 109 | "TRAIT_ITEM", |
110 | "IMPL_ITEM", | 110 | "IMPL_ITEM", |
111 | "TYPE_ITEM", | 111 | "TYPE_ITEM", |
112 | "MACRO_CALL", | ||
113 | "TOKEN_TREE", | ||
112 | 114 | ||
113 | "PAREN_TYPE", | 115 | "PAREN_TYPE", |
114 | "TUPLE_TYPE", | 116 | "TUPLE_TYPE", |
diff --git a/src/grammar/items/mod.rs b/src/grammar/items/mod.rs index 1ed0aea07..8f766901e 100644 --- a/src/grammar/items/mod.rs +++ b/src/grammar/items/mod.rs | |||
@@ -5,27 +5,43 @@ mod structs; | |||
5 | mod traits; | 5 | mod traits; |
6 | mod use_item; | 6 | mod use_item; |
7 | 7 | ||
8 | // test mod_contents | ||
9 | // fn foo() {} | ||
10 | // macro_rules! foo {} | ||
11 | // foo::bar!(); | ||
12 | // super::baz! {} | ||
13 | // struct S; | ||
8 | pub(super) fn mod_contents(p: &mut Parser, stop_on_r_curly: bool) { | 14 | pub(super) fn mod_contents(p: &mut Parser, stop_on_r_curly: bool) { |
9 | attributes::inner_attributes(p); | 15 | attributes::inner_attributes(p); |
10 | while !p.at(EOF) && !(stop_on_r_curly && p.at(R_CURLY)) { | 16 | while !p.at(EOF) && !(stop_on_r_curly && p.at(R_CURLY)) { |
11 | item(p, stop_on_r_curly) | 17 | item_or_macro(p, stop_on_r_curly) |
12 | } | 18 | } |
13 | } | 19 | } |
14 | 20 | ||
15 | pub(super) fn item(p: &mut Parser, stop_on_r_curly: bool) { | 21 | pub(super) fn item_or_macro(p: &mut Parser, stop_on_r_curly: bool) { |
16 | let m = p.start(); | 22 | let m = p.start(); |
17 | match maybe_item(p) { | 23 | match maybe_item(p) { |
18 | MaybeItem::Item(kind) => { | 24 | MaybeItem::Item(kind) => { |
19 | m.complete(p, kind); | 25 | m.complete(p, kind); |
20 | } | 26 | } |
21 | MaybeItem::None => { | 27 | MaybeItem::None => { |
22 | m.abandon(p); | 28 | if paths::is_path_start(p) { |
23 | if p.at(L_CURLY) { | 29 | match macro_call(p) { |
24 | error_block(p, "expected an item"); | 30 | MacroFlavor::Curly => (), |
25 | } else if !p.at(EOF) && !(stop_on_r_curly && p.at(R_CURLY)) { | 31 | MacroFlavor::NonCurly => { |
26 | p.err_and_bump("expected an item"); | 32 | p.expect(SEMI); |
33 | } | ||
34 | } | ||
35 | m.complete(p, MACRO_CALL); | ||
27 | } else { | 36 | } else { |
28 | p.error("expected an item"); | 37 | m.abandon(p); |
38 | if p.at(L_CURLY) { | ||
39 | error_block(p, "expected an item"); | ||
40 | } else if !p.at(EOF) && !(stop_on_r_curly && p.at(R_CURLY)) { | ||
41 | p.err_and_bump("expected an item"); | ||
42 | } else { | ||
43 | p.error("expected an item"); | ||
44 | } | ||
29 | } | 45 | } |
30 | } | 46 | } |
31 | MaybeItem::Modifiers => { | 47 | MaybeItem::Modifiers => { |
@@ -260,3 +276,49 @@ fn mod_item(p: &mut Parser) { | |||
260 | } | 276 | } |
261 | } | 277 | } |
262 | } | 278 | } |
279 | |||
280 | enum MacroFlavor { | ||
281 | Curly, | ||
282 | NonCurly, | ||
283 | } | ||
284 | |||
285 | fn macro_call(p: &mut Parser) -> MacroFlavor { | ||
286 | assert!(paths::is_path_start(p)); | ||
287 | paths::use_path(p); | ||
288 | p.expect(EXCL); | ||
289 | p.eat(IDENT); | ||
290 | let flavor = match p.current() { | ||
291 | L_CURLY => { | ||
292 | token_tree(p); | ||
293 | MacroFlavor::Curly | ||
294 | } | ||
295 | L_PAREN | L_BRACK => { | ||
296 | token_tree(p); | ||
297 | MacroFlavor::NonCurly | ||
298 | } | ||
299 | _ => { | ||
300 | p.error("expected `{`, `[`, `(`"); | ||
301 | MacroFlavor::NonCurly | ||
302 | }, | ||
303 | }; | ||
304 | |||
305 | flavor | ||
306 | } | ||
307 | |||
308 | fn token_tree(p: &mut Parser) { | ||
309 | let closing_paren_kind = match p.current() { | ||
310 | L_CURLY => R_CURLY, | ||
311 | L_PAREN => R_PAREN, | ||
312 | L_BRACK => R_BRACK, | ||
313 | _ => unreachable!(), | ||
314 | }; | ||
315 | p.bump(); | ||
316 | while !p.at(EOF) && !p.at(closing_paren_kind) { | ||
317 | match p.current() { | ||
318 | L_CURLY | L_PAREN | L_BRACK => token_tree(p), | ||
319 | R_CURLY | R_PAREN | R_BRACK => p.err_and_bump("unmatched brace"), | ||
320 | _ => p.bump() | ||
321 | } | ||
322 | }; | ||
323 | p.expect(closing_paren_kind); | ||
324 | } | ||
diff --git a/src/grammar/items/traits.rs b/src/grammar/items/traits.rs index 0614e8ab6..7c0935371 100644 --- a/src/grammar/items/traits.rs +++ b/src/grammar/items/traits.rs | |||
@@ -45,7 +45,7 @@ pub(super) fn impl_item(p: &mut Parser) { | |||
45 | // fn bar(&self) {} | 45 | // fn bar(&self) {} |
46 | // } | 46 | // } |
47 | while !p.at(EOF) && !p.at(R_CURLY) { | 47 | while !p.at(EOF) && !p.at(R_CURLY) { |
48 | item(p, true); | 48 | item_or_macro(p, true); |
49 | } | 49 | } |
50 | p.expect(R_CURLY); | 50 | p.expect(R_CURLY); |
51 | } | 51 | } |
diff --git a/src/syntax_kinds/generated.rs b/src/syntax_kinds/generated.rs index 1d3d3b9c1..8ac13fd63 100644 --- a/src/syntax_kinds/generated.rs +++ b/src/syntax_kinds/generated.rs | |||
@@ -103,6 +103,8 @@ pub enum SyntaxKind { | |||
103 | TRAIT_ITEM, | 103 | TRAIT_ITEM, |
104 | IMPL_ITEM, | 104 | IMPL_ITEM, |
105 | TYPE_ITEM, | 105 | TYPE_ITEM, |
106 | MACRO_CALL, | ||
107 | TOKEN_TREE, | ||
106 | PAREN_TYPE, | 108 | PAREN_TYPE, |
107 | TUPLE_TYPE, | 109 | TUPLE_TYPE, |
108 | NEVER_TYPE, | 110 | NEVER_TYPE, |
@@ -322,6 +324,8 @@ impl SyntaxKind { | |||
322 | TRAIT_ITEM => &SyntaxInfo { name: "TRAIT_ITEM" }, | 324 | TRAIT_ITEM => &SyntaxInfo { name: "TRAIT_ITEM" }, |
323 | IMPL_ITEM => &SyntaxInfo { name: "IMPL_ITEM" }, | 325 | IMPL_ITEM => &SyntaxInfo { name: "IMPL_ITEM" }, |
324 | TYPE_ITEM => &SyntaxInfo { name: "TYPE_ITEM" }, | 326 | TYPE_ITEM => &SyntaxInfo { name: "TYPE_ITEM" }, |
327 | MACRO_CALL => &SyntaxInfo { name: "MACRO_CALL" }, | ||
328 | TOKEN_TREE => &SyntaxInfo { name: "TOKEN_TREE" }, | ||
325 | PAREN_TYPE => &SyntaxInfo { name: "PAREN_TYPE" }, | 329 | PAREN_TYPE => &SyntaxInfo { name: "PAREN_TYPE" }, |
326 | TUPLE_TYPE => &SyntaxInfo { name: "TUPLE_TYPE" }, | 330 | TUPLE_TYPE => &SyntaxInfo { name: "TUPLE_TYPE" }, |
327 | NEVER_TYPE => &SyntaxInfo { name: "NEVER_TYPE" }, | 331 | NEVER_TYPE => &SyntaxInfo { name: "NEVER_TYPE" }, |
diff --git a/tests/data/parser/err/0008_item_block_recovery.txt b/tests/data/parser/err/0008_item_block_recovery.txt index 80253d8af..62ca31080 100644 --- a/tests/data/parser/err/0008_item_block_recovery.txt +++ b/tests/data/parser/err/0008_item_block_recovery.txt | |||
@@ -13,15 +13,15 @@ FILE@[0; 95) | |||
13 | WHITESPACE@[10; 11) | 13 | WHITESPACE@[10; 11) |
14 | R_CURLY@[11; 12) | 14 | R_CURLY@[11; 12) |
15 | WHITESPACE@[12; 14) | 15 | WHITESPACE@[12; 14) |
16 | err: `expected an item` | 16 | MACRO_CALL@[14; 20) |
17 | ERROR@[14; 17) | 17 | PATH@[14; 17) |
18 | IDENT@[14; 17) "bar" | 18 | PATH_SEGMENT@[14; 17) |
19 | err: `expected an item` | 19 | NAME_REF@[14; 17) |
20 | ERROR@[17; 18) | 20 | IDENT@[14; 17) "bar" |
21 | err: `expected EXCL` | ||
21 | L_PAREN@[17; 18) | 22 | L_PAREN@[17; 18) |
22 | err: `expected an item` | ||
23 | ERROR@[18; 20) | ||
24 | R_PAREN@[18; 19) | 23 | R_PAREN@[18; 19) |
24 | err: `expected SEMI` | ||
25 | WHITESPACE@[19; 20) | 25 | WHITESPACE@[19; 20) |
26 | err: `expected an item` | 26 | err: `expected an item` |
27 | ERROR@[20; 82) | 27 | ERROR@[20; 82) |
diff --git a/tests/data/parser/inline/0078_mod_contents.rs b/tests/data/parser/inline/0078_mod_contents.rs new file mode 100644 index 000000000..24a15c5c5 --- /dev/null +++ b/tests/data/parser/inline/0078_mod_contents.rs | |||
@@ -0,0 +1,5 @@ | |||
1 | fn foo() {} | ||
2 | macro_rules! foo {} | ||
3 | foo::bar!(); | ||
4 | super::baz! {} | ||
5 | struct S; | ||
diff --git a/tests/data/parser/inline/0078_mod_contents.txt b/tests/data/parser/inline/0078_mod_contents.txt new file mode 100644 index 000000000..4f97c3ee3 --- /dev/null +++ b/tests/data/parser/inline/0078_mod_contents.txt | |||
@@ -0,0 +1,62 @@ | |||
1 | FILE@[0; 70) | ||
2 | FN_ITEM@[0; 12) | ||
3 | FN_KW@[0; 2) | ||
4 | NAME@[2; 6) | ||
5 | WHITESPACE@[2; 3) | ||
6 | IDENT@[3; 6) "foo" | ||
7 | PARAM_LIST@[6; 9) | ||
8 | L_PAREN@[6; 7) | ||
9 | R_PAREN@[7; 8) | ||
10 | WHITESPACE@[8; 9) | ||
11 | BLOCK_EXPR@[9; 12) | ||
12 | L_CURLY@[9; 10) | ||
13 | R_CURLY@[10; 11) | ||
14 | WHITESPACE@[11; 12) | ||
15 | MACRO_CALL@[12; 32) | ||
16 | PATH@[12; 23) | ||
17 | PATH_SEGMENT@[12; 23) | ||
18 | NAME_REF@[12; 23) | ||
19 | IDENT@[12; 23) "macro_rules" | ||
20 | EXCL@[23; 24) | ||
21 | WHITESPACE@[24; 25) | ||
22 | IDENT@[25; 28) "foo" | ||
23 | WHITESPACE@[28; 29) | ||
24 | L_CURLY@[29; 30) | ||
25 | R_CURLY@[30; 31) | ||
26 | WHITESPACE@[31; 32) | ||
27 | MACRO_CALL@[32; 45) | ||
28 | PATH@[32; 40) | ||
29 | PATH@[32; 35) | ||
30 | PATH_SEGMENT@[32; 35) | ||
31 | NAME_REF@[32; 35) | ||
32 | IDENT@[32; 35) "foo" | ||
33 | COLONCOLON@[35; 37) | ||
34 | PATH_SEGMENT@[37; 40) | ||
35 | NAME_REF@[37; 40) | ||
36 | IDENT@[37; 40) "bar" | ||
37 | EXCL@[40; 41) | ||
38 | L_PAREN@[41; 42) | ||
39 | R_PAREN@[42; 43) | ||
40 | SEMI@[43; 44) | ||
41 | WHITESPACE@[44; 45) | ||
42 | MACRO_CALL@[45; 60) | ||
43 | PATH@[45; 55) | ||
44 | PATH@[45; 50) | ||
45 | PATH_SEGMENT@[45; 50) | ||
46 | SUPER_KW@[45; 50) | ||
47 | COLONCOLON@[50; 52) | ||
48 | PATH_SEGMENT@[52; 55) | ||
49 | NAME_REF@[52; 55) | ||
50 | IDENT@[52; 55) "baz" | ||
51 | EXCL@[55; 56) | ||
52 | WHITESPACE@[56; 57) | ||
53 | L_CURLY@[57; 58) | ||
54 | R_CURLY@[58; 59) | ||
55 | WHITESPACE@[59; 60) | ||
56 | STRUCT_ITEM@[60; 70) | ||
57 | STRUCT_KW@[60; 66) | ||
58 | NAME@[66; 68) | ||
59 | WHITESPACE@[66; 67) | ||
60 | IDENT@[67; 68) "S" | ||
61 | SEMI@[68; 69) | ||
62 | WHITESPACE@[69; 70) | ||