diff options
author | Aleksey Kladov <[email protected]> | 2018-01-07 18:40:18 +0000 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2018-01-07 18:40:18 +0000 |
commit | 7bc974ab2c29f896a0d9ca952ad306a9ed38f6f2 (patch) | |
tree | 2c39c8dcde0080a065ef0e8d59e5c4147b330a2b | |
parent | 5562931e4f3c6c57e9122c3ce34d941fb1ff6e5b (diff) |
G: some attributes
-rw-r--r-- | grammar.ron | 1 | ||||
-rw-r--r-- | src/parser/event_parser/grammar.rs | 52 | ||||
-rw-r--r-- | src/syntax_kinds.rs | 4 | ||||
-rw-r--r-- | tests/data/parser/ok/0006_inner_attributes.txt | 58 |
4 files changed, 83 insertions, 32 deletions
diff --git a/grammar.ron b/grammar.ron index 39cb0a543..e3b450d2b 100644 --- a/grammar.ron +++ b/grammar.ron | |||
@@ -66,5 +66,6 @@ Grammar( | |||
66 | "STRUCT_FIELD", | 66 | "STRUCT_FIELD", |
67 | "FN_ITEM", | 67 | "FN_ITEM", |
68 | "ATTR", | 68 | "ATTR", |
69 | "META_ITEM", | ||
69 | ] | 70 | ] |
70 | ) \ No newline at end of file | 71 | ) \ No newline at end of file |
diff --git a/src/parser/event_parser/grammar.rs b/src/parser/event_parser/grammar.rs index 64c6718cb..acf27aec9 100644 --- a/src/parser/event_parser/grammar.rs +++ b/src/parser/event_parser/grammar.rs | |||
@@ -34,7 +34,7 @@ fn item(p: &mut Parser) { | |||
34 | 34 | ||
35 | fn struct_item(p: &mut Parser) { | 35 | fn struct_item(p: &mut Parser) { |
36 | p.expect(IDENT) | 36 | p.expect(IDENT) |
37 | && p.curly_block(|p| comma_list(p, struct_field)); | 37 | && p.curly_block(|p| comma_list(p, EOF, struct_field)); |
38 | } | 38 | } |
39 | 39 | ||
40 | fn struct_field(p: &mut Parser) -> bool { | 40 | fn struct_field(p: &mut Parser) -> bool { |
@@ -52,19 +52,45 @@ fn fn_item(p: &mut Parser) { | |||
52 | // Paths, types, attributes, and stuff // | 52 | // Paths, types, attributes, and stuff // |
53 | 53 | ||
54 | fn inner_attributes(p: &mut Parser) { | 54 | fn inner_attributes(p: &mut Parser) { |
55 | many(p, inner_attribute) | 55 | many(p, |p| attribute(p, true)) |
56 | } | 56 | } |
57 | 57 | ||
58 | fn inner_attribute(p: &mut Parser) -> bool { | 58 | fn attribute(p: &mut Parser, inner: bool) -> bool { |
59 | if !(p.lookahead(&[EXCL, POUND])) { | 59 | let attr_start = inner && p.lookahead(&[POUND, EXCL, L_BRACK]) |
60 | || !inner && p.lookahead(&[POUND, L_BRACK]); | ||
61 | if !attr_start { | ||
60 | return false; | 62 | return false; |
61 | } | 63 | } |
62 | node(p, ATTR, |p| { | 64 | node(p, ATTR, |p| { |
63 | p.bump_n(2); | 65 | p.bump_n(if inner { 3 } else { 2 }); |
66 | meta_item(p) && p.expect(R_BRACK); | ||
64 | }); | 67 | }); |
65 | true | 68 | true |
66 | } | 69 | } |
67 | 70 | ||
71 | fn meta_item(p: &mut Parser) -> bool { | ||
72 | node_if(p, IDENT, META_ITEM, |p| { | ||
73 | if p.eat(EQ) { | ||
74 | if !literal(p) { | ||
75 | p.error() | ||
76 | .message("expected literal") | ||
77 | .emit(); | ||
78 | } | ||
79 | } else if p.eat(L_PAREN) { | ||
80 | comma_list(p, R_PAREN, meta_item_inner); | ||
81 | p.expect(R_PAREN); | ||
82 | } | ||
83 | }) | ||
84 | } | ||
85 | |||
86 | fn meta_item_inner(p: &mut Parser) -> bool { | ||
87 | meta_item(p) || literal(p) | ||
88 | } | ||
89 | |||
90 | fn literal(p: &mut Parser) -> bool { | ||
91 | p.eat(INT_NUMBER) || p.eat(FLOAT_NUMBER) | ||
92 | } | ||
93 | |||
68 | fn outer_attributes(_: &mut Parser) { | 94 | fn outer_attributes(_: &mut Parser) { |
69 | } | 95 | } |
70 | 96 | ||
@@ -75,7 +101,12 @@ fn visibility(_: &mut Parser) { | |||
75 | 101 | ||
76 | // Error recovery and high-order utils // | 102 | // Error recovery and high-order utils // |
77 | 103 | ||
78 | fn node_if<F: FnOnce(&mut Parser)>(p: &mut Parser, first: SyntaxKind, node_kind: SyntaxKind, rest: F) -> bool { | 104 | fn node_if<F: FnOnce(&mut Parser)>( |
105 | p: &mut Parser, | ||
106 | first: SyntaxKind, | ||
107 | node_kind: SyntaxKind, | ||
108 | rest: F | ||
109 | ) -> bool { | ||
79 | p.current() == first && { node(p, node_kind, |p| { p.bump(); rest(p); }); true } | 110 | p.current() == first && { node(p, node_kind, |p| { p.bump(); rest(p); }); true } |
80 | } | 111 | } |
81 | 112 | ||
@@ -89,10 +120,9 @@ fn many<F: Fn(&mut Parser) -> bool>(p: &mut Parser, f: F) { | |||
89 | while f(p) { } | 120 | while f(p) { } |
90 | } | 121 | } |
91 | 122 | ||
92 | fn comma_list<F: Fn(&mut Parser) -> bool>(p: &mut Parser, f: F) { | 123 | fn comma_list<F: Fn(&mut Parser) -> bool>(p: &mut Parser, end: SyntaxKind, f: F) { |
93 | many(p, |p| { | 124 | many(p, |p| { |
94 | f(p); | 125 | if !f(p) || p.current() == end { |
95 | if p.current() == EOF { | ||
96 | false | 126 | false |
97 | } else { | 127 | } else { |
98 | p.expect(COMMA); | 128 | p.expect(COMMA); |
@@ -157,4 +187,8 @@ impl<'p> Parser<'p> { | |||
157 | self.bump(); | 187 | self.bump(); |
158 | } | 188 | } |
159 | } | 189 | } |
190 | |||
191 | fn eat(&mut self, kind: SyntaxKind) -> bool { | ||
192 | self.current() == kind && { self.bump(); true } | ||
193 | } | ||
160 | } \ No newline at end of file | 194 | } \ No newline at end of file |
diff --git a/src/syntax_kinds.rs b/src/syntax_kinds.rs index 67c840a3e..eea7819a3 100644 --- a/src/syntax_kinds.rs +++ b/src/syntax_kinds.rs | |||
@@ -63,8 +63,9 @@ pub const STRUCT_ITEM: SyntaxKind = SyntaxKind(58); | |||
63 | pub const STRUCT_FIELD: SyntaxKind = SyntaxKind(59); | 63 | pub const STRUCT_FIELD: SyntaxKind = SyntaxKind(59); |
64 | pub const FN_ITEM: SyntaxKind = SyntaxKind(60); | 64 | pub const FN_ITEM: SyntaxKind = SyntaxKind(60); |
65 | pub const ATTR: SyntaxKind = SyntaxKind(61); | 65 | pub const ATTR: SyntaxKind = SyntaxKind(61); |
66 | pub const META_ITEM: SyntaxKind = SyntaxKind(62); | ||
66 | 67 | ||
67 | static INFOS: [SyntaxInfo; 62] = [ | 68 | static INFOS: [SyntaxInfo; 63] = [ |
68 | SyntaxInfo { name: "USE_KW" }, | 69 | SyntaxInfo { name: "USE_KW" }, |
69 | SyntaxInfo { name: "FN_KW" }, | 70 | SyntaxInfo { name: "FN_KW" }, |
70 | SyntaxInfo { name: "STRUCT_KW" }, | 71 | SyntaxInfo { name: "STRUCT_KW" }, |
@@ -127,6 +128,7 @@ static INFOS: [SyntaxInfo; 62] = [ | |||
127 | SyntaxInfo { name: "STRUCT_FIELD" }, | 128 | SyntaxInfo { name: "STRUCT_FIELD" }, |
128 | SyntaxInfo { name: "FN_ITEM" }, | 129 | SyntaxInfo { name: "FN_ITEM" }, |
129 | SyntaxInfo { name: "ATTR" }, | 130 | SyntaxInfo { name: "ATTR" }, |
131 | SyntaxInfo { name: "META_ITEM" }, | ||
130 | ]; | 132 | ]; |
131 | 133 | ||
132 | pub(crate) fn syntax_info(kind: SyntaxKind) -> &'static SyntaxInfo { | 134 | pub(crate) fn syntax_info(kind: SyntaxKind) -> &'static SyntaxInfo { |
diff --git a/tests/data/parser/ok/0006_inner_attributes.txt b/tests/data/parser/ok/0006_inner_attributes.txt index c837979d1..a19d2f49c 100644 --- a/tests/data/parser/ok/0006_inner_attributes.txt +++ b/tests/data/parser/ok/0006_inner_attributes.txt | |||
@@ -1,44 +1,58 @@ | |||
1 | FILE@[0; 236) | 1 | FILE@[0; 236) |
2 | ERROR@[0; 236) | 2 | ATTR@[0; 9) |
3 | err: `expected item` | ||
4 | POUND@[0; 1) | 3 | POUND@[0; 1) |
5 | EXCL@[1; 2) | 4 | EXCL@[1; 2) |
6 | L_BRACK@[2; 3) | 5 | L_BRACK@[2; 3) |
7 | IDENT@[3; 7) | 6 | META_ITEM@[3; 7) |
7 | IDENT@[3; 7) | ||
8 | R_BRACK@[7; 8) | 8 | R_BRACK@[7; 8) |
9 | WHITESPACE@[8; 9) | 9 | WHITESPACE@[8; 9) |
10 | ATTR@[9; 24) | ||
10 | POUND@[9; 10) | 11 | POUND@[9; 10) |
11 | EXCL@[10; 11) | 12 | EXCL@[10; 11) |
12 | L_BRACK@[11; 12) | 13 | L_BRACK@[11; 12) |
13 | IDENT@[12; 16) | 14 | META_ITEM@[12; 22) |
14 | L_PAREN@[16; 17) | 15 | IDENT@[12; 16) |
15 | IDENT@[17; 21) | 16 | L_PAREN@[16; 17) |
16 | R_PAREN@[21; 22) | 17 | META_ITEM@[17; 21) |
18 | IDENT@[17; 21) | ||
19 | R_PAREN@[21; 22) | ||
17 | R_BRACK@[22; 23) | 20 | R_BRACK@[22; 23) |
18 | WHITESPACE@[23; 24) | 21 | WHITESPACE@[23; 24) |
22 | ATTR@[24; 40) | ||
19 | POUND@[24; 25) | 23 | POUND@[24; 25) |
20 | EXCL@[25; 26) | 24 | EXCL@[25; 26) |
21 | L_BRACK@[26; 27) | 25 | L_BRACK@[26; 27) |
22 | IDENT@[27; 31) | 26 | META_ITEM@[27; 38) |
23 | L_PAREN@[31; 32) | 27 | IDENT@[27; 31) |
24 | IDENT@[32; 37) | 28 | L_PAREN@[31; 32) |
25 | R_PAREN@[37; 38) | 29 | META_ITEM@[32; 37) |
30 | IDENT@[32; 37) | ||
31 | R_PAREN@[37; 38) | ||
26 | R_BRACK@[38; 39) | 32 | R_BRACK@[38; 39) |
27 | WHITESPACE@[39; 40) | 33 | WHITESPACE@[39; 40) |
34 | ATTR@[40; 66) | ||
28 | POUND@[40; 41) | 35 | POUND@[40; 41) |
29 | EXCL@[41; 42) | 36 | EXCL@[41; 42) |
30 | L_BRACK@[42; 43) | 37 | L_BRACK@[42; 43) |
31 | IDENT@[43; 47) | 38 | META_ITEM@[43; 66) |
32 | L_PAREN@[47; 48) | 39 | IDENT@[43; 47) |
33 | IDENT@[48; 53) | 40 | L_PAREN@[47; 48) |
34 | COMMA@[53; 54) | 41 | META_ITEM@[48; 53) |
35 | WHITESPACE@[54; 55) | 42 | IDENT@[48; 53) |
36 | INT_NUMBER@[55; 58) | 43 | COMMA@[53; 54) |
37 | COMMA@[58; 59) | 44 | WHITESPACE@[54; 55) |
38 | WHITESPACE@[59; 60) | 45 | INT_NUMBER@[55; 58) |
39 | IDENT@[60; 64) | 46 | COMMA@[58; 59) |
40 | COMMA@[64; 65) | 47 | META_ITEM@[59; 64) |
41 | WHITESPACE@[65; 66) | 48 | WHITESPACE@[59; 60) |
49 | IDENT@[60; 64) | ||
50 | COMMA@[64; 65) | ||
51 | err: `expected R_PAREN` | ||
52 | WHITESPACE@[65; 66) | ||
53 | err: `expected R_BRACK` | ||
54 | ERROR@[66; 236) | ||
55 | err: `expected item` | ||
42 | STRING@[66; 72) | 56 | STRING@[66; 72) |
43 | COMMA@[72; 73) | 57 | COMMA@[72; 73) |
44 | WHITESPACE@[73; 74) | 58 | WHITESPACE@[73; 74) |