parser/grammar/items/
adt.rs

1use crate::grammar::attributes::ATTRIBUTE_FIRST;
2
3use super::*;
4
5// test struct_item
6// struct S {}
7pub(super) fn strukt(p: &mut Parser<'_>, m: Marker) {
8    p.bump(T![struct]);
9    struct_or_union(p, m, true);
10}
11
12// test union_item
13// struct U { i: i32, f: f32 }
14pub(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                    //FIXME: special case `(` error message
31                    p.error("expected `;` or `{`");
32                }
33            }
34        }
35        T!['{'] => record_field_list(p),
36        // test unit_struct
37        // struct S;
38        T![;] if is_struct => {
39            p.bump(T![;]);
40        }
41        // test tuple_struct
42        // struct S(String, usize);
43        T!['('] if is_struct => {
44            tuple_field_list(p);
45            // test tuple_struct_where
46            // struct S<T>(T) where T: Clone;
47            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            // test variant_discriminant
97            // enum E { X(i32) = 10 }
98            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
109// test record_field_list
110// struct S { a: i32, b: f32, unsafe c: u8 }
111pub(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        // test record_field_attrs
131        // struct S { #[attr] f: f32 }
132        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            // test record_field_default_values
140            // struct S { f: f32 = 0.0 }
141            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
155// test_err tuple_field_list_recovery
156// struct S(struct S;
157// struct S(A,,B);
158fn 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            // test tuple_field_attrs
171            // struct S (#[attr] f32);
172            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}