diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/parser/event_parser/grammar/attributes.rs | 96 | ||||
-rw-r--r-- | src/parser/event_parser/grammar/items.rs | 10 | ||||
-rw-r--r-- | src/parser/event_parser/grammar/mod.rs | 6 | ||||
-rw-r--r-- | src/parser/event_parser/mod.rs | 3 | ||||
-rw-r--r-- | src/parser/event_parser/parser.rs | 23 |
5 files changed, 98 insertions, 40 deletions
diff --git a/src/parser/event_parser/grammar/attributes.rs b/src/parser/event_parser/grammar/attributes.rs index 2d04a1a41..045840059 100644 --- a/src/parser/event_parser/grammar/attributes.rs +++ b/src/parser/event_parser/grammar/attributes.rs | |||
@@ -1,60 +1,84 @@ | |||
1 | use super::*; | 1 | use super::*; |
2 | 2 | ||
3 | #[derive(PartialEq, Eq)] | ||
4 | enum AttrKind { | ||
5 | Inner, Outer | ||
6 | } | ||
7 | |||
8 | pub(super) fn inner_attributes(p: &mut Parser) { | 3 | pub(super) fn inner_attributes(p: &mut Parser) { |
9 | repeat(p, |p| attribute(p, AttrKind::Inner)) | 4 | while p.at([POUND, EXCL]) { |
5 | attribute(p, true) | ||
6 | } | ||
10 | } | 7 | } |
11 | 8 | ||
12 | pub(super) fn outer_attributes(p: &mut Parser) { | 9 | pub(super) fn outer_attributes(p: &mut Parser) { |
13 | repeat(p, |p| attribute(p, AttrKind::Outer)) | 10 | while p.at(POUND) { |
11 | attribute(p, false) | ||
12 | } | ||
14 | } | 13 | } |
15 | 14 | ||
16 | 15 | ||
17 | fn attribute(p: &mut Parser, kind: AttrKind) -> bool { | 16 | fn attribute(p: &mut Parser, inner: bool){ |
18 | if p.at(POUND) { | 17 | let attr = p.start(); |
19 | if kind == AttrKind::Inner && p.raw_lookahead(1) != EXCL { | 18 | assert!(p.at(POUND)); |
20 | return false; | 19 | p.bump(); |
21 | } | 20 | |
22 | let attr = p.start(); | 21 | if inner { |
22 | assert!(p.at(EXCL)); | ||
23 | p.bump(); | 23 | p.bump(); |
24 | if kind == AttrKind::Inner { | ||
25 | p.bump(); | ||
26 | } | ||
27 | p.expect(L_BRACK) && meta_item(p) && p.expect(R_BRACK); | ||
28 | attr.complete(p, ATTR); | ||
29 | true | ||
30 | } else { | ||
31 | false | ||
32 | } | 24 | } |
25 | |||
26 | if p.expect(L_BRACK) { | ||
27 | meta_item(p); | ||
28 | p.expect(R_BRACK); | ||
29 | } | ||
30 | attr.complete(p, ATTR); | ||
33 | } | 31 | } |
34 | 32 | ||
35 | fn meta_item(p: &mut Parser) -> bool { | 33 | fn meta_item(p: &mut Parser) { |
36 | if p.at(IDENT) { | 34 | if p.at(IDENT) { |
37 | let meta_item = p.start(); | 35 | let meta_item = p.start(); |
38 | p.bump(); | 36 | p.bump(); |
39 | if p.eat(EQ) { | 37 | match p.current() { |
40 | if !expressions::literal(p) { | 38 | EQ => { |
41 | p.error() | 39 | p.bump(); |
42 | .message("expected literal") | 40 | if !expressions::literal(p) { |
43 | .emit(); | 41 | p.error() |
42 | .message("expected literal") | ||
43 | .emit(); | ||
44 | } | ||
44 | } | 45 | } |
45 | } else if p.eat(L_PAREN) { | 46 | L_PAREN => meta_item_arg_list(p), |
46 | comma_list(p, R_PAREN, meta_item_inner); | 47 | _ => (), |
47 | p.expect(R_PAREN); | ||
48 | } | 48 | } |
49 | meta_item.complete(p, META_ITEM); | 49 | meta_item.complete(p, META_ITEM); |
50 | true | ||
51 | } else { | 50 | } else { |
52 | false | 51 | p.error() |
52 | .message("expected attribute value") | ||
53 | .emit() | ||
53 | } | 54 | } |
54 | |||
55 | } | 55 | } |
56 | 56 | ||
57 | fn meta_item_inner(p: &mut Parser) -> bool { | 57 | fn meta_item_arg_list(p: &mut Parser) { |
58 | meta_item(p) || expressions::literal(p) | 58 | assert!(p.at(L_PAREN)); |
59 | } | 59 | p.bump(); |
60 | loop { | ||
61 | match p.current() { | ||
62 | EOF | R_PAREN => break, | ||
63 | IDENT => meta_item(p), | ||
64 | c => if !expressions::literal(p) { | ||
65 | let message = "expected attribute"; | ||
60 | 66 | ||
67 | if items::ITEM_FIRST.contains(c) { | ||
68 | p.error().message(message).emit(); | ||
69 | return; | ||
70 | } | ||
71 | |||
72 | let err = p.start(); | ||
73 | p.error().message(message).emit(); | ||
74 | p.bump(); | ||
75 | err.complete(p, ERROR); | ||
76 | continue | ||
77 | } | ||
78 | } | ||
79 | if !p.at(R_PAREN) { | ||
80 | p.expect(COMMA); | ||
81 | } | ||
82 | } | ||
83 | p.expect(R_PAREN); | ||
84 | } | ||
diff --git a/src/parser/event_parser/grammar/items.rs b/src/parser/event_parser/grammar/items.rs index c9a890553..12b6d06c7 100644 --- a/src/parser/event_parser/grammar/items.rs +++ b/src/parser/event_parser/grammar/items.rs | |||
@@ -7,6 +7,16 @@ pub(super) fn mod_contents(p: &mut Parser) { | |||
7 | } | 7 | } |
8 | } | 8 | } |
9 | 9 | ||
10 | pub(super) const ITEM_FIRST: TokenSet = token_set![ | ||
11 | EXTERN_KW, | ||
12 | MOD_KW, | ||
13 | USE_KW, | ||
14 | STRUCT_KW, | ||
15 | FN_KW, | ||
16 | PUB_KW, | ||
17 | POUND, | ||
18 | ]; | ||
19 | |||
10 | fn item(p: &mut Parser) { | 20 | fn item(p: &mut Parser) { |
11 | let item = p.start(); | 21 | let item = p.start(); |
12 | attributes::outer_attributes(p); | 22 | attributes::outer_attributes(p); |
diff --git a/src/parser/event_parser/grammar/mod.rs b/src/parser/event_parser/grammar/mod.rs index d3b63c4c1..32e4db698 100644 --- a/src/parser/event_parser/grammar/mod.rs +++ b/src/parser/event_parser/grammar/mod.rs | |||
@@ -1,4 +1,4 @@ | |||
1 | use super::parser::Parser; | 1 | use super::parser::{Parser, TokenSet}; |
2 | use {SyntaxKind}; | 2 | use {SyntaxKind}; |
3 | use tree::EOF; | 3 | use tree::EOF; |
4 | use syntax_kinds::*; | 4 | use syntax_kinds::*; |
@@ -80,8 +80,8 @@ fn comma_list<F: Fn(&mut Parser) -> bool>(p: &mut Parser, end: SyntaxKind, f: F) | |||
80 | 80 | ||
81 | 81 | ||
82 | impl<'p> Parser<'p> { | 82 | impl<'p> Parser<'p> { |
83 | fn at(&self, kind: SyntaxKind) -> bool { | 83 | fn at<L: Lookahead>(&self, l: L) -> bool { |
84 | self.current() == kind | 84 | l.is_ahead(self) |
85 | } | 85 | } |
86 | 86 | ||
87 | pub(crate) fn expect(&mut self, kind: SyntaxKind) -> bool { | 87 | pub(crate) fn expect(&mut self, kind: SyntaxKind) -> bool { |
diff --git a/src/parser/event_parser/mod.rs b/src/parser/event_parser/mod.rs index 7c81182e3..b9ffded9d 100644 --- a/src/parser/event_parser/mod.rs +++ b/src/parser/event_parser/mod.rs | |||
@@ -1,7 +1,8 @@ | |||
1 | use {Token, SyntaxKind}; | 1 | use {Token, SyntaxKind}; |
2 | 2 | ||
3 | mod grammar; | 3 | #[macro_use] |
4 | mod parser; | 4 | mod parser; |
5 | mod grammar; | ||
5 | 6 | ||
6 | #[derive(Debug)] | 7 | #[derive(Debug)] |
7 | pub(crate) enum Event { | 8 | pub(crate) enum Event { |
diff --git a/src/parser/event_parser/parser.rs b/src/parser/event_parser/parser.rs index 2bc9dd34f..2cbe370be 100644 --- a/src/parser/event_parser/parser.rs +++ b/src/parser/event_parser/parser.rs | |||
@@ -67,6 +67,29 @@ impl CompleteMarker { | |||
67 | } | 67 | } |
68 | } | 68 | } |
69 | 69 | ||
70 | pub(crate) struct TokenSet { | ||
71 | pub tokens: &'static [SyntaxKind] | ||
72 | } | ||
73 | |||
74 | impl TokenSet { | ||
75 | pub fn contains(&self, kind: SyntaxKind) -> bool { | ||
76 | self.tokens.contains(&kind) | ||
77 | } | ||
78 | } | ||
79 | |||
80 | #[macro_export] | ||
81 | macro_rules! token_set { | ||
82 | ($($t:ident),*) => { | ||
83 | TokenSet { | ||
84 | tokens: &[$($t),*], | ||
85 | } | ||
86 | }; | ||
87 | |||
88 | ($($t:ident),* ,) => { | ||
89 | token_set!($($t),*) | ||
90 | }; | ||
91 | } | ||
92 | |||
70 | 93 | ||
71 | pub(crate) struct Parser<'t> { | 94 | pub(crate) struct Parser<'t> { |
72 | #[allow(unused)] | 95 | #[allow(unused)] |