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