sigil_parser/plurality/
parser.rs

1//! # Plurality Parser Extensions
2//!
3//! Parser rules for plurality constructs:
4//! - Alter definitions: `alter Name: Category { ... }`
5//! - Alter blocks: `alter Name { ... }`
6//! - Switch expressions: `switch to Alter { ... }` or `switch! to Alter { ... }`
7//! - Headspace definitions: `headspace Name { ... }`
8//! - Co-con channels: `cocon<A, B> name { ... }`
9//! - Reality definitions: `reality entity Name { ... }`
10//! - Split expressions: `split! from Alter { ... }`
11//! - Trigger handlers: `on trigger Name { ... } where condition { ... }`
12
13use 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
21// ============================================================================
22// PARSER EXTENSION TRAIT
23// ============================================================================
24
25/// Extension trait for parsing plurality constructs
26pub trait PluralityParser {
27    // Top-level items
28    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    // Expressions
36    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    // Type extensions
42    fn parse_alter_sourced_type(&mut self) -> ParseResult<AlterSourcedType>;
43
44    // Helpers
45    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    // ========================================================================
52    // TOP-LEVEL ITEMS
53    // ========================================================================
54
55    /// Parse a top-level plurality item
56    fn parse_plurality_item(&mut self) -> ParseResult<PluralityItem> {
57        let visibility = self.parse_visibility()?;
58
59        match self.current_token() {
60            Some(Token::Alter) => Ok(PluralityItem::Alter(self.parse_alter_def(visibility)?)),
61            Some(Token::Headspace) => Ok(PluralityItem::Headspace(
62                self.parse_headspace_def(visibility)?,
63            )),
64            Some(Token::Reality) => Ok(PluralityItem::Reality(self.parse_reality_def(visibility)?)),
65            Some(Token::CoCon) => Ok(PluralityItem::CoConChannel(self.parse_cocon_channel()?)),
66            Some(Token::On) => Ok(PluralityItem::TriggerHandler(self.parse_trigger_handler()?)),
67            Some(t) => Err(ParseError::UnexpectedToken {
68                expected: "plurality item (alter, headspace, reality, cocon, or trigger handler)"
69                    .to_string(),
70                found: t.clone(),
71                span: self.current_span(),
72            }),
73            None => Err(ParseError::UnexpectedEof),
74        }
75    }
76
77    /// Parse an alter definition
78    ///
79    /// ```sigil
80    /// alter Abaddon: Council {
81    ///     archetype: Goetia::Abaddon,
82    ///     preferred_reality: RealityLayer::Fractured,
83    ///     abilities: [...],
84    ///     triggers: [...],
85    ///     anima: { ... },
86    ///     states: { ... }
87    /// }
88    /// ```
89    fn parse_alter_def(&mut self, visibility: Visibility) -> ParseResult<AlterDef> {
90        let start = self.current_span();
91
92        // Expect 'alter' keyword
93        self.expect(Token::Alter)?;
94
95        // Parse alter name
96        let name = self.parse_ident()?;
97
98        // Parse optional category (: Council, : Servant, etc.)
99        let category = if self.consume_if(&Token::Colon) {
100            let cat_ident = self.parse_ident()?;
101            AlterCategory::from_ident(&cat_ident)
102        } else {
103            AlterCategory::Custom
104        };
105
106        // Parse optional generics
107        let generics = self.parse_generics_opt()?;
108
109        // Parse optional where clause
110        let where_clause = self.parse_where_clause_opt()?;
111
112        // Parse body
113        self.expect(Token::LBrace)?;
114        let body = self.parse_alter_body()?;
115        self.expect(Token::RBrace)?;
116
117        let end = self.current_span();
118
119        Ok(AlterDef {
120            visibility,
121            attrs: Vec::new(),
122            name,
123            category,
124            generics,
125            where_clause,
126            body,
127            span: start.merge(end),
128        })
129    }
130
131    /// Parse a headspace definition
132    ///
133    /// ```sigil
134    /// headspace InnerWorld {
135    ///     location Citadel: Sanctuary { ... }
136    ///     fn navigate(from: Location, to: Location) -> NavigationResult@? { ... }
137    /// }
138    /// ```
139    fn parse_headspace_def(&mut self, visibility: Visibility) -> ParseResult<HeadspaceDef> {
140        let start = self.current_span();
141
142        self.expect(Token::Headspace)?;
143        let name = self.parse_ident()?;
144
145        self.expect(Token::LBrace)?;
146
147        let mut locations = Vec::new();
148        let mut methods = Vec::new();
149
150        while !self.check(&Token::RBrace) && !self.is_eof() {
151            self.skip_comments();
152
153            if self.check(&Token::Location) {
154                locations.push(self.parse_location_def()?);
155            } else if self.check(&Token::Fn) || self.check(&Token::Async) {
156                methods.push(self.parse_alter_method()?);
157            } else if self.check(&Token::RBrace) {
158                break;
159            } else {
160                return Err(ParseError::UnexpectedToken {
161                    expected: "location or method".to_string(),
162                    found: self.current_token().cloned().unwrap_or(Token::RBrace),
163                    span: self.current_span(),
164                });
165            }
166        }
167
168        self.expect(Token::RBrace)?;
169        let end = self.current_span();
170
171        Ok(HeadspaceDef {
172            visibility,
173            name,
174            locations,
175            methods,
176            span: start.merge(end),
177        })
178    }
179
180    /// Parse a reality definition
181    ///
182    /// ```sigil
183    /// reality entity Church {
184    ///     layer Grounded { ... }
185    ///     layer Fractured { ... }
186    ///     transform Grounded -> Fractured: on perception > 0.5,
187    /// }
188    /// ```
189    fn parse_reality_def(&mut self, visibility: Visibility) -> ParseResult<RealityDef> {
190        let start = self.current_span();
191
192        self.expect(Token::Reality)?;
193        self.expect_ident("entity")?;
194        let name = self.parse_ident()?;
195
196        self.expect(Token::LBrace)?;
197
198        let mut layers = Vec::new();
199        let mut transforms = Vec::new();
200
201        while !self.check(&Token::RBrace) && !self.is_eof() {
202            self.skip_comments();
203
204            if self.check(&Token::Layer) {
205                layers.push(self.parse_reality_layer()?);
206            } else if self.check_ident("transform") {
207                transforms.push(self.parse_reality_transform()?);
208            } else if self.check(&Token::RBrace) {
209                break;
210            } else {
211                return Err(ParseError::UnexpectedToken {
212                    expected: "layer or transform".to_string(),
213                    found: self.current_token().cloned().unwrap_or(Token::RBrace),
214                    span: self.current_span(),
215                });
216            }
217        }
218
219        self.expect(Token::RBrace)?;
220        let end = self.current_span();
221
222        Ok(RealityDef {
223            visibility,
224            name,
225            layers,
226            transforms,
227            span: start.merge(end),
228        })
229    }
230
231    /// Parse a co-conscious channel
232    ///
233    /// ```sigil
234    /// cocon<Stolas, Paimon> knowledge_share {
235    ///     fn share_discovery(info: Knowledge!) -> Acknowledgment~ { ... }
236    /// }
237    /// ```
238    fn parse_cocon_channel(&mut self) -> ParseResult<CoConChannel> {
239        let start = self.current_span();
240
241        self.expect(Token::CoCon)?;
242        self.expect(Token::Lt)?;
243
244        // Parse participating alters
245        let mut participants = Vec::new();
246        participants.push(self.parse_ident()?);
247        while self.consume_if(&Token::Comma) {
248            if self.check(&Token::Gt) {
249                break;
250            }
251            participants.push(self.parse_ident()?);
252        }
253        self.expect_gt()?;
254
255        let name = self.parse_ident()?;
256        let body = self.parse_block()?;
257        let end = self.current_span();
258
259        Ok(CoConChannel {
260            participants,
261            name,
262            body,
263            span: start.merge(end),
264        })
265    }
266
267    /// Parse a trigger handler
268    ///
269    /// ```sigil
270    /// on trigger ThreatDetected { level: threat } where threat > 0.9 {
271    ///     switch! to Abaddon { ... }
272    /// }
273    /// ```
274    fn parse_trigger_handler(&mut self) -> ParseResult<TriggerHandler> {
275        let start = self.current_span();
276
277        self.expect(Token::On)?;
278        self.expect(Token::Trigger)?;
279
280        // Parse trigger pattern
281        let pattern = self.parse_trigger_pattern()?;
282
283        // Parse optional guard
284        let guard = if self.consume_if(&Token::Where) {
285            Some(self.parse_expr()?)
286        } else {
287            None
288        };
289
290        // Parse handler body
291        let body = self.parse_block()?;
292        let end = self.current_span();
293
294        Ok(TriggerHandler {
295            pattern,
296            guard,
297            body,
298            span: start.merge(end),
299        })
300    }
301
302    // ========================================================================
303    // EXPRESSIONS
304    // ========================================================================
305
306    /// Parse a plurality-specific expression
307    fn parse_plurality_expr(&mut self) -> ParseResult<PluralityExpr> {
308        match self.current_token() {
309            Some(Token::Alter) => Ok(PluralityExpr::AlterBlock(self.parse_alter_block()?)),
310            Some(Token::Switch) => Ok(PluralityExpr::Switch(self.parse_switch_expr()?)),
311            Some(Token::Split) => Ok(PluralityExpr::Split(self.parse_split_expr()?)),
312            Some(t) => Err(ParseError::UnexpectedToken {
313                expected: "plurality expression (alter, switch, or split)".to_string(),
314                found: t.clone(),
315                span: self.current_span(),
316            }),
317            None => Err(ParseError::UnexpectedEof),
318        }
319    }
320
321    /// Parse an alter block (scoped fronting)
322    ///
323    /// ```sigil
324    /// alter Abaddon {
325    ///     let threat = perceive_entity(enemy);
326    /// }
327    /// ```
328    fn parse_alter_block(&mut self) -> ParseResult<AlterBlock> {
329        let start = self.current_span();
330
331        self.expect(Token::Alter)?;
332        let alter = self.parse_alter_expr()?;
333        let body = self.parse_block()?;
334        let end = self.current_span();
335
336        Ok(AlterBlock {
337            alter,
338            body,
339            span: start.merge(end),
340        })
341    }
342
343    /// Parse a switch expression
344    ///
345    /// ```sigil
346    /// switch to Beleth {
347    ///     reason: SwitchReason::TacticalNeed,
348    ///     urgency: 0.8,
349    ///     then: { ... },
350    ///     else: { ... },
351    /// }
352    /// ```
353    fn parse_switch_expr(&mut self) -> ParseResult<SwitchExpr> {
354        let start = self.current_span();
355
356        self.expect(Token::Switch)?;
357
358        // Check for forced switch (switch!)
359        let forced = self.consume_if(&Token::Bang);
360
361        self.expect(Token::To)?;
362        let target = self.parse_alter_expr()?;
363
364        // Parse switch configuration block
365        let config = if self.check(&Token::LBrace) {
366            self.parse_switch_config()?
367        } else {
368            SwitchConfig::default()
369        };
370
371        let end = self.current_span();
372
373        Ok(SwitchExpr {
374            forced,
375            target,
376            config,
377            span: start.merge(end),
378        })
379    }
380
381    /// Parse a split expression
382    ///
383    /// ```sigil
384    /// split! from trauma.primary_holder {
385    ///     purpose: SplitPurpose::TraumaHolder,
386    ///     memories: inherited_memories(),
387    ///     traits: possibly_inverted_traits(),
388    /// }
389    /// ```
390    fn parse_split_expr(&mut self) -> ParseResult<SplitExpr> {
391        let start = self.current_span();
392
393        self.expect(Token::Split)?;
394        self.expect(Token::Bang)?; // split! is always forced
395        self.expect(Token::From)?;
396
397        let parent = self.parse_alter_expr()?;
398        let config = self.parse_split_config()?;
399        let end = self.current_span();
400
401        Ok(SplitExpr {
402            parent,
403            config,
404            span: start.merge(end),
405        })
406    }
407
408    // ========================================================================
409    // TYPE EXTENSIONS
410    // ========================================================================
411
412    /// Parse a type with optional alter-source marker
413    ///
414    /// ```sigil
415    /// WorldState@!     // Fronting alter's view
416    /// Vec<Voice>@~     // Co-conscious report
417    /// Memory@?         // Dormant alter's uncertain memory
418    /// State@‽          // Blended paradoxical state
419    /// ```
420    fn parse_alter_sourced_type(&mut self) -> ParseResult<AlterSourcedType> {
421        let start = self.current_span();
422        let inner = self.parse_type()?;
423
424        // Check for alter-source marker
425        if let Some(marker) = self.try_parse_alter_source_marker() {
426            let end = self.current_span();
427            let alter_source = match marker {
428                AlterSourceMarker::Fronting => AlterSource::Fronting,
429                AlterSourceMarker::CoCon => AlterSource::CoConscious(None),
430                AlterSourceMarker::Dormant => AlterSource::Dormant(None),
431                AlterSourceMarker::Blended => AlterSource::Blended(Vec::new()),
432            };
433
434            Ok(AlterSourcedType {
435                inner,
436                alter_source,
437                span: start.merge(end),
438            })
439        } else {
440            // No alter-source, return with Fronting as default
441            let end = self.current_span();
442            Ok(AlterSourcedType {
443                inner,
444                alter_source: AlterSource::Fronting,
445                span: start.merge(end),
446            })
447        }
448    }
449
450    // ========================================================================
451    // HELPERS
452    // ========================================================================
453
454    /// Parse an alter expression (reference to an alter)
455    fn parse_alter_expr(&mut self) -> ParseResult<AlterExpr> {
456        match self.current_token() {
457            Some(Token::Ident(_)) => {
458                let ident = self.parse_ident()?;
459
460                // Check for method call like `council·fronter()`
461                if self.check(&Token::MiddleDot) {
462                    self.advance();
463                    let method = self.parse_ident()?;
464                    if self.check(&Token::LParen) {
465                        // Parse method call arguments
466                        self.advance(); // consume (
467                        let mut args = Vec::new();
468                        while !self.check(&Token::RParen) && !self.is_eof() {
469                            args.push(self.parse_expr()?);
470                            if !self.consume_if(&Token::Comma) {
471                                break;
472                            }
473                        }
474                        self.expect(Token::RParen)?;
475
476                        // Build method call expression
477                        let receiver_path = crate::ast::TypePath {
478                            segments: vec![crate::ast::PathSegment {
479                                ident: ident.clone(),
480                                generics: None,
481                            }],
482                        };
483                        let call_expr = Expr::MethodCall {
484                            receiver: Box::new(Expr::Path(receiver_path)),
485                            method,
486                            type_args: None,
487                            args,
488                        };
489                        return Ok(AlterExpr::CurrentFronter(Box::new(call_expr)));
490                    }
491                    // Reconstruct as path expression with combined name
492                    let combined_path = crate::ast::TypePath {
493                        segments: vec![crate::ast::PathSegment {
494                            ident: Ident {
495                                name: format!("{}.{}", ident.name, method.name),
496                                evidentiality: None,
497                                affect: None,
498                                span: ident.span.merge(method.span),
499                            },
500                            generics: None,
501                        }],
502                    };
503                    return Ok(AlterExpr::Expr(Box::new(Expr::Path(combined_path))));
504                }
505
506                Ok(AlterExpr::Named(ident))
507            }
508            Some(_) => {
509                // Parse as general expression
510                let expr = self.parse_expr()?;
511                Ok(AlterExpr::Expr(Box::new(expr)))
512            }
513            None => Err(ParseError::UnexpectedEof),
514        }
515    }
516
517    /// Parse an alter-source annotation (@!, @~, @?, @‽, or @AlterName)
518    fn parse_alter_source(&mut self) -> ParseResult<Option<AlterSource>> {
519        if !self.check(&Token::At) {
520            return Ok(None);
521        }
522
523        self.advance(); // consume @
524
525        match self.current_token() {
526            Some(Token::Bang) => {
527                self.advance();
528                Ok(Some(AlterSource::Fronting))
529            }
530            Some(Token::Tilde) => {
531                self.advance();
532                Ok(Some(AlterSource::CoConscious(None)))
533            }
534            Some(Token::Question) => {
535                self.advance();
536                Ok(Some(AlterSource::Dormant(None)))
537            }
538            Some(Token::Interrobang) => {
539                self.advance();
540                Ok(Some(AlterSource::Blended(Vec::new())))
541            }
542            Some(Token::Ident(_)) => {
543                let ident = self.parse_ident()?;
544                match ident.name.as_str() {
545                    "Fronting" => Ok(Some(AlterSource::Fronting)),
546                    "CoCon" => Ok(Some(AlterSource::CoConscious(None))),
547                    "Dormant" => Ok(Some(AlterSource::Dormant(None))),
548                    "Blended" => Ok(Some(AlterSource::Blended(Vec::new()))),
549                    _ => Ok(Some(AlterSource::Named(ident))),
550                }
551            }
552            _ => Ok(None),
553        }
554    }
555
556    /// Try to parse an alter-source marker if present
557    fn try_parse_alter_source_marker(&mut self) -> Option<AlterSourceMarker> {
558        if !self.check(&Token::At) {
559            return None;
560        }
561
562        // Peek at next token
563        let next = self.peek_next()?;
564        let marker = match next {
565            Token::Bang => Some(AlterSourceMarker::Fronting),
566            Token::Tilde => Some(AlterSourceMarker::CoCon),
567            Token::Question => Some(AlterSourceMarker::Dormant),
568            Token::Interrobang => Some(AlterSourceMarker::Blended),
569            _ => None,
570        };
571
572        if marker.is_some() {
573            self.advance(); // consume @
574            self.advance(); // consume marker
575        }
576
577        marker
578    }
579}
580
581// ============================================================================
582// PRIVATE PARSER HELPERS
583// ============================================================================
584
585impl<'a> Parser<'a> {
586    /// Check if current token is a specific identifier
587    fn check_ident(&self, name: &str) -> bool {
588        matches!(self.current_token(), Some(Token::Ident(s)) if s == name)
589    }
590
591    /// Expect a specific identifier
592    fn expect_ident(&mut self, name: &str) -> ParseResult<Span> {
593        match self.current_token() {
594            Some(Token::Ident(s)) if s == name => {
595                let span = self.current_span();
596                self.advance();
597                Ok(span)
598            }
599            Some(t) => Err(ParseError::UnexpectedToken {
600                expected: format!("identifier '{}'", name),
601                found: t.clone(),
602                span: self.current_span(),
603            }),
604            None => Err(ParseError::UnexpectedEof),
605        }
606    }
607
608    /// Parse the body of an alter definition
609    fn parse_alter_body(&mut self) -> ParseResult<AlterBody> {
610        let mut body = AlterBody {
611            archetype: None,
612            preferred_reality: None,
613            abilities: Vec::new(),
614            triggers: Vec::new(),
615            anima: None,
616            states: None,
617            special: Vec::new(),
618            methods: Vec::new(),
619            types: Vec::new(),
620        };
621
622        while !self.check(&Token::RBrace) && !self.is_eof() {
623            self.skip_comments();
624
625            match self.current_token() {
626                // Handle keyword tokens for anima and states
627                Some(Token::Anima) => {
628                    self.advance();
629                    self.expect(Token::Colon)?;
630                    body.anima = Some(self.parse_anima_config()?);
631                    self.consume_if(&Token::Comma);
632                }
633                Some(Token::States) => {
634                    self.advance();
635                    self.expect(Token::Colon)?;
636                    body.states = Some(self.parse_alter_state_machine()?);
637                    self.consume_if(&Token::Comma);
638                }
639                // Handle identifier-based fields
640                Some(Token::Ident(s)) => match s.as_str() {
641                    "archetype" => {
642                        self.advance();
643                        self.expect(Token::Colon)?;
644                        body.archetype = Some(self.parse_expr()?);
645                        self.consume_if(&Token::Comma);
646                    }
647                    "preferred_reality" => {
648                        self.advance();
649                        self.expect(Token::Colon)?;
650                        body.preferred_reality = Some(self.parse_expr()?);
651                        self.consume_if(&Token::Comma);
652                    }
653                    "abilities" => {
654                        self.advance();
655                        self.expect(Token::Colon)?;
656                        body.abilities = self.parse_bracketed_expr_list()?;
657                        self.consume_if(&Token::Comma);
658                    }
659                    "triggers" => {
660                        self.advance();
661                        self.expect(Token::Colon)?;
662                        body.triggers = self.parse_bracketed_expr_list()?;
663                        self.consume_if(&Token::Comma);
664                    }
665                    _ => {
666                        // Unknown field - error
667                        return Err(ParseError::UnexpectedToken {
668                            expected: "alter body field".to_string(),
669                            found: Token::Ident(s.clone()),
670                            span: self.current_span(),
671                        });
672                    }
673                },
674                Some(Token::Fn) | Some(Token::Async) => {
675                    body.methods.push(self.parse_alter_method()?);
676                }
677                Some(Token::Type) => {
678                    body.types.push(self.parse_alter_type_alias()?);
679                }
680                Some(Token::RBrace) => break,
681                Some(t) => {
682                    return Err(ParseError::UnexpectedToken {
683                        expected: "alter body field or method".to_string(),
684                        found: t.clone(),
685                        span: self.current_span(),
686                    });
687                }
688                None => return Err(ParseError::UnexpectedEof),
689            }
690        }
691
692        Ok(body)
693    }
694
695    /// Parse anima configuration
696    fn parse_anima_config(&mut self) -> ParseResult<AnimaConfig> {
697        self.expect(Token::LBrace)?;
698
699        let mut config = AnimaConfig {
700            base_arousal: None,
701            base_dominance: None,
702            expressiveness: None,
703            susceptibility: None,
704            extra: Vec::new(),
705        };
706
707        while !self.check(&Token::RBrace) && !self.is_eof() {
708            self.skip_comments();
709
710            let field_name = self.parse_ident()?;
711            self.expect(Token::Colon)?;
712            let value = self.parse_expr()?;
713
714            match field_name.name.as_str() {
715                "base_arousal" => config.base_arousal = Some(value),
716                "base_dominance" => config.base_dominance = Some(value),
717                "expressiveness" => config.expressiveness = Some(value),
718                "susceptibility" => config.susceptibility = Some(value),
719                _ => config.extra.push((field_name, value)),
720            }
721
722            self.consume_if(&Token::Comma);
723        }
724
725        self.expect(Token::RBrace)?;
726        Ok(config)
727    }
728
729    /// Parse alter state machine
730    fn parse_alter_state_machine(&mut self) -> ParseResult<AlterStateMachine> {
731        self.expect(Token::LBrace)?;
732
733        let mut transitions = Vec::new();
734
735        while !self.check(&Token::RBrace) && !self.is_eof() {
736            self.skip_comments();
737            transitions.push(self.parse_alter_transition()?);
738            self.consume_if(&Token::Comma);
739        }
740
741        self.expect(Token::RBrace)?;
742        Ok(AlterStateMachine { transitions })
743    }
744
745    /// Parse a single state transition
746    /// `Dormant -> Stirring: on Trigger::match`
747    fn parse_alter_transition(&mut self) -> ParseResult<AlterTransition> {
748        let from_ident = self.parse_ident()?;
749        let from = AlterState::from_ident(&from_ident);
750
751        self.expect(Token::Arrow)?;
752
753        let to_ident = self.parse_ident()?;
754        let to = AlterState::from_ident(&to_ident);
755
756        self.expect(Token::Colon)?;
757        self.expect(Token::On)?;
758
759        let on = self.parse_expr()?;
760
761        // Optional guard
762        let guard = if self.check(&Token::Where) {
763            self.advance();
764            Some(self.parse_expr()?)
765        } else {
766            None
767        };
768
769        // Optional action block
770        let action = if self.check(&Token::LBrace) {
771            Some(self.parse_block()?)
772        } else {
773            None
774        };
775
776        Ok(AlterTransition {
777            from,
778            to,
779            on,
780            guard,
781            action,
782        })
783    }
784
785    /// Parse an alter method
786    fn parse_alter_method(&mut self) -> ParseResult<AlterMethod> {
787        let visibility = self.parse_visibility()?;
788        let is_async = self.consume_if(&Token::Async);
789        self.expect(Token::Fn)?;
790        let name = self.parse_ident()?;
791
792        self.expect(Token::LParen)?;
793        let params = self.parse_params()?;
794        self.expect(Token::RParen)?;
795
796        let return_type = if self.consume_if(&Token::Arrow) {
797            Some(self.parse_type()?)
798        } else {
799            None
800        };
801
802        let body = if self.check(&Token::LBrace) {
803            Some(self.parse_block()?)
804        } else {
805            self.consume_if(&Token::Semi);
806            None
807        };
808
809        Ok(AlterMethod {
810            visibility,
811            is_async,
812            name,
813            params,
814            return_type,
815            body,
816        })
817    }
818
819    /// Parse an alter type alias
820    fn parse_alter_type_alias(&mut self) -> ParseResult<AlterTypeAlias> {
821        let visibility = self.parse_visibility()?;
822        self.expect(Token::Type)?;
823        let name = self.parse_ident()?;
824        self.expect(Token::Eq)?;
825        let ty = self.parse_type()?;
826        self.consume_if(&Token::Semi);
827
828        Ok(AlterTypeAlias {
829            visibility,
830            name,
831            ty,
832        })
833    }
834
835    /// Parse a location definition in headspace
836    fn parse_location_def(&mut self) -> ParseResult<LocationDef> {
837        self.expect(Token::Location)?;
838        let name = self.parse_ident()?;
839        self.expect(Token::Colon)?;
840        let location_type = self.parse_ident()?;
841
842        self.expect(Token::LBrace)?;
843
844        let mut fields = Vec::new();
845        let mut connections = Vec::new();
846        let mut hazards = Vec::new();
847
848        while !self.check(&Token::RBrace) && !self.is_eof() {
849            self.skip_comments();
850
851            let field_name = self.parse_ident()?;
852            self.expect(Token::Colon)?;
853
854            match field_name.name.as_str() {
855                "connections" => {
856                    // Parse array of stream definitions
857                    self.expect(Token::LBracket)?;
858                    while !self.check(&Token::RBracket) {
859                        connections.push(self.parse_stream_def()?);
860                        self.consume_if(&Token::Comma);
861                    }
862                    self.expect(Token::RBracket)?;
863                }
864                "hazards" => {
865                    hazards = self.parse_bracketed_expr_list()?;
866                }
867                _ => {
868                    let value = self.parse_expr()?;
869                    fields.push((field_name, value));
870                }
871            }
872
873            self.consume_if(&Token::Comma);
874        }
875
876        self.expect(Token::RBrace)?;
877
878        Ok(LocationDef {
879            name,
880            location_type,
881            fields,
882            connections,
883            hazards,
884        })
885    }
886
887    /// Parse a stream definition
888    /// `stream!(Target, bidirectional: true, locked: false)`
889    fn parse_stream_def(&mut self) -> ParseResult<StreamDef> {
890        // Could be `stream!(...)` macro or inline definition
891        let target = self.parse_ident()?;
892
893        let mut bidirectional = false;
894        let mut locked = false;
895        let mut content = None;
896
897        // Check for options
898        if self.consume_if(&Token::Comma) {
899            while !self.check(&Token::RParen)
900                && !self.check(&Token::RBracket)
901                && !self.check(&Token::Comma)
902                && !self.is_eof()
903            {
904                let opt_name = self.parse_ident()?;
905                self.expect(Token::Colon)?;
906
907                match opt_name.name.as_str() {
908                    "bidirectional" => {
909                        bidirectional = self.consume_if(&Token::True);
910                        if !bidirectional {
911                            self.consume_if(&Token::False);
912                        }
913                    }
914                    "locked" => {
915                        locked = self.consume_if(&Token::True);
916                        if !locked {
917                            self.consume_if(&Token::False);
918                        }
919                    }
920                    "content" => {
921                        content = Some(self.parse_expr()?);
922                    }
923                    _ => {}
924                }
925
926                if !self.consume_if(&Token::Comma) {
927                    break;
928                }
929            }
930        }
931
932        Ok(StreamDef {
933            target,
934            content,
935            bidirectional,
936            locked,
937        })
938    }
939
940    /// Parse a reality layer
941    fn parse_reality_layer(&mut self) -> ParseResult<RealityLayer> {
942        self.expect(Token::Layer)?;
943        let name = self.parse_ident()?;
944
945        self.expect(Token::LBrace)?;
946
947        let mut fields = Vec::new();
948
949        while !self.check(&Token::RBrace) && !self.is_eof() {
950            self.skip_comments();
951
952            let field_name = self.parse_ident()?;
953            self.expect(Token::Colon)?;
954            let value = self.parse_expr()?;
955            fields.push((field_name, value));
956
957            self.consume_if(&Token::Comma);
958        }
959
960        self.expect(Token::RBrace)?;
961
962        Ok(RealityLayer { name, fields })
963    }
964
965    /// Parse a reality transform rule
966    fn parse_reality_transform(&mut self) -> ParseResult<RealityTransform> {
967        self.expect_ident("transform")?;
968        let from = self.parse_ident()?;
969        self.expect(Token::Arrow)?;
970        let to = self.parse_ident()?;
971        self.expect(Token::Colon)?;
972        self.expect(Token::On)?;
973        let condition = self.parse_expr()?;
974        self.consume_if(&Token::Comma);
975
976        Ok(RealityTransform {
977            from,
978            to,
979            condition,
980        })
981    }
982
983    /// Parse switch configuration
984    fn parse_switch_config(&mut self) -> ParseResult<SwitchConfig> {
985        self.expect(Token::LBrace)?;
986
987        let mut config = SwitchConfig {
988            reason: None,
989            urgency: None,
990            requires: None,
991            then_block: None,
992            else_block: None,
993            emergency_block: None,
994            bypass_deliberation: false,
995        };
996
997        while !self.check(&Token::RBrace) && !self.is_eof() {
998            self.skip_comments();
999
1000            let field_name = self.parse_ident()?;
1001            self.expect(Token::Colon)?;
1002
1003            match field_name.name.as_str() {
1004                "reason" => config.reason = Some(self.parse_expr()?),
1005                "urgency" => config.urgency = Some(self.parse_expr()?),
1006                "requires" => config.requires = Some(self.parse_expr()?),
1007                "then" => config.then_block = Some(self.parse_block()?),
1008                "else" => config.else_block = Some(self.parse_block()?),
1009                "emergency" => config.emergency_block = Some(self.parse_block()?),
1010                "bypass_deliberation" => {
1011                    config.bypass_deliberation = self.consume_if(&Token::True);
1012                    if !config.bypass_deliberation {
1013                        self.consume_if(&Token::False);
1014                    }
1015                }
1016                _ => {
1017                    // Skip unknown fields
1018                    let _ = self.parse_expr()?;
1019                }
1020            }
1021
1022            self.consume_if(&Token::Comma);
1023        }
1024
1025        self.expect(Token::RBrace)?;
1026        Ok(config)
1027    }
1028
1029    /// Parse split configuration
1030    fn parse_split_config(&mut self) -> ParseResult<SplitConfig> {
1031        self.expect(Token::LBrace)?;
1032
1033        let mut config = SplitConfig {
1034            purpose: None,
1035            memories: None,
1036            traits: None,
1037            extra: Vec::new(),
1038        };
1039
1040        while !self.check(&Token::RBrace) && !self.is_eof() {
1041            self.skip_comments();
1042
1043            let field_name = self.parse_ident()?;
1044            self.expect(Token::Colon)?;
1045            let value = self.parse_expr()?;
1046
1047            match field_name.name.as_str() {
1048                "purpose" => config.purpose = Some(value),
1049                "memories" => config.memories = Some(value),
1050                "traits" => config.traits = Some(value),
1051                _ => config.extra.push((field_name, value)),
1052            }
1053
1054            self.consume_if(&Token::Comma);
1055        }
1056
1057        self.expect(Token::RBrace)?;
1058        Ok(config)
1059    }
1060
1061    /// Parse trigger pattern
1062    fn parse_trigger_pattern(&mut self) -> ParseResult<TriggerPattern> {
1063        let trigger_type = self.parse_ident()?;
1064
1065        let mut fields = Vec::new();
1066
1067        if self.consume_if(&Token::LBrace) {
1068            while !self.check(&Token::RBrace) && !self.is_eof() {
1069                let field_name = self.parse_ident()?;
1070                self.expect(Token::Colon)?;
1071                let binding = self.parse_ident()?;
1072                fields.push((field_name, binding));
1073
1074                if !self.consume_if(&Token::Comma) {
1075                    break;
1076                }
1077            }
1078            self.expect(Token::RBrace)?;
1079        }
1080
1081        Ok(TriggerPattern {
1082            trigger_type,
1083            fields,
1084        })
1085    }
1086
1087    /// Parse a list of expressions in brackets
1088    fn parse_bracketed_expr_list(&mut self) -> ParseResult<Vec<Expr>> {
1089        self.expect(Token::LBracket)?;
1090
1091        let mut exprs = Vec::new();
1092
1093        while !self.check(&Token::RBracket) && !self.is_eof() {
1094            exprs.push(self.parse_expr()?);
1095            if !self.consume_if(&Token::Comma) {
1096                break;
1097            }
1098        }
1099
1100        self.expect(Token::RBracket)?;
1101        Ok(exprs)
1102    }
1103}
1104
1105// ============================================================================
1106// DEFAULT IMPLEMENTATIONS
1107// ============================================================================
1108
1109impl Default for SwitchConfig {
1110    fn default() -> Self {
1111        Self {
1112            reason: None,
1113            urgency: None,
1114            requires: None,
1115            then_block: None,
1116            else_block: None,
1117            emergency_block: None,
1118            bypass_deliberation: false,
1119        }
1120    }
1121}
1122
1123// ============================================================================
1124// TESTS
1125// ============================================================================
1126
1127#[cfg(test)]
1128mod tests {
1129    use super::*;
1130
1131    fn parse_plurality(source: &str) -> ParseResult<PluralityItem> {
1132        let mut parser = Parser::new(source);
1133        parser.parse_plurality_item()
1134    }
1135
1136    #[test]
1137    fn test_parse_alter_def_basic() {
1138        let source = r#"
1139            alter Abaddon: Council {
1140                archetype: Goetia::Abaddon,
1141            }
1142        "#;
1143        let result = parse_plurality(source);
1144        assert!(result.is_ok());
1145        if let Ok(PluralityItem::Alter(def)) = result {
1146            assert_eq!(def.name.name, "Abaddon");
1147            assert_eq!(def.category, AlterCategory::Council);
1148        }
1149    }
1150
1151    #[test]
1152    fn test_parse_switch_expr() {
1153        let source = r#"
1154            alter test {
1155                switch to Beleth {
1156                    reason: SwitchReason::Combat,
1157                    urgency: 0.8,
1158                }
1159            }
1160        "#;
1161        // This would need full parser integration to test
1162    }
1163}