1use crate::ast::{Span, TypeAnnotation};
10use crate::error::{Result, ShapeError};
11use crate::parser::string_literals::parse_string_literal;
12use pest::iterators::Pair;
13use std::collections::HashMap;
14
15use super::{Rule, pair_location, pair_span};
16
17pub fn parse_type_annotation(pair: Pair<Rule>) -> Result<TypeAnnotation> {
19 let pair_loc = pair_location(&pair);
20
21 match pair.as_rule() {
22 Rule::type_annotation => {
23 let loc = pair_loc.clone();
24 let mut inner = pair.into_inner();
25 let type_part = inner.next().ok_or_else(|| ShapeError::ParseError {
26 message: "expected type annotation content".to_string(),
27 location: Some(loc.clone()),
28 })?;
29 parse_type_annotation(type_part)
30 }
31 Rule::union_type => {
32 let mut types = Vec::new();
33 for inner in pair.into_inner() {
34 types.push(parse_type_annotation(inner)?);
35 }
36 if types.len() == 1 {
37 Ok(types.remove(0))
38 } else {
39 Ok(TypeAnnotation::Union(types))
40 }
41 }
42 Rule::intersection_type => {
43 let mut types = Vec::new();
44 for inner in pair.into_inner() {
45 types.push(parse_type_annotation(inner)?);
46 }
47 if types.len() == 1 {
48 Ok(types.remove(0))
49 } else {
50 Ok(TypeAnnotation::Intersection(types))
51 }
52 }
53 Rule::optional_type => {
54 let inner = pair
55 .clone()
56 .into_inner()
57 .next()
58 .ok_or_else(|| ShapeError::ParseError {
59 message: "expected type in optional type annotation".to_string(),
60 location: Some(pair_loc),
61 })?;
62 let mut ty = parse_type_annotation(inner)?;
63 if pair.as_str().trim_end().ends_with('?') {
64 ty = TypeAnnotation::option(ty);
65 }
66 Ok(ty)
67 }
68 Rule::primary_type => {
69 let inner = pair
70 .clone()
71 .into_inner()
72 .next()
73 .ok_or_else(|| ShapeError::ParseError {
74 message: "expected type in primary type annotation".to_string(),
75 location: Some(pair_loc),
76 })?;
77 let mut ty = parse_type_annotation(inner)?;
78 let mut remaining = pair.as_str().trim();
79 while remaining.ends_with("[]") {
80 ty = TypeAnnotation::Array(Box::new(ty));
81 remaining = &remaining[..remaining.len() - 2];
82 }
83 Ok(ty)
84 }
85 Rule::non_array_type => {
86 let mut inner = pair.clone().into_inner();
87 let inner_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
88 message: "expected type in non-array type annotation".to_string(),
89 location: Some(pair_loc),
90 })?;
91 if pair.as_str().trim_start().starts_with("Vec<")
92 && inner_pair.as_rule() == Rule::type_annotation
93 {
94 let inner_ty = parse_type_annotation(inner_pair)?;
95 return Ok(TypeAnnotation::Array(Box::new(inner_ty)));
96 }
97 parse_type_annotation(inner_pair)
98 }
99 Rule::basic_type => parse_basic_type(pair.as_str()),
100 Rule::tuple_type => {
101 let mut members = Vec::new();
102 for inner in pair.into_inner() {
103 if inner.as_rule() == Rule::type_annotation {
104 members.push(parse_type_annotation(inner)?);
105 }
106 }
107 Ok(TypeAnnotation::Tuple(members))
108 }
109 Rule::object_type => parse_object_type(pair),
110 Rule::function_type => parse_function_type(pair),
111 Rule::dyn_type => {
112 let trait_names: Vec<_> = pair
113 .into_inner()
114 .filter(|p| p.as_rule() == Rule::qualified_ident)
115 .map(|p| p.as_str().into())
116 .collect();
117 Ok(TypeAnnotation::Dyn(trait_names))
118 }
119 Rule::unit_type => Ok(TypeAnnotation::Basic("()".to_string())),
120 Rule::generic_type => parse_generic_type(pair),
121 Rule::type_param => {
122 let param = parse_type_param(pair)?;
123 Ok(param.type_annotation)
124 }
125 Rule::ident => Ok(TypeAnnotation::Reference(pair.as_str().into())),
126 _ => Err(ShapeError::ParseError {
127 message: format!("invalid type annotation: {:?}", pair.as_rule()),
128 location: Some(pair_loc),
129 }),
130 }
131}
132
133pub fn parse_basic_type(name: &str) -> Result<TypeAnnotation> {
135 Ok(match name {
136 "void" => TypeAnnotation::Void,
137 "never" => TypeAnnotation::Never,
138 "undefined" => TypeAnnotation::Undefined,
139 other if other.contains("::") => TypeAnnotation::Reference(other.into()),
140 other => TypeAnnotation::Basic(other.to_string()),
141 })
142}
143
144pub fn parse_object_type(pair: Pair<Rule>) -> Result<TypeAnnotation> {
146 let mut fields = Vec::new();
147 for inner in pair.into_inner() {
148 if inner.as_rule() == Rule::object_type_member_list {
149 for member in inner.into_inner() {
150 if member.as_rule() == Rule::object_type_member {
151 fields.push(parse_object_type_member(member)?);
152 }
153 }
154 }
155 }
156 Ok(TypeAnnotation::Object(fields))
157}
158
159pub fn parse_object_type_member(pair: Pair<Rule>) -> Result<crate::ast::ObjectTypeField> {
161 let pair_loc = pair_location(&pair);
162 let mut inner = pair.clone().into_inner();
163 let mut annotations = Vec::new();
164
165 let first = inner.next().ok_or_else(|| ShapeError::ParseError {
166 message: "expected field name in object type member".to_string(),
167 location: Some(pair_loc.clone()),
168 })?;
169
170 let name_pair = if first.as_rule() == Rule::annotations {
171 annotations = super::functions::parse_annotations(first)?;
172 inner.next().ok_or_else(|| ShapeError::ParseError {
173 message: "expected field name after annotations in object type member".to_string(),
174 location: Some(pair_loc.clone()),
175 })?
176 } else {
177 first
178 };
179 let name = name_pair.as_str().to_string();
180
181 let type_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
182 message: format!("expected type annotation for field '{}'", name),
183 location: Some(pair_loc),
184 })?;
185 let type_annotation = parse_type_annotation(type_pair)?;
186
187 let before_colon = pair.as_str().split(':').next().unwrap_or("");
188 let optional = before_colon.contains('?');
189
190 Ok(crate::ast::ObjectTypeField {
191 name,
192 optional,
193 type_annotation,
194 annotations,
195 })
196}
197
198pub fn parse_function_type(pair: Pair<Rule>) -> Result<TypeAnnotation> {
200 let mut params = Vec::new();
201 let mut return_type = None;
202
203 for inner in pair.into_inner() {
204 match inner.as_rule() {
205 Rule::type_param_list => {
206 params = parse_type_param_list(inner)?;
207 }
208 Rule::type_annotation => {
209 return_type = Some(parse_type_annotation(inner)?);
210 }
211 _ => {}
212 }
213 }
214
215 let returns = return_type.ok_or_else(|| ShapeError::ParseError {
216 message: "Function type missing return type".to_string(),
217 location: None,
218 })?;
219
220 Ok(TypeAnnotation::Function {
221 params,
222 returns: Box::new(returns),
223 })
224}
225
226pub fn parse_type_param_list(pair: Pair<Rule>) -> Result<Vec<crate::ast::FunctionParam>> {
228 let mut params = Vec::new();
229 for inner in pair.into_inner() {
230 if inner.as_rule() == Rule::type_param {
231 params.push(parse_type_param(inner)?);
232 }
233 }
234 Ok(params)
235}
236
237pub fn parse_type_param(pair: Pair<Rule>) -> Result<crate::ast::FunctionParam> {
239 let pair_loc = pair_location(&pair);
240 let mut inner = pair.clone().into_inner();
241 let first = inner.next().ok_or_else(|| ShapeError::ParseError {
242 message: "expected type parameter content".to_string(),
243 location: Some(pair_loc.clone()),
244 })?;
245
246 if first.as_rule() == Rule::ident {
247 let name = first.as_str().to_string();
248 let type_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
249 message: format!("type parameter '{}' missing type annotation", name),
250 location: Some(pair_loc),
251 })?;
252 let type_annotation = parse_type_annotation(type_pair)?;
253 let before_colon = pair.as_str().split(':').next().unwrap_or("");
254 let optional = before_colon.contains('?');
255 Ok(crate::ast::FunctionParam {
256 name: Some(name),
257 optional,
258 type_annotation,
259 })
260 } else {
261 let type_annotation = parse_type_annotation(first)?;
262 Ok(crate::ast::FunctionParam {
263 name: None,
264 optional: false,
265 type_annotation,
266 })
267 }
268}
269
270fn unwrap_documented_pair<'a>(
271 pair: Pair<'a, Rule>,
272 documented_rule: Rule,
273 inner_rule: Rule,
274 context: &'static str,
275) -> Result<(Option<crate::ast::DocComment>, Pair<'a, Rule>)> {
276 if pair.as_rule() == inner_rule {
277 return Ok((None, pair));
278 }
279
280 if pair.as_rule() != documented_rule {
281 return Err(ShapeError::ParseError {
282 message: format!("expected {}", context),
283 location: Some(pair_location(&pair)),
284 });
285 }
286
287 let pair_loc = pair_location(&pair);
288 let mut inner = pair.into_inner();
289 let mut doc_comment = None;
290 let mut item = inner.next().ok_or_else(|| ShapeError::ParseError {
291 message: format!("expected {}", context),
292 location: Some(pair_loc.clone()),
293 })?;
294
295 if item.as_rule() == Rule::doc_comment {
296 doc_comment = Some(super::docs::parse_doc_comment(item));
297 item = inner.next().ok_or_else(|| ShapeError::ParseError {
298 message: format!("expected {} after doc comment", context),
299 location: Some(pair_loc.clone()),
300 })?;
301 }
302
303 if item.as_rule() != inner_rule {
304 return Err(ShapeError::ParseError {
305 message: format!("expected {}", context),
306 location: Some(pair_location(&item)),
307 });
308 }
309
310 Ok((doc_comment, item))
311}
312
313pub fn parse_type_params(pair: Pair<Rule>) -> Result<Vec<crate::ast::TypeParam>> {
314 let pair_loc = pair_location(&pair);
315 let mut params = Vec::new();
316 for param_pair in pair.into_inner() {
317 if matches!(
318 param_pair.as_rule(),
319 Rule::documented_type_param_name | Rule::type_param_name
320 ) {
321 let (doc_comment, param_pair) = unwrap_documented_pair(
322 param_pair,
323 Rule::documented_type_param_name,
324 Rule::type_param_name,
325 "type parameter",
326 )?;
327 let param_span = pair_span(¶m_pair);
328 let mut param_inner = param_pair.into_inner();
329 let first = param_inner.next().ok_or_else(|| ShapeError::ParseError {
330 message: "expected type parameter name".to_string(),
331 location: Some(pair_loc.clone()),
332 })?;
333
334 if first.as_rule() == Rule::const_type_param {
342 let mut const_inner = first.into_inner();
343 let name_pair =
344 const_inner.next().ok_or_else(|| ShapeError::ParseError {
345 message: "expected const generic parameter name".to_string(),
346 location: Some(pair_loc.clone()),
347 })?;
348 let name = name_pair.as_str().to_string();
349 let ty_pair = const_inner.next().ok_or_else(|| ShapeError::ParseError {
350 message: "expected const generic parameter type annotation".to_string(),
351 location: Some(pair_loc.clone()),
352 })?;
353 let ty = parse_type_annotation(ty_pair)?;
354 let mut default = None;
355 for remaining in const_inner {
356 if remaining.as_rule() == Rule::expression {
357 default = Some(crate::parser::expressions::parse_expression(remaining)?);
358 }
359 }
360 params.push(crate::ast::TypeParam::Const {
361 name,
362 span: param_span,
363 doc_comment,
364 ty,
365 default,
366 });
367 continue;
368 }
369
370 let name = first.as_str().to_string();
371 let mut default_type = None;
372 let mut trait_bounds = Vec::new();
373 for remaining in param_inner {
374 match remaining.as_rule() {
375 Rule::type_annotation => {
376 default_type = Some(parse_type_annotation(remaining)?);
377 }
378 Rule::trait_bound_list => {
379 for bound_ident in remaining.into_inner() {
380 if bound_ident.as_rule() == Rule::qualified_ident {
381 trait_bounds.push(bound_ident.as_str().into());
382 }
383 }
384 }
385 _ => {}
386 }
387 }
388 params.push(crate::ast::TypeParam::Type {
389 name,
390 span: param_span,
391 doc_comment,
392 default_type,
393 trait_bounds,
394 });
395 }
396 }
397 Ok(params)
398}
399
400pub fn parse_builtin_type_decl(pair: Pair<Rule>) -> Result<crate::ast::BuiltinTypeDecl> {
405 let pair_loc = pair_location(&pair);
406 let mut name = String::new();
407 let mut name_span = crate::ast::Span::DUMMY;
408 let mut type_params = None;
409
410 for inner in pair.into_inner() {
411 match inner.as_rule() {
412 Rule::ident => {
413 if name.is_empty() {
414 name = inner.as_str().to_string();
415 name_span = super::pair_span(&inner);
416 }
417 }
418 Rule::type_params => {
419 type_params = Some(parse_type_params(inner)?);
420 }
421 _ => {}
422 }
423 }
424
425 if name.is_empty() {
426 return Err(ShapeError::ParseError {
427 message: "expected builtin type name".to_string(),
428 location: Some(pair_loc),
429 });
430 }
431
432 Ok(crate::ast::BuiltinTypeDecl {
433 name,
434 name_span,
435 doc_comment: None,
436 type_params,
437 })
438}
439
440pub fn parse_generic_type(pair: Pair<Rule>) -> Result<TypeAnnotation> {
442 let pair_loc = pair_location(&pair);
443 let mut inner = pair.into_inner();
444 let name = inner
445 .next()
446 .ok_or_else(|| ShapeError::ParseError {
447 message: "expected generic type name".to_string(),
448 location: Some(pair_loc.clone()),
449 })?
450 .as_str()
451 .to_string();
452 let mut args = Vec::new();
453 for arg in inner {
454 if arg.as_rule() == Rule::type_annotation {
455 args.push(parse_type_annotation(arg)?);
456 }
457 }
458 if name == "Matrix" {
459 return Err(ShapeError::ParseError {
460 message: "Matrix<T> has been removed; use Mat<T> instead".to_string(),
461 location: Some(pair_loc),
462 });
463 }
464 if (name == "Vec" || name == "Array") && args.len() == 1 {
465 Ok(TypeAnnotation::Array(Box::new(args.remove(0))))
466 } else {
467 Ok(TypeAnnotation::Generic { name: name.into(), args })
468 }
469}
470
471pub fn parse_comptime_field_overrides(
476 pair: Pair<Rule>,
477) -> Result<HashMap<String, crate::ast::Expr>> {
478 let mut overrides = HashMap::new();
479
480 for override_pair in pair.into_inner() {
481 if override_pair.as_rule() == Rule::comptime_field_override {
482 let mut inner = override_pair.into_inner();
483
484 let key_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
485 message: "Missing parameter name in override".to_string(),
486 location: None,
487 })?;
488 let key = key_pair.as_str().to_string();
489
490 let expr_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
491 message: "Missing expression in parameter override".to_string(),
492 location: None,
493 })?;
494 let expr = super::expressions::parse_expression(expr_pair)?;
495
496 overrides.insert(key, expr);
497 }
498 }
499
500 Ok(overrides)
501}
502
503pub fn parse_struct_type_def(pair: Pair<Rule>) -> Result<crate::ast::StructTypeDef> {
507 let pair_loc = pair_location(&pair);
508 let mut inner = pair.into_inner();
509
510 let mut annotations = Vec::new();
511 let mut type_params = None;
512 let mut fields = Vec::new();
513
514 let first = inner.next().ok_or_else(|| ShapeError::ParseError {
516 message: "Missing struct type name".to_string(),
517 location: Some(pair_loc.clone()),
518 })?;
519
520 let name = if first.as_rule() == Rule::annotations {
521 annotations = super::functions::parse_annotations(first)?;
522 let name_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
523 message: "Missing struct type name after annotations".to_string(),
524 location: Some(pair_loc.clone()),
525 })?;
526 name_pair.as_str().to_string()
527 } else {
528 first.as_str().to_string()
529 };
530
531 for part in inner {
532 match part.as_rule() {
533 Rule::type_params => {
534 type_params = Some(parse_type_params(part)?);
535 }
536 Rule::struct_field_list => {
537 for field_pair in part.into_inner() {
538 if matches!(
539 field_pair.as_rule(),
540 Rule::documented_struct_field | Rule::struct_field
541 ) {
542 fields.push(parse_struct_field(field_pair)?);
543 }
544 }
545 }
546 _ => {}
547 }
548 }
549
550 Ok(crate::ast::StructTypeDef {
551 name,
552 doc_comment: None,
553 type_params,
554 fields,
555 methods: Vec::new(),
556 annotations,
557 native_layout: None,
558 })
559}
560
561pub fn parse_native_struct_type_def(pair: Pair<Rule>) -> Result<crate::ast::StructTypeDef> {
565 let pair_loc = pair_location(&pair);
566 let mut annotations = Vec::new();
567 let mut abi: Option<String> = None;
568 let mut name: Option<String> = None;
569 let mut type_params = None;
570 let mut fields = Vec::new();
571
572 for part in pair.into_inner() {
573 match part.as_rule() {
574 Rule::annotations => {
575 annotations = super::functions::parse_annotations(part)?;
576 }
577 Rule::extern_abi => {
578 abi = Some(super::functions::parse_extern_abi(part)?);
579 }
580 Rule::ident => {
581 if name.is_none() {
582 name = Some(part.as_str().to_string());
583 }
584 }
585 Rule::type_params => {
586 type_params = Some(parse_type_params(part)?);
587 }
588 Rule::struct_field_list => {
589 for field_pair in part.into_inner() {
590 if matches!(
591 field_pair.as_rule(),
592 Rule::documented_struct_field | Rule::struct_field
593 ) {
594 fields.push(parse_struct_field(field_pair)?);
595 }
596 }
597 }
598 _ => {}
599 }
600 }
601
602 let abi = abi.ok_or_else(|| ShapeError::ParseError {
603 message: "native layout type declaration requires an ABI name".to_string(),
604 location: Some(pair_loc.clone()),
605 })?;
606
607 if abi.trim() != "C" {
608 return Err(ShapeError::ParseError {
609 message: format!(
610 "unsupported native ABI '{}': only C is currently supported for type layouts",
611 abi
612 ),
613 location: Some(pair_loc.clone()),
614 });
615 }
616
617 let name = name.ok_or_else(|| ShapeError::ParseError {
618 message: "Missing native layout type name".to_string(),
619 location: Some(pair_loc),
620 })?;
621
622 Ok(crate::ast::StructTypeDef {
623 name,
624 doc_comment: None,
625 type_params,
626 fields,
627 methods: Vec::new(),
628 annotations,
629 native_layout: Some(crate::ast::NativeLayoutBinding { abi }),
630 })
631}
632
633fn parse_struct_field(pair: Pair<Rule>) -> Result<crate::ast::StructField> {
637 let (doc_comment, pair) = unwrap_documented_pair(
638 pair,
639 Rule::documented_struct_field,
640 Rule::struct_field,
641 "struct field",
642 )?;
643 let pair_loc = pair_location(&pair);
644 let span = pair_span(&pair);
645 let mut inner = pair.into_inner();
646
647 let mut annotations = vec![];
648 let mut is_comptime = false;
649
650 let first = inner.next().ok_or_else(|| ShapeError::ParseError {
652 message: "Missing struct field name".to_string(),
653 location: Some(pair_loc.clone()),
654 })?;
655
656 let mut current = first;
657
658 if current.as_rule() == Rule::annotations {
659 annotations = super::functions::parse_annotations(current)?;
660 current = inner.next().ok_or_else(|| ShapeError::ParseError {
661 message: "Missing struct field name after annotations".to_string(),
662 location: Some(pair_loc.clone()),
663 })?;
664 }
665
666 if current.as_rule() == Rule::comptime_keyword {
667 is_comptime = true;
668 current = inner.next().ok_or_else(|| ShapeError::ParseError {
669 message: "Missing struct field name after 'comptime'".to_string(),
670 location: Some(pair_loc.clone()),
671 })?;
672 }
673
674 let name = current.as_str().to_string();
675
676 let type_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
677 message: format!("Missing type annotation for struct field '{}'", name),
678 location: Some(pair_loc),
679 })?;
680 let type_annotation = parse_type_annotation(type_pair)?;
681
682 let default_value = if let Some(expr_pair) = inner.next() {
684 Some(super::expressions::parse_expression(expr_pair)?)
685 } else {
686 None
687 };
688
689 Ok(crate::ast::StructField {
690 annotations,
691 is_comptime,
692 name,
693 span,
694 doc_comment,
695 type_annotation,
696 default_value,
697 })
698}
699
700pub fn parse_type_alias_def(pair: Pair<Rule>) -> Result<crate::ast::TypeAliasDef> {
704 let mut inner = pair.into_inner();
705
706 let name_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
708 message: "Missing type alias name".to_string(),
709 location: None,
710 })?;
711 let name = name_pair.as_str().to_string();
712
713 let mut type_params = None;
715 let mut type_annotation = None;
716 let mut meta_param_overrides = None;
717
718 for part in inner {
719 match part.as_rule() {
720 Rule::type_params => {
721 type_params = Some(parse_type_params(part)?);
723 }
724 Rule::type_annotation => {
725 type_annotation = Some(parse_type_annotation(part)?);
726 }
727 Rule::comptime_field_overrides => {
728 meta_param_overrides = Some(parse_comptime_field_overrides(part)?);
729 }
730 _ => {}
731 }
732 }
733
734 let type_annotation = type_annotation.ok_or_else(|| ShapeError::ParseError {
735 message: "Type alias missing type annotation".to_string(),
736 location: None,
737 })?;
738
739 Ok(crate::ast::TypeAliasDef {
740 name,
741 doc_comment: None,
742 type_params,
743 type_annotation,
744 meta_param_overrides,
745 })
746}
747
748pub fn parse_enum_def(pair: Pair<Rule>) -> Result<crate::ast::EnumDef> {
752 let pair_loc = pair_location(&pair);
753 let inner = pair.into_inner();
754
755 let mut annotations = Vec::new();
756 let mut name = String::new();
757 let mut type_params = None;
758 let mut members = Vec::new();
759
760 for part in inner {
761 match part.as_rule() {
762 Rule::annotations => {
763 annotations = crate::parser::functions::parse_annotations(part)?;
764 }
765 Rule::ident => {
766 if name.is_empty() {
767 name = part.as_str().to_string();
768 }
769 }
770 Rule::type_params => {
771 type_params = Some(parse_type_params(part)?);
772 }
773 Rule::enum_member_list => {
774 for member_pair in part.into_inner() {
775 if matches!(
776 member_pair.as_rule(),
777 Rule::documented_enum_member | Rule::enum_member
778 ) {
779 members.push(parse_enum_member(member_pair)?);
780 }
781 }
782 }
783 Rule::documented_enum_member | Rule::enum_member => {
784 members.push(parse_enum_member(part)?);
785 }
786 _ => {}
787 }
788 }
789
790 if name.is_empty() {
791 return Err(ShapeError::ParseError {
792 message: "Missing enum name".to_string(),
793 location: Some(pair_loc),
794 });
795 }
796
797 Ok(crate::ast::EnumDef {
798 name,
799 doc_comment: None,
800 type_params,
801 members,
802 annotations,
803 })
804}
805
806fn parse_enum_member(pair: Pair<Rule>) -> Result<crate::ast::EnumMember> {
807 let (doc_comment, pair) = unwrap_documented_pair(
808 pair,
809 Rule::documented_enum_member,
810 Rule::enum_member,
811 "enum member",
812 )?;
813 let pair_loc = pair_location(&pair);
814 let span = pair_span(&pair);
815 let inner = pair
816 .into_inner()
817 .next()
818 .ok_or_else(|| ShapeError::ParseError {
819 message: "expected enum member content".to_string(),
820 location: Some(pair_loc.clone()),
821 })?;
822
823 match inner.as_rule() {
824 Rule::enum_variant_unit => {
825 let mut unit_inner = inner.into_inner();
826 let name_pair = unit_inner.next().ok_or_else(|| ShapeError::ParseError {
827 message: "expected enum variant name".to_string(),
828 location: Some(pair_loc.clone()),
829 })?;
830 let name = name_pair.as_str().to_string();
831 let value = if let Some(val_pair) = unit_inner.next() {
832 match val_pair.as_rule() {
833 Rule::string => Some(crate::ast::EnumValue::String(parse_string_literal(
834 val_pair.as_str(),
835 )?)),
836 Rule::number => {
837 let n: f64 =
838 val_pair
839 .as_str()
840 .parse()
841 .map_err(|e| ShapeError::ParseError {
842 message: format!("Invalid enum value number: {}", e),
843 location: Some(pair_loc.clone()),
844 })?;
845 Some(crate::ast::EnumValue::Number(n))
846 }
847 _ => {
848 return Err(ShapeError::ParseError {
849 message: "invalid enum unit value".to_string(),
850 location: Some(pair_loc),
851 });
852 }
853 }
854 } else {
855 None
856 };
857
858 Ok(crate::ast::EnumMember {
859 name,
860 kind: crate::ast::EnumMemberKind::Unit { value },
861 span,
862 doc_comment,
863 })
864 }
865 Rule::enum_variant_tuple => {
866 let mut tuple_inner = inner.into_inner();
867 let name_pair = tuple_inner.next().ok_or_else(|| ShapeError::ParseError {
868 message: "expected enum variant name".to_string(),
869 location: Some(pair_loc.clone()),
870 })?;
871 let name = name_pair.as_str().to_string();
872 let mut fields = Vec::new();
873 for type_pair in tuple_inner {
874 if type_pair.as_rule() == Rule::type_annotation {
875 fields.push(parse_type_annotation(type_pair)?);
876 }
877 }
878 Ok(crate::ast::EnumMember {
879 name,
880 kind: crate::ast::EnumMemberKind::Tuple(fields),
881 span,
882 doc_comment,
883 })
884 }
885 Rule::enum_variant_struct => {
886 let mut struct_inner = inner.into_inner();
887 let name_pair = struct_inner.next().ok_or_else(|| ShapeError::ParseError {
888 message: "expected enum variant name".to_string(),
889 location: Some(pair_loc.clone()),
890 })?;
891 let name = name_pair.as_str().to_string();
892 let mut fields = Vec::new();
893 for part in struct_inner {
894 if part.as_rule() == Rule::object_type_member_list {
895 for field_pair in part.into_inner() {
896 if field_pair.as_rule() == Rule::object_type_member {
897 fields.push(parse_object_type_member(field_pair)?);
898 }
899 }
900 }
901 }
902 Ok(crate::ast::EnumMember {
903 name,
904 kind: crate::ast::EnumMemberKind::Struct(fields),
905 span,
906 doc_comment,
907 })
908 }
909 _ => Err(ShapeError::ParseError {
910 message: format!("unexpected enum member rule: {:?}", inner.as_rule()),
911 location: Some(pair_loc),
912 }),
913 }
914}
915
916pub fn parse_interface_def(pair: Pair<Rule>) -> Result<crate::ast::InterfaceDef> {
920 let pair_loc = pair_location(&pair);
921 let mut inner = pair.into_inner();
922
923 let name_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
924 message: "Missing interface name".to_string(),
925 location: Some(pair_loc.clone()),
926 })?;
927 let name = name_pair.as_str().to_string();
928
929 let mut type_params = None;
930 let mut members = Vec::new();
931
932 for part in inner {
933 match part.as_rule() {
934 Rule::type_params => {
935 type_params = Some(parse_type_params(part)?);
936 }
937 Rule::interface_body => {
938 members = parse_interface_body(part)?;
939 }
940 _ => {}
941 }
942 }
943
944 Ok(crate::ast::InterfaceDef {
945 name,
946 doc_comment: None,
947 type_params,
948 members,
949 })
950}
951
952pub fn parse_trait_def(pair: Pair<Rule>) -> Result<crate::ast::TraitDef> {
959 let pair_loc = pair_location(&pair);
960 let inner = pair.into_inner();
961
962 let mut annotations = Vec::new();
963 let mut type_params = None;
964 let mut super_traits = Vec::new();
965 let mut members = Vec::new();
966 let mut name = String::new();
967
968 for part in inner {
970 match part.as_rule() {
971 Rule::annotations => {
972 annotations = crate::parser::functions::parse_annotations(part)?;
973 }
974 Rule::ident => {
975 if name.is_empty() {
976 name = part.as_str().to_string();
977 }
978 }
979 Rule::type_params => {
980 type_params = Some(parse_type_params(part)?);
981 }
982 Rule::supertrait_list => {
983 for inner_part in part.into_inner() {
984 if inner_part.as_rule() == Rule::optional_type {
985 super_traits.push(parse_type_annotation(inner_part)?);
986 }
987 }
988 }
989 Rule::trait_body => {
990 members = parse_trait_body(part)?;
991 }
992 _ => {}
993 }
994 }
995
996 if name.is_empty() {
997 return Err(ShapeError::ParseError {
998 message: "Missing trait name".to_string(),
999 location: Some(pair_loc),
1000 });
1001 }
1002
1003 Ok(crate::ast::TraitDef {
1004 name,
1005 doc_comment: None,
1006 type_params,
1007 super_traits,
1008 members,
1009 annotations,
1010 })
1011}
1012
1013fn parse_trait_body(pair: Pair<Rule>) -> Result<Vec<crate::ast::TraitMember>> {
1014 let mut members = Vec::new();
1015
1016 for trait_member in pair.into_inner() {
1017 if trait_member.as_rule() != Rule::trait_member {
1018 continue;
1019 }
1020
1021 let mut member_inner = trait_member.into_inner();
1022 let mut doc_comment = None;
1023 let mut inner = member_inner.next().ok_or_else(|| ShapeError::ParseError {
1024 message: "expected trait member".to_string(),
1025 location: None,
1026 })?;
1027
1028 if inner.as_rule() == Rule::doc_comment {
1029 doc_comment = Some(super::docs::parse_doc_comment(inner));
1030 inner = member_inner.next().ok_or_else(|| ShapeError::ParseError {
1031 message: "expected trait member after doc comment".to_string(),
1032 location: None,
1033 })?;
1034 }
1035
1036 if inner.as_rule() == Rule::trait_member_core {
1037 inner = inner
1038 .into_inner()
1039 .next()
1040 .ok_or_else(|| ShapeError::ParseError {
1041 message: "expected trait member".to_string(),
1042 location: None,
1043 })?;
1044 }
1045
1046 match inner.as_rule() {
1047 Rule::associated_type_decl => {
1048 let (name, bounds, span) = parse_associated_type_decl(inner)?;
1049 members.push(crate::ast::TraitMember::AssociatedType {
1050 name,
1051 bounds,
1052 span,
1053 doc_comment,
1054 });
1055 }
1056 Rule::method_def => {
1057 let mut method = parse_method_def_shared(inner)?;
1058 method.doc_comment = doc_comment;
1059 members.push(crate::ast::TraitMember::Default(method));
1060 }
1061 Rule::interface_member | Rule::documented_interface_member => {
1062 let mut im = parse_interface_member(inner)?;
1063 if let Some(doc_comment) = doc_comment {
1064 attach_interface_member_doc_comment(&mut im, doc_comment);
1065 }
1066 members.push(crate::ast::TraitMember::Required(im));
1067 }
1068 _ => {}
1069 }
1070 }
1071
1072 Ok(members)
1073}
1074
1075fn parse_associated_type_decl(pair: Pair<Rule>) -> Result<(String, Vec<TypeAnnotation>, Span)> {
1077 let span = pair_span(&pair);
1078 let mut inner = pair.into_inner();
1079
1080 let name_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
1081 message: "expected associated type name".to_string(),
1082 location: None,
1083 })?;
1084 let name = name_pair.as_str().to_string();
1085
1086 let mut bounds = Vec::new();
1087 for remaining in inner {
1088 if remaining.as_rule() == Rule::trait_bound_list {
1089 for bound_ident in remaining.into_inner() {
1090 if bound_ident.as_rule() == Rule::qualified_ident {
1091 bounds.push(TypeAnnotation::Basic(bound_ident.as_str().to_string()));
1092 }
1093 }
1094 }
1095 }
1096
1097 Ok((name, bounds, span))
1098}
1099
1100pub(crate) fn parse_method_def_shared(pair: Pair<Rule>) -> Result<crate::ast::types::MethodDef> {
1102 use crate::ast::types::MethodDef;
1103
1104 let is_async = pair.as_str().trim_start().starts_with("async");
1106 let span = pair_span(&pair);
1107
1108 let mut md_inner = pair.into_inner();
1109
1110 let name_pair = md_inner.next().ok_or_else(|| ShapeError::ParseError {
1111 message: "Missing method name".to_string(),
1112 location: None,
1113 })?;
1114 let name = name_pair.as_str().to_string();
1115
1116 let mut params = Vec::new();
1117 let mut type_params = None;
1118 let mut when_clause = None;
1119 let mut return_type = None;
1120 let mut body = Vec::new();
1121
1122 for part in md_inner {
1123 match part.as_rule() {
1124 Rule::type_params => {
1125 type_params = Some(parse_type_params(part)?);
1126 }
1127 Rule::function_params => {
1128 for param_pair in part.into_inner() {
1129 if param_pair.as_rule() == Rule::function_param {
1130 params.push(super::functions::parse_function_param(param_pair)?);
1131 }
1132 }
1133 }
1134 Rule::when_clause => {
1135 if let Some(expr_pair) = part.into_inner().next() {
1136 when_clause = Some(Box::new(crate::parser::expressions::parse_expression(
1137 expr_pair,
1138 )?));
1139 }
1140 }
1141 Rule::return_type => {
1142 if let Some(type_pair) = part.into_inner().next() {
1143 return_type = Some(parse_type_annotation(type_pair)?);
1144 }
1145 }
1146 Rule::function_body => {
1147 body = super::statements::parse_statements(part.into_inner())?;
1148 }
1149 _ => {}
1150 }
1151 }
1152
1153 Ok(MethodDef {
1154 name,
1155 span,
1156 declaring_module_path: None,
1157 doc_comment: None,
1158 annotations: Vec::new(),
1159 type_params,
1160 params,
1161 when_clause,
1162 return_type,
1163 body,
1164 is_async,
1165 })
1166}
1167
1168pub(crate) fn parse_documented_method_def_shared(
1169 pair: Pair<Rule>,
1170) -> Result<crate::ast::types::MethodDef> {
1171 if pair.as_rule() == Rule::method_def {
1172 return parse_method_def_shared(pair);
1173 }
1174 assert_eq!(pair.as_rule(), Rule::documented_method_def);
1175 let inner = pair.into_inner();
1176 let mut doc_comment = None;
1177 let mut annotations = Vec::new();
1178 let mut method_pair = None;
1179
1180 for child in inner {
1181 match child.as_rule() {
1182 Rule::doc_comment => {
1183 doc_comment = Some(super::docs::parse_doc_comment(child));
1184 }
1185 Rule::annotations => {
1186 annotations = super::functions::parse_annotations(child)?;
1187 }
1188 Rule::method_def => {
1189 method_pair = Some(child);
1190 }
1191 _ => {}
1192 }
1193 }
1194
1195 let method_pair = method_pair.ok_or_else(|| ShapeError::ParseError {
1196 message: "expected method definition".to_string(),
1197 location: None,
1198 })?;
1199 let mut method = parse_method_def_shared(method_pair)?;
1200 method.doc_comment = doc_comment;
1201 method.annotations = annotations;
1202 Ok(method)
1203}
1204
1205fn parse_interface_body(pair: Pair<Rule>) -> Result<Vec<crate::ast::InterfaceMember>> {
1206 let mut members = Vec::new();
1207 for inner in pair.into_inner() {
1208 if inner.as_rule() == Rule::interface_member_list {
1209 for member in inner.into_inner() {
1210 if matches!(
1211 member.as_rule(),
1212 Rule::documented_interface_member | Rule::interface_member
1213 ) {
1214 members.push(parse_interface_member(member)?);
1215 }
1216 }
1217 }
1218 }
1219 Ok(members)
1220}
1221
1222fn parse_interface_member(pair: Pair<Rule>) -> Result<crate::ast::InterfaceMember> {
1223 let (doc_comment, pair) = unwrap_documented_pair(
1224 pair,
1225 Rule::documented_interface_member,
1226 Rule::interface_member,
1227 "interface member",
1228 )?;
1229 let pair_loc = pair_location(&pair);
1230 let raw = pair.as_str();
1231 let trimmed = raw.trim_start();
1232 let span = pair_span(&pair);
1233
1234 if trimmed.starts_with('[') {
1235 return parse_interface_index_signature(pair, trimmed, doc_comment);
1236 }
1237
1238 let mut inner = pair.into_inner();
1239 let name_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
1240 message: "expected interface member name".to_string(),
1241 location: Some(pair_loc.clone()),
1242 })?;
1243 let name = name_pair.as_str().to_string();
1244
1245 let (optional, is_method) = parse_interface_member_kind(trimmed, &name);
1246
1247 let mut params = Vec::new();
1248 let mut type_annotation = None;
1249 for part in inner {
1250 match part.as_rule() {
1251 Rule::type_param_list => {
1252 params = parse_type_param_list(part)?;
1253 }
1254 Rule::type_annotation => {
1255 type_annotation = Some(parse_type_annotation(part)?);
1256 }
1257 _ => {}
1258 }
1259 }
1260
1261 let type_annotation = type_annotation.ok_or_else(|| ShapeError::ParseError {
1262 message: format!("interface member '{}' missing type annotation", name),
1263 location: Some(pair_loc),
1264 })?;
1265
1266 if is_method {
1267 Ok(crate::ast::InterfaceMember::Method {
1268 name,
1269 optional,
1270 params,
1271 return_type: type_annotation,
1272 is_async: false,
1273 span,
1274 doc_comment,
1275 })
1276 } else {
1277 Ok(crate::ast::InterfaceMember::Property {
1278 name,
1279 optional,
1280 type_annotation,
1281 span,
1282 doc_comment,
1283 })
1284 }
1285}
1286
1287fn parse_interface_member_kind(raw: &str, name: &str) -> (bool, bool) {
1288 let trimmed = raw.trim_start();
1289 let Some(mut rest) = trimmed.strip_prefix(name) else {
1290 return (false, false);
1291 };
1292 rest = rest.trim_start();
1293 let mut optional = false;
1294 if rest.starts_with('?') {
1295 optional = true;
1296 rest = rest[1..].trim_start();
1297 }
1298 let is_method = rest.starts_with('(');
1299 (optional, is_method)
1300}
1301
1302fn parse_interface_index_signature(
1303 pair: Pair<Rule>,
1304 raw: &str,
1305 doc_comment: Option<crate::ast::DocComment>,
1306) -> Result<crate::ast::InterfaceMember> {
1307 let pair_loc = pair_location(&pair);
1308 let span = pair_span(&pair);
1309 let mut inner = pair.into_inner();
1310 let name_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
1311 message: "expected index signature parameter name".to_string(),
1312 location: Some(pair_loc.clone()),
1313 })?;
1314 let param_name = name_pair.as_str().to_string();
1315
1316 let mut return_type = None;
1317 for part in inner {
1318 if part.as_rule() == Rule::type_annotation {
1319 return_type = Some(parse_type_annotation(part)?);
1320 }
1321 }
1322
1323 let return_type = return_type.ok_or_else(|| ShapeError::ParseError {
1324 message: "index signature missing return type".to_string(),
1325 location: Some(pair_loc.clone()),
1326 })?;
1327
1328 let param_type =
1329 parse_index_signature_param_type(raw).ok_or_else(|| ShapeError::ParseError {
1330 message: "index signature missing parameter type".to_string(),
1331 location: Some(pair_loc),
1332 })?;
1333
1334 Ok(crate::ast::InterfaceMember::IndexSignature {
1335 param_name,
1336 param_type,
1337 return_type,
1338 span,
1339 doc_comment,
1340 })
1341}
1342
1343fn attach_interface_member_doc_comment(
1344 member: &mut crate::ast::InterfaceMember,
1345 doc_comment: crate::ast::DocComment,
1346) {
1347 match member {
1348 crate::ast::InterfaceMember::Property {
1349 doc_comment: slot, ..
1350 }
1351 | crate::ast::InterfaceMember::Method {
1352 doc_comment: slot, ..
1353 }
1354 | crate::ast::InterfaceMember::IndexSignature {
1355 doc_comment: slot, ..
1356 } => *slot = Some(doc_comment),
1357 }
1358}
1359
1360fn parse_index_signature_param_type(raw: &str) -> Option<String> {
1361 let trimmed = raw.trim();
1362 let open = trimmed.find('[')?;
1363 let close = trimmed[open + 1..].find(']')? + open + 1;
1364 let inside = trimmed[open + 1..close].trim();
1365 let mut parts = inside.splitn(2, ':');
1366 parts.next()?;
1367 let param_type = parts.next()?.trim();
1368 if param_type == "string" || param_type == "number" {
1369 Some(param_type.to_string())
1370 } else {
1371 None
1372 }
1373}