aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/grammar.ron2
-rw-r--r--src/grammar/items/mod.rs78
-rw-r--r--src/grammar/items/traits.rs2
-rw-r--r--src/syntax_kinds/generated.rs4
-rw-r--r--tests/data/parser/err/0008_item_block_recovery.txt14
-rw-r--r--tests/data/parser/inline/0078_mod_contents.rs5
-rw-r--r--tests/data/parser/inline/0078_mod_contents.txt62
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;
5mod traits; 5mod traits;
6mod use_item; 6mod use_item;
7 7
8// test mod_contents
9// fn foo() {}
10// macro_rules! foo {}
11// foo::bar!();
12// super::baz! {}
13// struct S;
8pub(super) fn mod_contents(p: &mut Parser, stop_on_r_curly: bool) { 14pub(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
15pub(super) fn item(p: &mut Parser, stop_on_r_curly: bool) { 21pub(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
280enum MacroFlavor {
281 Curly,
282 NonCurly,
283}
284
285fn 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
308fn 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 @@
1fn foo() {}
2macro_rules! foo {}
3foo::bar!();
4super::baz! {}
5struct 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 @@
1FILE@[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)