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        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(); // e.g. List<T>
781
782        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}