diff options
author | Aleksey Kladov <[email protected]> | 2019-02-21 10:27:45 +0000 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2019-02-21 10:27:45 +0000 |
commit | d334b5a1db9ec6a57f54077d422a3f4b3c8c1178 (patch) | |
tree | 9d930fe43452e8188594c612de433a77524e4754 /crates/ra_syntax/src/parsing/grammar/items.rs | |
parent | 18b0c509f77a8e06141fee6668532cced1ebf5d8 (diff) |
move parser to a separate crate
Diffstat (limited to 'crates/ra_syntax/src/parsing/grammar/items.rs')
-rw-r--r-- | crates/ra_syntax/src/parsing/grammar/items.rs | 392 |
1 files changed, 0 insertions, 392 deletions
diff --git a/crates/ra_syntax/src/parsing/grammar/items.rs b/crates/ra_syntax/src/parsing/grammar/items.rs deleted file mode 100644 index 4b962c1f3..000000000 --- a/crates/ra_syntax/src/parsing/grammar/items.rs +++ /dev/null | |||
@@ -1,392 +0,0 @@ | |||
1 | mod consts; | ||
2 | mod nominal; | ||
3 | mod traits; | ||
4 | mod use_item; | ||
5 | |||
6 | pub(crate) use self::{ | ||
7 | expressions::{match_arm_list, named_field_list}, | ||
8 | nominal::{enum_variant_list, named_field_def_list}, | ||
9 | traits::{impl_item_list, trait_item_list}, | ||
10 | use_item::use_tree_list, | ||
11 | }; | ||
12 | use super::*; | ||
13 | |||
14 | // test mod_contents | ||
15 | // fn foo() {} | ||
16 | // macro_rules! foo {} | ||
17 | // foo::bar!(); | ||
18 | // super::baz! {} | ||
19 | // struct S; | ||
20 | pub(super) fn mod_contents(p: &mut Parser, stop_on_r_curly: bool) { | ||
21 | attributes::inner_attributes(p); | ||
22 | while !p.at(EOF) && !(stop_on_r_curly && p.at(R_CURLY)) { | ||
23 | item_or_macro(p, stop_on_r_curly, ItemFlavor::Mod) | ||
24 | } | ||
25 | } | ||
26 | |||
27 | pub(super) enum ItemFlavor { | ||
28 | Mod, | ||
29 | Trait, | ||
30 | } | ||
31 | |||
32 | pub(super) const ITEM_RECOVERY_SET: TokenSet = token_set![ | ||
33 | FN_KW, STRUCT_KW, ENUM_KW, IMPL_KW, TRAIT_KW, CONST_KW, STATIC_KW, LET_KW, MOD_KW, PUB_KW, | ||
34 | CRATE_KW | ||
35 | ]; | ||
36 | |||
37 | pub(super) fn item_or_macro(p: &mut Parser, stop_on_r_curly: bool, flavor: ItemFlavor) { | ||
38 | let m = p.start(); | ||
39 | attributes::outer_attributes(p); | ||
40 | match maybe_item(p, flavor) { | ||
41 | MaybeItem::Item(kind) => { | ||
42 | m.complete(p, kind); | ||
43 | } | ||
44 | MaybeItem::None => { | ||
45 | if paths::is_path_start(p) { | ||
46 | match macro_call(p) { | ||
47 | BlockLike::Block => (), | ||
48 | BlockLike::NotBlock => { | ||
49 | p.expect(SEMI); | ||
50 | } | ||
51 | } | ||
52 | m.complete(p, MACRO_CALL); | ||
53 | } else { | ||
54 | m.abandon(p); | ||
55 | if p.at(L_CURLY) { | ||
56 | error_block(p, "expected an item"); | ||
57 | } else if p.at(R_CURLY) && !stop_on_r_curly { | ||
58 | let e = p.start(); | ||
59 | p.error("unmatched `}`"); | ||
60 | p.bump(); | ||
61 | e.complete(p, ERROR); | ||
62 | } else if !p.at(EOF) && !p.at(R_CURLY) { | ||
63 | p.err_and_bump("expected an item"); | ||
64 | } else { | ||
65 | p.error("expected an item"); | ||
66 | } | ||
67 | } | ||
68 | } | ||
69 | MaybeItem::Modifiers => { | ||
70 | p.error("expected fn, trait or impl"); | ||
71 | m.complete(p, ERROR); | ||
72 | } | ||
73 | } | ||
74 | } | ||
75 | |||
76 | pub(super) enum MaybeItem { | ||
77 | None, | ||
78 | Item(SyntaxKind), | ||
79 | Modifiers, | ||
80 | } | ||
81 | |||
82 | pub(super) fn maybe_item(p: &mut Parser, flavor: ItemFlavor) -> MaybeItem { | ||
83 | opt_visibility(p); | ||
84 | if let Some(kind) = items_without_modifiers(p) { | ||
85 | return MaybeItem::Item(kind); | ||
86 | } | ||
87 | |||
88 | let mut has_mods = false; | ||
89 | // modifiers | ||
90 | has_mods |= p.eat(CONST_KW); | ||
91 | |||
92 | // test_err unsafe_block_in_mod | ||
93 | // fn foo(){} unsafe { } fn bar(){} | ||
94 | if p.at(UNSAFE_KW) && p.nth(1) != L_CURLY { | ||
95 | p.eat(UNSAFE_KW); | ||
96 | has_mods = true; | ||
97 | } | ||
98 | if p.at(EXTERN_KW) { | ||
99 | has_mods = true; | ||
100 | abi(p); | ||
101 | } | ||
102 | if p.at(IDENT) && p.at_contextual_kw("auto") && p.nth(1) == TRAIT_KW { | ||
103 | p.bump_remap(AUTO_KW); | ||
104 | has_mods = true; | ||
105 | } | ||
106 | if p.at(IDENT) && p.at_contextual_kw("default") && p.nth(1) == IMPL_KW { | ||
107 | p.bump_remap(DEFAULT_KW); | ||
108 | has_mods = true; | ||
109 | } | ||
110 | |||
111 | // items | ||
112 | let kind = match p.current() { | ||
113 | // test extern_fn | ||
114 | // extern fn foo() {} | ||
115 | |||
116 | // test const_fn | ||
117 | // const fn foo() {} | ||
118 | |||
119 | // test const_unsafe_fn | ||
120 | // const unsafe fn foo() {} | ||
121 | |||
122 | // test unsafe_extern_fn | ||
123 | // unsafe extern "C" fn foo() {} | ||
124 | |||
125 | // test unsafe_fn | ||
126 | // unsafe fn foo() {} | ||
127 | FN_KW => { | ||
128 | fn_def(p, flavor); | ||
129 | FN_DEF | ||
130 | } | ||
131 | |||
132 | // test unsafe_trait | ||
133 | // unsafe trait T {} | ||
134 | |||
135 | // test auto_trait | ||
136 | // auto trait T {} | ||
137 | |||
138 | // test unsafe_auto_trait | ||
139 | // unsafe auto trait T {} | ||
140 | TRAIT_KW => { | ||
141 | traits::trait_def(p); | ||
142 | TRAIT_DEF | ||
143 | } | ||
144 | |||
145 | // test unsafe_impl | ||
146 | // unsafe impl Foo {} | ||
147 | |||
148 | // test default_impl | ||
149 | // default impl Foo {} | ||
150 | |||
151 | // test unsafe_default_impl | ||
152 | // unsafe default impl Foo {} | ||
153 | IMPL_KW => { | ||
154 | traits::impl_block(p); | ||
155 | IMPL_BLOCK | ||
156 | } | ||
157 | _ => { | ||
158 | return if has_mods { MaybeItem::Modifiers } else { MaybeItem::None }; | ||
159 | } | ||
160 | }; | ||
161 | |||
162 | MaybeItem::Item(kind) | ||
163 | } | ||
164 | |||
165 | fn items_without_modifiers(p: &mut Parser) -> Option<SyntaxKind> { | ||
166 | let la = p.nth(1); | ||
167 | let kind = match p.current() { | ||
168 | // test extern_crate | ||
169 | // extern crate foo; | ||
170 | EXTERN_KW if la == CRATE_KW => { | ||
171 | extern_crate_item(p); | ||
172 | EXTERN_CRATE_ITEM | ||
173 | } | ||
174 | TYPE_KW => { | ||
175 | type_def(p); | ||
176 | TYPE_DEF | ||
177 | } | ||
178 | MOD_KW => { | ||
179 | mod_item(p); | ||
180 | MODULE | ||
181 | } | ||
182 | STRUCT_KW => { | ||
183 | // test struct_items | ||
184 | // struct Foo; | ||
185 | // struct Foo {} | ||
186 | // struct Foo(); | ||
187 | // struct Foo(String, usize); | ||
188 | // struct Foo { | ||
189 | // a: i32, | ||
190 | // b: f32, | ||
191 | // } | ||
192 | nominal::struct_def(p, STRUCT_KW); | ||
193 | if p.at(SEMI) { | ||
194 | p.err_and_bump( | ||
195 | "expected item, found `;`\n\ | ||
196 | consider removing this semicolon", | ||
197 | ); | ||
198 | } | ||
199 | STRUCT_DEF | ||
200 | } | ||
201 | IDENT if p.at_contextual_kw("union") && p.nth(1) == IDENT => { | ||
202 | // test union_items | ||
203 | // union Foo {} | ||
204 | // union Foo { | ||
205 | // a: i32, | ||
206 | // b: f32, | ||
207 | // } | ||
208 | nominal::struct_def(p, UNION_KW); | ||
209 | STRUCT_DEF | ||
210 | } | ||
211 | ENUM_KW => { | ||
212 | nominal::enum_def(p); | ||
213 | ENUM_DEF | ||
214 | } | ||
215 | USE_KW => { | ||
216 | use_item::use_item(p); | ||
217 | USE_ITEM | ||
218 | } | ||
219 | CONST_KW if (la == IDENT || la == MUT_KW) => { | ||
220 | consts::const_def(p); | ||
221 | CONST_DEF | ||
222 | } | ||
223 | STATIC_KW => { | ||
224 | consts::static_def(p); | ||
225 | STATIC_DEF | ||
226 | } | ||
227 | // test extern_block | ||
228 | // extern {} | ||
229 | EXTERN_KW | ||
230 | if la == L_CURLY || ((la == STRING || la == RAW_STRING) && p.nth(2) == L_CURLY) => | ||
231 | { | ||
232 | abi(p); | ||
233 | extern_item_list(p); | ||
234 | EXTERN_BLOCK | ||
235 | } | ||
236 | _ => return None, | ||
237 | }; | ||
238 | Some(kind) | ||
239 | } | ||
240 | |||
241 | fn extern_crate_item(p: &mut Parser) { | ||
242 | assert!(p.at(EXTERN_KW)); | ||
243 | p.bump(); | ||
244 | assert!(p.at(CRATE_KW)); | ||
245 | p.bump(); | ||
246 | name_ref(p); | ||
247 | opt_alias(p); | ||
248 | p.expect(SEMI); | ||
249 | } | ||
250 | |||
251 | pub(crate) fn extern_item_list(p: &mut Parser) { | ||
252 | assert!(p.at(L_CURLY)); | ||
253 | let m = p.start(); | ||
254 | p.bump(); | ||
255 | mod_contents(p, true); | ||
256 | p.expect(R_CURLY); | ||
257 | m.complete(p, EXTERN_ITEM_LIST); | ||
258 | } | ||
259 | |||
260 | fn fn_def(p: &mut Parser, flavor: ItemFlavor) { | ||
261 | assert!(p.at(FN_KW)); | ||
262 | p.bump(); | ||
263 | |||
264 | name_r(p, ITEM_RECOVERY_SET); | ||
265 | // test function_type_params | ||
266 | // fn foo<T: Clone + Copy>(){} | ||
267 | type_params::opt_type_param_list(p); | ||
268 | |||
269 | if p.at(L_PAREN) { | ||
270 | match flavor { | ||
271 | ItemFlavor::Mod => params::param_list(p), | ||
272 | ItemFlavor::Trait => params::param_list_opt_patterns(p), | ||
273 | } | ||
274 | } else { | ||
275 | p.error("expected function arguments"); | ||
276 | } | ||
277 | // test function_ret_type | ||
278 | // fn foo() {} | ||
279 | // fn bar() -> () {} | ||
280 | opt_fn_ret_type(p); | ||
281 | |||
282 | // test function_where_clause | ||
283 | // fn foo<T>() where T: Copy {} | ||
284 | type_params::opt_where_clause(p); | ||
285 | |||
286 | // test fn_decl | ||
287 | // trait T { fn foo(); } | ||
288 | if p.at(SEMI) { | ||
289 | p.bump(); | ||
290 | } else { | ||
291 | expressions::block(p) | ||
292 | } | ||
293 | } | ||
294 | |||
295 | // test type_item | ||
296 | // type Foo = Bar; | ||
297 | fn type_def(p: &mut Parser) { | ||
298 | assert!(p.at(TYPE_KW)); | ||
299 | p.bump(); | ||
300 | |||
301 | name(p); | ||
302 | |||
303 | // test type_item_type_params | ||
304 | // type Result<T> = (); | ||
305 | type_params::opt_type_param_list(p); | ||
306 | |||
307 | if p.at(COLON) { | ||
308 | type_params::bounds(p); | ||
309 | } | ||
310 | |||
311 | // test type_item_where_clause | ||
312 | // type Foo where Foo: Copy = (); | ||
313 | type_params::opt_where_clause(p); | ||
314 | |||
315 | if p.eat(EQ) { | ||
316 | types::type_(p); | ||
317 | } | ||
318 | p.expect(SEMI); | ||
319 | } | ||
320 | |||
321 | pub(crate) fn mod_item(p: &mut Parser) { | ||
322 | assert!(p.at(MOD_KW)); | ||
323 | p.bump(); | ||
324 | |||
325 | name(p); | ||
326 | if p.at(L_CURLY) { | ||
327 | mod_item_list(p); | ||
328 | } else if !p.eat(SEMI) { | ||
329 | p.error("expected `;` or `{`"); | ||
330 | } | ||
331 | } | ||
332 | |||
333 | pub(crate) fn mod_item_list(p: &mut Parser) { | ||
334 | assert!(p.at(L_CURLY)); | ||
335 | let m = p.start(); | ||
336 | p.bump(); | ||
337 | mod_contents(p, true); | ||
338 | p.expect(R_CURLY); | ||
339 | m.complete(p, ITEM_LIST); | ||
340 | } | ||
341 | |||
342 | fn macro_call(p: &mut Parser) -> BlockLike { | ||
343 | assert!(paths::is_path_start(p)); | ||
344 | paths::use_path(p); | ||
345 | macro_call_after_excl(p) | ||
346 | } | ||
347 | |||
348 | pub(super) fn macro_call_after_excl(p: &mut Parser) -> BlockLike { | ||
349 | p.expect(EXCL); | ||
350 | if p.at(IDENT) { | ||
351 | name(p); | ||
352 | } | ||
353 | match p.current() { | ||
354 | L_CURLY => { | ||
355 | token_tree(p); | ||
356 | BlockLike::Block | ||
357 | } | ||
358 | L_PAREN | L_BRACK => { | ||
359 | token_tree(p); | ||
360 | BlockLike::NotBlock | ||
361 | } | ||
362 | _ => { | ||
363 | p.error("expected `{`, `[`, `(`"); | ||
364 | BlockLike::NotBlock | ||
365 | } | ||
366 | } | ||
367 | } | ||
368 | |||
369 | pub(crate) fn token_tree(p: &mut Parser) { | ||
370 | let closing_paren_kind = match p.current() { | ||
371 | L_CURLY => R_CURLY, | ||
372 | L_PAREN => R_PAREN, | ||
373 | L_BRACK => R_BRACK, | ||
374 | _ => unreachable!(), | ||
375 | }; | ||
376 | let m = p.start(); | ||
377 | p.bump(); | ||
378 | while !p.at(EOF) && !p.at(closing_paren_kind) { | ||
379 | match p.current() { | ||
380 | L_CURLY | L_PAREN | L_BRACK => token_tree(p), | ||
381 | R_CURLY => { | ||
382 | p.error("unmatched `}`"); | ||
383 | m.complete(p, TOKEN_TREE); | ||
384 | return; | ||
385 | } | ||
386 | R_PAREN | R_BRACK => p.err_and_bump("unmatched brace"), | ||
387 | _ => p.bump(), | ||
388 | } | ||
389 | } | ||
390 | p.expect(closing_paren_kind); | ||
391 | m.complete(p, TOKEN_TREE); | ||
392 | } | ||