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) => {
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    /// Parse an alter definition
84    ///
85    /// ```sigil
86    /// alter Abaddon: Council {
87    ///     archetype: Goetia::Abaddon,
88    ///     preferred_reality: RealityLayer::Fractured,
89    ///     abilities: [...],
90    ///     triggers: [...],
91    ///     anima: { ... },
92    ///     states: { ... }
93    /// }
94    /// ```
95    fn parse_alter_def(&mut self, visibility: Visibility) -> ParseResult<AlterDef> {
96        let start = self.current_span();
97
98        // Expect 'alter' keyword
99        self.expect(Token::Alter)?;
100
101        // Parse alter name
102        let name = self.parse_ident()?;
103
104        // Parse optional category (: Council, : Servant, etc.)
105        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        // Parse optional generics
113        let generics = self.parse_generics_opt()?;
114
115        // Parse optional where clause
116        let where_clause = self.parse_where_clause_opt()?;
117
118        // Parse body
119        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    /// Parse a headspace definition
138    ///
139    /// ```sigil
140    /// headspace InnerWorld {
141    ///     location Citadel: Sanctuary { ... }
142    ///     fn navigate(from: Location, to: Location) -> NavigationResult@? { ... }
143    /// }
144    /// ```
145    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    /// Parse a reality definition
187    ///
188    /// ```sigil
189    /// reality entity Church {
190    ///     layer Grounded { ... }
191    ///     layer Fractured { ... }
192    ///     transform Grounded -> Fractured: on perception > 0.5,
193    /// }
194    /// ```
195    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    /// Parse a co-conscious channel
238    ///
239    /// ```sigil
240    /// cocon<Stolas, Paimon> knowledge_share {
241    ///     fn share_discovery(info: Knowledge!) -> Acknowledgment~ { ... }
242    /// }
243    /// ```
244    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        // Parse participating alters
251        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    /// Parse a trigger handler
274    ///
275    /// ```sigil
276    /// on trigger ThreatDetected { level: threat } where threat > 0.9 {
277    ///     switch! to Abaddon { ... }
278    /// }
279    /// ```
280    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        // Parse trigger pattern
287        let pattern = self.parse_trigger_pattern()?;
288
289        // Parse optional guard
290        let guard = if self.consume_if(&Token::Where) {
291            Some(self.parse_expr()?)
292        } else {
293            None
294        };
295
296        // Parse handler body
297        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    // ========================================================================
309    // EXPRESSIONS
310    // ========================================================================
311
312    /// Parse a plurality-specific expression
313    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    /// Parse an alter block (scoped fronting)
334    ///
335    /// ```sigil
336    /// alter Abaddon {
337    ///     let threat = perceive_entity(enemy);
338    /// }
339    /// ```
340    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    /// Parse a switch expression
356    ///
357    /// ```sigil
358    /// switch to Beleth {
359    ///     reason: SwitchReason::TacticalNeed,
360    ///     urgency: 0.8,
361    ///     then: { ... },
362    ///     else: { ... },
363    /// }
364    /// ```
365    fn parse_switch_expr(&mut self) -> ParseResult<SwitchExpr> {
366        let start = self.current_span();
367
368        self.expect(Token::Switch)?;
369
370        // Check for forced switch (switch!)
371        let forced = self.consume_if(&Token::Bang);
372
373        self.expect(Token::To)?;
374        let target = self.parse_alter_expr()?;
375
376        // Parse switch configuration block
377        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    /// Parse a split expression
394    ///
395    /// ```sigil
396    /// split! from trauma.primary_holder {
397    ///     purpose: SplitPurpose::TraumaHolder,
398    ///     memories: inherited_memories(),
399    ///     traits: possibly_inverted_traits(),
400    /// }
401    /// ```
402    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)?; // split! is always forced
407        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    // ========================================================================
421    // TYPE EXTENSIONS
422    // ========================================================================
423
424    /// Parse a type with optional alter-source marker
425    ///
426    /// ```sigil
427    /// WorldState@!     // Fronting alter's view
428    /// Vec<Voice>@~     // Co-conscious report
429    /// Memory@?         // Dormant alter's uncertain memory
430    /// State@‽          // Blended paradoxical state
431    /// ```
432    fn parse_alter_sourced_type(&mut self) -> ParseResult<AlterSourcedType> {
433        let start = self.current_span();
434        let inner = self.parse_type()?;
435
436        // Check for alter-source marker
437        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            // No alter-source, return with Fronting as default
453            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    // ========================================================================
463    // HELPERS
464    // ========================================================================
465
466    /// Parse an alter expression (reference to an alter)
467    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                // Check for method call like `council·fronter()`
473                if self.check(&Token::MiddleDot) {
474                    self.advance();
475                    let method = self.parse_ident()?;
476                    if self.check(&Token::LParen) {
477                        // Parse method call arguments
478                        self.advance(); // consume (
479                        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                        // Build method call expression
489                        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                    // Reconstruct as path expression with combined name
504                    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                // Parse as general expression
522                let expr = self.parse_expr()?;
523                Ok(AlterExpr::Expr(Box::new(expr)))
524            }
525            None => Err(ParseError::UnexpectedEof),
526        }
527    }
528
529    /// Parse an alter-source annotation (@!, @~, @?, @‽, or @AlterName)
530    fn parse_alter_source(&mut self) -> ParseResult<Option<AlterSource>> {
531        if !self.check(&Token::At) {
532            return Ok(None);
533        }
534
535        self.advance(); // consume @
536
537        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    /// Try to parse an alter-source marker if present
569    fn try_parse_alter_source_marker(&mut self) -> Option<AlterSourceMarker> {
570        if !self.check(&Token::At) {
571            return None;
572        }
573
574        // Peek at next token
575        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(); // consume @
586            self.advance(); // consume marker
587        }
588
589        marker
590    }
591}
592
593// ============================================================================
594// PRIVATE PARSER HELPERS
595// ============================================================================
596
597impl<'a> Parser<'a> {
598    /// Check if current token is a specific identifier
599    fn check_ident(&self, name: &str) -> bool {
600        matches!(self.current_token(), Some(Token::Ident(s)) if s == name)
601    }
602
603    /// Expect a specific identifier
604    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    /// Parse the body of an alter definition
621    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                // Handle keyword tokens for anima and states
639                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                // Handle identifier-based fields
652                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                        // Unknown field - error
679                        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    /// Parse anima configuration
708    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    /// Parse alter state machine
742    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    /// Parse a single state transition
758    /// `Dormant -> Stirring: on Trigger::match`
759    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        // Optional guard
774        let guard = if self.check(&Token::Where) {
775            self.advance();
776            Some(self.parse_expr()?)
777        } else {
778            None
779        };
780
781        // Optional action block
782        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    /// Parse an alter method
798    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    /// Parse an alter type alias
832    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    /// Parse a location definition in headspace
848    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                    // Parse array of stream definitions
869                    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    /// Parse a stream definition
900    /// `stream!(Target, bidirectional: true, locked: false)`
901    fn parse_stream_def(&mut self) -> ParseResult<StreamDef> {
902        // Could be `stream!(...)` macro or inline definition
903        let target = self.parse_ident()?;
904
905        let mut bidirectional = false;
906        let mut locked = false;
907        let mut content = None;
908
909        // Check for options
910        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    /// Parse a reality layer
953    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    /// Parse a reality transform rule
978    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    /// Parse switch configuration
992    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                    // Skip unknown fields
1026                    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    /// Parse split configuration
1038    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    /// Parse trigger pattern
1070    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    /// Parse a list of expressions in brackets
1096    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
1113// ============================================================================
1114// DEFAULT IMPLEMENTATIONS
1115// ============================================================================
1116
1117impl 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// ============================================================================
1132// TESTS
1133// ============================================================================
1134
1135#[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        // This would need full parser integration to test
1170    }
1171}