1use crate::ast::{Block, Expr, Generics, Ident, Param, TypeExpr, Visibility, WhereClause};
14use crate::lexer::Token;
15use crate::parser::{ParseError, ParseResult, Parser};
16use crate::span::Span;
17
18use super::ast::*;
19use super::lexer::{AlterSourceMarker, ForcedOperation, PluralityTokenStream};
20
21pub trait PluralityParser {
27 fn parse_plurality_item(&mut self) -> ParseResult<PluralityItem>;
29 fn parse_alter_def(&mut self, visibility: Visibility) -> ParseResult<AlterDef>;
30 fn parse_headspace_def(&mut self, visibility: Visibility) -> ParseResult<HeadspaceDef>;
31 fn parse_reality_def(&mut self, visibility: Visibility) -> ParseResult<RealityDef>;
32 fn parse_cocon_channel(&mut self) -> ParseResult<CoConChannel>;
33 fn parse_trigger_handler(&mut self) -> ParseResult<TriggerHandler>;
34
35 fn parse_plurality_expr(&mut self) -> ParseResult<PluralityExpr>;
37 fn parse_alter_block(&mut self) -> ParseResult<AlterBlock>;
38 fn parse_switch_expr(&mut self) -> ParseResult<SwitchExpr>;
39 fn parse_split_expr(&mut self) -> ParseResult<SplitExpr>;
40
41 fn parse_alter_sourced_type(&mut self) -> ParseResult<AlterSourcedType>;
43
44 fn parse_alter_expr(&mut self) -> ParseResult<AlterExpr>;
46 fn parse_alter_source(&mut self) -> ParseResult<Option<AlterSource>>;
47 fn try_parse_alter_source_marker(&mut self) -> Option<AlterSourceMarker>;
48}
49
50impl<'a> PluralityParser for Parser<'a> {
51 fn parse_plurality_item(&mut self) -> ParseResult<PluralityItem> {
57 let visibility = self.parse_visibility()?;
58
59 match self.current_token() {
60 Some(Token::Alter) => {
61 Ok(PluralityItem::Alter(self.parse_alter_def(visibility)?))
62 }
63 Some(Token::Headspace) => {
64 Ok(PluralityItem::Headspace(self.parse_headspace_def(visibility)?))
65 }
66 Some(Token::Reality) => {
67 Ok(PluralityItem::Reality(self.parse_reality_def(visibility)?))
68 }
69 Some(Token::CoCon) => {
70 Ok(PluralityItem::CoConChannel(self.parse_cocon_channel()?))
71 }
72 Some(Token::On) => Ok(PluralityItem::TriggerHandler(self.parse_trigger_handler()?)),
73 Some(t) => Err(ParseError::UnexpectedToken {
74 expected: "plurality item (alter, headspace, reality, cocon, or trigger handler)"
75 .to_string(),
76 found: t.clone(),
77 span: self.current_span(),
78 }),
79 None => Err(ParseError::UnexpectedEof),
80 }
81 }
82
83 fn parse_alter_def(&mut self, visibility: Visibility) -> ParseResult<AlterDef> {
96 let start = self.current_span();
97
98 self.expect(Token::Alter)?;
100
101 let name = self.parse_ident()?;
103
104 let category = if self.consume_if(&Token::Colon) {
106 let cat_ident = self.parse_ident()?;
107 AlterCategory::from_ident(&cat_ident)
108 } else {
109 AlterCategory::Custom
110 };
111
112 let generics = self.parse_generics_opt()?;
114
115 let where_clause = self.parse_where_clause_opt()?;
117
118 self.expect(Token::LBrace)?;
120 let body = self.parse_alter_body()?;
121 self.expect(Token::RBrace)?;
122
123 let end = self.current_span();
124
125 Ok(AlterDef {
126 visibility,
127 attrs: Vec::new(),
128 name,
129 category,
130 generics,
131 where_clause,
132 body,
133 span: start.merge(end),
134 })
135 }
136
137 fn parse_headspace_def(&mut self, visibility: Visibility) -> ParseResult<HeadspaceDef> {
146 let start = self.current_span();
147
148 self.expect(Token::Headspace)?;
149 let name = self.parse_ident()?;
150
151 self.expect(Token::LBrace)?;
152
153 let mut locations = Vec::new();
154 let mut methods = Vec::new();
155
156 while !self.check(&Token::RBrace) && !self.is_eof() {
157 self.skip_comments();
158
159 if self.check(&Token::Location) {
160 locations.push(self.parse_location_def()?);
161 } else if self.check(&Token::Fn) || self.check(&Token::Async) {
162 methods.push(self.parse_alter_method()?);
163 } else if self.check(&Token::RBrace) {
164 break;
165 } else {
166 return Err(ParseError::UnexpectedToken {
167 expected: "location or method".to_string(),
168 found: self.current_token().cloned().unwrap_or(Token::RBrace),
169 span: self.current_span(),
170 });
171 }
172 }
173
174 self.expect(Token::RBrace)?;
175 let end = self.current_span();
176
177 Ok(HeadspaceDef {
178 visibility,
179 name,
180 locations,
181 methods,
182 span: start.merge(end),
183 })
184 }
185
186 fn parse_reality_def(&mut self, visibility: Visibility) -> ParseResult<RealityDef> {
196 let start = self.current_span();
197
198 self.expect(Token::Reality)?;
199 self.expect_ident("entity")?;
200 let name = self.parse_ident()?;
201
202 self.expect(Token::LBrace)?;
203
204 let mut layers = Vec::new();
205 let mut transforms = Vec::new();
206
207 while !self.check(&Token::RBrace) && !self.is_eof() {
208 self.skip_comments();
209
210 if self.check(&Token::Layer) {
211 layers.push(self.parse_reality_layer()?);
212 } else if self.check_ident("transform") {
213 transforms.push(self.parse_reality_transform()?);
214 } else if self.check(&Token::RBrace) {
215 break;
216 } else {
217 return Err(ParseError::UnexpectedToken {
218 expected: "layer or transform".to_string(),
219 found: self.current_token().cloned().unwrap_or(Token::RBrace),
220 span: self.current_span(),
221 });
222 }
223 }
224
225 self.expect(Token::RBrace)?;
226 let end = self.current_span();
227
228 Ok(RealityDef {
229 visibility,
230 name,
231 layers,
232 transforms,
233 span: start.merge(end),
234 })
235 }
236
237 fn parse_cocon_channel(&mut self) -> ParseResult<CoConChannel> {
245 let start = self.current_span();
246
247 self.expect(Token::CoCon)?;
248 self.expect(Token::Lt)?;
249
250 let mut participants = Vec::new();
252 participants.push(self.parse_ident()?);
253 while self.consume_if(&Token::Comma) {
254 if self.check(&Token::Gt) {
255 break;
256 }
257 participants.push(self.parse_ident()?);
258 }
259 self.expect_gt()?;
260
261 let name = self.parse_ident()?;
262 let body = self.parse_block()?;
263 let end = self.current_span();
264
265 Ok(CoConChannel {
266 participants,
267 name,
268 body,
269 span: start.merge(end),
270 })
271 }
272
273 fn parse_trigger_handler(&mut self) -> ParseResult<TriggerHandler> {
281 let start = self.current_span();
282
283 self.expect(Token::On)?;
284 self.expect(Token::Trigger)?;
285
286 let pattern = self.parse_trigger_pattern()?;
288
289 let guard = if self.consume_if(&Token::Where) {
291 Some(self.parse_expr()?)
292 } else {
293 None
294 };
295
296 let body = self.parse_block()?;
298 let end = self.current_span();
299
300 Ok(TriggerHandler {
301 pattern,
302 guard,
303 body,
304 span: start.merge(end),
305 })
306 }
307
308 fn parse_plurality_expr(&mut self) -> ParseResult<PluralityExpr> {
314 match self.current_token() {
315 Some(Token::Alter) => {
316 Ok(PluralityExpr::AlterBlock(self.parse_alter_block()?))
317 }
318 Some(Token::Switch) => {
319 Ok(PluralityExpr::Switch(self.parse_switch_expr()?))
320 }
321 Some(Token::Split) => {
322 Ok(PluralityExpr::Split(self.parse_split_expr()?))
323 }
324 Some(t) => Err(ParseError::UnexpectedToken {
325 expected: "plurality expression (alter, switch, or split)".to_string(),
326 found: t.clone(),
327 span: self.current_span(),
328 }),
329 None => Err(ParseError::UnexpectedEof),
330 }
331 }
332
333 fn parse_alter_block(&mut self) -> ParseResult<AlterBlock> {
341 let start = self.current_span();
342
343 self.expect(Token::Alter)?;
344 let alter = self.parse_alter_expr()?;
345 let body = self.parse_block()?;
346 let end = self.current_span();
347
348 Ok(AlterBlock {
349 alter,
350 body,
351 span: start.merge(end),
352 })
353 }
354
355 fn parse_switch_expr(&mut self) -> ParseResult<SwitchExpr> {
366 let start = self.current_span();
367
368 self.expect(Token::Switch)?;
369
370 let forced = self.consume_if(&Token::Bang);
372
373 self.expect(Token::To)?;
374 let target = self.parse_alter_expr()?;
375
376 let config = if self.check(&Token::LBrace) {
378 self.parse_switch_config()?
379 } else {
380 SwitchConfig::default()
381 };
382
383 let end = self.current_span();
384
385 Ok(SwitchExpr {
386 forced,
387 target,
388 config,
389 span: start.merge(end),
390 })
391 }
392
393 fn parse_split_expr(&mut self) -> ParseResult<SplitExpr> {
403 let start = self.current_span();
404
405 self.expect(Token::Split)?;
406 self.expect(Token::Bang)?; self.expect(Token::From)?;
408
409 let parent = self.parse_alter_expr()?;
410 let config = self.parse_split_config()?;
411 let end = self.current_span();
412
413 Ok(SplitExpr {
414 parent,
415 config,
416 span: start.merge(end),
417 })
418 }
419
420 fn parse_alter_sourced_type(&mut self) -> ParseResult<AlterSourcedType> {
433 let start = self.current_span();
434 let inner = self.parse_type()?;
435
436 if let Some(marker) = self.try_parse_alter_source_marker() {
438 let end = self.current_span();
439 let alter_source = match marker {
440 AlterSourceMarker::Fronting => AlterSource::Fronting,
441 AlterSourceMarker::CoCon => AlterSource::CoConscious(None),
442 AlterSourceMarker::Dormant => AlterSource::Dormant(None),
443 AlterSourceMarker::Blended => AlterSource::Blended(Vec::new()),
444 };
445
446 Ok(AlterSourcedType {
447 inner,
448 alter_source,
449 span: start.merge(end),
450 })
451 } else {
452 let end = self.current_span();
454 Ok(AlterSourcedType {
455 inner,
456 alter_source: AlterSource::Fronting,
457 span: start.merge(end),
458 })
459 }
460 }
461
462 fn parse_alter_expr(&mut self) -> ParseResult<AlterExpr> {
468 match self.current_token() {
469 Some(Token::Ident(_)) => {
470 let ident = self.parse_ident()?;
471
472 if self.check(&Token::MiddleDot) {
474 self.advance();
475 let method = self.parse_ident()?;
476 if self.check(&Token::LParen) {
477 self.advance(); let mut args = Vec::new();
480 while !self.check(&Token::RParen) && !self.is_eof() {
481 args.push(self.parse_expr()?);
482 if !self.consume_if(&Token::Comma) {
483 break;
484 }
485 }
486 self.expect(Token::RParen)?;
487
488 let receiver_path = crate::ast::TypePath {
490 segments: vec![crate::ast::PathSegment {
491 ident: ident.clone(),
492 generics: None,
493 }],
494 };
495 let call_expr = Expr::MethodCall {
496 receiver: Box::new(Expr::Path(receiver_path)),
497 method,
498 type_args: None,
499 args,
500 };
501 return Ok(AlterExpr::CurrentFronter(Box::new(call_expr)));
502 }
503 let combined_path = crate::ast::TypePath {
505 segments: vec![crate::ast::PathSegment {
506 ident: Ident {
507 name: format!("{}.{}", ident.name, method.name),
508 evidentiality: None,
509 affect: None,
510 span: ident.span.merge(method.span),
511 },
512 generics: None,
513 }],
514 };
515 return Ok(AlterExpr::Expr(Box::new(Expr::Path(combined_path))));
516 }
517
518 Ok(AlterExpr::Named(ident))
519 }
520 Some(_) => {
521 let expr = self.parse_expr()?;
523 Ok(AlterExpr::Expr(Box::new(expr)))
524 }
525 None => Err(ParseError::UnexpectedEof),
526 }
527 }
528
529 fn parse_alter_source(&mut self) -> ParseResult<Option<AlterSource>> {
531 if !self.check(&Token::At) {
532 return Ok(None);
533 }
534
535 self.advance(); match self.current_token() {
538 Some(Token::Bang) => {
539 self.advance();
540 Ok(Some(AlterSource::Fronting))
541 }
542 Some(Token::Tilde) => {
543 self.advance();
544 Ok(Some(AlterSource::CoConscious(None)))
545 }
546 Some(Token::Question) => {
547 self.advance();
548 Ok(Some(AlterSource::Dormant(None)))
549 }
550 Some(Token::Interrobang) => {
551 self.advance();
552 Ok(Some(AlterSource::Blended(Vec::new())))
553 }
554 Some(Token::Ident(_)) => {
555 let ident = self.parse_ident()?;
556 match ident.name.as_str() {
557 "Fronting" => Ok(Some(AlterSource::Fronting)),
558 "CoCon" => Ok(Some(AlterSource::CoConscious(None))),
559 "Dormant" => Ok(Some(AlterSource::Dormant(None))),
560 "Blended" => Ok(Some(AlterSource::Blended(Vec::new()))),
561 _ => Ok(Some(AlterSource::Named(ident))),
562 }
563 }
564 _ => Ok(None),
565 }
566 }
567
568 fn try_parse_alter_source_marker(&mut self) -> Option<AlterSourceMarker> {
570 if !self.check(&Token::At) {
571 return None;
572 }
573
574 let next = self.peek_next()?;
576 let marker = match next {
577 Token::Bang => Some(AlterSourceMarker::Fronting),
578 Token::Tilde => Some(AlterSourceMarker::CoCon),
579 Token::Question => Some(AlterSourceMarker::Dormant),
580 Token::Interrobang => Some(AlterSourceMarker::Blended),
581 _ => None,
582 };
583
584 if marker.is_some() {
585 self.advance(); self.advance(); }
588
589 marker
590 }
591}
592
593impl<'a> Parser<'a> {
598 fn check_ident(&self, name: &str) -> bool {
600 matches!(self.current_token(), Some(Token::Ident(s)) if s == name)
601 }
602
603 fn expect_ident(&mut self, name: &str) -> ParseResult<Span> {
605 match self.current_token() {
606 Some(Token::Ident(s)) if s == name => {
607 let span = self.current_span();
608 self.advance();
609 Ok(span)
610 }
611 Some(t) => Err(ParseError::UnexpectedToken {
612 expected: format!("identifier '{}'", name),
613 found: t.clone(),
614 span: self.current_span(),
615 }),
616 None => Err(ParseError::UnexpectedEof),
617 }
618 }
619
620 fn parse_alter_body(&mut self) -> ParseResult<AlterBody> {
622 let mut body = AlterBody {
623 archetype: None,
624 preferred_reality: None,
625 abilities: Vec::new(),
626 triggers: Vec::new(),
627 anima: None,
628 states: None,
629 special: Vec::new(),
630 methods: Vec::new(),
631 types: Vec::new(),
632 };
633
634 while !self.check(&Token::RBrace) && !self.is_eof() {
635 self.skip_comments();
636
637 match self.current_token() {
638 Some(Token::Anima) => {
640 self.advance();
641 self.expect(Token::Colon)?;
642 body.anima = Some(self.parse_anima_config()?);
643 self.consume_if(&Token::Comma);
644 }
645 Some(Token::States) => {
646 self.advance();
647 self.expect(Token::Colon)?;
648 body.states = Some(self.parse_alter_state_machine()?);
649 self.consume_if(&Token::Comma);
650 }
651 Some(Token::Ident(s)) => match s.as_str() {
653 "archetype" => {
654 self.advance();
655 self.expect(Token::Colon)?;
656 body.archetype = Some(self.parse_expr()?);
657 self.consume_if(&Token::Comma);
658 }
659 "preferred_reality" => {
660 self.advance();
661 self.expect(Token::Colon)?;
662 body.preferred_reality = Some(self.parse_expr()?);
663 self.consume_if(&Token::Comma);
664 }
665 "abilities" => {
666 self.advance();
667 self.expect(Token::Colon)?;
668 body.abilities = self.parse_bracketed_expr_list()?;
669 self.consume_if(&Token::Comma);
670 }
671 "triggers" => {
672 self.advance();
673 self.expect(Token::Colon)?;
674 body.triggers = self.parse_bracketed_expr_list()?;
675 self.consume_if(&Token::Comma);
676 }
677 _ => {
678 return Err(ParseError::UnexpectedToken {
680 expected: "alter body field".to_string(),
681 found: Token::Ident(s.clone()),
682 span: self.current_span(),
683 });
684 }
685 },
686 Some(Token::Fn) | Some(Token::Async) => {
687 body.methods.push(self.parse_alter_method()?);
688 }
689 Some(Token::Type) => {
690 body.types.push(self.parse_alter_type_alias()?);
691 }
692 Some(Token::RBrace) => break,
693 Some(t) => {
694 return Err(ParseError::UnexpectedToken {
695 expected: "alter body field or method".to_string(),
696 found: t.clone(),
697 span: self.current_span(),
698 });
699 }
700 None => return Err(ParseError::UnexpectedEof),
701 }
702 }
703
704 Ok(body)
705 }
706
707 fn parse_anima_config(&mut self) -> ParseResult<AnimaConfig> {
709 self.expect(Token::LBrace)?;
710
711 let mut config = AnimaConfig {
712 base_arousal: None,
713 base_dominance: None,
714 expressiveness: None,
715 susceptibility: None,
716 extra: Vec::new(),
717 };
718
719 while !self.check(&Token::RBrace) && !self.is_eof() {
720 self.skip_comments();
721
722 let field_name = self.parse_ident()?;
723 self.expect(Token::Colon)?;
724 let value = self.parse_expr()?;
725
726 match field_name.name.as_str() {
727 "base_arousal" => config.base_arousal = Some(value),
728 "base_dominance" => config.base_dominance = Some(value),
729 "expressiveness" => config.expressiveness = Some(value),
730 "susceptibility" => config.susceptibility = Some(value),
731 _ => config.extra.push((field_name, value)),
732 }
733
734 self.consume_if(&Token::Comma);
735 }
736
737 self.expect(Token::RBrace)?;
738 Ok(config)
739 }
740
741 fn parse_alter_state_machine(&mut self) -> ParseResult<AlterStateMachine> {
743 self.expect(Token::LBrace)?;
744
745 let mut transitions = Vec::new();
746
747 while !self.check(&Token::RBrace) && !self.is_eof() {
748 self.skip_comments();
749 transitions.push(self.parse_alter_transition()?);
750 self.consume_if(&Token::Comma);
751 }
752
753 self.expect(Token::RBrace)?;
754 Ok(AlterStateMachine { transitions })
755 }
756
757 fn parse_alter_transition(&mut self) -> ParseResult<AlterTransition> {
760 let from_ident = self.parse_ident()?;
761 let from = AlterState::from_ident(&from_ident);
762
763 self.expect(Token::Arrow)?;
764
765 let to_ident = self.parse_ident()?;
766 let to = AlterState::from_ident(&to_ident);
767
768 self.expect(Token::Colon)?;
769 self.expect(Token::On)?;
770
771 let on = self.parse_expr()?;
772
773 let guard = if self.check(&Token::Where) {
775 self.advance();
776 Some(self.parse_expr()?)
777 } else {
778 None
779 };
780
781 let action = if self.check(&Token::LBrace) {
783 Some(self.parse_block()?)
784 } else {
785 None
786 };
787
788 Ok(AlterTransition {
789 from,
790 to,
791 on,
792 guard,
793 action,
794 })
795 }
796
797 fn parse_alter_method(&mut self) -> ParseResult<AlterMethod> {
799 let visibility = self.parse_visibility()?;
800 let is_async = self.consume_if(&Token::Async);
801 self.expect(Token::Fn)?;
802 let name = self.parse_ident()?;
803
804 self.expect(Token::LParen)?;
805 let params = self.parse_params()?;
806 self.expect(Token::RParen)?;
807
808 let return_type = if self.consume_if(&Token::Arrow) {
809 Some(self.parse_type()?)
810 } else {
811 None
812 };
813
814 let body = if self.check(&Token::LBrace) {
815 Some(self.parse_block()?)
816 } else {
817 self.consume_if(&Token::Semi);
818 None
819 };
820
821 Ok(AlterMethod {
822 visibility,
823 is_async,
824 name,
825 params,
826 return_type,
827 body,
828 })
829 }
830
831 fn parse_alter_type_alias(&mut self) -> ParseResult<AlterTypeAlias> {
833 let visibility = self.parse_visibility()?;
834 self.expect(Token::Type)?;
835 let name = self.parse_ident()?;
836 self.expect(Token::Eq)?;
837 let ty = self.parse_type()?;
838 self.consume_if(&Token::Semi);
839
840 Ok(AlterTypeAlias {
841 visibility,
842 name,
843 ty,
844 })
845 }
846
847 fn parse_location_def(&mut self) -> ParseResult<LocationDef> {
849 self.expect(Token::Location)?;
850 let name = self.parse_ident()?;
851 self.expect(Token::Colon)?;
852 let location_type = self.parse_ident()?;
853
854 self.expect(Token::LBrace)?;
855
856 let mut fields = Vec::new();
857 let mut connections = Vec::new();
858 let mut hazards = Vec::new();
859
860 while !self.check(&Token::RBrace) && !self.is_eof() {
861 self.skip_comments();
862
863 let field_name = self.parse_ident()?;
864 self.expect(Token::Colon)?;
865
866 match field_name.name.as_str() {
867 "connections" => {
868 self.expect(Token::LBracket)?;
870 while !self.check(&Token::RBracket) {
871 connections.push(self.parse_stream_def()?);
872 self.consume_if(&Token::Comma);
873 }
874 self.expect(Token::RBracket)?;
875 }
876 "hazards" => {
877 hazards = self.parse_bracketed_expr_list()?;
878 }
879 _ => {
880 let value = self.parse_expr()?;
881 fields.push((field_name, value));
882 }
883 }
884
885 self.consume_if(&Token::Comma);
886 }
887
888 self.expect(Token::RBrace)?;
889
890 Ok(LocationDef {
891 name,
892 location_type,
893 fields,
894 connections,
895 hazards,
896 })
897 }
898
899 fn parse_stream_def(&mut self) -> ParseResult<StreamDef> {
902 let target = self.parse_ident()?;
904
905 let mut bidirectional = false;
906 let mut locked = false;
907 let mut content = None;
908
909 if self.consume_if(&Token::Comma) {
911 while !self.check(&Token::RParen)
912 && !self.check(&Token::RBracket)
913 && !self.check(&Token::Comma)
914 && !self.is_eof()
915 {
916 let opt_name = self.parse_ident()?;
917 self.expect(Token::Colon)?;
918
919 match opt_name.name.as_str() {
920 "bidirectional" => {
921 bidirectional = self.consume_if(&Token::True);
922 if !bidirectional {
923 self.consume_if(&Token::False);
924 }
925 }
926 "locked" => {
927 locked = self.consume_if(&Token::True);
928 if !locked {
929 self.consume_if(&Token::False);
930 }
931 }
932 "content" => {
933 content = Some(self.parse_expr()?);
934 }
935 _ => {}
936 }
937
938 if !self.consume_if(&Token::Comma) {
939 break;
940 }
941 }
942 }
943
944 Ok(StreamDef {
945 target,
946 content,
947 bidirectional,
948 locked,
949 })
950 }
951
952 fn parse_reality_layer(&mut self) -> ParseResult<RealityLayer> {
954 self.expect(Token::Layer)?;
955 let name = self.parse_ident()?;
956
957 self.expect(Token::LBrace)?;
958
959 let mut fields = Vec::new();
960
961 while !self.check(&Token::RBrace) && !self.is_eof() {
962 self.skip_comments();
963
964 let field_name = self.parse_ident()?;
965 self.expect(Token::Colon)?;
966 let value = self.parse_expr()?;
967 fields.push((field_name, value));
968
969 self.consume_if(&Token::Comma);
970 }
971
972 self.expect(Token::RBrace)?;
973
974 Ok(RealityLayer { name, fields })
975 }
976
977 fn parse_reality_transform(&mut self) -> ParseResult<RealityTransform> {
979 self.expect_ident("transform")?;
980 let from = self.parse_ident()?;
981 self.expect(Token::Arrow)?;
982 let to = self.parse_ident()?;
983 self.expect(Token::Colon)?;
984 self.expect(Token::On)?;
985 let condition = self.parse_expr()?;
986 self.consume_if(&Token::Comma);
987
988 Ok(RealityTransform { from, to, condition })
989 }
990
991 fn parse_switch_config(&mut self) -> ParseResult<SwitchConfig> {
993 self.expect(Token::LBrace)?;
994
995 let mut config = SwitchConfig {
996 reason: None,
997 urgency: None,
998 requires: None,
999 then_block: None,
1000 else_block: None,
1001 emergency_block: None,
1002 bypass_deliberation: false,
1003 };
1004
1005 while !self.check(&Token::RBrace) && !self.is_eof() {
1006 self.skip_comments();
1007
1008 let field_name = self.parse_ident()?;
1009 self.expect(Token::Colon)?;
1010
1011 match field_name.name.as_str() {
1012 "reason" => config.reason = Some(self.parse_expr()?),
1013 "urgency" => config.urgency = Some(self.parse_expr()?),
1014 "requires" => config.requires = Some(self.parse_expr()?),
1015 "then" => config.then_block = Some(self.parse_block()?),
1016 "else" => config.else_block = Some(self.parse_block()?),
1017 "emergency" => config.emergency_block = Some(self.parse_block()?),
1018 "bypass_deliberation" => {
1019 config.bypass_deliberation = self.consume_if(&Token::True);
1020 if !config.bypass_deliberation {
1021 self.consume_if(&Token::False);
1022 }
1023 }
1024 _ => {
1025 let _ = self.parse_expr()?;
1027 }
1028 }
1029
1030 self.consume_if(&Token::Comma);
1031 }
1032
1033 self.expect(Token::RBrace)?;
1034 Ok(config)
1035 }
1036
1037 fn parse_split_config(&mut self) -> ParseResult<SplitConfig> {
1039 self.expect(Token::LBrace)?;
1040
1041 let mut config = SplitConfig {
1042 purpose: None,
1043 memories: None,
1044 traits: None,
1045 extra: Vec::new(),
1046 };
1047
1048 while !self.check(&Token::RBrace) && !self.is_eof() {
1049 self.skip_comments();
1050
1051 let field_name = self.parse_ident()?;
1052 self.expect(Token::Colon)?;
1053 let value = self.parse_expr()?;
1054
1055 match field_name.name.as_str() {
1056 "purpose" => config.purpose = Some(value),
1057 "memories" => config.memories = Some(value),
1058 "traits" => config.traits = Some(value),
1059 _ => config.extra.push((field_name, value)),
1060 }
1061
1062 self.consume_if(&Token::Comma);
1063 }
1064
1065 self.expect(Token::RBrace)?;
1066 Ok(config)
1067 }
1068
1069 fn parse_trigger_pattern(&mut self) -> ParseResult<TriggerPattern> {
1071 let trigger_type = self.parse_ident()?;
1072
1073 let mut fields = Vec::new();
1074
1075 if self.consume_if(&Token::LBrace) {
1076 while !self.check(&Token::RBrace) && !self.is_eof() {
1077 let field_name = self.parse_ident()?;
1078 self.expect(Token::Colon)?;
1079 let binding = self.parse_ident()?;
1080 fields.push((field_name, binding));
1081
1082 if !self.consume_if(&Token::Comma) {
1083 break;
1084 }
1085 }
1086 self.expect(Token::RBrace)?;
1087 }
1088
1089 Ok(TriggerPattern {
1090 trigger_type,
1091 fields,
1092 })
1093 }
1094
1095 fn parse_bracketed_expr_list(&mut self) -> ParseResult<Vec<Expr>> {
1097 self.expect(Token::LBracket)?;
1098
1099 let mut exprs = Vec::new();
1100
1101 while !self.check(&Token::RBracket) && !self.is_eof() {
1102 exprs.push(self.parse_expr()?);
1103 if !self.consume_if(&Token::Comma) {
1104 break;
1105 }
1106 }
1107
1108 self.expect(Token::RBracket)?;
1109 Ok(exprs)
1110 }
1111}
1112
1113impl Default for SwitchConfig {
1118 fn default() -> Self {
1119 Self {
1120 reason: None,
1121 urgency: None,
1122 requires: None,
1123 then_block: None,
1124 else_block: None,
1125 emergency_block: None,
1126 bypass_deliberation: false,
1127 }
1128 }
1129}
1130
1131#[cfg(test)]
1136mod tests {
1137 use super::*;
1138
1139 fn parse_plurality(source: &str) -> ParseResult<PluralityItem> {
1140 let mut parser = Parser::new(source);
1141 parser.parse_plurality_item()
1142 }
1143
1144 #[test]
1145 fn test_parse_alter_def_basic() {
1146 let source = r#"
1147 alter Abaddon: Council {
1148 archetype: Goetia::Abaddon,
1149 }
1150 "#;
1151 let result = parse_plurality(source);
1152 assert!(result.is_ok());
1153 if let Ok(PluralityItem::Alter(def)) = result {
1154 assert_eq!(def.name.name, "Abaddon");
1155 assert_eq!(def.category, AlterCategory::Council);
1156 }
1157 }
1158
1159 #[test]
1160 fn test_parse_switch_expr() {
1161 let source = r#"
1162 alter test {
1163 switch to Beleth {
1164 reason: SwitchReason::Combat,
1165 urgency: 0.8,
1166 }
1167 }
1168 "#;
1169 }
1171}