diff options
Diffstat (limited to 'crates/parser/src/grammar/attributes.rs')
-rw-r--r-- | crates/parser/src/grammar/attributes.rs | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/crates/parser/src/grammar/attributes.rs b/crates/parser/src/grammar/attributes.rs new file mode 100644 index 000000000..dab0f62c3 --- /dev/null +++ b/crates/parser/src/grammar/attributes.rs | |||
@@ -0,0 +1,48 @@ | |||
1 | //! FIXME: write short doc here | ||
2 | |||
3 | use super::*; | ||
4 | |||
5 | pub(super) fn inner_attrs(p: &mut Parser) { | ||
6 | while p.at(T![#]) && p.nth(1) == T![!] { | ||
7 | attr(p, true) | ||
8 | } | ||
9 | } | ||
10 | |||
11 | pub(super) fn outer_attrs(p: &mut Parser) { | ||
12 | while p.at(T![#]) { | ||
13 | attr(p, false) | ||
14 | } | ||
15 | } | ||
16 | |||
17 | fn attr(p: &mut Parser, inner: bool) { | ||
18 | let attr = p.start(); | ||
19 | assert!(p.at(T![#])); | ||
20 | p.bump(T![#]); | ||
21 | |||
22 | if inner { | ||
23 | assert!(p.at(T![!])); | ||
24 | p.bump(T![!]); | ||
25 | } | ||
26 | |||
27 | if p.eat(T!['[']) { | ||
28 | paths::use_path(p); | ||
29 | |||
30 | match p.current() { | ||
31 | T![=] => { | ||
32 | p.bump(T![=]); | ||
33 | if expressions::literal(p).is_none() { | ||
34 | p.error("expected literal"); | ||
35 | } | ||
36 | } | ||
37 | T!['('] | T!['['] | T!['{'] => items::token_tree(p), | ||
38 | _ => {} | ||
39 | } | ||
40 | |||
41 | if !p.eat(T![']']) { | ||
42 | p.error("expected `]`"); | ||
43 | } | ||
44 | } else { | ||
45 | p.error("expected `[`"); | ||
46 | } | ||
47 | attr.complete(p, ATTR); | ||
48 | } | ||