1use ecow::EcoString;
2
3use super::Parser;
4use crate::ast::{
5 Annotation, Attribute, AttributeArg, EnumFieldDefinition, EnumVariant, Expression, Generic,
6 Literal, ParentInterface, Span, StructFieldDefinition, StructKind, ValueEnumVariant,
7 VariantFields, Visibility,
8};
9use crate::lex::Token;
10use crate::lex::TokenKind::*;
11use crate::parse::error::ParseError;
12use crate::types::Type;
13
14impl<'source> Parser<'source> {
15 pub(crate) fn parse_attributes(&mut self) -> Vec<Attribute> {
16 let mut attributes = vec![];
17 loop {
18 self.advance_if(Semicolon);
19 if !self.is(Hash) {
20 break;
21 }
22 if let Some(attribute) = self.parse_attribute() {
23 attributes.push(attribute);
24 }
25 }
26 attributes
27 }
28
29 fn parse_attribute(&mut self) -> Option<Attribute> {
30 let start = self.current_token();
31 self.ensure(Hash);
32
33 if !self.is(LeftSquareBracket) {
34 self.track_error("expected `[` after `#`", "Add `[` to start the attribute");
35 return None;
36 }
37 self.next();
38
39 if !self.is(Identifier) {
40 self.track_error(
41 "expected attribute name",
42 "Add an attribute name like `json` or `db`",
43 );
44 while self.is_not(RightSquareBracket) && !self.at_eof() {
45 self.next();
46 }
47 self.advance_if(RightSquareBracket);
48 return None;
49 }
50
51 let name = self.read_identifier();
52 let args = if self.advance_if(LeftParen) {
53 self.parse_attribute_args()
54 } else {
55 vec![]
56 };
57
58 if !self.advance_if(RightSquareBracket) {
59 self.track_error("expected `]`", "Add `]` to close the attribute");
60 }
61
62 Some(Attribute {
63 name: name.to_string(),
64 args,
65 span: self.span_from_tokens(start),
66 })
67 }
68
69 fn parse_attribute_args(&mut self) -> Vec<AttributeArg> {
70 let mut args = vec![];
71
72 while self.is_not(RightParen) && !self.at_eof() {
73 if let Some(arg) = self.parse_attribute_arg() {
74 args.push(arg);
75 }
76
77 if !self.advance_if(Comma) {
78 break;
79 }
80 }
81
82 self.ensure(RightParen);
83 args
84 }
85
86 fn parse_attribute_arg(&mut self) -> Option<AttributeArg> {
87 if self.advance_if(Bang) {
88 if self.is(Identifier) {
89 return Some(AttributeArg::NegatedFlag(
90 self.read_identifier().to_string(),
91 ));
92 } else {
93 self.track_error(
94 "expected identifier after `!`",
95 "Add an identifier like `omitempty` after `!`",
96 );
97 return None;
98 }
99 }
100
101 if self.is(Identifier) {
102 return Some(AttributeArg::Flag(self.read_identifier().to_string()));
103 }
104
105 if self.is(String) {
106 let token = self.current_token();
107 self.next();
108 let text = token.text;
109 let value = if text.len() >= 2 {
110 &text[1..text.len() - 1]
111 } else {
112 text
113 };
114 return Some(AttributeArg::String(value.to_string()));
115 }
116
117 if self.is(Backtick) {
118 let token = self.current_token();
119 self.next();
120 let text = token.text;
121 let value = if text.len() >= 2 {
122 &text[1..text.len() - 1]
123 } else {
124 text
125 };
126 return Some(AttributeArg::Raw(value.to_string()));
127 }
128
129 self.track_error(
130 "expected attribute argument",
131 "Add a flag (e.g. `omitempty`), string (e.g. `\"name\"`), or raw tag (e.g. `` `json:\"name\"` ``)",
132 );
133 None
134 }
135
136 pub fn parse_enum_definition(
137 &mut self,
138 doc: Option<std::string::String>,
139 attributes: Vec<Attribute>,
140 ) -> Expression {
141 let start = self.current_token();
142
143 self.ensure(Enum);
144
145 let name_token = self.current_token();
146 let name_span = Span::new(self.file_id, name_token.byte_offset, name_token.byte_length);
147 let name = self.read_identifier();
148 let generics = self.parse_generics();
149
150 let underlying_start = self.current_token();
151 let underlying_ty = if self.advance_if(Colon) {
152 let annotation = self.parse_annotation();
153 Some((annotation, underlying_start))
154 } else {
155 None
156 };
157
158 self.ensure(LeftCurlyBrace);
159
160 if self.peek_is_value_enum_variant() {
161 if !generics.is_empty() {
162 let generics_span = generics.first().expect("non-empty").span;
163 let param_word = if generics.len() == 1 {
164 "parameter"
165 } else {
166 "parameters"
167 };
168 let error = ParseError::new(
169 "Value enum with generics",
170 generics_span,
171 "not allowed on value enums",
172 )
173 .with_parse_code("value_enum_generics")
174 .with_help(format!(
175 "Remove the generic {}. Value enums represent Go const groups, which cannot be generic.",
176 param_word
177 ));
178 self.errors.push(error);
179 }
180
181 let underlying_ty = underlying_ty.map(|(annotation, _)| annotation);
182 return self.parse_value_enum_body(doc, name, name_span, underlying_ty, start);
183 }
184
185 if let Some((_, underlying_token)) = underlying_ty {
186 let underlying_span = Span::new(
187 self.file_id,
188 underlying_token.byte_offset,
189 underlying_token.byte_length,
190 );
191 let error = ParseError::new(
192 "Underlying type on regular enum",
193 underlying_span,
194 "only allowed on value enums",
195 )
196 .with_parse_code("enum_underlying_type")
197 .with_help(
198 "Remove the `: type` annotation. Underlying types are allowed only on value enums, which represent Go const groups.",
199 );
200 self.errors.push(error);
201 }
202
203 self.parse_regular_enum_body(doc, attributes, name, name_span, generics, start)
204 }
205
206 fn peek_is_value_enum_variant(&self) -> bool {
207 if self.is(RightCurlyBrace) {
208 return false;
209 }
210
211 let mut offset = 0;
212 while self.stream.peek_ahead(offset).kind == DocComment {
213 offset += 1;
214 }
215
216 self.stream.peek_ahead(offset).kind == Identifier
217 && self.stream.peek_ahead(offset + 1).kind == Equal
218 }
219
220 fn parse_regular_enum_body(
221 &mut self,
222 doc: Option<std::string::String>,
223 attributes: Vec<Attribute>,
224 name: EcoString,
225 name_span: Span,
226 generics: Vec<Generic>,
227 start: Token<'source>,
228 ) -> Expression {
229 let mut variants = vec![];
230 let mut seen_variants: Vec<(EcoString, Span)> = vec![];
231
232 while self.is_not(RightCurlyBrace) {
233 let start_position = self.stream.position;
234
235 let variant_doc = self.collect_doc_comments().map(|(text, _)| text);
236 if let Some(variant) = self.parse_enum_variant_with_doc(variant_doc) {
237 if let Some((_, first_span)) =
238 seen_variants.iter().find(|(n, _)| n == &variant.name)
239 {
240 self.error_duplicate_enum_variant(
241 &variant.name,
242 *first_span,
243 variant.name_span,
244 );
245 } else {
246 seen_variants.push((variant.name.clone(), variant.name_span));
247 }
248 variants.push(variant);
249 }
250 self.expect_comma_or(RightCurlyBrace);
251 self.ensure_progress(start_position, RightCurlyBrace);
252 }
253
254 self.ensure(RightCurlyBrace);
255
256 Expression::Enum {
257 doc,
258 attributes,
259 name,
260 name_span,
261 generics,
262 variants,
263 visibility: Visibility::Private,
264 span: self.span_from_tokens(start),
265 }
266 }
267
268 fn parse_value_enum_body(
269 &mut self,
270 doc: Option<std::string::String>,
271 name: EcoString,
272 name_span: Span,
273 underlying_ty: Option<Annotation>,
274 start: Token<'source>,
275 ) -> Expression {
276 let mut variants = vec![];
277 let mut seen_variants: Vec<(EcoString, Span)> = vec![];
278
279 while self.is_not(RightCurlyBrace) {
280 let start_position = self.stream.position;
281
282 let variant_doc = self.collect_doc_comments().map(|(text, _)| text);
283 if let Some(variant) = self.parse_value_enum_variant_with_doc(variant_doc) {
284 if let Some((_, first_span)) =
285 seen_variants.iter().find(|(n, _)| n == &variant.name)
286 {
287 self.error_duplicate_enum_variant(
288 &variant.name,
289 *first_span,
290 variant.name_span,
291 );
292 } else {
293 seen_variants.push((variant.name.clone(), variant.name_span));
294 }
295 variants.push(variant);
296 }
297 self.expect_comma_or(RightCurlyBrace);
298 self.ensure_progress(start_position, RightCurlyBrace);
299 }
300
301 self.ensure(RightCurlyBrace);
302
303 Expression::ValueEnum {
304 doc,
305 name,
306 name_span,
307 underlying_ty,
308 variants,
309 visibility: Visibility::Public,
310 span: self.span_from_tokens(start),
311 }
312 }
313
314 fn parse_enum_variant_with_doc(
315 &mut self,
316 doc: Option<std::string::String>,
317 ) -> Option<EnumVariant> {
318 if self.is_not(Identifier) {
319 self.track_error(
320 "expected variant name",
321 "Variant names must be identifiers.",
322 );
323 return None;
324 }
325
326 let name_token = self.current_token();
327 let name_span = Span::new(self.file_id, name_token.byte_offset, name_token.byte_length);
328 let name = self.read_identifier();
329 let fields = self.parse_enum_variant_fields();
330
331 Some(EnumVariant {
332 doc,
333 name,
334 name_span,
335 fields,
336 })
337 }
338
339 fn parse_value_enum_variant_with_doc(
340 &mut self,
341 doc: Option<std::string::String>,
342 ) -> Option<ValueEnumVariant> {
343 if self.is_not(Identifier) {
344 self.track_error(
345 "expected variant name",
346 "Variant names must be identifiers.",
347 );
348 return None;
349 }
350
351 let name_token = self.current_token();
352 let name_span = Span::new(self.file_id, name_token.byte_offset, name_token.byte_length);
353 let name = self.read_identifier();
354
355 let (value, value_span) = if self.is(Equal) {
356 let eq_token = self.current_token();
357 let start_offset = eq_token.byte_offset;
358 self.next(); let (value, value_end) = self.parse_value_enum_variant_value();
360 let span = Span::new(self.file_id, start_offset, value_end - start_offset);
361 (value, span)
362 } else {
363 (
364 Literal::Integer {
365 value: 0,
366 text: None,
367 },
368 name_span,
369 )
370 };
371
372 Some(ValueEnumVariant {
373 doc,
374 name,
375 name_span,
376 value,
377 value_span,
378 })
379 }
380
381 fn parse_value_enum_variant_value(&mut self) -> (Literal, u32) {
382 let token = self.current_token();
383
384 match token.kind {
385 Integer => {
386 let text = token.text;
387 let end = token.byte_offset + token.byte_length;
388 self.next();
389 (Self::parse_integer_literal(text), end)
390 }
391 String => {
392 let text = token.text;
393 let end = token.byte_offset + token.byte_length;
394 self.next();
395 (Literal::String(text[1..text.len() - 1].to_string()), end)
396 }
397 Minus => {
398 self.next();
399 let next_token = self.current_token();
400 if next_token.kind == Integer {
401 let text = next_token.text;
402 let end = next_token.byte_offset + next_token.byte_length;
403 self.next();
404 if let Literal::Integer { value, text: orig } =
405 Self::parse_integer_literal(text)
406 {
407 (
408 Literal::Integer {
409 value: (-(value as i64)) as u64,
410 text: orig.map(|t| format!("-{}", t)),
411 },
412 end,
413 )
414 } else {
415 self.track_error(
416 "expected integer after `-`",
417 "Use `-42` for negative integers.",
418 );
419 (
420 Literal::Integer {
421 value: 0,
422 text: None,
423 },
424 next_token.byte_offset,
425 )
426 }
427 } else {
428 self.track_error(
429 "expected integer after `-`",
430 "Use `-42` for negative integers.",
431 );
432 (
433 Literal::Integer {
434 value: 0,
435 text: None,
436 },
437 next_token.byte_offset,
438 )
439 }
440 }
441 _ => {
442 self.track_error(
443 "expected integer or string literal",
444 "Value enum variants require integer or string values.",
445 );
446 (
447 Literal::Integer {
448 value: 0,
449 text: None,
450 },
451 token.byte_offset,
452 )
453 }
454 }
455 }
456
457 fn parse_integer_literal(text: &str) -> Literal {
458 let value = if text.starts_with("0x") || text.starts_with("0X") {
459 u64::from_str_radix(&text[2..].replace('_', ""), 16).unwrap_or(0)
460 } else if text.starts_with("0o") || text.starts_with("0O") {
461 u64::from_str_radix(&text[2..].replace('_', ""), 8).unwrap_or(0)
462 } else if text.starts_with("0b") || text.starts_with("0B") {
463 u64::from_str_radix(&text[2..].replace('_', ""), 2).unwrap_or(0)
464 } else if text.starts_with('0')
465 && text.len() > 1
466 && text.chars().nth(1).is_some_and(|c| c.is_ascii_digit())
467 {
468 u64::from_str_radix(&text[1..].replace('_', ""), 8).unwrap_or(0)
469 } else {
470 text.replace('_', "").parse().unwrap_or(0)
471 };
472
473 Literal::Integer {
474 value,
475 text: Some(text.to_string()),
476 }
477 }
478
479 fn parse_enum_variant_fields(&mut self) -> VariantFields {
480 if self.advance_if(LeftParen) {
481 return self.parse_tuple_variant_fields();
482 }
483
484 if self.advance_if(LeftCurlyBrace) {
485 return self.parse_struct_variant_fields();
486 }
487
488 VariantFields::Unit
489 }
490
491 fn parse_tuple_variant_fields(&mut self) -> VariantFields {
492 let mut fields = vec![];
493
494 loop {
495 if self.at_eof()
496 || self.is(RightParen)
497 || self.is(RightCurlyBrace)
498 || !self.can_start_annotation()
499 {
500 break;
501 }
502
503 let field = EnumFieldDefinition {
504 name: format!("field{}", fields.len()).into(),
505 name_span: Span::dummy(),
506 annotation: self.parse_annotation(),
507 ty: Type::uninferred(),
508 };
509
510 fields.push(field);
511
512 self.expect_comma_or(RightParen);
513 }
514
515 self.ensure(RightParen);
516
517 VariantFields::Tuple(fields)
518 }
519
520 fn parse_struct_variant_fields(&mut self) -> VariantFields {
521 let mut fields = vec![];
522 let mut seen_fields: Vec<(EcoString, Span)> = vec![];
523
524 loop {
525 if self.at_eof()
526 || self.is(RightCurlyBrace)
527 || self.at_item_boundary()
528 || self.is_not(Identifier)
529 {
530 break;
531 }
532
533 let name_token = self.current_token();
534 let name_span = Span::new(self.file_id, name_token.byte_offset, name_token.byte_length);
535 let name = self.read_identifier();
536 self.ensure(Colon);
537 let annotation = self.parse_annotation();
538
539 if let Some((_, first_span)) = seen_fields.iter().find(|(n, _)| n == &name) {
540 self.error_duplicate_struct_field(&name, *first_span, name_span);
541 } else {
542 seen_fields.push((name.clone(), name_span));
543 }
544
545 let field = EnumFieldDefinition {
546 name,
547 name_span,
548 annotation,
549 ty: Type::uninferred(),
550 };
551
552 fields.push(field);
553
554 self.expect_comma_or(RightCurlyBrace);
555 }
556
557 self.ensure(RightCurlyBrace);
558
559 VariantFields::Struct(fields)
560 }
561
562 pub fn parse_struct_definition(
563 &mut self,
564 doc: Option<std::string::String>,
565 attributes: Vec<Attribute>,
566 ) -> Expression {
567 let start = self.current_token();
568
569 self.ensure(Struct);
570
571 let name_token = self.current_token();
572 let name_span = Span::new(self.file_id, name_token.byte_offset, name_token.byte_length);
573 let name = self.read_identifier();
574 let generics = self.parse_generics();
575
576 if self.is(LeftParen) {
577 return self.parse_tuple_struct(doc, attributes, name, name_span, generics, start);
578 }
579
580 self.parse_named_struct(doc, attributes, name, name_span, generics, start)
581 }
582
583 fn parse_named_struct(
584 &mut self,
585 doc: Option<std::string::String>,
586 attributes: Vec<Attribute>,
587 name: EcoString,
588 name_span: Span,
589 generics: Vec<Generic>,
590 start: Token<'source>,
591 ) -> Expression {
592 let mut fields = vec![];
593 let mut seen_fields: Vec<(EcoString, Span)> = vec![];
594
595 self.ensure(LeftCurlyBrace);
596
597 while self.is_not(RightCurlyBrace) {
598 let start_position = self.stream.position;
599
600 let field_attributes = self.parse_attributes();
601 let field_doc = self.collect_doc_comments().map(|(text, _)| text);
602 if let Some(field) = self.parse_struct_field_with_doc(field_doc, field_attributes) {
603 if let Some((_, first_span)) = seen_fields.iter().find(|(n, _)| n == &field.name) {
604 self.error_duplicate_struct_field(&field.name, *first_span, field.name_span);
605 } else {
606 seen_fields.push((field.name.clone(), field.name_span));
607 }
608 fields.push(field);
609 }
610 self.expect_comma_or(RightCurlyBrace);
611 self.ensure_progress(start_position, RightCurlyBrace);
612 }
613
614 self.ensure(RightCurlyBrace);
615
616 Expression::Struct {
617 doc,
618 attributes,
619 name,
620 name_span,
621 generics,
622 fields,
623 kind: StructKind::Record,
624 visibility: Visibility::Private,
625 span: self.span_from_tokens(start),
626 }
627 }
628
629 fn parse_tuple_struct(
630 &mut self,
631 doc: Option<std::string::String>,
632 attributes: Vec<Attribute>,
633 name: EcoString,
634 name_span: Span,
635 generics: Vec<Generic>,
636 start: Token<'source>,
637 ) -> Expression {
638 self.ensure(LeftParen);
639
640 let mut fields = vec![];
641 let mut index = 0;
642
643 while self.is_not(RightParen) {
644 if self.at_eof() || self.at_item_boundary() || !self.can_start_annotation() {
645 break;
646 }
647
648 let field_start = self.current_token();
649 let annotation = self.parse_annotation();
650 let field_span = self.span_from_tokens(field_start);
651
652 fields.push(StructFieldDefinition {
653 doc: None,
654 attributes: vec![],
655 name: format!("_{}", index).into(),
656 name_span: field_span,
657 annotation,
658 visibility: Visibility::Private,
659 ty: Type::uninferred(),
660 });
661
662 index += 1;
663 self.expect_comma_or(RightParen);
664 }
665
666 self.ensure(RightParen);
667
668 Expression::Struct {
669 doc,
670 attributes,
671 name,
672 name_span,
673 generics,
674 fields,
675 kind: StructKind::Tuple,
676 visibility: Visibility::Private,
677 span: self.span_from_tokens(start),
678 }
679 }
680
681 fn parse_struct_field_with_doc(
682 &mut self,
683 doc: Option<std::string::String>,
684 attributes: Vec<Attribute>,
685 ) -> Option<StructFieldDefinition> {
686 let visibility = if self.advance_if(Pub) {
687 Visibility::Public
688 } else {
689 Visibility::Private
690 };
691
692 if self.is_not(Identifier) {
693 self.track_error("expected field name", "Field names must be identifiers.");
694 return None;
695 }
696
697 let name_token = self.current_token();
698 let name_span = Span::new(self.file_id, name_token.byte_offset, name_token.byte_length);
699 let name = self.read_identifier();
700
701 self.ensure(Colon);
702
703 Some(StructFieldDefinition {
704 doc,
705 attributes,
706 visibility,
707 name,
708 name_span,
709 annotation: self.parse_annotation(),
710 ty: Type::uninferred(),
711 })
712 }
713
714 pub fn parse_const_definition(&mut self, doc: Option<std::string::String>) -> Expression {
715 let start = self.current_token();
716
717 self.ensure(Const);
718
719 let identifier_token = self.current_token();
720 let identifier_span = Span::new(
721 self.file_id,
722 identifier_token.byte_offset,
723 identifier_token.byte_length,
724 );
725 let identifier = self.read_identifier();
726 let annotation = if self.advance_if(Colon) {
727 Some(self.parse_annotation())
728 } else {
729 None
730 };
731
732 let expression = if self.advance_if(Equal) {
733 self.parse_expression()
734 } else {
735 Expression::NoOp
736 };
737
738 Expression::Const {
739 doc,
740 identifier,
741 identifier_span,
742 annotation,
743 expression: expression.into(),
744 visibility: Visibility::Private,
745 ty: Type::uninferred(),
746 span: self.span_from_tokens(start),
747 }
748 }
749
750 pub fn parse_var_declaration(&mut self, doc: Option<std::string::String>) -> Expression {
751 let start = self.current_token();
752
753 self.ensure(Var);
754
755 let name_token = self.current_token();
756 let name_span = Span::new(self.file_id, name_token.byte_offset, name_token.byte_length);
757 let name = self.read_identifier();
758
759 self.ensure(Colon);
760 let annotation = self.parse_annotation();
761
762 Expression::VariableDeclaration {
763 doc,
764 name,
765 name_span,
766 annotation,
767 visibility: Visibility::Private,
768 ty: Type::uninferred(),
769 span: self.span_from_tokens(start),
770 }
771 }
772
773 pub fn parse_impl_block(&mut self) -> Expression {
774 let start = self.current_token();
775
776 self.ensure(Impl);
777
778 let generics = self.parse_generics();
779
780 let receiver = self.parse_annotation(); let (receiver_name, annotation) = match &receiver {
783 Annotation::Constructor { name, .. } => (name.clone(), receiver),
784 _ => {
785 self.track_error("expected `impl` receiver", "Use `impl TypeName { ... }`.");
786 ("".into(), Annotation::Unknown)
787 }
788 };
789
790 if self.is(For) {
791 self.track_error(
792 "invalid syntax",
793 "Lisette types satisfy interfaces automatically by having the required methods. Use `impl Type { ... }` to add methods.",
794 );
795 self.next();
796 self.parse_annotation();
797 }
798
799 let mut methods = vec![];
800
801 self.ensure(LeftCurlyBrace);
802
803 while self.is_not(RightCurlyBrace) {
804 self.advance_if(Semicolon);
805 if self.is(RightCurlyBrace) {
806 break;
807 }
808
809 let method_doc = self.collect_doc_comments();
810 let method_attrs = self.parse_attributes();
811 let is_public = self.advance_if(Pub);
812
813 if self.is(Function) {
814 let method = self.parse_function(method_doc.map(|(text, _)| text), method_attrs);
815 let method = if is_public {
816 method.set_public()
817 } else {
818 method
819 };
820 methods.push(method);
821 } else {
822 if let Some((_, span)) = method_doc {
823 self.error_detached_doc_comment(span);
824 }
825 self.track_error(
826 "expected `fn` in impl block",
827 "Only functions are allowed in `impl` blocks.",
828 );
829 self.next();
830 }
831 }
832
833 self.ensure(RightCurlyBrace);
834
835 Expression::ImplBlock {
836 annotation,
837 methods,
838 receiver_name,
839 generics,
840 ty: Type::uninferred(),
841 span: self.span_from_tokens(start),
842 }
843 }
844
845 pub fn parse_interface_definition(&mut self, doc: Option<std::string::String>) -> Expression {
846 let start = self.current_token();
847
848 self.ensure(Interface);
849
850 let name_token = self.current_token();
851 let name_span = Span::new(self.file_id, name_token.byte_offset, name_token.byte_length);
852 let name = self.read_identifier();
853
854 let generics = self.parse_generics();
855
856 let mut parents = vec![];
857 let mut seen_parents: Vec<(EcoString, Span)> = vec![];
858 let mut method_signatures = vec![];
859 let mut seen_methods: Vec<(EcoString, Span)> = vec![];
860
861 self.ensure(LeftCurlyBrace);
862
863 while self.is_not(RightCurlyBrace) {
864 self.advance_if(Semicolon);
865 if self.is(RightCurlyBrace) {
866 break;
867 }
868
869 let item_doc = self.collect_doc_comments();
870 let method_attrs = self.parse_attributes();
871 match self.current_token().kind {
872 Function => {
873 let method =
874 self.parse_interface_method(item_doc.map(|(text, _)| text), method_attrs);
875 if let Expression::Function {
876 ref name,
877 ref name_span,
878 ..
879 } = method
880 {
881 if let Some((_, first_span)) = seen_methods.iter().find(|(n, _)| n == name)
882 {
883 self.error_duplicate_interface_method(name, *first_span, *name_span);
884 } else {
885 seen_methods.push((name.clone(), *name_span));
886 }
887 }
888 method_signatures.push(method);
889 self.advance_if(Semicolon);
890 }
891
892 Impl => {
893 if let Some((_, span)) = item_doc {
894 self.error_detached_doc_comment(span);
895 }
896 self.ensure(Impl);
897
898 let parent_start = self.current_token();
899 let annotation = self.parse_annotation();
900 let parent_span = self.span_from_tokens(parent_start);
901
902 if let Annotation::Constructor { name, .. } = &annotation {
903 if let Some((_, first_span)) =
904 seen_parents.iter().find(|(n, _)| n == name.as_str())
905 {
906 self.error_duplicate_impl_parent(*first_span, parent_span);
907 } else {
908 seen_parents.push((name.clone(), parent_span));
909 }
910 }
911
912 parents.push(ParentInterface {
913 annotation,
914 ty: Type::uninferred(),
915 span: parent_span,
916 });
917 self.advance_if(Semicolon);
918 }
919
920 _ => {
921 if let Some((_, span)) = item_doc {
922 self.error_detached_doc_comment(span);
923 }
924 self.track_error(
925 "expected `fn` or `impl`",
926 "Only functions and `impl` blocks are allowed in interfaces.",
927 );
928 self.next();
929 }
930 }
931 }
932
933 self.ensure(RightCurlyBrace);
934
935 Expression::Interface {
936 doc,
937 name,
938 name_span,
939 generics,
940 parents,
941 method_signatures,
942 visibility: Visibility::Private,
943 span: self.span_from_tokens(start),
944 }
945 }
946}