1use crate::ast::{
9 DataRef, EnumConstructorPayload, Expr, JoinBranch, JoinExpr, JoinKind, RangeKind, Span, Spanned,
10};
11use crate::error::{Result, ShapeError};
12use crate::parser::{Rule, pair_location};
13use pest::iterators::Pair;
14
15use super::super::pair_span;
16
17pub fn parse_expression(pair: Pair<Rule>) -> Result<Expr> {
19 let pair_loc = pair_location(&pair);
20 match pair.as_rule() {
21 Rule::expression => {
22 let inner = pair
23 .into_inner()
24 .next()
25 .ok_or_else(|| ShapeError::ParseError {
26 message: "expected expression content".to_string(),
27 location: Some(pair_loc),
28 })?;
29 parse_expression(inner)
30 }
31 Rule::assignment_expr => super::binary_ops::parse_assignment_expr(pair),
32 Rule::ternary_expr => super::binary_ops::parse_ternary_expr(pair),
33 Rule::null_coalesce_expr => super::binary_ops::parse_null_coalesce_expr(pair),
34 Rule::context_expr => super::binary_ops::parse_context_expr(pair),
35 Rule::or_expr => super::binary_ops::parse_or_expr(pair),
36 Rule::range_expr => super::binary_ops::parse_range_expr(pair),
37 _ => Err(ShapeError::ParseError {
38 message: format!("expected expression, got {:?}", pair.as_rule()),
39 location: Some(pair_loc),
40 }),
41 }
42}
43
44pub fn parse_postfix_expr(pair: Pair<Rule>) -> Result<Expr> {
46 let pair_loc = pair_location(&pair);
47 let mut inner = pair.into_inner();
48 let primary_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
49 message: "expected primary expression".to_string(),
50 location: Some(pair_loc),
51 })?;
52 let mut expr = parse_primary_expr(primary_pair)?;
53
54 let postfix_ops: Vec<_> = inner.collect();
56 let mut i = 0;
57
58 while i < postfix_ops.len() {
59 let postfix = &postfix_ops[i];
60 match postfix.as_rule() {
61 Rule::property_access | Rule::optional_property_access => {
62 let is_optional = postfix.as_rule() == Rule::optional_property_access;
63 let postfix_loc = pair_location(postfix);
64 let property = postfix
65 .clone()
66 .into_inner()
67 .next()
68 .ok_or_else(|| ShapeError::ParseError {
69 message: "expected property name after '.'".to_string(),
70 location: Some(postfix_loc),
71 })?
72 .as_str()
73 .to_string();
74
75 let full_span = Span::new(expr.span().start, pair_span(postfix).end);
76
77 if i + 1 < postfix_ops.len() && postfix_ops[i + 1].as_rule() == Rule::function_call
79 {
80 let (args, named_args) =
81 super::functions::parse_arg_list(postfix_ops[i + 1].clone())?;
82 expr = Expr::MethodCall {
83 receiver: Box::new(expr),
84 method: property,
85 args,
86 named_args,
87 optional: is_optional,
88 span: full_span,
89 };
90 i += 2; } else {
92 expr = Expr::PropertyAccess {
93 object: Box::new(expr),
94 property,
95 optional: is_optional,
96 span: full_span,
97 };
98 i += 1;
99 }
100 }
101 Rule::index_access => {
102 let postfix_loc = pair_location(postfix);
103 let postfix_span = pair_span(postfix);
104 if let Expr::Identifier(ref id, _) = expr {
106 if id == "candle" {
107 let index_expr = postfix.clone().into_inner().next().ok_or_else(|| {
108 ShapeError::ParseError {
109 message: "expected index expression in data access".to_string(),
110 location: Some(postfix_loc.clone()),
111 }
112 })?;
113 let (index, timeframe) = super::data_refs::parse_index_expr(index_expr)?;
114 expr = Expr::DataRef(DataRef { index, timeframe }, postfix_span);
115 i += 1;
116 continue;
117 }
118 }
119 if let Expr::DataRef(ref mut data_ref, _) = expr {
121 let index_expr = postfix.clone().into_inner().next().ok_or_else(|| {
122 ShapeError::ParseError {
123 message: "expected index expression in data access".to_string(),
124 location: Some(postfix_loc.clone()),
125 }
126 })?;
127 let (index, timeframe_override) =
128 super::data_refs::parse_index_expr(index_expr)?;
129 data_ref.index = index;
130 if timeframe_override.is_some() {
132 data_ref.timeframe = timeframe_override;
133 }
134 i += 1;
135 continue;
136 }
137 let index_expr_pair =
139 postfix
140 .clone()
141 .into_inner()
142 .next()
143 .ok_or_else(|| ShapeError::ParseError {
144 message: "expected index expression".to_string(),
145 location: Some(postfix_loc),
146 })?;
147 let (index_expr, end_expr) =
148 super::data_refs::parse_index_expr_general(index_expr_pair)?;
149 expr = Expr::IndexAccess {
150 object: Box::new(expr),
151 index: Box::new(index_expr),
152 end_index: end_expr.map(Box::new),
153 span: postfix_span,
154 };
155 i += 1;
156 }
157 Rule::function_call => {
158 let (args, named_args) = super::functions::parse_arg_list(postfix.clone())?;
159 if let Expr::Identifier(name, _) = expr {
160 expr = Expr::FunctionCall {
161 name,
162 args,
163 named_args,
164 span: pair_span(postfix),
165 };
166 } else {
167 let full_span = Span::new(expr.span().start, pair_span(postfix).end);
169 expr = Expr::MethodCall {
170 receiver: Box::new(expr),
171 method: "__call__".to_string(),
172 args,
173 named_args,
174 optional: false,
175 span: full_span,
176 };
177 }
178 i += 1;
179 }
180 Rule::type_assertion_suffix => {
181 let mut inner = postfix.clone().into_inner();
182
183 let first = inner.next().ok_or_else(|| ShapeError::ParseError {
185 message: "Type assertion missing type annotation".to_string(),
186 location: None,
187 })?;
188 let type_pair = if first.as_rule() == Rule::as_keyword {
189 inner.next().ok_or_else(|| ShapeError::ParseError {
190 message: "Type assertion missing type annotation after 'as'".to_string(),
191 location: None,
192 })?
193 } else {
194 first
195 };
196 let type_annotation = crate::parser::parse_type_annotation(type_pair)?;
197
198 let meta_param_overrides = if let Some(overrides_pair) = inner.next() {
200 if overrides_pair.as_rule() == Rule::comptime_field_overrides {
201 Some(crate::parser::types::parse_comptime_field_overrides(
202 overrides_pair,
203 )?)
204 } else {
205 None
206 }
207 } else {
208 None
209 };
210
211 expr = Expr::TypeAssertion {
212 expr: Box::new(expr),
213 type_annotation,
214 meta_param_overrides,
215 span: pair_span(postfix),
216 };
217 i += 1;
218 }
219 Rule::using_impl_suffix => {
220 let impl_name = postfix
221 .clone()
222 .into_inner()
223 .next()
224 .ok_or_else(|| ShapeError::ParseError {
225 message: "Missing impl name after 'using'".to_string(),
226 location: Some(pair_location(postfix)),
227 })?
228 .as_str()
229 .to_string();
230 let full_span = Span::new(expr.span().start, pair_span(postfix).end);
231 expr = Expr::UsingImpl {
232 expr: Box::new(expr),
233 impl_name,
234 span: full_span,
235 };
236 i += 1;
237 }
238 Rule::try_operator => {
239 expr = Expr::TryOperator(Box::new(expr), pair_span(postfix));
241 i += 1;
242 }
243 _ => {
244 return Err(ShapeError::ParseError {
245 message: format!("Unexpected postfix operator: {:?}", postfix.as_rule()),
246 location: None,
247 });
248 }
249 }
250 }
251
252 Ok(expr)
253}
254
255pub fn parse_primary_expr(pair: Pair<Rule>) -> Result<Expr> {
257 let pair_loc = pair_location(&pair);
258 match pair.as_rule() {
260 Rule::primary_expr => {
261 let inner_pairs: Vec<_> = pair.clone().into_inner().collect();
263 if inner_pairs.is_empty() {
264 return Err(ShapeError::ParseError {
266 message: "empty primary expression".to_string(),
267 location: Some(pair_loc),
268 });
269 }
270 let first = inner_pairs
271 .into_iter()
272 .next()
273 .ok_or_else(|| ShapeError::ParseError {
274 message: "expected primary expression content".to_string(),
275 location: Some(pair_loc),
276 })?;
277 parse_primary_expr_inner(first)
278 }
279 _ => parse_primary_expr_inner(pair),
280 }
281}
282
283fn parse_primary_expr_inner(pair: Pair<Rule>) -> Result<Expr> {
285 let span = pair_span(&pair);
286 let pair_loc = pair_location(&pair);
287
288 match pair.as_rule() {
289 Rule::unit_literal => Ok(Expr::Literal(crate::ast::Literal::Unit, span)),
290 Rule::literal => super::literals::parse_literal(pair),
291 Rule::array_literal => super::literals::parse_array_literal(pair),
292 Rule::data_ref => super::data_refs::parse_data_ref(pair),
293 Rule::time_ref => Ok(Expr::TimeRef(super::temporal::parse_time_ref(pair)?, span)),
294 Rule::datetime_expr => Ok(Expr::DateTime(
295 super::temporal::parse_datetime_expr(pair)?,
296 span,
297 )),
298 Rule::pattern_name => {
299 let name_pair = pair
300 .into_inner()
301 .next()
302 .ok_or_else(|| ShapeError::ParseError {
303 message: "expected pattern name".to_string(),
304 location: Some(pair_loc),
305 })?;
306 Ok(Expr::PatternRef(name_pair.as_str().to_string(), span))
307 }
308 Rule::qualified_function_call_expr => parse_qualified_function_call_expr(pair),
309 Rule::enum_constructor_expr => parse_enum_constructor_expr(pair),
310 Rule::ident => Ok(Expr::Identifier(pair.as_str().to_string(), span)),
311 Rule::expression => parse_expression(pair),
312 Rule::temporal_nav => super::temporal::parse_temporal_nav(pair),
313 Rule::timeframe_expr => super::temporal::parse_timeframe_expr(pair),
314 Rule::async_let_expr => super::control_flow::parse_async_let_expr(pair),
315 Rule::async_scope_expr => super::control_flow::parse_async_scope_expr(pair),
316 Rule::if_expr => super::control_flow::parse_if_expr(pair),
317 Rule::while_expr => super::control_flow::parse_while_expr(pair),
318 Rule::for_expr => super::control_flow::parse_for_expr(pair),
319 Rule::loop_expr => super::control_flow::parse_loop_expr(pair),
320 Rule::let_expr => super::control_flow::parse_let_expr(pair),
321 Rule::match_expr => super::control_flow::parse_match_expr(pair),
322 Rule::break_expr => super::control_flow::parse_break_expr(pair),
323 Rule::continue_expr => Ok(Expr::Continue(span)),
324 Rule::return_expr => super::control_flow::parse_return_expr(pair),
325 Rule::block_expr => super::control_flow::parse_block_expr(pair),
326 Rule::object_literal => super::literals::parse_object_literal(pair),
327 Rule::function_expr => super::functions::parse_function_expr(pair),
328 Rule::some_expr => parse_some_expr(pair),
329 Rule::duration => super::temporal::parse_duration(pair),
330 Rule::primary_expr => parse_primary_expr(pair),
332 Rule::postfix_expr => parse_postfix_expr(pair),
334 Rule::list_comprehension => super::comprehensions::parse_list_comprehension(pair),
335 Rule::await_expr => parse_await_expr(pair),
336 Rule::struct_literal => parse_struct_literal(pair),
337 Rule::from_query_expr => super::control_flow::parse_from_query_expr(pair),
338 Rule::comptime_for_expr => parse_comptime_for_expr(pair),
339 Rule::comptime_block => parse_comptime_block(pair),
340 Rule::annotated_expr => parse_annotated_expr(pair),
341 Rule::datetime_range => {
342 let (start, end) = super::temporal::parse_datetime_range(pair)?;
344 match end {
345 Some(end_expr) => Ok(Expr::Range {
346 start: Some(Box::new(start)),
347 end: Some(Box::new(end_expr)),
348 kind: RangeKind::Inclusive, span,
350 }),
351 None => Ok(start),
352 }
353 }
354 _ => Err(ShapeError::ParseError {
355 message: format!("Unexpected primary expression: {:?}", pair.as_rule()),
356 location: None,
357 }),
358 }
359}
360
361fn parse_qualified_function_call_expr(pair: Pair<Rule>) -> Result<Expr> {
362 let span = pair_span(&pair);
363 let pair_loc = pair_location(&pair);
364 let mut inner = pair.into_inner();
365
366 let path_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
367 message: "expected qualified call target".to_string(),
368 location: Some(pair_loc.clone()),
369 })?;
370 let (namespace, function) = parse_enum_variant_path(path_pair)?;
371
372 let call_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
373 message: "expected argument list after qualified call target".to_string(),
374 location: Some(pair_loc),
375 })?;
376 let (args, named_args) = super::functions::parse_arg_list(call_pair)?;
377
378 Ok(Expr::QualifiedFunctionCall {
379 namespace,
380 function,
381 args,
382 named_args,
383 span,
384 })
385}
386
387fn parse_some_expr(pair: Pair<Rule>) -> Result<Expr> {
389 let span = pair_span(&pair);
390 let pair_loc = pair_location(&pair);
391 let inner = pair
392 .into_inner()
393 .next()
394 .ok_or_else(|| ShapeError::ParseError {
395 message: "expected expression in Some()".to_string(),
396 location: Some(pair_loc),
397 })?;
398 let inner_expr = parse_expression(inner)?;
399 Ok(Expr::FunctionCall {
400 name: "Some".to_string(),
401 args: vec![inner_expr],
402 named_args: vec![],
403 span,
404 })
405}
406
407fn parse_await_expr(pair: Pair<Rule>) -> Result<Expr> {
409 let span = pair_span(&pair);
410 let pair_loc = pair_location(&pair);
411 let inner_pairs: Vec<_> = pair
413 .into_inner()
414 .filter(|p| p.as_rule() != Rule::await_keyword)
415 .collect();
416
417 if inner_pairs.is_empty() {
418 return Err(ShapeError::ParseError {
419 message: "expected expression after 'await'".to_string(),
420 location: Some(pair_loc),
421 });
422 }
423
424 let first = &inner_pairs[0];
426 match first.as_rule() {
427 Rule::join_expr => {
428 let join = parse_join_expr(first.clone())?;
430 let join_span = pair_span(first);
431 Ok(Expr::Await(
432 Box::new(Expr::Join(Box::new(join), join_span)),
433 span,
434 ))
435 }
436 Rule::annotation => {
437 let mut annotations = Vec::new();
439 let mut target_pair = None;
440
441 for p in &inner_pairs {
442 match p.as_rule() {
443 Rule::annotation => {
444 annotations.push(crate::parser::functions::parse_annotation(p.clone())?);
445 }
446 Rule::postfix_expr => {
447 target_pair = Some(p.clone());
448 }
449 _ => {}
450 }
451 }
452
453 let target = target_pair.ok_or_else(|| ShapeError::ParseError {
454 message: "expected expression after annotations in await".to_string(),
455 location: Some(pair_loc),
456 })?;
457
458 let mut expr = parse_postfix_expr(target)?;
459
460 for annotation in annotations.into_iter().rev() {
462 let anno_span = Span::new(annotation.span.start, expr.span().end);
463 expr = Expr::Annotated {
464 annotation,
465 target: Box::new(expr),
466 span: anno_span,
467 };
468 }
469
470 Ok(Expr::Await(Box::new(expr), span))
471 }
472 Rule::postfix_expr => {
473 let expr = parse_postfix_expr(first.clone())?;
475 Ok(Expr::Await(Box::new(expr), span))
476 }
477 _ => Err(ShapeError::ParseError {
478 message: format!(
479 "unexpected token in await expression: {:?}",
480 first.as_rule()
481 ),
482 location: Some(pair_loc),
483 }),
484 }
485}
486
487fn parse_join_expr(pair: Pair<Rule>) -> Result<JoinExpr> {
489 let span = pair_span(&pair);
490 let pair_loc = pair_location(&pair);
491 let mut inner = pair.into_inner();
492
493 let kind_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
495 message: "expected join strategy (all, race, any, settle)".to_string(),
496 location: Some(pair_loc.clone()),
497 })?;
498 let kind = match kind_pair.as_str() {
499 "all" => JoinKind::All,
500 "race" => JoinKind::Race,
501 "any" => JoinKind::Any,
502 "settle" => JoinKind::Settle,
503 other => {
504 return Err(ShapeError::ParseError {
505 message: format!(
506 "unknown join strategy: '{}'. Expected all, race, any, or settle",
507 other
508 ),
509 location: Some(pair_location(&kind_pair)),
510 });
511 }
512 };
513
514 let branch_list_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
516 message: "expected join branches".to_string(),
517 location: Some(pair_loc),
518 })?;
519
520 let mut branches = Vec::new();
521 for branch_pair in branch_list_pair.into_inner() {
522 if branch_pair.as_rule() == Rule::join_branch {
523 branches.push(parse_join_branch(branch_pair)?);
524 }
525 }
526
527 Ok(JoinExpr {
528 kind,
529 branches,
530 span,
531 })
532}
533
534fn parse_join_branch(pair: Pair<Rule>) -> Result<JoinBranch> {
536 let inner_pairs: Vec<_> = pair.into_inner().collect();
537
538 let mut annotations = Vec::new();
539 let mut label = None;
540 let mut expr = None;
541
542 let mut i = 0;
550
551 while i < inner_pairs.len() && inner_pairs[i].as_rule() == Rule::annotation {
553 annotations.push(crate::parser::functions::parse_annotation(
554 inner_pairs[i].clone(),
555 )?);
556 i += 1;
557 }
558
559 if i < inner_pairs.len() && inner_pairs[i].as_rule() == Rule::ident {
561 if i + 1 < inner_pairs.len() && inner_pairs[i + 1].as_rule() == Rule::expression {
566 label = Some(inner_pairs[i].as_str().to_string());
567 i += 1;
568 expr = Some(parse_expression(inner_pairs[i].clone())?);
569 } else {
570 expr = Some(parse_expression(inner_pairs[i].clone())?);
572 }
573 } else if i < inner_pairs.len() {
574 expr = Some(parse_expression(inner_pairs[i].clone())?);
575 }
576
577 let expr = expr.ok_or_else(|| ShapeError::ParseError {
578 message: "expected expression in join branch".to_string(),
579 location: None,
580 })?;
581
582 Ok(JoinBranch {
583 label,
584 expr,
585 annotations,
586 })
587}
588
589fn parse_struct_literal(pair: Pair<Rule>) -> Result<Expr> {
594 let span = pair_span(&pair);
595 let pair_loc = pair_location(&pair);
596 let mut inner = pair.into_inner();
597
598 let name_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
599 message: "expected struct type name".to_string(),
600 location: Some(pair_loc.clone()),
601 })?;
602 let type_name = name_pair.as_str().to_string();
603
604 let mut fields = Vec::new();
605
606 if let Some(fields_pair) = inner.next() {
608 if fields_pair.as_rule() == Rule::object_fields {
609 for field_item_pair in fields_pair.into_inner() {
610 if field_item_pair.as_rule() != Rule::object_field_item {
611 continue;
612 }
613 let field_item_loc = pair_location(&field_item_pair);
614 let field_item_inner =
615 field_item_pair
616 .into_inner()
617 .next()
618 .ok_or_else(|| ShapeError::ParseError {
619 message: "expected struct field content".to_string(),
620 location: Some(field_item_loc.clone()),
621 })?;
622 match field_item_inner.as_rule() {
623 Rule::object_field => {
624 let mut field_inner = field_item_inner.into_inner();
625 let field_kind =
626 field_inner.next().ok_or_else(|| ShapeError::ParseError {
627 message: "expected struct field content".to_string(),
628 location: Some(field_item_loc.clone()),
629 })?;
630 match field_kind.as_rule() {
631 Rule::object_value_field => {
632 let mut value_inner = field_kind.into_inner();
633 let key_pair =
634 value_inner.next().ok_or_else(|| ShapeError::ParseError {
635 message: "expected struct field key".to_string(),
636 location: Some(field_item_loc.clone()),
637 })?;
638 let key_pair = if key_pair.as_rule() == Rule::object_field_name {
639 key_pair.into_inner().next().ok_or_else(|| {
640 ShapeError::ParseError {
641 message: "expected struct field key".to_string(),
642 location: Some(field_item_loc.clone()),
643 }
644 })?
645 } else {
646 key_pair
647 };
648 let key = key_pair.as_str().to_string();
649 let value_pair =
650 value_inner.next().ok_or_else(|| ShapeError::ParseError {
651 message: format!(
652 "expected value for struct field '{}'",
653 key
654 ),
655 location: Some(field_item_loc),
656 })?;
657 let value = parse_expression(value_pair)?;
658 fields.push((key, value));
659 }
660 _ => {
661 return Err(ShapeError::ParseError {
662 message: "typed fields and spreads are not supported in struct literals".to_string(),
663 location: Some(field_item_loc),
664 });
665 }
666 }
667 }
668 Rule::object_spread => {
669 return Err(ShapeError::ParseError {
670 message: "spread is not supported in struct literals".to_string(),
671 location: Some(field_item_loc),
672 });
673 }
674 _ => {}
675 }
676 }
677 }
678 }
679
680 Ok(Expr::StructLiteral {
681 type_name: type_name.into(),
682 fields,
683 span,
684 })
685}
686
687fn parse_enum_constructor_expr(pair: Pair<Rule>) -> Result<Expr> {
688 let span = pair_span(&pair);
689 let pair_loc = pair_location(&pair);
690 let mut inner = pair.into_inner();
691
692 let path_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
693 message: "expected enum variant path".to_string(),
694 location: Some(pair_loc.clone()),
695 })?;
696 let (enum_name, variant) = parse_enum_variant_path(path_pair)?;
697
698 let payload = if let Some(payload_pair) = inner.next() {
699 match payload_pair.as_rule() {
700 Rule::enum_tuple_payload => {
701 let (args, named_args) = super::functions::parse_arg_list(payload_pair)?;
702 if !named_args.is_empty() {
703 return Err(ShapeError::ParseError {
704 message: "named arguments are not allowed in enum tuple constructors"
705 .to_string(),
706 location: Some(pair_loc),
707 });
708 }
709 EnumConstructorPayload::Tuple(args)
710 }
711 Rule::enum_struct_payload => {
712 let fields = parse_enum_struct_payload(payload_pair)?;
713 EnumConstructorPayload::Struct(fields)
714 }
715 other => {
716 return Err(ShapeError::ParseError {
717 message: format!("unexpected enum constructor payload: {:?}", other),
718 location: Some(pair_loc),
719 });
720 }
721 }
722 } else {
723 EnumConstructorPayload::Unit
724 };
725
726 Ok(Expr::EnumConstructor {
727 enum_name: enum_name.into(),
728 variant,
729 payload,
730 span,
731 })
732}
733
734fn parse_enum_variant_path(pair: Pair<Rule>) -> Result<(String, String)> {
735 let pair_loc = pair_location(&pair);
736 let segments: Vec<&str> = pair
737 .into_inner()
738 .filter(|p| p.as_rule() == Rule::ident || p.as_rule() == Rule::variant_ident)
739 .map(|p| p.as_str())
740 .collect();
741 if segments.len() < 2 {
742 return Err(ShapeError::ParseError {
743 message: "expected at least Enum::Variant in path".to_string(),
744 location: Some(pair_loc),
745 });
746 }
747 let variant = segments.last().unwrap().to_string();
748 let enum_path = segments[..segments.len() - 1].join("::");
749 Ok((enum_path, variant))
750}
751
752fn parse_enum_struct_payload(pair: Pair<Rule>) -> Result<Vec<(String, Expr)>> {
753 let mut fields = Vec::new();
754
755 for inner in pair.into_inner() {
756 if inner.as_rule() != Rule::object_fields {
757 continue;
758 }
759 for field_item_pair in inner.into_inner() {
760 if field_item_pair.as_rule() != Rule::object_field_item {
761 continue;
762 }
763 let field_item_loc = pair_location(&field_item_pair);
764 let field_item_inner =
765 field_item_pair
766 .into_inner()
767 .next()
768 .ok_or_else(|| ShapeError::ParseError {
769 message: "expected enum struct field content".to_string(),
770 location: Some(field_item_loc.clone()),
771 })?;
772 match field_item_inner.as_rule() {
773 Rule::object_field => {
774 let mut field_inner = field_item_inner.into_inner();
775 let field_kind = field_inner.next().ok_or_else(|| ShapeError::ParseError {
776 message: "expected enum struct field content".to_string(),
777 location: Some(field_item_loc.clone()),
778 })?;
779 match field_kind.as_rule() {
780 Rule::object_value_field => {
781 let mut value_inner = field_kind.into_inner();
782 let key_pair =
783 value_inner.next().ok_or_else(|| ShapeError::ParseError {
784 message: "expected enum struct field key".to_string(),
785 location: Some(field_item_loc.clone()),
786 })?;
787 let key_pair = if key_pair.as_rule() == Rule::object_field_name {
788 key_pair.into_inner().next().ok_or_else(|| {
789 ShapeError::ParseError {
790 message: "expected enum struct field key".to_string(),
791 location: Some(field_item_loc.clone()),
792 }
793 })?
794 } else {
795 key_pair
796 };
797 let key = match key_pair.as_rule() {
798 Rule::ident | Rule::keyword => key_pair.as_str().to_string(),
799 _ => {
800 return Err(ShapeError::ParseError {
801 message: "unexpected enum struct field key".to_string(),
802 location: Some(pair_location(&key_pair)),
803 });
804 }
805 };
806 let value_pair =
807 value_inner.next().ok_or_else(|| ShapeError::ParseError {
808 message: format!("expected value for enum field '{}'", key),
809 location: Some(field_item_loc),
810 })?;
811 let value = parse_expression(value_pair)?;
812 fields.push((key, value));
813 }
814 Rule::object_typed_field => {
815 return Err(ShapeError::ParseError {
816 message: "typed fields are not allowed in enum constructors"
817 .to_string(),
818 location: Some(field_item_loc),
819 });
820 }
821 other => {
822 return Err(ShapeError::ParseError {
823 message: format!("unexpected enum field kind: {:?}", other),
824 location: Some(field_item_loc),
825 });
826 }
827 }
828 }
829 Rule::object_spread => {
830 return Err(ShapeError::ParseError {
831 message: "spread fields are not allowed in enum constructors".to_string(),
832 location: Some(field_item_loc),
833 });
834 }
835 other => {
836 return Err(ShapeError::ParseError {
837 message: format!("unexpected enum struct field: {:?}", other),
838 location: Some(field_item_loc),
839 });
840 }
841 }
842 }
843 }
844
845 Ok(fields)
846}
847
848fn parse_comptime_block(pair: Pair<Rule>) -> Result<Expr> {
853 let span = pair_span(&pair);
854 let pair_loc = pair_location(&pair);
855 let block_pair = pair
856 .into_inner()
857 .next()
858 .ok_or_else(|| ShapeError::ParseError {
859 message: "expected block after 'comptime'".to_string(),
860 location: Some(pair_loc),
861 })?;
862
863 let block_expr = super::control_flow::parse_block_expr(block_pair)?;
865 let stmts = block_items_to_statements(block_expr, span);
866 Ok(Expr::Comptime(stmts, span))
867}
868
869fn parse_comptime_for_expr(pair: Pair<Rule>) -> Result<Expr> {
874 use crate::ast::expr_helpers::ComptimeForExpr;
875 use crate::parser::statements::parse_statement;
876
877 let span = pair_span(&pair);
878 let pair_loc = pair_location(&pair);
879 let mut inner = pair.into_inner();
880
881 let var_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
883 message: "expected loop variable in comptime for".to_string(),
884 location: Some(pair_loc.clone()),
885 })?;
886 let variable = var_pair.as_str().to_string();
887
888 let iter_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
890 message: "expected iterable expression in comptime for".to_string(),
891 location: Some(pair_loc),
892 })?;
893 let iterable = parse_postfix_expr(iter_pair)?;
894
895 let mut body = Vec::new();
897 for stmt_pair in inner {
898 if stmt_pair.as_rule() == Rule::statement {
899 body.push(parse_statement(stmt_pair)?);
900 }
901 }
902
903 Ok(Expr::ComptimeFor(
904 Box::new(ComptimeForExpr {
905 variable,
906 iterable: Box::new(iterable),
907 body,
908 }),
909 span,
910 ))
911}
912
913pub(crate) fn block_items_to_statements(
917 block_expr: Expr,
918 span: Span,
919) -> Vec<crate::ast::Statement> {
920 use crate::ast::{BlockItem, Statement};
921
922 let items = match block_expr {
923 Expr::Block(block, _) => block.items,
924 other => return vec![Statement::Return(Some(other), span)],
926 };
927
928 let mut stmts = Vec::new();
929 let len = items.len();
930 for (i, item) in items.into_iter().enumerate() {
931 let is_last = i == len - 1;
932 match item {
933 BlockItem::VariableDecl(decl) => {
934 stmts.push(Statement::VariableDecl(decl, span));
935 }
936 BlockItem::Assignment(assign) => {
937 stmts.push(Statement::Assignment(assign, span));
938 }
939 BlockItem::Statement(stmt) => {
940 stmts.push(stmt);
941 }
942 BlockItem::Expression(expr) => {
943 if is_last {
944 stmts.push(Statement::Return(Some(expr), span));
946 } else {
947 stmts.push(Statement::Expression(expr, span));
948 }
949 }
950 }
951 }
952 stmts
953}
954
955fn parse_annotated_expr(pair: Pair<Rule>) -> Result<Expr> {
963 let span = pair_span(&pair);
964 let pair_loc = pair_location(&pair);
965 let inner_pairs: Vec<_> = pair.into_inner().collect();
966
967 if inner_pairs.is_empty() {
968 return Err(ShapeError::ParseError {
969 message: "expected annotations and expression".to_string(),
970 location: Some(pair_loc),
971 });
972 }
973
974 let mut annotations = Vec::new();
976 let mut target_pair = None;
977 for p in &inner_pairs {
978 match p.as_rule() {
979 Rule::annotation => {
980 annotations.push(crate::parser::functions::parse_annotation(p.clone())?);
981 }
982 _ => {
983 target_pair = Some(p.clone());
984 }
985 }
986 }
987
988 let target_pair = target_pair.ok_or_else(|| ShapeError::ParseError {
989 message: "expected expression after annotations".to_string(),
990 location: Some(pair_loc),
991 })?;
992 let target = parse_postfix_expr(target_pair)?;
993
994 let mut result = target;
997 for annotation in annotations.into_iter().rev() {
998 result = Expr::Annotated {
999 annotation,
1000 target: Box::new(result),
1001 span,
1002 };
1003 }
1004
1005 Ok(result)
1006}
1007
1008