aboutsummaryrefslogtreecommitdiff
path: root/src/grammar
diff options
context:
space:
mode:
Diffstat (limited to 'src/grammar')
-rw-r--r--src/grammar/items/mod.rs78
-rw-r--r--src/grammar/items/traits.rs2
2 files changed, 71 insertions, 9 deletions
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}