parser/grammar/items/
adt.rs1use crate::grammar::attributes::ATTRIBUTE_FIRST;
2
3use super::*;
4
5pub(super) fn strukt(p: &mut Parser<'_>, m: Marker) {
8 p.bump(T![struct]);
9 struct_or_union(p, m, true);
10}
11
12pub(super) fn union(p: &mut Parser<'_>, m: Marker) {
15 assert!(p.at_contextual_kw(T![union]));
16 p.bump_remap(T![union]);
17 struct_or_union(p, m, false);
18}
19
20fn struct_or_union(p: &mut Parser<'_>, m: Marker, is_struct: bool) {
21 name_r(p, ITEM_RECOVERY_SET);
22 generic_params::opt_generic_param_list(p);
23 match p.current() {
24 T![where] => {
25 generic_params::opt_where_clause(p);
26 match p.current() {
27 T![;] => p.bump(T![;]),
28 T!['{'] => record_field_list(p),
29 _ => {
30 p.error("expected `;` or `{`");
32 }
33 }
34 }
35 T!['{'] => record_field_list(p),
36 T![;] if is_struct => {
39 p.bump(T![;]);
40 }
41 T!['('] if is_struct => {
44 tuple_field_list(p);
45 generic_params::opt_where_clause(p);
48 p.expect(T![;]);
49 }
50 _ => p.error(if is_struct { "expected `;`, `{`, or `(`" } else { "expected `{`" }),
51 }
52 m.complete(p, if is_struct { STRUCT } else { UNION });
53}
54
55pub(super) fn enum_(p: &mut Parser<'_>, m: Marker) {
56 p.bump(T![enum]);
57 name_r(p, ITEM_RECOVERY_SET);
58 generic_params::opt_generic_param_list(p);
59 generic_params::opt_where_clause(p);
60 if p.at(T!['{']) {
61 variant_list(p);
62 } else {
63 p.error("expected `{`");
64 }
65 m.complete(p, ENUM);
66}
67
68pub(crate) fn variant_list(p: &mut Parser<'_>) {
69 assert!(p.at(T!['{']));
70 let m = p.start();
71 p.bump(T!['{']);
72 while !p.at(EOF) && !p.at(T!['}']) {
73 if p.at(T!['{']) {
74 error_block(p, "expected enum variant");
75 continue;
76 }
77 variant(p);
78 if !p.at(T!['}']) {
79 p.expect(T![,]);
80 }
81 }
82 p.expect(T!['}']);
83 m.complete(p, VARIANT_LIST);
84
85 fn variant(p: &mut Parser<'_>) {
86 let m = p.start();
87 attributes::outer_attrs(p);
88 if p.at(IDENT) {
89 name(p);
90 match p.current() {
91 T!['{'] => record_field_list(p),
92 T!['('] => tuple_field_list(p),
93 _ => (),
94 }
95
96 if p.eat(T![=]) {
99 expressions::expr(p);
100 }
101 m.complete(p, VARIANT);
102 } else {
103 m.abandon(p);
104 p.err_and_bump("expected enum variant");
105 }
106 }
107}
108
109pub(crate) fn record_field_list(p: &mut Parser<'_>) {
112 assert!(p.at(T!['{']));
113 let m = p.start();
114 p.bump(T!['{']);
115 while !p.at(T!['}']) && !p.at(EOF) {
116 if p.at(T!['{']) {
117 error_block(p, "expected field");
118 continue;
119 }
120 record_field(p);
121 if !p.at(T!['}']) {
122 p.expect(T![,]);
123 }
124 }
125 p.expect(T!['}']);
126 m.complete(p, RECORD_FIELD_LIST);
127
128 fn record_field(p: &mut Parser<'_>) {
129 let m = p.start();
130 attributes::outer_attrs(p);
133 opt_visibility(p, false);
134 p.eat(T![unsafe]);
135 if p.at(IDENT) {
136 name(p);
137 p.expect(T![:]);
138 types::type_(p);
139 if p.eat(T![=]) {
142 expressions::expr(p);
143 }
144 m.complete(p, RECORD_FIELD);
145 } else {
146 m.abandon(p);
147 p.err_and_bump("expected field declaration");
148 }
149 }
150}
151
152const TUPLE_FIELD_FIRST: TokenSet =
153 types::TYPE_FIRST.union(ATTRIBUTE_FIRST).union(VISIBILITY_FIRST);
154
155fn tuple_field_list(p: &mut Parser<'_>) {
159 assert!(p.at(T!['(']));
160 let m = p.start();
161 delimited(
162 p,
163 T!['('],
164 T![')'],
165 T![,],
166 || "expected tuple field".into(),
167 TUPLE_FIELD_FIRST,
168 |p| {
169 let m = p.start();
170 attributes::outer_attrs(p);
173 let has_vis = opt_visibility(p, true);
174 if !p.at_ts(types::TYPE_FIRST) {
175 p.error("expected a type");
176 if has_vis {
177 m.complete(p, ERROR);
178 } else {
179 m.abandon(p);
180 }
181 return false;
182 }
183 types::type_(p);
184 m.complete(p, TUPLE_FIELD);
185 true
186 },
187 );
188
189 m.complete(p, TUPLE_FIELD_LIST);
190}