diff options
Diffstat (limited to 'src/parser/grammar/items/structs.rs')
-rw-r--r-- | src/parser/grammar/items/structs.rs | 117 |
1 files changed, 117 insertions, 0 deletions
diff --git a/src/parser/grammar/items/structs.rs b/src/parser/grammar/items/structs.rs new file mode 100644 index 000000000..69d95c698 --- /dev/null +++ b/src/parser/grammar/items/structs.rs | |||
@@ -0,0 +1,117 @@ | |||
1 | use super::*; | ||
2 | |||
3 | pub(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_params::list(p); | ||
11 | match p.current() { | ||
12 | WHERE_KW => { | ||
13 | type_params::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 | |||
43 | pub(super) fn enum_item(p: &mut Parser) { | ||
44 | assert!(p.at(ENUM_KW)); | ||
45 | p.bump(); | ||
46 | p.expect(IDENT); | ||
47 | type_params::list(p); | ||
48 | type_params::where_clause(p); | ||
49 | if p.expect(L_CURLY) { | ||
50 | while !p.at(EOF) && !p.at(R_CURLY) { | ||
51 | let var = p.start(); | ||
52 | attributes::outer_attributes(p); | ||
53 | if p.at(IDENT) { | ||
54 | p.bump(); | ||
55 | match p.current() { | ||
56 | L_CURLY => named_fields(p), | ||
57 | L_PAREN => pos_fields(p), | ||
58 | EQ => { | ||
59 | p.bump(); | ||
60 | expressions::expr(p); | ||
61 | } | ||
62 | _ => (), | ||
63 | } | ||
64 | var.complete(p, ENUM_VARIANT); | ||
65 | } else { | ||
66 | var.abandon(p); | ||
67 | p.err_and_bump("expected enum variant"); | ||
68 | } | ||
69 | if !p.at(R_CURLY) { | ||
70 | p.expect(COMMA); | ||
71 | } | ||
72 | } | ||
73 | p.expect(R_CURLY); | ||
74 | } | ||
75 | } | ||
76 | |||
77 | fn named_fields(p: &mut Parser) { | ||
78 | assert!(p.at(L_CURLY)); | ||
79 | p.bump(); | ||
80 | while !p.at(R_CURLY) && !p.at(EOF) { | ||
81 | named_field(p); | ||
82 | if !p.at(R_CURLY) { | ||
83 | p.expect(COMMA); | ||
84 | } | ||
85 | } | ||
86 | p.expect(R_CURLY); | ||
87 | |||
88 | fn named_field(p: &mut Parser) { | ||
89 | let field = p.start(); | ||
90 | visibility(p); | ||
91 | if p.expect(IDENT) { | ||
92 | p.expect(COLON); | ||
93 | types::type_ref(p); | ||
94 | field.complete(p, NAMED_FIELD); | ||
95 | } else { | ||
96 | field.abandon(p); | ||
97 | p.err_and_bump("expected field declaration"); | ||
98 | } | ||
99 | } | ||
100 | } | ||
101 | |||
102 | fn pos_fields(p: &mut Parser) { | ||
103 | if !p.expect(L_PAREN) { | ||
104 | return; | ||
105 | } | ||
106 | while !p.at(R_PAREN) && !p.at(EOF) { | ||
107 | let pos_field = p.start(); | ||
108 | visibility(p); | ||
109 | types::type_ref(p); | ||
110 | pos_field.complete(p, POS_FIELD); | ||
111 | |||
112 | if !p.at(R_PAREN) { | ||
113 | p.expect(COMMA); | ||
114 | } | ||
115 | } | ||
116 | p.expect(R_PAREN); | ||
117 | } | ||