diff options
Diffstat (limited to 'src/grammar')
-rw-r--r-- | src/grammar/items/mod.rs | 78 | ||||
-rw-r--r-- | src/grammar/items/traits.rs | 2 |
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; | |||
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 | } |