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("unexpected `[` in type", "Use `Slice<T>` for slice types.");
57 Annotation::Constructor {
58 name: "".into(),
59 params: vec![],
60 span,
61 }
62 }
63 _ => self.parse_named_annotation(),
64 }
65 }
66
67 fn parse_named_annotation(&mut self) -> Annotation {
68 let start = self.current_token();
69 let name = self.read_identifier_sequence();
70
71 let params = if self.advance_if(LeftAngleBracket) {
72 let mut type_params = vec![];
73
74 while self.can_start_annotation() {
75 type_params.push(self.parse_annotation());
76 match self.current_token().kind {
77 RightAngleBracket => break,
78 Comma => self.next(),
79 _ => break,
80 }
81 if self.is(RightAngleBracket) {
82 self.track_error("expected type", "Add a type or remove the trailing comma.");
83 }
84 }
85
86 if !self.advance_if(RightAngleBracket) {
87 self.track_error("expected `>`", "Add `>` to close the type arguments.");
88 }
89
90 type_params
91 } else {
92 vec![]
93 };
94
95 Annotation::Constructor {
96 name,
97 params,
98 span: self.span_from_tokens(start),
99 }
100 }
101
102 fn parse_function_annotation(&mut self) -> Annotation {
103 let start = self.current_token();
104 self.ensure(Function);
105 self.ensure(LeftParen);
106
107 let mut params = vec![];
108
109 while self.is_not(RightParen) {
110 params.push(self.parse_annotation());
111 self.expect_comma_or(RightParen);
112 }
113
114 self.ensure(RightParen);
115
116 let return_type = self.parse_function_return_annotation();
117
118 Annotation::Function {
119 params,
120 return_type: return_type.into(),
121 span: self.span_from_tokens(start),
122 }
123 }
124
125 fn parse_tuple_annotation(&mut self) -> Annotation {
126 let start = self.current_token();
127 self.ensure(LeftParen);
128
129 let mut annotations = vec![];
130 let mut has_trailing_comma = false;
131
132 while self.is_not(RightParen) {
133 annotations.push(self.parse_annotation());
134 has_trailing_comma = self.is(Comma);
135 self.expect_comma_or(RightParen);
136 }
137
138 self.ensure(RightParen);
139
140 let span = self.span_from_tokens(start);
141
142 if annotations.is_empty() {
143 return Annotation::unit();
144 }
145
146 if annotations.len() == 1 {
147 if has_trailing_comma {
148 self.error_tuple_arity(1, span);
149 }
150 return annotations.into_iter().next().expect("len is 1");
151 }
152
153 if annotations.len() > MAX_TUPLE_ARITY {
154 self.error_tuple_arity(annotations.len(), span);
155 }
156
157 Annotation::Tuple {
158 elements: annotations,
159 span,
160 }
161 }
162
163 pub fn parse_generics(&mut self) -> Vec<Generic> {
164 if !self.advance_if(LeftAngleBracket) {
165 return vec![];
166 }
167
168 let mut generics = vec![];
169
170 while self.is_not(RightAngleBracket) {
171 generics.push(self.parse_generic());
172 self.expect_comma_or(RightAngleBracket);
173 }
174
175 self.ensure(RightAngleBracket);
176
177 generics
178 }
179
180 fn parse_generic(&mut self) -> Generic {
181 let start = self.current_token();
182
183 Generic {
184 name: self.read_identifier(),
185 bounds: self.parse_generic_bounds(),
186 span: self.span_from_tokens(start),
187 }
188 }
189
190 fn parse_generic_bounds(&mut self) -> Vec<Annotation> {
191 if !self.advance_if(Colon) {
192 return vec![];
193 }
194
195 if self.is(RightAngleBracket) || self.is(Comma) {
196 self.track_error(
197 "expected bound after `:`",
198 "Provide a bound like `T: Display`.",
199 );
200 return vec![];
201 }
202
203 let mut bounds = vec![];
204
205 while self.is_not(RightAngleBracket) && self.is_not(Comma) {
206 bounds.push(self.parse_annotation());
207 if self.is(RightAngleBracket) || self.is(Comma) {
208 break;
209 }
210 if !self.advance_if(Plus) {
211 self.track_error(
212 "missing `+` between bounds",
213 "Use `+` to separate multiple bounds.",
214 );
215 break;
216 }
217 if self.is(RightAngleBracket) || self.is(Comma) {
218 self.track_error(
219 "expected bound after `+`",
220 "Provide a bound or remove the trailing `+`.",
221 );
222 }
223 }
224
225 bounds
226 }
227
228 pub fn parse_function_return_annotation(&mut self) -> Annotation {
229 if self.advance_if(Arrow) {
230 return self.parse_annotation();
231 }
232
233 Annotation::Unknown
234 }
235
236 pub fn parse_interface_method(
237 &mut self,
238 doc: Option<std::string::String>,
239 attributes: Vec<crate::ast::Attribute>,
240 ) -> Expression {
241 self.ensure(Function);
242
243 let start = self.current_token();
244 let name_token = self.current_token();
245 let name_span = Span::new(self.file_id, name_token.byte_offset, name_token.byte_length);
246 let name = self.read_identifier();
247
248 if self.is(LeftAngleBracket) {
249 let generics_start = self.current_token();
250 let generics = self.parse_generics(); let generics_span = self.span_from_tokens(generics_start);
252 self.error_interface_method_with_type_parameters(generics_span, generics.len());
253 }
254
255 Expression::Function {
256 doc,
257 attributes,
258 name,
259 name_span,
260 generics: vec![],
261 params: self.parse_function_params(),
262 return_annotation: self.parse_function_return_annotation(),
263 return_type: Type::uninferred(),
264 visibility: Visibility::Private,
265 body: Expression::NoOp.into(),
266 ty: Type::uninferred(),
267 span: self.span_from_tokens(start),
268 }
269 }
270
271 pub fn parse_type_alias_with_doc(&mut self, doc: Option<std::string::String>) -> Expression {
272 let start = self.current_token();
273
274 self.ensure(Type);
275
276 let name_token = self.current_token();
277 let name_span = Span::new(self.file_id, name_token.byte_offset, name_token.byte_length);
278 let name = self.read_identifier();
279 let generics = self.parse_generics();
280
281 let annotation = if self.advance_if(Equal) {
282 self.parse_annotation()
283 } else {
284 Annotation::Opaque {
285 span: self.span_from_tokens(start),
286 }
287 };
288
289 Expression::TypeAlias {
290 doc,
291 name,
292 name_span,
293 generics,
294 annotation,
295 ty: Type::uninferred(),
296 visibility: Visibility::Private,
297 span: self.span_from_tokens(start),
298 }
299 }
300}