diff options
author | Aleksey Kladov <[email protected]> | 2018-08-04 11:17:24 +0100 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2018-08-04 11:17:24 +0100 |
commit | e919db3731968ae7a6877530d2cb645b0495d5fd (patch) | |
tree | 02c8f9a9accf0db8f89bdf9c8a8293a81f557568 /src/grammar/items | |
parent | 7264c3294b3c460da459774058c9b9fa77edac12 (diff) |
refine item parsing
Diffstat (limited to 'src/grammar/items')
-rw-r--r-- | src/grammar/items/mod.rs | 298 | ||||
-rw-r--r-- | src/grammar/items/traits.rs | 2 |
2 files changed, 136 insertions, 164 deletions
diff --git a/src/grammar/items/mod.rs b/src/grammar/items/mod.rs index a1150e2ac..1ed0aea07 100644 --- a/src/grammar/items/mod.rs +++ b/src/grammar/items/mod.rs | |||
@@ -8,173 +8,136 @@ mod use_item; | |||
8 | pub(super) fn mod_contents(p: &mut Parser, stop_on_r_curly: bool) { | 8 | pub(super) fn mod_contents(p: &mut Parser, stop_on_r_curly: bool) { |
9 | attributes::inner_attributes(p); | 9 | attributes::inner_attributes(p); |
10 | while !p.at(EOF) && !(stop_on_r_curly && p.at(R_CURLY)) { | 10 | while !p.at(EOF) && !(stop_on_r_curly && p.at(R_CURLY)) { |
11 | item(p); | 11 | item(p, stop_on_r_curly) |
12 | } | ||
13 | } | ||
14 | |||
15 | pub(super) fn item(p: &mut Parser, stop_on_r_curly: bool) { | ||
16 | let m = p.start(); | ||
17 | match maybe_item(p) { | ||
18 | MaybeItem::Item(kind) => { | ||
19 | m.complete(p, kind); | ||
20 | } | ||
21 | MaybeItem::None => { | ||
22 | m.abandon(p); | ||
23 | if p.at(L_CURLY) { | ||
24 | error_block(p, "expected an item"); | ||
25 | } else if !p.at(EOF) && !(stop_on_r_curly && p.at(R_CURLY)) { | ||
26 | p.err_and_bump("expected an item"); | ||
27 | } else { | ||
28 | p.error("expected an item"); | ||
29 | } | ||
30 | } | ||
31 | MaybeItem::Modifiers => { | ||
32 | p.error("expected fn, trait or impl"); | ||
33 | m.complete(p, ERROR); | ||
34 | } | ||
12 | } | 35 | } |
13 | } | 36 | } |
14 | 37 | ||
15 | pub(super) const ITEM_FIRST: TokenSet = | 38 | pub(super) const ITEM_FIRST: TokenSet = |
16 | token_set![EXTERN_KW, MOD_KW, USE_KW, STRUCT_KW, ENUM_KW, FN_KW, PUB_KW, POUND]; | 39 | token_set![EXTERN_KW, MOD_KW, USE_KW, STRUCT_KW, ENUM_KW, FN_KW, PUB_KW, POUND]; |
17 | 40 | ||
18 | pub(super) fn item(p: &mut Parser) { | 41 | pub(super) enum MaybeItem { |
19 | let item = p.start(); | 42 | None, |
43 | Item(SyntaxKind), | ||
44 | Modifiers, | ||
45 | } | ||
46 | |||
47 | pub(super) fn maybe_item(p: &mut Parser) -> MaybeItem { | ||
20 | attributes::outer_attributes(p); | 48 | attributes::outer_attributes(p); |
21 | visibility(p); | 49 | visibility(p); |
22 | let la = p.nth(1); | 50 | if let Some(kind) = items_without_modifiers(p) { |
23 | let item_kind = match p.current() { | 51 | return MaybeItem::Item(kind); |
24 | USE_KW => { | 52 | } |
25 | use_item::use_item(p); | 53 | |
26 | USE_ITEM | 54 | let mut has_mods = false; |
27 | } | 55 | // modifiers |
28 | // test extern_crate | 56 | has_mods |= p.eat(CONST_KW); |
29 | // extern crate foo; | 57 | |
30 | EXTERN_KW if la == CRATE_KW => { | 58 | // test unsafe_block_in_mod |
31 | extern_crate_item(p); | 59 | // fn foo(){} unsafe { } fn bar(){} |
32 | EXTERN_CRATE_ITEM | 60 | if p.at(UNSAFE_KW) && p.nth(1) != L_CURLY { |
33 | } | 61 | p.eat(UNSAFE_KW); |
34 | EXTERN_KW => { | 62 | has_mods = true; |
35 | abi(p); | 63 | } |
36 | match p.current() { | 64 | if p.at(EXTERN_KW) { |
37 | // test extern_fn | 65 | has_mods = true; |
38 | // extern fn foo() {} | 66 | abi(p); |
39 | FN_KW => { | 67 | } |
40 | fn_item(p); | 68 | if p.at(IDENT) && p.at_contextual_kw("auto") && p.nth(1) == TRAIT_KW { |
41 | FN_ITEM | 69 | p.bump_remap(AUTO_KW); |
42 | } | 70 | has_mods = true; |
43 | // test extern_block | 71 | } |
44 | // extern {} | 72 | if p.at(IDENT) && p.at_contextual_kw("default") && p.nth(1) == IMPL_KW { |
45 | L_CURLY => { | 73 | p.bump_remap(DEFAULT_KW); |
46 | extern_block(p); | 74 | has_mods = true; |
47 | EXTERN_BLOCK_EXPR | 75 | } |
48 | } | 76 | |
49 | // test extern_struct | 77 | // items |
50 | // extern struct Foo; | 78 | let kind = match p.current() { |
51 | _ => { | 79 | // test extern_fn |
52 | item.abandon(p); | 80 | // extern fn foo() {} |
53 | p.error("expected `fn` or `{`"); | 81 | |
54 | return; | 82 | // test const_fn |
55 | } | 83 | // const fn foo() {} |
56 | } | 84 | |
57 | } | 85 | // test const_unsafe_fn |
58 | STATIC_KW => { | 86 | // const unsafe fn foo() {} |
59 | consts::static_item(p); | 87 | |
60 | STATIC_ITEM | 88 | // test unsafe_extern_fn |
61 | } | 89 | // unsafe extern "C" fn foo() {} |
62 | CONST_KW => match p.nth(1) { | 90 | |
63 | // test const_fn | 91 | // test unsafe_fn |
64 | // const fn foo() {} | 92 | // unsafe fn foo() {} |
65 | FN_KW => { | 93 | FN_KW => { |
66 | p.bump(); | 94 | fn_item(p); |
67 | fn_item(p); | 95 | FN_ITEM |
68 | FN_ITEM | ||
69 | } | ||
70 | // test const_unsafe_fn | ||
71 | // const unsafe fn foo() {} | ||
72 | UNSAFE_KW if p.nth(2) == FN_KW => { | ||
73 | p.bump(); | ||
74 | p.bump(); | ||
75 | fn_item(p); | ||
76 | FN_ITEM | ||
77 | } | ||
78 | _ => { | ||
79 | consts::const_item(p); | ||
80 | CONST_ITEM | ||
81 | } | ||
82 | }, | ||
83 | UNSAFE_KW => { | ||
84 | p.bump(); | ||
85 | let la = p.nth(1); | ||
86 | match p.current() { | ||
87 | // test unsafe_trait | ||
88 | // unsafe trait T {} | ||
89 | TRAIT_KW => { | ||
90 | traits::trait_item(p); | ||
91 | TRAIT_ITEM | ||
92 | } | ||
93 | |||
94 | // test unsafe_auto_trait | ||
95 | // unsafe auto trait T {} | ||
96 | IDENT if p.at_contextual_kw("auto") && la == TRAIT_KW => { | ||
97 | p.bump_remap(AUTO_KW); | ||
98 | traits::trait_item(p); | ||
99 | TRAIT_ITEM | ||
100 | } | ||
101 | |||
102 | // test unsafe_impl | ||
103 | // unsafe impl Foo {} | ||
104 | IMPL_KW => { | ||
105 | traits::impl_item(p); | ||
106 | IMPL_ITEM | ||
107 | } | ||
108 | |||
109 | // test unsafe_default_impl | ||
110 | // unsafe default impl Foo {} | ||
111 | IDENT if p.at_contextual_kw("default") && la == IMPL_KW => { | ||
112 | p.bump_remap(DEFAULT_KW); | ||
113 | traits::impl_item(p); | ||
114 | IMPL_ITEM | ||
115 | } | ||
116 | |||
117 | // test unsafe_extern_fn | ||
118 | // unsafe extern "C" fn foo() {} | ||
119 | EXTERN_KW => { | ||
120 | abi(p); | ||
121 | if !p.at(FN_KW) { | ||
122 | item.abandon(p); | ||
123 | p.error("expected function"); | ||
124 | return; | ||
125 | } | ||
126 | fn_item(p); | ||
127 | FN_ITEM | ||
128 | } | ||
129 | |||
130 | // test unsafe_fn | ||
131 | // unsafe fn foo() {} | ||
132 | FN_KW => { | ||
133 | fn_item(p); | ||
134 | FN_ITEM | ||
135 | } | ||
136 | |||
137 | t => { | ||
138 | item.abandon(p); | ||
139 | let message = "expected `trait`, `impl` or `fn`"; | ||
140 | |||
141 | // test unsafe_block_in_mod | ||
142 | // fn foo(){} unsafe { } fn bar(){} | ||
143 | if t == L_CURLY { | ||
144 | error_block(p, message); | ||
145 | } else { | ||
146 | p.error(message); | ||
147 | } | ||
148 | return; | ||
149 | } | ||
150 | } | ||
151 | } | ||
152 | TRAIT_KW => { | ||
153 | traits::trait_item(p); | ||
154 | TRAIT_ITEM | ||
155 | } | 96 | } |
97 | |||
98 | // test unsafe_trait | ||
99 | // unsafe trait T {} | ||
100 | |||
156 | // test auto_trait | 101 | // test auto_trait |
157 | // auto trait T {} | 102 | // auto trait T {} |
158 | IDENT if p.at_contextual_kw("auto") && la == TRAIT_KW => { | 103 | |
159 | p.bump_remap(AUTO_KW); | 104 | // test unsafe_auto_trait |
105 | // unsafe auto trait T {} | ||
106 | TRAIT_KW => { | ||
160 | traits::trait_item(p); | 107 | traits::trait_item(p); |
161 | TRAIT_ITEM | 108 | TRAIT_ITEM |
162 | } | 109 | } |
163 | IMPL_KW => { | 110 | |
164 | traits::impl_item(p); | 111 | // test unsafe_impl |
165 | IMPL_ITEM | 112 | // unsafe impl Foo {} |
166 | } | 113 | |
167 | // test default_impl | 114 | // test default_impl |
168 | // default impl Foo {} | 115 | // default impl Foo {} |
169 | IDENT if p.at_contextual_kw("default") && la == IMPL_KW => { | 116 | |
170 | p.bump_remap(DEFAULT_KW); | 117 | // test unsafe_default_impl |
118 | // unsafe default impl Foo {} | ||
119 | IMPL_KW => { | ||
171 | traits::impl_item(p); | 120 | traits::impl_item(p); |
172 | IMPL_ITEM | 121 | IMPL_ITEM |
173 | } | 122 | } |
123 | _ => return if has_mods { | ||
124 | MaybeItem::Modifiers | ||
125 | } else { | ||
126 | MaybeItem::None | ||
127 | } | ||
128 | }; | ||
174 | 129 | ||
175 | FN_KW => { | 130 | MaybeItem::Item(kind) |
176 | fn_item(p); | 131 | } |
177 | FN_ITEM | 132 | |
133 | fn items_without_modifiers(p: &mut Parser) -> Option<SyntaxKind> { | ||
134 | let la = p.nth(1); | ||
135 | let kind = match p.current() { | ||
136 | // test extern_crate | ||
137 | // extern crate foo; | ||
138 | EXTERN_KW if la == CRATE_KW => { | ||
139 | extern_crate_item(p); | ||
140 | EXTERN_CRATE_ITEM | ||
178 | } | 141 | } |
179 | TYPE_KW => { | 142 | TYPE_KW => { |
180 | type_item(p); | 143 | type_item(p); |
@@ -186,31 +149,40 @@ pub(super) fn item(p: &mut Parser) { | |||
186 | } | 149 | } |
187 | STRUCT_KW => { | 150 | STRUCT_KW => { |
188 | structs::struct_item(p); | 151 | structs::struct_item(p); |
152 | if p.at(SEMI) { | ||
153 | p.err_and_bump( | ||
154 | "expected item, found `;`\n\ | ||
155 | consider removing this semicolon" | ||
156 | ); | ||
157 | } | ||
189 | STRUCT_ITEM | 158 | STRUCT_ITEM |
190 | } | 159 | } |
191 | ENUM_KW => { | 160 | ENUM_KW => { |
192 | structs::enum_item(p); | 161 | structs::enum_item(p); |
193 | ENUM_ITEM | 162 | ENUM_ITEM |
194 | } | 163 | } |
195 | L_CURLY => { | 164 | USE_KW => { |
196 | item.abandon(p); | 165 | use_item::use_item(p); |
197 | error_block(p, "expected item"); | 166 | USE_ITEM |
198 | return; | ||
199 | } | 167 | } |
200 | err_token => { | 168 | CONST_KW if (la == IDENT || la == MUT_KW) => { |
201 | item.abandon(p); | 169 | consts::const_item(p); |
202 | let message = if err_token == SEMI { | 170 | CONST_ITEM |
203 | //TODO: if the item is incomplete, this message is misleading | 171 | } |
204 | "expected item, found `;`\n\ | 172 | STATIC_KW => { |
205 | consider removing this semicolon" | 173 | consts::static_item(p); |
206 | } else { | 174 | STATIC_ITEM |
207 | "expected item" | 175 | } |
208 | }; | 176 | // test extern_block |
209 | p.err_and_bump(message); | 177 | // extern {} |
210 | return; | 178 | EXTERN_KW if la == L_CURLY || ((la == STRING || la == RAW_STRING) && p.nth(2) == L_CURLY) => { |
179 | abi(p); | ||
180 | extern_block(p); | ||
181 | EXTERN_BLOCK_EXPR | ||
211 | } | 182 | } |
183 | _ => return None, | ||
212 | }; | 184 | }; |
213 | item.complete(p, item_kind); | 185 | Some(kind) |
214 | } | 186 | } |
215 | 187 | ||
216 | fn extern_crate_item(p: &mut Parser) { | 188 | fn extern_crate_item(p: &mut Parser) { |
diff --git a/src/grammar/items/traits.rs b/src/grammar/items/traits.rs index bda13e565..0614e8ab6 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); | 48 | item(p, true); |
49 | } | 49 | } |
50 | p.expect(R_CURLY); | 50 | p.expect(R_CURLY); |
51 | } | 51 | } |