lisette_syntax/parse/
annotations.rs1use super::{MAX_TUPLE_ARITY, Parser};
2use crate::ast::{Annotation, Expression, Generic, Span, Visibility};
3use crate::lex::TokenKind::*;
4use crate::types::Type;
5
6impl<'source> Parser<'source> {
7 pub fn parse_annotation(&mut self) -> Annotation {
8 if !self.enter_recursion() {
9 self.resync_on_error();
10 return Annotation::Unknown;
11 }
12 let result = self.parse_annotation_inner();
13 self.leave_recursion();
14 result
15 }
16
17 fn parse_annotation_inner(&mut self) -> Annotation {
18 match self.current_token().kind {
19 Function => self.parse_function_annotation(),
20 LeftParen => self.parse_tuple_annotation(),
21 LeftSquareBracket => {
22 let start = self.current_token();
23 self.next();
24 if self.advance_if(RightSquareBracket) {
25 let type_token = self.current_token();
26 let type_name = if type_token.kind == Identifier {
27 type_token.text.to_string()
28 } else {
29 "T".to_string()
30 };
31 let span_end = if type_token.kind == Identifier {
32 type_token.byte_offset + type_token.byte_length
33 } else {
34 start.byte_offset + 2
35 };
36 let error_span = Span::new(
37 self.file_id,
38 start.byte_offset,
39 span_end - start.byte_offset,
40 );
41 self.track_error_at(
42 error_span,
43 "invalid syntax for `Slice`",
44 format!("Use `Slice<{}>` instead of `[]{}`", type_name, type_name),
45 );
46 if self.current_token().kind == Identifier {
47 return self.parse_named_annotation();
48 }
49 return Annotation::Constructor {
50 name: "Slice".into(),
51 params: vec![],
52 span: error_span,
53 };
54 }
55 let span = self.span_from_tokens(start);
56 self.track_error(
57 "unexpected `[` in type",
58 "Use `Slice<T>` for slice types or `Array<T, N>` for fixed-size arrays.",
59 );
60 Annotation::Constructor {
61 name: "".into(),
62 params: vec![],
63 span,
64 }
65 }
66 _ => self.parse_named_annotation(),
67 }
68 }
69
70 fn parse_named_annotation(&mut self) -> Annotation {
71 let start = self.current_token();
72 let name = self.read_identifier_sequence();
73
74 let params = if self.advance_if(LeftAngleBracket) {
75 let mut type_params = vec![];
76
77 while self.can_start_annotation() {
78 type_params.push(self.parse_annotation());
79 match self.current_token().kind {
80 RightAngleBracket => break,
81 Comma => self.next(),
82 _ => break,
83 }
84 if self.is(RightAngleBracket) {
85 self.track_error("expected type", "Add a type or remove the trailing comma.");
86 }
87 }
88
89 if !self.advance_if(RightAngleBracket) {
90 self.track_error("expected `>`", "Add `>` to close the type arguments.");
91 }
92
93 type_params
94 } else {
95 vec![]
96 };
97
98 Annotation::Constructor {
99 name,
100 params,
101 span: self.span_from_tokens(start),
102 }
103 }
104
105 fn parse_function_annotation(&mut self) -> Annotation {
106 let start = self.current_token();
107 self.ensure(Function);
108 self.ensure(LeftParen);
109
110 let mut params = vec![];
111
112 while self.is_not(RightParen) {
113 params.push(self.parse_annotation());
114 self.expect_comma_or(RightParen);
115 }
116
117 self.ensure(RightParen);
118
119 let return_type = self.parse_function_return_annotation();
120
121 Annotation::Function {
122 params,
123 return_type: return_type.into(),
124 span: self.span_from_tokens(start),
125 }
126 }
127
128 fn parse_tuple_annotation(&mut self) -> Annotation {
129 let start = self.current_token();
130 self.ensure(LeftParen);
131
132 let mut annotations = vec![];
133 let mut has_trailing_comma = false;
134
135 while self.is_not(RightParen) {
136 annotations.push(self.parse_annotation());
137 has_trailing_comma = self.is(Comma);
138 self.expect_comma_or(RightParen);
139 }
140
141 self.ensure(RightParen);
142
143 let span = self.span_from_tokens(start);
144
145 if annotations.is_empty() {
146 return Annotation::unit();
147 }
148
149 if annotations.len() == 1 {
150 if has_trailing_comma {
151 self.error_tuple_arity(1, span);
152 }
153 return annotations.into_iter().next().expect("len is 1");
154 }
155
156 if annotations.len() > MAX_TUPLE_ARITY {
157 self.error_tuple_arity(annotations.len(), span);
158 }
159
160 Annotation::Tuple {
161 elements: annotations,
162 span,
163 }
164 }
165
166 pub fn parse_generics(&mut self) -> Vec<Generic> {
167 if !self.advance_if(LeftAngleBracket) {
168 return vec![];
169 }
170
171 let mut generics = vec![];
172
173 while self.is_not(RightAngleBracket) {
174 generics.push(self.parse_generic());
175 self.expect_comma_or(RightAngleBracket);
176 }
177
178 self.ensure(RightAngleBracket);
179
180 generics
181 }
182
183 fn parse_generic(&mut self) -> Generic {
184 let start = self.current_token();
185
186 Generic {
187 name: self.read_identifier(),
188 bounds: self.parse_generic_bounds(),
189 span: self.span_from_tokens(start),
190 }
191 }
192
193 fn parse_generic_bounds(&mut self) -> Vec<Annotation> {
194 if !self.advance_if(Colon) {
195 return vec![];
196 }
197
198 if self.is(RightAngleBracket) || self.is(Comma) {
199 self.track_error(
200 "expected bound after `:`",
201 "Provide a bound like `T: Display`.",
202 );
203 return vec![];
204 }
205
206 let mut bounds = vec![];
207
208 while self.is_not(RightAngleBracket) && self.is_not(Comma) {
209 bounds.push(self.parse_annotation());
210 if self.is(RightAngleBracket) || self.is(Comma) {
211 break;
212 }
213 if !self.advance_if(Plus) {
214 self.track_error(
215 "missing `+` between bounds",
216 "Use `+` to separate multiple bounds.",
217 );
218 break;
219 }
220 if self.is(RightAngleBracket) || self.is(Comma) {
221 self.track_error(
222 "expected bound after `+`",
223 "Provide a bound or remove the trailing `+`.",
224 );
225 }
226 }
227
228 bounds
229 }
230
231 pub fn parse_function_return_annotation(&mut self) -> Annotation {
232 if self.advance_if(Arrow) {
233 return self.parse_annotation();
234 }
235
236 Annotation::Unknown
237 }
238
239 pub fn parse_interface_method(
240 &mut self,
241 doc: Option<std::string::String>,
242 attributes: Vec<crate::ast::Attribute>,
243 ) -> Expression {
244 self.ensure(Function);
245
246 let start = self.current_token();
247 let name_token = self.current_token();
248 let name_span = Span::new(self.file_id, name_token.byte_offset, name_token.byte_length);
249 let name = self.read_identifier();
250
251 if self.is(LeftAngleBracket) {
252 let generics_start = self.current_token();
253 let generics = self.parse_generics(); let generics_span = self.span_from_tokens(generics_start);
255 self.error_interface_method_with_type_parameters(generics_span, generics.len());
256 }
257
258 Expression::Function {
259 doc,
260 attributes,
261 name,
262 name_span,
263 generics: vec![],
264 params: self.parse_function_params(),
265 return_annotation: self.parse_function_return_annotation(),
266 return_type: Type::uninferred(),
267 visibility: Visibility::Private,
268 body: Expression::NoOp.into(),
269 ty: Type::uninferred(),
270 span: self.span_from_tokens(start),
271 }
272 }
273
274 pub fn parse_type_alias_with_doc(&mut self, doc: Option<std::string::String>) -> Expression {
275 let start = self.current_token();
276
277 self.ensure(Type);
278
279 let name_token = self.current_token();
280 let name_span = Span::new(self.file_id, name_token.byte_offset, name_token.byte_length);
281 let name = self.read_identifier();
282 let generics = self.parse_generics();
283
284 let annotation = if self.advance_if(Equal) {
285 self.parse_annotation()
286 } else {
287 Annotation::Opaque {
288 span: self.span_from_tokens(start),
289 }
290 };
291
292 Expression::TypeAlias {
293 doc,
294 name,
295 name_span,
296 generics,
297 annotation,
298 ty: Type::uninferred(),
299 visibility: Visibility::Private,
300 span: self.span_from_tokens(start),
301 }
302 }
303}