aboutsummaryrefslogtreecommitdiff
path: root/src/parser/event_parser/grammar/items
diff options
context:
space:
mode:
Diffstat (limited to 'src/parser/event_parser/grammar/items')
-rw-r--r--src/parser/event_parser/grammar/items/mod.rs220
-rw-r--r--src/parser/event_parser/grammar/items/structs.rs83
2 files changed, 303 insertions, 0 deletions
diff --git a/src/parser/event_parser/grammar/items/mod.rs b/src/parser/event_parser/grammar/items/mod.rs
new file mode 100644
index 000000000..f10fb230b
--- /dev/null
+++ b/src/parser/event_parser/grammar/items/mod.rs
@@ -0,0 +1,220 @@
1use super::*;
2
3mod structs;
4
5pub(super) fn mod_contents(p: &mut Parser, stop_on_r_curly: bool) {
6 attributes::inner_attributes(p);
7 while !p.at(EOF) && !(stop_on_r_curly && p.at(R_CURLY)) {
8 item(p);
9 }
10}
11
12pub(super) const ITEM_FIRST: TokenSet =
13 token_set![EXTERN_KW, MOD_KW, USE_KW, STRUCT_KW, FN_KW, PUB_KW, POUND,];
14
15fn item(p: &mut Parser) {
16 let item = p.start();
17 attributes::outer_attributes(p);
18 visibility(p);
19 let la = p.nth(1);
20 let item_kind = match p.current() {
21 EXTERN_KW if la == CRATE_KW => {
22 extern_crate_item(p);
23 EXTERN_CRATE_ITEM
24 }
25 MOD_KW => {
26 mod_item(p);
27 MOD_ITEM
28 }
29 USE_KW => {
30 use_item(p);
31 USE_ITEM
32 }
33 STRUCT_KW => {
34 structs::struct_item(p);
35 STRUCT_ITEM
36 }
37 FN_KW => {
38 fn_item(p);
39 FN_ITEM
40 }
41 L_CURLY => {
42 item.abandon(p);
43 error_block(p, "expected item");
44 return;
45 }
46 err_token => {
47 item.abandon(p);
48 let message = if err_token == SEMI {
49 //TODO: if the item is incomplete, this message is misleading
50 "expected item, found `;`\n\
51 consider removing this semicolon"
52 } else {
53 "expected item"
54 };
55 p.err_and_bump(message);
56 return;
57 }
58 };
59 item.complete(p, item_kind);
60}
61
62fn type_param_list(p: &mut Parser) {
63 if !p.at(L_ANGLE) {
64 return;
65 }
66 let m = p.start();
67 p.bump();
68
69 while !p.at(EOF) && !p.at(R_ANGLE) {
70 match p.current() {
71 LIFETIME => lifetime_param(p),
72 IDENT => type_param(p),
73 _ => p.err_and_bump("expected type parameter"),
74 }
75 if !p.at(R_ANGLE) && !p.expect(COMMA) {
76 break;
77 }
78 }
79 p.expect(R_ANGLE);
80 m.complete(p, TYPE_PARAM_LIST);
81
82 fn lifetime_param(p: &mut Parser) {
83 assert!(p.at(LIFETIME));
84 let m = p.start();
85 p.bump();
86 if p.eat(COLON) {
87 while p.at(LIFETIME) {
88 p.bump();
89 if !p.eat(PLUS) {
90 break;
91 }
92 }
93 }
94 m.complete(p, LIFETIME_PARAM);
95 }
96
97 fn type_param(p: &mut Parser) {
98 assert!(p.at(IDENT));
99 let m = p.start();
100 p.bump();
101 m.complete(p, TYPE_PARAM);
102 //TODO: bounds
103 }
104}
105
106fn where_clause(_: &mut Parser) {}
107
108fn extern_crate_item(p: &mut Parser) {
109 assert!(p.at(EXTERN_KW));
110 p.bump();
111 assert!(p.at(CRATE_KW));
112 p.bump();
113
114 p.expect(IDENT) && alias(p) && p.expect(SEMI);
115}
116
117fn mod_item(p: &mut Parser) {
118 assert!(p.at(MOD_KW));
119 p.bump();
120
121 if p.expect(IDENT) && !p.eat(SEMI) {
122 if p.expect(L_CURLY) {
123 mod_contents(p, true);
124 p.expect(R_CURLY);
125 }
126 }
127}
128
129pub(super) fn is_use_tree_start(kind: SyntaxKind) -> bool {
130 kind == STAR || kind == L_CURLY
131}
132
133fn use_item(p: &mut Parser) {
134 assert!(p.at(USE_KW));
135 p.bump();
136
137 use_tree(p);
138 p.expect(SEMI);
139
140 fn use_tree(p: &mut Parser) {
141 let la = p.nth(1);
142 let m = p.start();
143 match (p.current(), la) {
144 (STAR, _) => p.bump(),
145 (COLONCOLON, STAR) => {
146 p.bump();
147 p.bump();
148 }
149 (L_CURLY, _) | (COLONCOLON, L_CURLY) => {
150 if p.at(COLONCOLON) {
151 p.bump();
152 }
153 nested_trees(p);
154 }
155 _ if paths::is_path_start(p) => {
156 paths::use_path(p);
157 match p.current() {
158 AS_KW => {
159 alias(p);
160 }
161 COLONCOLON => {
162 p.bump();
163 match p.current() {
164 STAR => {
165 p.bump();
166 }
167 L_CURLY => nested_trees(p),
168 _ => {
169 // is this unreachable?
170 p.error().message("expected `{` or `*`").emit();
171 }
172 }
173 }
174 _ => (),
175 }
176 }
177 _ => {
178 m.abandon(p);
179 p.err_and_bump("expected one of `*`, `::`, `{`, `self`, `super`, `indent`");
180 return;
181 }
182 }
183 m.complete(p, USE_TREE);
184 }
185
186 fn nested_trees(p: &mut Parser) {
187 assert!(p.at(L_CURLY));
188 p.bump();
189 while !p.at(EOF) && !p.at(R_CURLY) {
190 use_tree(p);
191 if !p.at(R_CURLY) {
192 p.expect(COMMA);
193 }
194 }
195 p.expect(R_CURLY);
196 }
197}
198
199fn fn_item(p: &mut Parser) {
200 assert!(p.at(FN_KW));
201 p.bump();
202
203 p.expect(IDENT);
204 if p.at(L_PAREN) {
205 fn_value_parameters(p);
206 } else {
207 p.error().message("expected function arguments").emit();
208 }
209
210 if p.at(L_CURLY) {
211 p.expect(L_CURLY);
212 p.expect(R_CURLY);
213 }
214
215 fn fn_value_parameters(p: &mut Parser) {
216 assert!(p.at(L_PAREN));
217 p.bump();
218 p.expect(R_PAREN);
219 }
220}
diff --git a/src/parser/event_parser/grammar/items/structs.rs b/src/parser/event_parser/grammar/items/structs.rs
new file mode 100644
index 000000000..0934f3d28
--- /dev/null
+++ b/src/parser/event_parser/grammar/items/structs.rs
@@ -0,0 +1,83 @@
1use super::*;
2
3pub(super) fn struct_item(p: &mut Parser) {
4 assert!(p.at(STRUCT_KW));
5 p.bump();
6
7 if !p.expect(IDENT) {
8 return;
9 }
10 type_param_list(p);
11 match p.current() {
12 WHERE_KW => {
13 where_clause(p);
14 match p.current() {
15 SEMI => {
16 p.bump();
17 return;
18 }
19 L_CURLY => named_fields(p),
20 _ => {
21 //TODO: special case `(` error message
22 p.error().message("expected `;` or `{`").emit();
23 return;
24 }
25 }
26 }
27 SEMI => {
28 p.bump();
29 return;
30 }
31 L_CURLY => named_fields(p),
32 L_PAREN => {
33 pos_fields(p);
34 p.expect(SEMI);
35 }
36 _ => {
37 p.error().message("expected `;`, `{`, or `(`").emit();
38 return;
39 }
40 }
41}
42
43fn named_fields(p: &mut Parser) {
44 assert!(p.at(L_CURLY));
45 p.bump();
46 while !p.at(R_CURLY) && !p.at(EOF) {
47 named_field(p);
48 if !p.at(R_CURLY) {
49 p.expect(COMMA);
50 }
51 }
52 p.expect(R_CURLY);
53
54 fn named_field(p: &mut Parser) {
55 let field = p.start();
56 visibility(p);
57 if p.expect(IDENT) {
58 p.expect(COLON);
59 types::type_ref(p);
60 field.complete(p, NAMED_FIELD);
61 } else {
62 field.abandon(p);
63 p.err_and_bump("expected field declaration");
64 }
65 }
66}
67
68fn pos_fields(p: &mut Parser) {
69 if !p.expect(L_PAREN) {
70 return;
71 }
72 while !p.at(R_PAREN) && !p.at(EOF) {
73 let pos_field = p.start();
74 visibility(p);
75 types::type_ref(p);
76 pos_field.complete(p, POS_FIELD);
77
78 if !p.at(R_PAREN) {
79 p.expect(COMMA);
80 }
81 }
82 p.expect(R_PAREN);
83}