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 {
85 receiver: Box::new(expr),
86 method: property,
87 args,
88 named_args,
89 span: full_span,
90 };
91 i += 2; } else {
93 expr = Expr::PropertyAccess {
94 object: Box::new(expr),
95 property,
96 optional: is_optional,
97 span: full_span,
98 };
99 i += 1;
100 }
101 }
102 Rule::index_access => {
103 let postfix_loc = pair_location(postfix);
104 let postfix_span = pair_span(postfix);
105 if let Expr::Identifier(ref id, _) = expr {
107 if id == "candle" {
108 let index_expr = postfix.clone().into_inner().next().ok_or_else(|| {
109 ShapeError::ParseError {
110 message: "expected index expression in data access".to_string(),
111 location: Some(postfix_loc.clone()),
112 }
113 })?;
114 let (index, timeframe) = super::data_refs::parse_index_expr(index_expr)?;
115 expr = Expr::DataRef(DataRef { index, timeframe }, postfix_span);
116 i += 1;
117 continue;
118 }
119 }
120 if let Expr::DataRef(ref mut data_ref, _) = expr {
122 let index_expr = postfix.clone().into_inner().next().ok_or_else(|| {
123 ShapeError::ParseError {
124 message: "expected index expression in data access".to_string(),
125 location: Some(postfix_loc.clone()),
126 }
127 })?;
128 let (index, timeframe_override) =
129 super::data_refs::parse_index_expr(index_expr)?;
130 data_ref.index = index;
131 if timeframe_override.is_some() {
133 data_ref.timeframe = timeframe_override;
134 }
135 i += 1;
136 continue;
137 }
138 let index_expr_pair =
140 postfix
141 .clone()
142 .into_inner()
143 .next()
144 .ok_or_else(|| ShapeError::ParseError {
145 message: "expected index expression".to_string(),
146 location: Some(postfix_loc),
147 })?;
148 let (index_expr, end_expr) =
149 super::data_refs::parse_index_expr_general(index_expr_pair)?;
150 expr = Expr::IndexAccess {
151 object: Box::new(expr),
152 index: Box::new(index_expr),
153 end_index: end_expr.map(Box::new),
154 span: postfix_span,
155 };
156 i += 1;
157 }
158 Rule::function_call => {
159 let (args, named_args) = super::functions::parse_arg_list(postfix.clone())?;
160 if let Expr::Identifier(name, _) = expr {
161 expr = Expr::FunctionCall {
162 name,
163 args,
164 named_args,
165 span: pair_span(postfix),
166 };
167 } else {
168 let full_span = Span::new(expr.span().start, pair_span(postfix).end);
170 expr = Expr::MethodCall {
171 receiver: Box::new(expr),
172 method: "__call__".to_string(),
173 args,
174 named_args,
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::enum_constructor_expr => parse_enum_constructor_expr(pair),
309 Rule::ident => Ok(Expr::Identifier(pair.as_str().to_string(), span)),
310 Rule::expression => parse_expression(pair),
311 Rule::temporal_nav => super::temporal::parse_temporal_nav(pair),
312 Rule::timeframe_expr => super::temporal::parse_timeframe_expr(pair),
313 Rule::async_let_expr => super::control_flow::parse_async_let_expr(pair),
314 Rule::async_scope_expr => super::control_flow::parse_async_scope_expr(pair),
315 Rule::if_expr => super::control_flow::parse_if_expr(pair),
316 Rule::while_expr => super::control_flow::parse_while_expr(pair),
317 Rule::for_expr => super::control_flow::parse_for_expr(pair),
318 Rule::loop_expr => super::control_flow::parse_loop_expr(pair),
319 Rule::let_expr => super::control_flow::parse_let_expr(pair),
320 Rule::match_expr => super::control_flow::parse_match_expr(pair),
321 Rule::break_expr => super::control_flow::parse_break_expr(pair),
322 Rule::continue_expr => Ok(Expr::Continue(span)),
323 Rule::return_expr => super::control_flow::parse_return_expr(pair),
324 Rule::block_expr => super::control_flow::parse_block_expr(pair),
325 Rule::object_literal => super::literals::parse_object_literal(pair),
326 Rule::function_expr => super::functions::parse_function_expr(pair),
327 Rule::some_expr => parse_some_expr(pair),
328 Rule::duration => super::temporal::parse_duration(pair),
329 Rule::primary_expr => parse_primary_expr(pair),
331 Rule::postfix_expr => parse_postfix_expr(pair),
333 Rule::list_comprehension => super::comprehensions::parse_list_comprehension(pair),
334 Rule::await_expr => parse_await_expr(pair),
335 Rule::struct_literal => parse_struct_literal(pair),
336 Rule::from_query_expr => super::control_flow::parse_from_query_expr(pair),
337 Rule::comptime_for_expr => parse_comptime_for_expr(pair),
338 Rule::comptime_block => parse_comptime_block(pair),
339 Rule::annotated_expr => parse_annotated_expr(pair),
340 Rule::datetime_range => {
341 let (start, end) = super::temporal::parse_datetime_range(pair)?;
343 match end {
344 Some(end_expr) => Ok(Expr::Range {
345 start: Some(Box::new(start)),
346 end: Some(Box::new(end_expr)),
347 kind: RangeKind::Inclusive, span,
349 }),
350 None => Ok(start),
351 }
352 }
353 _ => Err(ShapeError::ParseError {
354 message: format!("Unexpected primary expression: {:?}", pair.as_rule()),
355 location: None,
356 }),
357 }
358}
359
360fn parse_some_expr(pair: Pair<Rule>) -> Result<Expr> {
362 let span = pair_span(&pair);
363 let pair_loc = pair_location(&pair);
364 let inner = pair
365 .into_inner()
366 .next()
367 .ok_or_else(|| ShapeError::ParseError {
368 message: "expected expression in Some()".to_string(),
369 location: Some(pair_loc),
370 })?;
371 let inner_expr = parse_expression(inner)?;
372 Ok(Expr::FunctionCall {
373 name: "Some".to_string(),
374 args: vec![inner_expr],
375 named_args: vec![],
376 span,
377 })
378}
379
380fn parse_await_expr(pair: Pair<Rule>) -> Result<Expr> {
382 let span = pair_span(&pair);
383 let pair_loc = pair_location(&pair);
384 let inner_pairs: Vec<_> = pair
386 .into_inner()
387 .filter(|p| p.as_rule() != Rule::await_keyword)
388 .collect();
389
390 if inner_pairs.is_empty() {
391 return Err(ShapeError::ParseError {
392 message: "expected expression after 'await'".to_string(),
393 location: Some(pair_loc),
394 });
395 }
396
397 let first = &inner_pairs[0];
399 match first.as_rule() {
400 Rule::join_expr => {
401 let join = parse_join_expr(first.clone())?;
403 let join_span = pair_span(first);
404 Ok(Expr::Await(
405 Box::new(Expr::Join(Box::new(join), join_span)),
406 span,
407 ))
408 }
409 Rule::annotation => {
410 let mut annotations = Vec::new();
412 let mut target_pair = None;
413
414 for p in &inner_pairs {
415 match p.as_rule() {
416 Rule::annotation => {
417 annotations.push(crate::parser::functions::parse_annotation(p.clone())?);
418 }
419 Rule::postfix_expr => {
420 target_pair = Some(p.clone());
421 }
422 _ => {}
423 }
424 }
425
426 let target = target_pair.ok_or_else(|| ShapeError::ParseError {
427 message: "expected expression after annotations in await".to_string(),
428 location: Some(pair_loc),
429 })?;
430
431 let mut expr = parse_postfix_expr(target)?;
432
433 for annotation in annotations.into_iter().rev() {
435 let anno_span = Span::new(annotation.span.start, expr.span().end);
436 expr = Expr::Annotated {
437 annotation,
438 target: Box::new(expr),
439 span: anno_span,
440 };
441 }
442
443 Ok(Expr::Await(Box::new(expr), span))
444 }
445 Rule::postfix_expr => {
446 let expr = parse_postfix_expr(first.clone())?;
448 Ok(Expr::Await(Box::new(expr), span))
449 }
450 _ => Err(ShapeError::ParseError {
451 message: format!(
452 "unexpected token in await expression: {:?}",
453 first.as_rule()
454 ),
455 location: Some(pair_loc),
456 }),
457 }
458}
459
460fn parse_join_expr(pair: Pair<Rule>) -> Result<JoinExpr> {
462 let span = pair_span(&pair);
463 let pair_loc = pair_location(&pair);
464 let mut inner = pair.into_inner();
465
466 let kind_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
468 message: "expected join strategy (all, race, any, settle)".to_string(),
469 location: Some(pair_loc.clone()),
470 })?;
471 let kind = match kind_pair.as_str() {
472 "all" => JoinKind::All,
473 "race" => JoinKind::Race,
474 "any" => JoinKind::Any,
475 "settle" => JoinKind::Settle,
476 other => {
477 return Err(ShapeError::ParseError {
478 message: format!(
479 "unknown join strategy: '{}'. Expected all, race, any, or settle",
480 other
481 ),
482 location: Some(pair_location(&kind_pair)),
483 });
484 }
485 };
486
487 let branch_list_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
489 message: "expected join branches".to_string(),
490 location: Some(pair_loc),
491 })?;
492
493 let mut branches = Vec::new();
494 for branch_pair in branch_list_pair.into_inner() {
495 if branch_pair.as_rule() == Rule::join_branch {
496 branches.push(parse_join_branch(branch_pair)?);
497 }
498 }
499
500 Ok(JoinExpr {
501 kind,
502 branches,
503 span,
504 })
505}
506
507fn parse_join_branch(pair: Pair<Rule>) -> Result<JoinBranch> {
509 let inner_pairs: Vec<_> = pair.into_inner().collect();
510
511 let mut annotations = Vec::new();
512 let mut label = None;
513 let mut expr = None;
514
515 let mut i = 0;
523
524 while i < inner_pairs.len() && inner_pairs[i].as_rule() == Rule::annotation {
526 annotations.push(crate::parser::functions::parse_annotation(
527 inner_pairs[i].clone(),
528 )?);
529 i += 1;
530 }
531
532 if i < inner_pairs.len() && inner_pairs[i].as_rule() == Rule::ident {
534 if i + 1 < inner_pairs.len() && inner_pairs[i + 1].as_rule() == Rule::expression {
539 label = Some(inner_pairs[i].as_str().to_string());
540 i += 1;
541 expr = Some(parse_expression(inner_pairs[i].clone())?);
542 } else {
543 expr = Some(parse_expression(inner_pairs[i].clone())?);
545 }
546 } else if i < inner_pairs.len() {
547 expr = Some(parse_expression(inner_pairs[i].clone())?);
548 }
549
550 let expr = expr.ok_or_else(|| ShapeError::ParseError {
551 message: "expected expression in join branch".to_string(),
552 location: None,
553 })?;
554
555 Ok(JoinBranch {
556 label,
557 expr,
558 annotations,
559 })
560}
561
562fn parse_struct_literal(pair: Pair<Rule>) -> Result<Expr> {
567 let span = pair_span(&pair);
568 let pair_loc = pair_location(&pair);
569 let mut inner = pair.into_inner();
570
571 let name_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
572 message: "expected struct type name".to_string(),
573 location: Some(pair_loc.clone()),
574 })?;
575 let type_name = name_pair.as_str().to_string();
576
577 let mut fields = Vec::new();
578
579 if let Some(fields_pair) = inner.next() {
581 if fields_pair.as_rule() == Rule::object_fields {
582 for field_item_pair in fields_pair.into_inner() {
583 if field_item_pair.as_rule() != Rule::object_field_item {
584 continue;
585 }
586 let field_item_loc = pair_location(&field_item_pair);
587 let field_item_inner =
588 field_item_pair
589 .into_inner()
590 .next()
591 .ok_or_else(|| ShapeError::ParseError {
592 message: "expected struct field content".to_string(),
593 location: Some(field_item_loc.clone()),
594 })?;
595 match field_item_inner.as_rule() {
596 Rule::object_field => {
597 let mut field_inner = field_item_inner.into_inner();
598 let field_kind =
599 field_inner.next().ok_or_else(|| ShapeError::ParseError {
600 message: "expected struct field content".to_string(),
601 location: Some(field_item_loc.clone()),
602 })?;
603 match field_kind.as_rule() {
604 Rule::object_value_field => {
605 let mut value_inner = field_kind.into_inner();
606 let key_pair =
607 value_inner.next().ok_or_else(|| ShapeError::ParseError {
608 message: "expected struct field key".to_string(),
609 location: Some(field_item_loc.clone()),
610 })?;
611 let key_pair = if key_pair.as_rule() == Rule::object_field_name {
612 key_pair.into_inner().next().ok_or_else(|| {
613 ShapeError::ParseError {
614 message: "expected struct field key".to_string(),
615 location: Some(field_item_loc.clone()),
616 }
617 })?
618 } else {
619 key_pair
620 };
621 let key = key_pair.as_str().to_string();
622 let value_pair =
623 value_inner.next().ok_or_else(|| ShapeError::ParseError {
624 message: format!(
625 "expected value for struct field '{}'",
626 key
627 ),
628 location: Some(field_item_loc),
629 })?;
630 let value = parse_expression(value_pair)?;
631 fields.push((key, value));
632 }
633 _ => {
634 return Err(ShapeError::ParseError {
635 message: "typed fields and spreads are not supported in struct literals".to_string(),
636 location: Some(field_item_loc),
637 });
638 }
639 }
640 }
641 Rule::object_spread => {
642 return Err(ShapeError::ParseError {
643 message: "spread is not supported in struct literals".to_string(),
644 location: Some(field_item_loc),
645 });
646 }
647 _ => {}
648 }
649 }
650 }
651 }
652
653 Ok(Expr::StructLiteral {
654 type_name,
655 fields,
656 span,
657 })
658}
659
660fn parse_enum_constructor_expr(pair: Pair<Rule>) -> Result<Expr> {
661 let span = pair_span(&pair);
662 let pair_loc = pair_location(&pair);
663 let mut inner = pair.into_inner();
664
665 let path_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
666 message: "expected enum variant path".to_string(),
667 location: Some(pair_loc.clone()),
668 })?;
669 let (enum_name, variant) = parse_enum_variant_path(path_pair)?;
670
671 let payload = if let Some(payload_pair) = inner.next() {
672 match payload_pair.as_rule() {
673 Rule::enum_tuple_payload => {
674 let (args, named_args) = super::functions::parse_arg_list(payload_pair)?;
675 if !named_args.is_empty() {
676 return Err(ShapeError::ParseError {
677 message: "named arguments are not allowed in enum tuple constructors"
678 .to_string(),
679 location: Some(pair_loc),
680 });
681 }
682 EnumConstructorPayload::Tuple(args)
683 }
684 Rule::enum_struct_payload => {
685 let fields = parse_enum_struct_payload(payload_pair)?;
686 EnumConstructorPayload::Struct(fields)
687 }
688 other => {
689 return Err(ShapeError::ParseError {
690 message: format!("unexpected enum constructor payload: {:?}", other),
691 location: Some(pair_loc),
692 });
693 }
694 }
695 } else {
696 EnumConstructorPayload::Unit
697 };
698
699 Ok(Expr::EnumConstructor {
700 enum_name,
701 variant,
702 payload,
703 span,
704 })
705}
706
707fn parse_enum_variant_path(pair: Pair<Rule>) -> Result<(String, String)> {
708 let pair_loc = pair_location(&pair);
709 let mut inner = pair.into_inner();
710 let enum_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
711 message: "expected enum name".to_string(),
712 location: Some(pair_loc.clone()),
713 })?;
714 let variant_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
715 message: "expected enum variant name".to_string(),
716 location: Some(pair_loc),
717 })?;
718 Ok((
719 enum_pair.as_str().to_string(),
720 variant_pair.as_str().to_string(),
721 ))
722}
723
724fn parse_enum_struct_payload(pair: Pair<Rule>) -> Result<Vec<(String, Expr)>> {
725 let mut fields = Vec::new();
726
727 for inner in pair.into_inner() {
728 if inner.as_rule() != Rule::object_fields {
729 continue;
730 }
731 for field_item_pair in inner.into_inner() {
732 if field_item_pair.as_rule() != Rule::object_field_item {
733 continue;
734 }
735 let field_item_loc = pair_location(&field_item_pair);
736 let field_item_inner =
737 field_item_pair
738 .into_inner()
739 .next()
740 .ok_or_else(|| ShapeError::ParseError {
741 message: "expected enum struct field content".to_string(),
742 location: Some(field_item_loc.clone()),
743 })?;
744 match field_item_inner.as_rule() {
745 Rule::object_field => {
746 let mut field_inner = field_item_inner.into_inner();
747 let field_kind = field_inner.next().ok_or_else(|| ShapeError::ParseError {
748 message: "expected enum struct field content".to_string(),
749 location: Some(field_item_loc.clone()),
750 })?;
751 match field_kind.as_rule() {
752 Rule::object_value_field => {
753 let mut value_inner = field_kind.into_inner();
754 let key_pair =
755 value_inner.next().ok_or_else(|| ShapeError::ParseError {
756 message: "expected enum struct field key".to_string(),
757 location: Some(field_item_loc.clone()),
758 })?;
759 let key_pair = if key_pair.as_rule() == Rule::object_field_name {
760 key_pair.into_inner().next().ok_or_else(|| {
761 ShapeError::ParseError {
762 message: "expected enum struct field key".to_string(),
763 location: Some(field_item_loc.clone()),
764 }
765 })?
766 } else {
767 key_pair
768 };
769 let key = match key_pair.as_rule() {
770 Rule::ident | Rule::keyword => key_pair.as_str().to_string(),
771 _ => {
772 return Err(ShapeError::ParseError {
773 message: "unexpected enum struct field key".to_string(),
774 location: Some(pair_location(&key_pair)),
775 });
776 }
777 };
778 let value_pair =
779 value_inner.next().ok_or_else(|| ShapeError::ParseError {
780 message: format!("expected value for enum field '{}'", key),
781 location: Some(field_item_loc),
782 })?;
783 let value = parse_expression(value_pair)?;
784 fields.push((key, value));
785 }
786 Rule::object_typed_field => {
787 return Err(ShapeError::ParseError {
788 message: "typed fields are not allowed in enum constructors"
789 .to_string(),
790 location: Some(field_item_loc),
791 });
792 }
793 other => {
794 return Err(ShapeError::ParseError {
795 message: format!("unexpected enum field kind: {:?}", other),
796 location: Some(field_item_loc),
797 });
798 }
799 }
800 }
801 Rule::object_spread => {
802 return Err(ShapeError::ParseError {
803 message: "spread fields are not allowed in enum constructors".to_string(),
804 location: Some(field_item_loc),
805 });
806 }
807 other => {
808 return Err(ShapeError::ParseError {
809 message: format!("unexpected enum struct field: {:?}", other),
810 location: Some(field_item_loc),
811 });
812 }
813 }
814 }
815 }
816
817 Ok(fields)
818}
819
820fn parse_comptime_block(pair: Pair<Rule>) -> Result<Expr> {
825 let span = pair_span(&pair);
826 let pair_loc = pair_location(&pair);
827 let block_pair = pair
828 .into_inner()
829 .next()
830 .ok_or_else(|| ShapeError::ParseError {
831 message: "expected block after 'comptime'".to_string(),
832 location: Some(pair_loc),
833 })?;
834
835 let block_expr = super::control_flow::parse_block_expr(block_pair)?;
837 let stmts = block_items_to_statements(block_expr, span);
838 Ok(Expr::Comptime(stmts, span))
839}
840
841fn parse_comptime_for_expr(pair: Pair<Rule>) -> Result<Expr> {
846 use crate::ast::expr_helpers::ComptimeForExpr;
847 use crate::parser::statements::parse_statement;
848
849 let span = pair_span(&pair);
850 let pair_loc = pair_location(&pair);
851 let mut inner = pair.into_inner();
852
853 let var_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
855 message: "expected loop variable in comptime for".to_string(),
856 location: Some(pair_loc.clone()),
857 })?;
858 let variable = var_pair.as_str().to_string();
859
860 let iter_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
862 message: "expected iterable expression in comptime for".to_string(),
863 location: Some(pair_loc),
864 })?;
865 let iterable = parse_postfix_expr(iter_pair)?;
866
867 let mut body = Vec::new();
869 for stmt_pair in inner {
870 if stmt_pair.as_rule() == Rule::statement {
871 body.push(parse_statement(stmt_pair)?);
872 }
873 }
874
875 Ok(Expr::ComptimeFor(
876 Box::new(ComptimeForExpr {
877 variable,
878 iterable: Box::new(iterable),
879 body,
880 }),
881 span,
882 ))
883}
884
885pub(crate) fn block_items_to_statements(
889 block_expr: Expr,
890 span: Span,
891) -> Vec<crate::ast::Statement> {
892 use crate::ast::{BlockItem, Statement};
893
894 let items = match block_expr {
895 Expr::Block(block, _) => block.items,
896 other => return vec![Statement::Return(Some(other), span)],
898 };
899
900 let mut stmts = Vec::new();
901 let len = items.len();
902 for (i, item) in items.into_iter().enumerate() {
903 let is_last = i == len - 1;
904 match item {
905 BlockItem::VariableDecl(decl) => {
906 stmts.push(Statement::VariableDecl(decl, span));
907 }
908 BlockItem::Assignment(assign) => {
909 stmts.push(Statement::Assignment(assign, span));
910 }
911 BlockItem::Statement(stmt) => {
912 stmts.push(stmt);
913 }
914 BlockItem::Expression(expr) => {
915 if is_last {
916 stmts.push(Statement::Return(Some(expr), span));
918 } else {
919 stmts.push(Statement::Expression(expr, span));
920 }
921 }
922 }
923 }
924 stmts
925}
926
927fn parse_annotated_expr(pair: Pair<Rule>) -> Result<Expr> {
935 let span = pair_span(&pair);
936 let pair_loc = pair_location(&pair);
937 let inner_pairs: Vec<_> = pair.into_inner().collect();
938
939 if inner_pairs.is_empty() {
940 return Err(ShapeError::ParseError {
941 message: "expected annotations and expression".to_string(),
942 location: Some(pair_loc),
943 });
944 }
945
946 let mut annotations = Vec::new();
948 let mut target_pair = None;
949 for p in &inner_pairs {
950 match p.as_rule() {
951 Rule::annotation => {
952 annotations.push(crate::parser::functions::parse_annotation(p.clone())?);
953 }
954 _ => {
955 target_pair = Some(p.clone());
956 }
957 }
958 }
959
960 let target_pair = target_pair.ok_or_else(|| ShapeError::ParseError {
961 message: "expected expression after annotations".to_string(),
962 location: Some(pair_loc),
963 })?;
964 let target = parse_postfix_expr(target_pair)?;
965
966 let mut result = target;
969 for annotation in annotations.into_iter().rev() {
970 result = Expr::Annotated {
971 annotation,
972 target: Box::new(result),
973 span,
974 };
975 }
976
977 Ok(result)
978}
979
980