1use ecow::EcoString;
2
3use super::Parser;
4use crate::ast::{
5 Annotation, Attribute, AttributeArg, EnumFieldDefinition, EnumVariant, Expression, Generic,
6 Literal, ParentInterface, Span, StructFieldDefinition, StructKind, ValueEnumVariant,
7 VariantFields, Visibility,
8};
9use crate::lex::Token;
10use crate::lex::TokenKind::*;
11use crate::parse::error::ParseError;
12use crate::types::Type;
13
14impl<'source> Parser<'source> {
15 pub(crate) fn parse_attributes(&mut self) -> Vec<Attribute> {
16 let mut attributes = vec![];
17 loop {
18 self.advance_if(Semicolon);
19 if !self.is(Hash) {
20 break;
21 }
22 if let Some(attribute) = self.parse_attribute() {
23 attributes.push(attribute);
24 }
25 }
26 attributes
27 }
28
29 fn parse_attribute(&mut self) -> Option<Attribute> {
30 let start = self.current_token();
31 self.ensure(Hash);
32
33 if !self.is(LeftSquareBracket) {
34 self.track_error("expected `[` after `#`", "Add `[` to start the attribute");
35 return None;
36 }
37 self.next();
38
39 if !self.is(Identifier) {
40 self.track_error(
41 "expected attribute name",
42 "Add an attribute name like `json` or `db`",
43 );
44 while self.is_not(RightSquareBracket) && !self.at_eof() {
45 self.next();
46 }
47 self.advance_if(RightSquareBracket);
48 return None;
49 }
50
51 let name = self.read_identifier();
52 let args = if self.advance_if(LeftParen) {
53 self.parse_attribute_args()
54 } else {
55 vec![]
56 };
57
58 if !self.advance_if(RightSquareBracket) {
59 self.track_error("expected `]`", "Add `]` to close the attribute");
60 }
61
62 Some(Attribute {
63 name: name.to_string(),
64 args,
65 span: self.span_from_tokens(start),
66 })
67 }
68
69 fn parse_attribute_args(&mut self) -> Vec<AttributeArg> {
70 let mut args = vec![];
71
72 while self.is_not(RightParen) && !self.at_eof() {
73 if let Some(arg) = self.parse_attribute_arg() {
74 args.push(arg);
75 }
76
77 if !self.advance_if(Comma) {
78 break;
79 }
80 }
81
82 self.ensure(RightParen);
83 args
84 }
85
86 fn parse_attribute_arg(&mut self) -> Option<AttributeArg> {
87 if self.advance_if(Bang) {
88 if self.is(Identifier) {
89 return Some(AttributeArg::NegatedFlag(
90 self.read_identifier().to_string(),
91 ));
92 } else {
93 self.track_error(
94 "expected identifier after `!`",
95 "Add an identifier like `omitempty` after `!`",
96 );
97 return None;
98 }
99 }
100
101 if self.is(Identifier) {
102 return Some(AttributeArg::Flag(self.read_identifier().to_string()));
103 }
104
105 if self.is(String) {
106 let token = self.current_token();
107 self.next();
108 let text = token.text;
109 let value = if text.len() >= 2 {
110 &text[1..text.len() - 1]
111 } else {
112 text
113 };
114 return Some(AttributeArg::String(value.to_string()));
115 }
116
117 if self.is(Backtick) {
118 let token = self.current_token();
119 self.next();
120 let text = token.text;
121 let value = if text.len() >= 2 {
122 &text[1..text.len() - 1]
123 } else {
124 text
125 };
126 return Some(AttributeArg::Raw(value.to_string()));
127 }
128
129 self.track_error(
130 "expected attribute argument",
131 "Add a flag (e.g. `omitempty`), string (e.g. `\"name\"`), or raw tag (e.g. `` `json:\"name\"` ``)",
132 );
133 None
134 }
135
136 pub fn parse_enum_definition(
137 &mut self,
138 doc: Option<std::string::String>,
139 attributes: Vec<Attribute>,
140 ) -> Expression {
141 let start = self.current_token();
142
143 self.ensure(Enum);
144
145 let name_token = self.current_token();
146 let name_span = Span::new(self.file_id, name_token.byte_offset, name_token.byte_length);
147 let name = self.read_identifier();
148 let generics = self.parse_generics();
149
150 let underlying_start = self.current_token();
151 let underlying_ty = if self.advance_if(Colon) {
152 let annotation = self.parse_annotation();
153 Some((annotation, underlying_start))
154 } else {
155 None
156 };
157
158 self.ensure(LeftCurlyBrace);
159
160 if self.peek_is_value_enum_variant() {
161 if !generics.is_empty() {
162 let generics_span = generics.first().expect("non-empty").span;
163 let param_word = if generics.len() == 1 {
164 "parameter"
165 } else {
166 "parameters"
167 };
168 let error = ParseError::new(
169 "Value enum with generics",
170 generics_span,
171 "not allowed on value enums",
172 )
173 .with_parse_code("value_enum_generics")
174 .with_help(format!(
175 "Remove the generic {}. Value enums represent Go const groups, which cannot be generic.",
176 param_word
177 ));
178 self.errors.push(error);
179 }
180
181 let underlying_ty = underlying_ty.map(|(annotation, _)| annotation);
182 return self.parse_value_enum_body(doc, name, name_span, underlying_ty, start);
183 }
184
185 if let Some((_, underlying_token)) = underlying_ty {
186 let underlying_span = Span::new(
187 self.file_id,
188 underlying_token.byte_offset,
189 underlying_token.byte_length,
190 );
191 let error = ParseError::new(
192 "Underlying type on regular enum",
193 underlying_span,
194 "only allowed on value enums",
195 )
196 .with_parse_code("enum_underlying_type")
197 .with_help(
198 "Remove the `: type` annotation. Underlying types are allowed only on value enums, which represent Go const groups.",
199 );
200 self.errors.push(error);
201 }
202
203 self.parse_regular_enum_body(doc, attributes, name, name_span, generics, start)
204 }
205
206 fn peek_is_value_enum_variant(&self) -> bool {
207 if self.is(RightCurlyBrace) {
208 return false;
209 }
210
211 let mut offset = 0;
212 while self.stream.peek_ahead(offset).kind == DocComment {
213 offset += 1;
214 }
215
216 self.stream.peek_ahead(offset).kind == Identifier
217 && self.stream.peek_ahead(offset + 1).kind == Equal
218 }
219
220 fn parse_regular_enum_body(
221 &mut self,
222 doc: Option<std::string::String>,
223 attributes: Vec<Attribute>,
224 name: EcoString,
225 name_span: Span,
226 generics: Vec<Generic>,
227 start: Token<'source>,
228 ) -> Expression {
229 let mut variants = vec![];
230 let mut seen_variants: Vec<(EcoString, Span)> = vec![];
231
232 while self.is_not(RightCurlyBrace) {
233 let start_position = self.stream.position;
234
235 let variant_doc = self.collect_doc_comments().map(|(text, _)| text);
236 if let Some(variant) = self.parse_enum_variant_with_doc(variant_doc) {
237 if let Some((_, first_span)) =
238 seen_variants.iter().find(|(n, _)| n == &variant.name)
239 {
240 self.error_duplicate_enum_variant(
241 &variant.name,
242 *first_span,
243 variant.name_span,
244 );
245 } else {
246 seen_variants.push((variant.name.clone(), variant.name_span));
247 }
248 variants.push(variant);
249 }
250 self.expect_comma_or(RightCurlyBrace);
251 self.ensure_progress(start_position, RightCurlyBrace);
252 }
253
254 self.ensure(RightCurlyBrace);
255
256 Expression::Enum {
257 doc,
258 attributes,
259 name,
260 name_span,
261 generics,
262 variants,
263 visibility: Visibility::Private,
264 span: self.span_from_tokens(start),
265 }
266 }
267
268 fn parse_value_enum_body(
269 &mut self,
270 doc: Option<std::string::String>,
271 name: EcoString,
272 name_span: Span,
273 underlying_ty: Option<Annotation>,
274 start: Token<'source>,
275 ) -> Expression {
276 let mut variants = vec![];
277 let mut seen_variants: Vec<(EcoString, Span)> = vec![];
278
279 while self.is_not(RightCurlyBrace) {
280 let start_position = self.stream.position;
281
282 let variant_doc = self.collect_doc_comments().map(|(text, _)| text);
283 if let Some(variant) = self.parse_value_enum_variant_with_doc(variant_doc) {
284 if let Some((_, first_span)) =
285 seen_variants.iter().find(|(n, _)| n == &variant.name)
286 {
287 self.error_duplicate_enum_variant(
288 &variant.name,
289 *first_span,
290 variant.name_span,
291 );
292 } else {
293 seen_variants.push((variant.name.clone(), variant.name_span));
294 }
295 variants.push(variant);
296 }
297 self.expect_comma_or(RightCurlyBrace);
298 self.ensure_progress(start_position, RightCurlyBrace);
299 }
300
301 self.ensure(RightCurlyBrace);
302
303 Expression::ValueEnum {
304 doc,
305 name,
306 name_span,
307 underlying_ty,
308 variants,
309 visibility: Visibility::Public,
310 span: self.span_from_tokens(start),
311 }
312 }
313
314 fn parse_enum_variant_with_doc(
315 &mut self,
316 doc: Option<std::string::String>,
317 ) -> Option<EnumVariant> {
318 if self.is_not(Identifier) {
319 self.track_error(
320 "expected variant name",
321 "Variant names must be identifiers.",
322 );
323 return None;
324 }
325
326 let name_token = self.current_token();
327 let name_span = Span::new(self.file_id, name_token.byte_offset, name_token.byte_length);
328 let name = self.read_identifier();
329 let fields = self.parse_enum_variant_fields();
330
331 Some(EnumVariant {
332 doc,
333 name,
334 name_span,
335 fields,
336 })
337 }
338
339 fn parse_value_enum_variant_with_doc(
340 &mut self,
341 doc: Option<std::string::String>,
342 ) -> Option<ValueEnumVariant> {
343 if self.is_not(Identifier) {
344 self.track_error(
345 "expected variant name",
346 "Variant names must be identifiers.",
347 );
348 return None;
349 }
350
351 let name_token = self.current_token();
352 let name_span = Span::new(self.file_id, name_token.byte_offset, name_token.byte_length);
353 let name = self.read_identifier();
354
355 let (value, value_span) = if self.is(Equal) {
356 let eq_token = self.current_token();
357 let start_offset = eq_token.byte_offset;
358 self.next(); let (value, value_end) = self.parse_value_enum_variant_value();
360 let span = Span::new(self.file_id, start_offset, value_end - start_offset);
361 (value, span)
362 } else {
363 (
364 Literal::Integer {
365 value: 0,
366 text: None,
367 },
368 name_span,
369 )
370 };
371
372 Some(ValueEnumVariant {
373 doc,
374 name,
375 name_span,
376 value,
377 value_span,
378 })
379 }
380
381 fn parse_value_enum_variant_value(&mut self) -> (Literal, u32) {
382 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(); 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}