Skip to main content

lisette_syntax/parse/
definitions.rs

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(); // consume `=`
359            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        const EMPTY: Literal = Literal::Integer {
383            value: 0,
384            text: None,
385        };
386
387        let token = self.current_token();
388
389        match token.kind {
390            Integer => {
391                let text = token.text;
392                let end = token.byte_offset + token.byte_length;
393                let literal = self.parse_integer_text_with(text, true);
394                self.next();
395                (literal, end)
396            }
397            String => {
398                let text = token.text;
399                let end = token.byte_offset + token.byte_length;
400                self.next();
401                (
402                    Literal::String {
403                        value: text[1..text.len() - 1].to_string(),
404                        raw: false,
405                    },
406                    end,
407                )
408            }
409            Minus => {
410                let minus_offset = token.byte_offset;
411                self.next();
412                let next_token = self.current_token();
413                if next_token.kind != Integer {
414                    self.track_error(
415                        "expected integer after `-`",
416                        "Use `-42` for negative integers.",
417                    );
418                    return (EMPTY, next_token.byte_offset);
419                }
420                let text = next_token.text;
421                let end = next_token.byte_offset + next_token.byte_length;
422                let neg_span = Span::new(self.file_id, minus_offset, end - minus_offset);
423                let literal = self.parse_integer_text_with(text, true);
424                self.next();
425                let Literal::Integer { value, text: orig } = literal else {
426                    return (EMPTY, end);
427                };
428                if value > i64::MIN.unsigned_abs() {
429                    self.track_error_at(
430                        neg_span,
431                        "negative integer out of range",
432                        "Negative integer must be ≥ -9223372036854775808 (i64 minimum).",
433                    );
434                    return (EMPTY, end);
435                }
436                (
437                    Literal::Integer {
438                        value: value.wrapping_neg(),
439                        text: orig.map(|t| format!("-{t}")),
440                    },
441                    end,
442                )
443            }
444            _ => {
445                self.track_error(
446                    "expected integer or string literal",
447                    "Value enum variants require integer or string values.",
448                );
449                (EMPTY, token.byte_offset)
450            }
451        }
452    }
453
454    fn parse_enum_variant_fields(&mut self) -> VariantFields {
455        if self.advance_if(LeftParen) {
456            return self.parse_tuple_variant_fields();
457        }
458
459        if self.advance_if(LeftCurlyBrace) {
460            return self.parse_struct_variant_fields();
461        }
462
463        VariantFields::Unit
464    }
465
466    fn parse_tuple_variant_fields(&mut self) -> VariantFields {
467        let mut fields = vec![];
468
469        loop {
470            if self.at_eof()
471                || self.is(RightParen)
472                || self.is(RightCurlyBrace)
473                || !self.can_start_annotation()
474            {
475                break;
476            }
477
478            let field = EnumFieldDefinition {
479                name: format!("field{}", fields.len()).into(),
480                name_span: Span::dummy(),
481                annotation: self.parse_annotation(),
482                ty: Type::uninferred(),
483            };
484
485            fields.push(field);
486
487            self.expect_comma_or(RightParen);
488        }
489
490        self.ensure(RightParen);
491
492        VariantFields::Tuple(fields)
493    }
494
495    fn parse_struct_variant_fields(&mut self) -> VariantFields {
496        let mut fields = vec![];
497        let mut seen_fields: Vec<(EcoString, Span)> = vec![];
498
499        loop {
500            if self.at_eof()
501                || self.is(RightCurlyBrace)
502                || self.at_item_boundary()
503                || self.is_not(Identifier)
504            {
505                break;
506            }
507
508            let name_token = self.current_token();
509            let name_span = Span::new(self.file_id, name_token.byte_offset, name_token.byte_length);
510            let name = self.read_identifier();
511            self.ensure(Colon);
512            let annotation = self.parse_annotation();
513
514            if let Some((_, first_span)) = seen_fields.iter().find(|(n, _)| n == &name) {
515                self.error_duplicate_struct_field(&name, *first_span, name_span);
516            } else {
517                seen_fields.push((name.clone(), name_span));
518            }
519
520            let field = EnumFieldDefinition {
521                name,
522                name_span,
523                annotation,
524                ty: Type::uninferred(),
525            };
526
527            fields.push(field);
528
529            self.expect_comma_or(RightCurlyBrace);
530        }
531
532        self.ensure(RightCurlyBrace);
533
534        VariantFields::Struct(fields)
535    }
536
537    pub fn parse_struct_definition(
538        &mut self,
539        doc: Option<std::string::String>,
540        attributes: Vec<Attribute>,
541    ) -> Expression {
542        let start = self.current_token();
543
544        self.ensure(Struct);
545
546        let name_token = self.current_token();
547        let name_span = Span::new(self.file_id, name_token.byte_offset, name_token.byte_length);
548        let name = self.read_identifier();
549        let generics = self.parse_generics();
550
551        if self.is(LeftParen) {
552            return self.parse_tuple_struct(doc, attributes, name, name_span, generics, start);
553        }
554
555        self.parse_named_struct(doc, attributes, name, name_span, generics, start)
556    }
557
558    fn parse_named_struct(
559        &mut self,
560        doc: Option<std::string::String>,
561        attributes: Vec<Attribute>,
562        name: EcoString,
563        name_span: Span,
564        generics: Vec<Generic>,
565        start: Token<'source>,
566    ) -> Expression {
567        let mut fields = vec![];
568        let mut seen_fields: Vec<(EcoString, Span)> = vec![];
569
570        self.ensure(LeftCurlyBrace);
571
572        while self.is_not(RightCurlyBrace) {
573            let start_position = self.stream.position;
574
575            let field_attributes = self.parse_attributes();
576            let field_doc = self.collect_doc_comments().map(|(text, _)| text);
577            if let Some(field) = self.parse_struct_field_with_doc(field_doc, field_attributes) {
578                if let Some((_, first_span)) = seen_fields.iter().find(|(n, _)| n == &field.name) {
579                    self.error_duplicate_struct_field(&field.name, *first_span, field.name_span);
580                } else {
581                    seen_fields.push((field.name.clone(), field.name_span));
582                }
583                fields.push(field);
584            }
585            self.expect_comma_or(RightCurlyBrace);
586            self.ensure_progress(start_position, RightCurlyBrace);
587        }
588
589        self.ensure(RightCurlyBrace);
590
591        Expression::Struct {
592            doc,
593            attributes,
594            name,
595            name_span,
596            generics,
597            fields,
598            kind: StructKind::Record,
599            visibility: Visibility::Private,
600            span: self.span_from_tokens(start),
601        }
602    }
603
604    fn parse_tuple_struct(
605        &mut self,
606        doc: Option<std::string::String>,
607        attributes: Vec<Attribute>,
608        name: EcoString,
609        name_span: Span,
610        generics: Vec<Generic>,
611        start: Token<'source>,
612    ) -> Expression {
613        self.ensure(LeftParen);
614
615        let mut fields = vec![];
616        let mut index = 0;
617
618        while self.is_not(RightParen) {
619            if self.at_eof() || self.at_item_boundary() || !self.can_start_annotation() {
620                break;
621            }
622
623            let field_start = self.current_token();
624            let annotation = self.parse_annotation();
625            let field_span = self.span_from_tokens(field_start);
626
627            fields.push(StructFieldDefinition {
628                doc: None,
629                attributes: vec![],
630                name: format!("_{}", index).into(),
631                name_span: field_span,
632                annotation,
633                visibility: Visibility::Private,
634                ty: Type::uninferred(),
635            });
636
637            index += 1;
638            self.expect_comma_or(RightParen);
639        }
640
641        self.ensure(RightParen);
642
643        Expression::Struct {
644            doc,
645            attributes,
646            name,
647            name_span,
648            generics,
649            fields,
650            kind: StructKind::Tuple,
651            visibility: Visibility::Private,
652            span: self.span_from_tokens(start),
653        }
654    }
655
656    fn parse_struct_field_with_doc(
657        &mut self,
658        doc: Option<std::string::String>,
659        attributes: Vec<Attribute>,
660    ) -> Option<StructFieldDefinition> {
661        let visibility = if self.advance_if(Pub) {
662            Visibility::Public
663        } else {
664            Visibility::Private
665        };
666
667        if self.is(Mut) {
668            self.track_error(
669                "fields cannot be marked `mut`",
670                "Fields cannot be marked `mut`; mutability applies to bindings (`let mut x = ...`).",
671            );
672            self.next();
673        }
674
675        if self.is_not(Identifier) {
676            self.track_error("expected field name", "Field names must be identifiers.");
677            return None;
678        }
679
680        let name_token = self.current_token();
681        let name_span = Span::new(self.file_id, name_token.byte_offset, name_token.byte_length);
682        let name = self.read_identifier();
683
684        self.ensure(Colon);
685
686        Some(StructFieldDefinition {
687            doc,
688            attributes,
689            visibility,
690            name,
691            name_span,
692            annotation: self.parse_annotation(),
693            ty: Type::uninferred(),
694        })
695    }
696
697    pub fn parse_const_definition(&mut self, doc: Option<std::string::String>) -> Expression {
698        let start = self.current_token();
699
700        self.ensure(Const);
701
702        let identifier_token = self.current_token();
703        let identifier_span = Span::new(
704            self.file_id,
705            identifier_token.byte_offset,
706            identifier_token.byte_length,
707        );
708        let identifier = self.read_identifier();
709        let annotation = if self.advance_if(Colon) {
710            Some(self.parse_annotation())
711        } else {
712            None
713        };
714
715        let expression = if self.advance_if(Equal) {
716            self.parse_expression()
717        } else {
718            Expression::NoOp
719        };
720
721        Expression::Const {
722            doc,
723            identifier,
724            identifier_span,
725            annotation,
726            expression: expression.into(),
727            visibility: Visibility::Private,
728            ty: Type::uninferred(),
729            span: self.span_from_tokens(start),
730        }
731    }
732
733    pub fn parse_var_declaration(&mut self, doc: Option<std::string::String>) -> Expression {
734        let start = self.current_token();
735
736        self.ensure(Var);
737
738        let name_token = self.current_token();
739        let name_span = Span::new(self.file_id, name_token.byte_offset, name_token.byte_length);
740        let name = self.read_identifier();
741
742        self.ensure(Colon);
743        let annotation = self.parse_annotation();
744
745        Expression::VariableDeclaration {
746            doc,
747            name,
748            name_span,
749            annotation,
750            visibility: Visibility::Private,
751            ty: Type::uninferred(),
752            span: self.span_from_tokens(start),
753        }
754    }
755
756    pub fn parse_impl_block(&mut self) -> Expression {
757        let start = self.current_token();
758
759        self.ensure(Impl);
760
761        let generics = self.parse_generics();
762
763        let receiver = self.parse_annotation(); // e.g. List<T>
764
765        let (receiver_name, annotation) = match &receiver {
766            Annotation::Constructor { name, .. } => (name.clone(), receiver),
767            _ => {
768                self.track_error("expected `impl` receiver", "Use `impl TypeName { ... }`.");
769                ("".into(), Annotation::Unknown)
770            }
771        };
772
773        if self.is(For) {
774            self.track_error(
775                "invalid syntax",
776                "Lisette types satisfy interfaces automatically by having the required methods. Use `impl Type { ... }` to add methods.",
777            );
778            self.next();
779            self.parse_annotation();
780        }
781
782        let mut methods = vec![];
783
784        self.ensure(LeftCurlyBrace);
785
786        while self.is_not(RightCurlyBrace) {
787            self.advance_if(Semicolon);
788            if self.is(RightCurlyBrace) {
789                break;
790            }
791
792            let method_doc = self.collect_doc_comments();
793            let method_attrs = self.parse_attributes();
794            let is_public = self.advance_if(Pub);
795
796            if self.is(Function) {
797                let method = self.parse_function(method_doc.map(|(text, _)| text), method_attrs);
798                let method = if is_public {
799                    method.set_public()
800                } else {
801                    method
802                };
803                methods.push(method);
804            } else {
805                if let Some((_, span)) = method_doc {
806                    self.error_detached_doc_comment(span);
807                }
808                self.track_error(
809                    "expected `fn` in impl block",
810                    "Only functions are allowed in `impl` blocks.",
811                );
812                self.next();
813            }
814        }
815
816        self.ensure(RightCurlyBrace);
817
818        Expression::ImplBlock {
819            annotation,
820            methods,
821            receiver_name,
822            generics,
823            ty: Type::uninferred(),
824            span: self.span_from_tokens(start),
825        }
826    }
827
828    pub fn parse_interface_definition(&mut self, doc: Option<std::string::String>) -> Expression {
829        let start = self.current_token();
830
831        self.ensure(Interface);
832
833        let name_token = self.current_token();
834        let name_span = Span::new(self.file_id, name_token.byte_offset, name_token.byte_length);
835        let name = self.read_identifier();
836
837        let generics = self.parse_generics();
838
839        let mut parents = vec![];
840        let mut seen_parents: Vec<(EcoString, Span)> = vec![];
841        let mut method_signatures = vec![];
842        let mut seen_methods: Vec<(EcoString, Span)> = vec![];
843
844        self.ensure(LeftCurlyBrace);
845
846        while self.is_not(RightCurlyBrace) {
847            self.advance_if(Semicolon);
848            if self.is(RightCurlyBrace) {
849                break;
850            }
851
852            let item_doc = self.collect_doc_comments();
853            let method_attrs = self.parse_attributes();
854            match self.current_token().kind {
855                Function => {
856                    let method =
857                        self.parse_interface_method(item_doc.map(|(text, _)| text), method_attrs);
858                    if let Expression::Function {
859                        ref name,
860                        ref name_span,
861                        ..
862                    } = method
863                    {
864                        if let Some((_, first_span)) = seen_methods.iter().find(|(n, _)| n == name)
865                        {
866                            self.error_duplicate_interface_method(name, *first_span, *name_span);
867                        } else {
868                            seen_methods.push((name.clone(), *name_span));
869                        }
870                    }
871                    method_signatures.push(method);
872                    self.advance_if(Semicolon);
873                }
874
875                Impl => {
876                    if let Some((_, span)) = item_doc {
877                        self.error_detached_doc_comment(span);
878                    }
879                    self.ensure(Impl);
880
881                    let parent_start = self.current_token();
882                    let annotation = self.parse_annotation();
883                    let parent_span = self.span_from_tokens(parent_start);
884
885                    if let Annotation::Constructor { name, .. } = &annotation {
886                        if let Some((_, first_span)) =
887                            seen_parents.iter().find(|(n, _)| n == name.as_str())
888                        {
889                            self.error_duplicate_impl_parent(*first_span, parent_span);
890                        } else {
891                            seen_parents.push((name.clone(), parent_span));
892                        }
893                    }
894
895                    parents.push(ParentInterface {
896                        annotation,
897                        ty: Type::uninferred(),
898                        span: parent_span,
899                    });
900                    self.advance_if(Semicolon);
901                }
902
903                _ => {
904                    if let Some((_, span)) = item_doc {
905                        self.error_detached_doc_comment(span);
906                    }
907                    self.track_error(
908                        "expected `fn` or `impl`",
909                        "Only functions and `impl` blocks are allowed in interfaces.",
910                    );
911                    self.next();
912                }
913            }
914        }
915
916        self.ensure(RightCurlyBrace);
917
918        Expression::Interface {
919            doc,
920            name,
921            name_span,
922            generics,
923            parents,
924            method_signatures,
925            visibility: Visibility::Private,
926            span: self.span_from_tokens(start),
927        }
928    }
929}