aboutsummaryrefslogtreecommitdiff
path: root/src/grammar/items/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/grammar/items/mod.rs')
-rw-r--r--src/grammar/items/mod.rs290
1 files changed, 290 insertions, 0 deletions
diff --git a/src/grammar/items/mod.rs b/src/grammar/items/mod.rs
new file mode 100644
index 000000000..d5f75f13d
--- /dev/null
+++ b/src/grammar/items/mod.rs
@@ -0,0 +1,290 @@
1use super::*;
2
3mod consts;
4mod structs;
5mod traits;
6mod use_item;
7
8pub(super) fn mod_contents(p: &mut Parser, stop_on_r_curly: bool) {
9 attributes::inner_attributes(p);
10 while !p.at(EOF) && !(stop_on_r_curly && p.at(R_CURLY)) {
11 item(p);
12 }
13}
14
15pub(super) const ITEM_FIRST: TokenSet =
16 token_set![EXTERN_KW, MOD_KW, USE_KW, STRUCT_KW, ENUM_KW, FN_KW, PUB_KW, POUND];
17
18pub(super) fn item(p: &mut Parser) {
19 let item = p.start();
20 attributes::outer_attributes(p);
21 visibility(p);
22 let la = p.nth(1);
23 let item_kind = match p.current() {
24 USE_KW => {
25 use_item::use_item(p);
26 USE_ITEM
27 }
28 // test extern_crate
29 // extern crate foo;
30 EXTERN_KW if la == CRATE_KW => {
31 extern_crate_item(p);
32 EXTERN_CRATE_ITEM
33 }
34 EXTERN_KW => {
35 abi(p);
36 match p.current() {
37 // test extern_fn
38 // extern fn foo() {}
39 FN_KW => {
40 fn_item(p);
41 FN_ITEM
42 }
43 // test extern_block
44 // extern {}
45 L_CURLY => {
46 extern_block(p);
47 EXTERN_BLOCK
48 }
49 // test extern_struct
50 // extern struct Foo;
51 _ => {
52 item.abandon(p);
53 p.error("expected `fn` or `{`");
54 return;
55 }
56 }
57 }
58 STATIC_KW => {
59 consts::static_item(p);
60 STATIC_ITEM
61 }
62 CONST_KW => match p.nth(1) {
63 // test const_fn
64 // const fn foo() {}
65 FN_KW => {
66 p.bump();
67 fn_item(p);
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 }
156 // test auto_trait
157 // auto trait T {}
158 IDENT if p.at_contextual_kw("auto") && la == TRAIT_KW => {
159 p.bump_remap(AUTO_KW);
160 traits::trait_item(p);
161 TRAIT_ITEM
162 }
163 IMPL_KW => {
164 traits::impl_item(p);
165 IMPL_ITEM
166 }
167 // test default_impl
168 // default impl Foo {}
169 IDENT if p.at_contextual_kw("default") && la == IMPL_KW => {
170 p.bump_remap(DEFAULT_KW);
171 traits::impl_item(p);
172 IMPL_ITEM
173 }
174
175 FN_KW => {
176 fn_item(p);
177 FN_ITEM
178 }
179 TYPE_KW => {
180 type_item(p);
181 TYPE_ITEM
182 }
183 MOD_KW => {
184 mod_item(p);
185 MOD_ITEM
186 }
187 STRUCT_KW => {
188 structs::struct_item(p);
189 STRUCT_ITEM
190 }
191 ENUM_KW => {
192 structs::enum_item(p);
193 ENUM_ITEM
194 }
195 L_CURLY => {
196 item.abandon(p);
197 error_block(p, "expected item");
198 return;
199 }
200 err_token => {
201 item.abandon(p);
202 let message = if err_token == SEMI {
203 //TODO: if the item is incomplete, this message is misleading
204 "expected item, found `;`\n\
205 consider removing this semicolon"
206 } else {
207 "expected item"
208 };
209 p.err_and_bump(message);
210 return;
211 }
212 };
213 item.complete(p, item_kind);
214}
215
216fn extern_crate_item(p: &mut Parser) {
217 assert!(p.at(EXTERN_KW));
218 p.bump();
219 assert!(p.at(CRATE_KW));
220 p.bump();
221 name(p);
222 alias(p);
223 p.expect(SEMI);
224}
225
226fn extern_block(p: &mut Parser) {
227 assert!(p.at(L_CURLY));
228 p.bump();
229 p.expect(R_CURLY);
230}
231
232fn fn_item(p: &mut Parser) {
233 assert!(p.at(FN_KW));
234 p.bump();
235
236 name(p);
237 // test fn_item_type_params
238 // fn foo<T: Clone + Copy>(){}
239 type_params::type_param_list(p);
240
241 if p.at(L_PAREN) {
242 params::param_list(p);
243 } else {
244 p.error("expected function arguments");
245 }
246 // test fn_item_ret_type
247 // fn foo() {}
248 // fn bar() -> () {}
249 fn_ret_type(p);
250
251 // test fn_item_where_clause
252 // fn foo<T>() where T: Copy {}
253 type_params::where_clause(p);
254
255 expressions::block(p);
256}
257
258// test type_item
259// type Foo = Bar;
260fn type_item(p: &mut Parser) {
261 assert!(p.at(TYPE_KW));
262 p.bump();
263
264 name(p);
265
266 // test type_item_type_params
267 // type Result<T> = ();
268 type_params::type_param_list(p);
269
270 // test type_item_where_clause
271 // type Foo where Foo: Copy = ();
272 type_params::where_clause(p);
273
274 p.expect(EQ);
275 types::type_(p);
276 p.expect(SEMI);
277}
278
279fn mod_item(p: &mut Parser) {
280 assert!(p.at(MOD_KW));
281 p.bump();
282
283 name(p);
284 if !p.eat(SEMI) {
285 if p.expect(L_CURLY) {
286 mod_contents(p, true);
287 p.expect(R_CURLY);
288 }
289 }
290}