diff options
author | Aleksey Kladov <[email protected]> | 2019-11-25 13:55:09 +0000 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2019-11-25 14:50:49 +0000 |
commit | e1c0bdaf75f8d88a5c28b3e44def17d91d4f46b3 (patch) | |
tree | 15cb5466dd2fab58d1591afc50bd28aeab65359d /crates/ra_parser/src/grammar/items/nominal.rs | |
parent | be00d74c7b61fb82bdade482e95035a21f9dd736 (diff) |
Introduce dedicated AST node for union
Although structs and unions have the same syntax and differ only in
the keyword, re-using the single syntax node for both of them leads to
confusion in practice, and propagates further down the hir in an
upleasent way.
Moreover, static and consts also share syntax, but we use different
nodes for them.
Diffstat (limited to 'crates/ra_parser/src/grammar/items/nominal.rs')
-rw-r--r-- | crates/ra_parser/src/grammar/items/nominal.rs | 167 |
1 files changed, 0 insertions, 167 deletions
diff --git a/crates/ra_parser/src/grammar/items/nominal.rs b/crates/ra_parser/src/grammar/items/nominal.rs deleted file mode 100644 index 9d8fb8486..000000000 --- a/crates/ra_parser/src/grammar/items/nominal.rs +++ /dev/null | |||
@@ -1,167 +0,0 @@ | |||
1 | //! FIXME: write short doc here | ||
2 | |||
3 | use super::*; | ||
4 | |||
5 | pub(super) fn struct_def(p: &mut Parser, m: Marker, kind: SyntaxKind) { | ||
6 | assert!(p.at(T![struct]) || p.at_contextual_kw("union")); | ||
7 | p.bump_remap(kind); | ||
8 | |||
9 | name_r(p, ITEM_RECOVERY_SET); | ||
10 | type_params::opt_type_param_list(p); | ||
11 | match p.current() { | ||
12 | T![where] => { | ||
13 | type_params::opt_where_clause(p); | ||
14 | match p.current() { | ||
15 | T![;] => { | ||
16 | p.bump(T![;]); | ||
17 | } | ||
18 | T!['{'] => record_field_def_list(p), | ||
19 | _ => { | ||
20 | //FIXME: special case `(` error message | ||
21 | p.error("expected `;` or `{`"); | ||
22 | } | ||
23 | } | ||
24 | } | ||
25 | T![;] if kind == T![struct] => { | ||
26 | p.bump(T![;]); | ||
27 | } | ||
28 | T!['{'] => record_field_def_list(p), | ||
29 | T!['('] if kind == T![struct] => { | ||
30 | tuple_field_def_list(p); | ||
31 | // test tuple_struct_where | ||
32 | // struct Test<T>(T) where T: Clone; | ||
33 | // struct Test<T>(T); | ||
34 | type_params::opt_where_clause(p); | ||
35 | p.expect(T![;]); | ||
36 | } | ||
37 | _ if kind == T![struct] => { | ||
38 | p.error("expected `;`, `{`, or `(`"); | ||
39 | } | ||
40 | _ => { | ||
41 | p.error("expected `{`"); | ||
42 | } | ||
43 | } | ||
44 | m.complete(p, STRUCT_DEF); | ||
45 | } | ||
46 | |||
47 | pub(super) fn enum_def(p: &mut Parser, m: Marker) { | ||
48 | assert!(p.at(T![enum])); | ||
49 | p.bump(T![enum]); | ||
50 | name_r(p, ITEM_RECOVERY_SET); | ||
51 | type_params::opt_type_param_list(p); | ||
52 | type_params::opt_where_clause(p); | ||
53 | if p.at(T!['{']) { | ||
54 | enum_variant_list(p); | ||
55 | } else { | ||
56 | p.error("expected `{`") | ||
57 | } | ||
58 | m.complete(p, ENUM_DEF); | ||
59 | } | ||
60 | |||
61 | pub(crate) fn enum_variant_list(p: &mut Parser) { | ||
62 | assert!(p.at(T!['{'])); | ||
63 | let m = p.start(); | ||
64 | p.bump(T!['{']); | ||
65 | while !p.at(EOF) && !p.at(T!['}']) { | ||
66 | if p.at(T!['{']) { | ||
67 | error_block(p, "expected enum variant"); | ||
68 | continue; | ||
69 | } | ||
70 | let var = p.start(); | ||
71 | attributes::outer_attributes(p); | ||
72 | if p.at(IDENT) { | ||
73 | name(p); | ||
74 | match p.current() { | ||
75 | T!['{'] => record_field_def_list(p), | ||
76 | T!['('] => tuple_field_def_list(p), | ||
77 | T![=] => { | ||
78 | p.bump(T![=]); | ||
79 | expressions::expr(p); | ||
80 | } | ||
81 | _ => (), | ||
82 | } | ||
83 | var.complete(p, ENUM_VARIANT); | ||
84 | } else { | ||
85 | var.abandon(p); | ||
86 | p.err_and_bump("expected enum variant"); | ||
87 | } | ||
88 | if !p.at(T!['}']) { | ||
89 | p.expect(T![,]); | ||
90 | } | ||
91 | } | ||
92 | p.expect(T!['}']); | ||
93 | m.complete(p, ENUM_VARIANT_LIST); | ||
94 | } | ||
95 | |||
96 | pub(crate) fn record_field_def_list(p: &mut Parser) { | ||
97 | assert!(p.at(T!['{'])); | ||
98 | let m = p.start(); | ||
99 | p.bump(T!['{']); | ||
100 | while !p.at(T!['}']) && !p.at(EOF) { | ||
101 | if p.at(T!['{']) { | ||
102 | error_block(p, "expected field"); | ||
103 | continue; | ||
104 | } | ||
105 | record_field_def(p); | ||
106 | if !p.at(T!['}']) { | ||
107 | p.expect(T![,]); | ||
108 | } | ||
109 | } | ||
110 | p.expect(T!['}']); | ||
111 | m.complete(p, RECORD_FIELD_DEF_LIST); | ||
112 | |||
113 | fn record_field_def(p: &mut Parser) { | ||
114 | let m = p.start(); | ||
115 | // test record_field_attrs | ||
116 | // struct S { | ||
117 | // #[serde(with = "url_serde")] | ||
118 | // pub uri: Uri, | ||
119 | // } | ||
120 | attributes::outer_attributes(p); | ||
121 | opt_visibility(p); | ||
122 | if p.at(IDENT) { | ||
123 | name(p); | ||
124 | p.expect(T![:]); | ||
125 | types::type_(p); | ||
126 | m.complete(p, RECORD_FIELD_DEF); | ||
127 | } else { | ||
128 | m.abandon(p); | ||
129 | p.err_and_bump("expected field declaration"); | ||
130 | } | ||
131 | } | ||
132 | } | ||
133 | |||
134 | fn tuple_field_def_list(p: &mut Parser) { | ||
135 | assert!(p.at(T!['('])); | ||
136 | let m = p.start(); | ||
137 | if !p.expect(T!['(']) { | ||
138 | return; | ||
139 | } | ||
140 | while !p.at(T![')']) && !p.at(EOF) { | ||
141 | let m = p.start(); | ||
142 | // test tuple_field_attrs | ||
143 | // struct S ( | ||
144 | // #[serde(with = "url_serde")] | ||
145 | // pub Uri, | ||
146 | // ); | ||
147 | // | ||
148 | // enum S { | ||
149 | // Uri(#[serde(with = "url_serde")] Uri), | ||
150 | // } | ||
151 | attributes::outer_attributes(p); | ||
152 | opt_visibility(p); | ||
153 | if !p.at_ts(types::TYPE_FIRST) { | ||
154 | p.error("expected a type"); | ||
155 | m.complete(p, ERROR); | ||
156 | break; | ||
157 | } | ||
158 | types::type_(p); | ||
159 | m.complete(p, TUPLE_FIELD_DEF); | ||
160 | |||
161 | if !p.at(T![')']) { | ||
162 | p.expect(T![,]); | ||
163 | } | ||
164 | } | ||
165 | p.expect(T![')']); | ||
166 | m.complete(p, TUPLE_FIELD_DEF_LIST); | ||
167 | } | ||