sigil_parser/
parser.rs

1//! Recursive descent parser for Sigil.
2//!
3//! Handles polysynthetic pipe chains, morpheme expressions, and evidentiality.
4
5use crate::ast::*;
6use crate::lexer::{Lexer, Token};
7use crate::span::{Span, Spanned};
8use thiserror::Error;
9
10#[derive(Error, Debug)]
11pub enum ParseError {
12    #[error("Unexpected token: expected {expected}, found {found:?} at {span}")]
13    UnexpectedToken {
14        expected: String,
15        found: Token,
16        span: Span,
17    },
18    #[error("Unexpected end of file")]
19    UnexpectedEof,
20    #[error("Invalid number literal: {0}")]
21    InvalidNumber(String),
22    #[error("Parse error: {0}")]
23    Custom(String),
24}
25
26pub type ParseResult<T> = Result<T, ParseError>;
27
28/// Recursive descent parser for Sigil.
29pub struct Parser<'a> {
30    lexer: Lexer<'a>,
31    current: Option<(Token, Span)>,
32    /// Tracks whether we're parsing a condition (if/while/for) where < is comparison not generics
33    in_condition: bool,
34    /// Tracks if we have a pending `>` from splitting `>>` (Shr) in generic contexts
35    pending_gt: Option<Span>,
36}
37
38impl<'a> Parser<'a> {
39    pub fn new(source: &'a str) -> Self {
40        let mut lexer = Lexer::new(source);
41        let current = lexer.next_token();
42        Self {
43            lexer,
44            current,
45            in_condition: false,
46            pending_gt: None,
47        }
48    }
49
50    /// Parse a complete source file.
51    pub fn parse_file(&mut self) -> ParseResult<SourceFile> {
52        // Parse inner attributes first (#![...])
53        let mut attrs = Vec::new();
54        while matches!(self.current_token(), Some(Token::HashBang)) {
55            attrs.push(self.parse_inner_attribute()?);
56        }
57
58        // Build crate config from attributes
59        let config = self.build_crate_config(&attrs);
60
61        let mut items = Vec::new();
62        while !self.is_eof() {
63            // Skip comments
64            while matches!(
65                self.current_token(),
66                Some(
67                    Token::LineComment(_)
68                        | Token::TildeComment(_)
69                        | Token::BlockComment(_)
70                        | Token::DocComment(_)
71                )
72            ) {
73                self.advance();
74            }
75            if self.is_eof() {
76                break;
77            }
78            items.push(self.parse_item()?);
79        }
80        Ok(SourceFile {
81            attrs,
82            config,
83            items,
84        })
85    }
86
87    /// Parse an inner attribute: `#![name]` or `#![name(args)]`
88    fn parse_inner_attribute(&mut self) -> ParseResult<Attribute> {
89        self.expect(Token::HashBang)?;
90        self.expect(Token::LBracket)?;
91
92        let name = self.parse_ident()?;
93        let args = self.parse_attr_args()?;
94
95        self.expect(Token::RBracket)?;
96
97        Ok(Attribute {
98            name,
99            args,
100            is_inner: true,
101        })
102    }
103
104    /// Parse an outer attribute: `#[name]` or `#[name(args)]` or `@[name]` or `@[name(args)]`
105    /// The `@[]` syntax is the preferred Sigil style.
106    /// Also supports the shorthand `@[Clone, Debug]` which expands to `@[derive(Clone, Debug)]`
107    fn parse_outer_attribute(&mut self) -> ParseResult<Attribute> {
108        // Accept either # or @ as attribute prefix
109        let is_at_syntax = self.check(&Token::At);
110        if is_at_syntax {
111            self.advance();
112        } else {
113            self.expect(Token::Hash)?;
114        }
115        self.expect(Token::LBracket)?;
116
117        let name = self.parse_attr_name()?;
118
119        // Check for @[Ident, Ident, ...] shorthand for derive
120        // Only applies to @ syntax when we see a comma after the first identifier
121        if is_at_syntax && self.check(&Token::Comma) && !self.check(&Token::LParen) {
122            // This is the shorthand @[Clone, Debug] syntax - convert to derive
123            let mut args = vec![AttrArg::Ident(name)];
124            while self.consume_if(&Token::Comma) {
125                if self.check(&Token::RBracket) {
126                    break; // Trailing comma
127                }
128                args.push(AttrArg::Ident(self.parse_attr_name()?));
129            }
130            self.expect(Token::RBracket)?;
131
132            // Return as derive attribute
133            Ok(Attribute {
134                name: Ident {
135                    name: "derive".to_string(),
136                    evidentiality: None,
137                    affect: None,
138                    span: self.current_span(),
139                },
140                args: Some(AttrArgs::Paren(args)),
141                is_inner: false,
142            })
143        } else {
144            let args = self.parse_attr_args()?;
145            self.expect(Token::RBracket)?;
146
147            Ok(Attribute {
148                name,
149                args,
150                is_inner: false,
151            })
152        }
153    }
154
155    /// Parse an attribute name (identifier, keyword, or path like async_trait::async_trait).
156    fn parse_attr_name(&mut self) -> ParseResult<Ident> {
157        let span = self.current_span();
158        let first_name = match self.current_token().cloned() {
159            Some(Token::Ident(name)) => {
160                self.advance();
161                name
162            }
163            // Handle keywords that can be used as attribute names
164            Some(Token::Naked) => {
165                self.advance();
166                "naked".to_string()
167            }
168            Some(Token::Unsafe) => {
169                self.advance();
170                "unsafe".to_string()
171            }
172            Some(Token::Asm) => {
173                self.advance();
174                "asm".to_string()
175            }
176            Some(Token::Volatile) => {
177                self.advance();
178                "volatile".to_string()
179            }
180            Some(Token::Derive) => {
181                self.advance();
182                "derive".to_string()
183            }
184            Some(Token::Simd) => {
185                self.advance();
186                "simd".to_string()
187            }
188            Some(Token::Atomic) => {
189                self.advance();
190                "atomic".to_string()
191            }
192            Some(Token::Macro) => {
193                self.advance();
194                "macro".to_string()
195            }
196            Some(t) => {
197                return Err(ParseError::UnexpectedToken {
198                    expected: "attribute name".to_string(),
199                    found: t,
200                    span,
201                })
202            }
203            None => return Err(ParseError::UnexpectedEof),
204        };
205
206        // Check for path continuation: attr_name::next_segment::...
207        let mut full_name = first_name;
208        while self.consume_if(&Token::ColonColon) {
209            let segment = match self.current_token().cloned() {
210                Some(Token::Ident(name)) => {
211                    self.advance();
212                    name
213                }
214                Some(t) => {
215                    return Err(ParseError::UnexpectedToken {
216                        expected: "identifier after ::".to_string(),
217                        found: t,
218                        span: self.current_span(),
219                    })
220                }
221                None => return Err(ParseError::UnexpectedEof),
222            };
223            full_name = format!("{}::{}", full_name, segment);
224        }
225
226        Ok(Ident {
227            name: full_name,
228            evidentiality: None,
229            affect: None,
230            span,
231        })
232    }
233
234    /// Parse attribute arguments if present.
235    fn parse_attr_args(&mut self) -> ParseResult<Option<AttrArgs>> {
236        if self.consume_if(&Token::LParen) {
237            let mut args = Vec::new();
238
239            while !self.check(&Token::RParen) {
240                args.push(self.parse_attr_arg()?);
241                if !self.consume_if(&Token::Comma) {
242                    break;
243                }
244            }
245
246            self.expect(Token::RParen)?;
247            Ok(Some(AttrArgs::Paren(args)))
248        } else if self.consume_if(&Token::Eq) {
249            let expr = self.parse_expr()?;
250            Ok(Some(AttrArgs::Eq(Box::new(expr))))
251        } else {
252            Ok(None)
253        }
254    }
255
256    /// Parse a single attribute argument.
257    fn parse_attr_arg(&mut self) -> ParseResult<AttrArg> {
258        match self.current_token().cloned() {
259            Some(Token::StringLit(s)) => {
260                self.advance();
261                Ok(AttrArg::Literal(Literal::String(s)))
262            }
263            Some(Token::IntLit(s)) => {
264                self.advance();
265                Ok(AttrArg::Literal(Literal::Int {
266                    value: s,
267                    base: NumBase::Decimal,
268                    suffix: None,
269                }))
270            }
271            Some(Token::HexLit(s)) => {
272                self.advance();
273                Ok(AttrArg::Literal(Literal::Int {
274                    value: s,
275                    base: NumBase::Hex,
276                    suffix: None,
277                }))
278            }
279            Some(Token::BinaryLit(s)) => {
280                self.advance();
281                Ok(AttrArg::Literal(Literal::Int {
282                    value: s,
283                    base: NumBase::Binary,
284                    suffix: None,
285                }))
286            }
287            Some(Token::OctalLit(s)) => {
288                self.advance();
289                Ok(AttrArg::Literal(Literal::Int {
290                    value: s,
291                    base: NumBase::Octal,
292                    suffix: None,
293                }))
294            }
295            Some(Token::Ident(_)) => {
296                let ident = self.parse_ident()?;
297                self.parse_attr_arg_after_ident(ident)
298            }
299            // Handle keywords that might appear as feature names in attributes
300            Some(Token::Asm) => {
301                let span = self.current_span();
302                self.advance();
303                let ident = Ident {
304                    name: "asm".to_string(),
305                    evidentiality: None,
306                    affect: None,
307                    span,
308                };
309                self.parse_attr_arg_after_ident(ident)
310            }
311            Some(Token::Volatile) => {
312                let span = self.current_span();
313                self.advance();
314                let ident = Ident {
315                    name: "volatile".to_string(),
316                    evidentiality: None,
317                    affect: None,
318                    span,
319                };
320                self.parse_attr_arg_after_ident(ident)
321            }
322            Some(Token::Naked) => {
323                let span = self.current_span();
324                self.advance();
325                let ident = Ident {
326                    name: "naked".to_string(),
327                    evidentiality: None,
328                    affect: None,
329                    span,
330                };
331                self.parse_attr_arg_after_ident(ident)
332            }
333            Some(Token::Packed) => {
334                let span = self.current_span();
335                self.advance();
336                let ident = Ident {
337                    name: "packed".to_string(),
338                    evidentiality: None,
339                    affect: None,
340                    span,
341                };
342                self.parse_attr_arg_after_ident(ident)
343            }
344            Some(Token::Unsafe) => {
345                let span = self.current_span();
346                self.advance();
347                let ident = Ident {
348                    name: "unsafe".to_string(),
349                    evidentiality: None,
350                    affect: None,
351                    span,
352                };
353                self.parse_attr_arg_after_ident(ident)
354            }
355            Some(t) => Err(ParseError::UnexpectedToken {
356                expected: "attribute argument".to_string(),
357                found: t,
358                span: self.current_span(),
359            }),
360            None => Err(ParseError::UnexpectedEof),
361        }
362    }
363
364    /// Helper to continue parsing after an identifier in an attribute argument.
365    fn parse_attr_arg_after_ident(&mut self, ident: Ident) -> ParseResult<AttrArg> {
366        // Check for qualified path like serde::Serialize
367        if self.consume_if(&Token::ColonColon) || self.consume_if(&Token::MiddleDot) {
368            let mut path_parts = vec![ident.name.clone()];
369            loop {
370                let part = self.parse_ident()?;
371                path_parts.push(part.name);
372                if !self.consume_if(&Token::ColonColon) && !self.consume_if(&Token::MiddleDot) {
373                    break;
374                }
375            }
376            // Return the full qualified path as an identifier with :: separators
377            let full_path = path_parts.join("::");
378            return Ok(AttrArg::Ident(Ident {
379                name: full_path,
380                evidentiality: None,
381                affect: None,
382                span: ident.span.clone(),
383            }));
384        }
385        // Check for key = value
386        if self.consume_if(&Token::Eq) {
387            let value = self.parse_expr()?;
388            Ok(AttrArg::KeyValue {
389                key: ident,
390                value: Box::new(value),
391            })
392        }
393        // Check for nested attr(...)
394        else if self.check(&Token::LParen) {
395            let args = self.parse_attr_args()?;
396            Ok(AttrArg::Nested(Attribute {
397                name: ident,
398                args,
399                is_inner: false,
400            }))
401        }
402        // Just an identifier
403        else {
404            Ok(AttrArg::Ident(ident))
405        }
406    }
407
408    /// Parse interpolation parts from a string like "hello {name}, you are {age} years old"
409    /// Returns a vector of text segments and expression segments.
410    fn parse_interpolation_parts(&mut self, s: &str) -> ParseResult<Vec<InterpolationPart>> {
411        let mut parts = Vec::new();
412        let mut current_text = String::new();
413        let mut chars = s.chars().peekable();
414        let mut brace_depth = 0;
415        let mut expr_content = String::new();
416        let mut in_expr = false;
417
418        while let Some(c) = chars.next() {
419            if in_expr {
420                if c == '{' {
421                    brace_depth += 1;
422                    expr_content.push(c);
423                } else if c == '}' {
424                    if brace_depth > 0 {
425                        brace_depth -= 1;
426                        expr_content.push(c);
427                    } else {
428                        // End of expression - parse it
429                        in_expr = false;
430                        if !expr_content.is_empty() {
431                            // Parse the expression content
432                            let mut expr_parser = Parser::new(&expr_content);
433                            match expr_parser.parse_expr() {
434                                Ok(expr) => {
435                                    parts.push(InterpolationPart::Expr(Box::new(expr)));
436                                }
437                                Err(_) => {
438                                    // If parsing fails, treat as text
439                                    parts.push(InterpolationPart::Text(format!(
440                                        "{{{}}}",
441                                        expr_content
442                                    )));
443                                }
444                            }
445                        }
446                        expr_content.clear();
447                    }
448                } else {
449                    expr_content.push(c);
450                }
451            } else if c == '{' {
452                if chars.peek() == Some(&'{') {
453                    // Escaped brace {{
454                    chars.next();
455                    current_text.push('{');
456                } else {
457                    // Start of expression
458                    if !current_text.is_empty() {
459                        parts.push(InterpolationPart::Text(current_text.clone()));
460                        current_text.clear();
461                    }
462                    in_expr = true;
463                }
464            } else if c == '}' {
465                if chars.peek() == Some(&'}') {
466                    // Escaped brace }}
467                    chars.next();
468                    current_text.push('}');
469                } else {
470                    current_text.push(c);
471                }
472            } else {
473                current_text.push(c);
474            }
475        }
476
477        // Add any remaining text
478        if !current_text.is_empty() {
479            parts.push(InterpolationPart::Text(current_text));
480        }
481
482        // If we have no parts, add an empty text part
483        if parts.is_empty() {
484            parts.push(InterpolationPart::Text(String::new()));
485        }
486
487        Ok(parts)
488    }
489
490    /// Build crate configuration from parsed inner attributes.
491    fn build_crate_config(&self, attrs: &[Attribute]) -> CrateConfig {
492        let mut config = CrateConfig::default();
493        let mut linker = LinkerConfig::default();
494        let mut has_linker_config = false;
495
496        for attr in attrs {
497            match attr.name.name.as_str() {
498                "no_std" => config.no_std = true,
499                "no_main" => config.no_main = true,
500                "feature" => {
501                    if let Some(AttrArgs::Paren(args)) = &attr.args {
502                        for arg in args {
503                            if let AttrArg::Ident(ident) = arg {
504                                config.features.push(ident.name.clone());
505                            }
506                        }
507                    }
508                }
509                "target" => {
510                    let mut target = TargetConfig::default();
511                    if let Some(AttrArgs::Paren(args)) = &attr.args {
512                        for arg in args {
513                            if let AttrArg::KeyValue { key, value } = arg {
514                                if let Expr::Literal(Literal::String(s)) = value.as_ref() {
515                                    match key.name.as_str() {
516                                        "arch" => target.arch = Some(s.clone()),
517                                        "os" => target.os = Some(s.clone()),
518                                        "abi" => target.abi = Some(s.clone()),
519                                        _ => {}
520                                    }
521                                }
522                            }
523                        }
524                    }
525                    config.target = Some(target);
526                }
527                // Linker configuration attributes
528                "linker_script" => {
529                    if let Some(AttrArgs::Eq(value)) = &attr.args {
530                        if let Expr::Literal(Literal::String(s)) = value.as_ref() {
531                            linker.script = Some(s.clone());
532                            has_linker_config = true;
533                        }
534                    }
535                }
536                "entry_point" => {
537                    if let Some(AttrArgs::Eq(value)) = &attr.args {
538                        if let Expr::Literal(Literal::String(s)) = value.as_ref() {
539                            linker.entry_point = Some(s.clone());
540                            has_linker_config = true;
541                        }
542                    }
543                }
544                "base_address" => {
545                    if let Some(AttrArgs::Eq(value)) = &attr.args {
546                        if let Expr::Literal(Literal::Int { value: s, base, .. }) = value.as_ref() {
547                            let addr = Self::parse_int_value(s, *base);
548                            linker.base_address = Some(addr);
549                            has_linker_config = true;
550                        }
551                    }
552                }
553                "stack_size" => {
554                    if let Some(AttrArgs::Eq(value)) = &attr.args {
555                        if let Expr::Literal(Literal::Int { value: s, base, .. }) = value.as_ref() {
556                            let size = Self::parse_int_value(s, *base);
557                            linker.stack_size = Some(size);
558                            has_linker_config = true;
559                        }
560                    }
561                }
562                "link" => {
563                    // #![link(flag = "-nostdlib", flag = "-static")]
564                    if let Some(AttrArgs::Paren(args)) = &attr.args {
565                        for arg in args {
566                            if let AttrArg::KeyValue { key, value } = arg {
567                                if key.name == "flag" {
568                                    if let Expr::Literal(Literal::String(s)) = value.as_ref() {
569                                        linker.flags.push(s.clone());
570                                        has_linker_config = true;
571                                    }
572                                }
573                            }
574                        }
575                    }
576                }
577                _ => {}
578            }
579        }
580
581        if has_linker_config {
582            config.linker = Some(linker);
583        }
584
585        config
586    }
587
588    /// Parse an integer value from string with given base.
589    fn parse_int_value(s: &str, base: NumBase) -> u64 {
590        // Strip prefix based on base
591        let (stripped, radix) = match base {
592            NumBase::Binary => (
593                s.strip_prefix("0b").or(s.strip_prefix("0B")).unwrap_or(s),
594                2,
595            ),
596            NumBase::Octal => (
597                s.strip_prefix("0o").or(s.strip_prefix("0O")).unwrap_or(s),
598                8,
599            ),
600            NumBase::Decimal => (s, 10),
601            NumBase::Hex => (
602                s.strip_prefix("0x").or(s.strip_prefix("0X")).unwrap_or(s),
603                16,
604            ),
605            NumBase::Vigesimal => (
606                s.strip_prefix("0v").or(s.strip_prefix("0V")).unwrap_or(s),
607                20,
608            ),
609            NumBase::Duodecimal => (
610                s.strip_prefix("0d").or(s.strip_prefix("0D")).unwrap_or(s),
611                12,
612            ),
613            NumBase::Sexagesimal => (
614                s.strip_prefix("0s").or(s.strip_prefix("0S")).unwrap_or(s),
615                60,
616            ),
617            NumBase::Explicit(r) => (s, r as u32),
618        };
619        // Remove underscores (numeric separators) and parse
620        let clean: String = stripped.chars().filter(|c| *c != '_').collect();
621        u64::from_str_radix(&clean, radix).unwrap_or(0)
622    }
623
624    // === Token utilities ===
625
626    pub(crate) fn current_token(&self) -> Option<&Token> {
627        self.current.as_ref().map(|(t, _)| t)
628    }
629
630    pub(crate) fn current_span(&self) -> Span {
631        self.current.as_ref().map(|(_, s)| *s).unwrap_or_default()
632    }
633
634    pub(crate) fn advance(&mut self) -> Option<(Token, Span)> {
635        let prev = self.current.take();
636        self.current = self.lexer.next_token();
637        prev
638    }
639
640    pub(crate) fn is_eof(&self) -> bool {
641        self.current.is_none()
642    }
643
644    pub(crate) fn expect(&mut self, expected: Token) -> ParseResult<Span> {
645        match &self.current {
646            Some((token, span))
647                if std::mem::discriminant(token) == std::mem::discriminant(&expected) =>
648            {
649                let span = *span;
650                self.advance();
651                Ok(span)
652            }
653            Some((token, span)) => Err(ParseError::UnexpectedToken {
654                expected: format!("{:?}", expected),
655                found: token.clone(),
656                span: *span,
657            }),
658            None => Err(ParseError::UnexpectedEof),
659        }
660    }
661
662    /// Expect struct keyword (Token::Struct or Token::Sigma for Σ)
663    pub(crate) fn expect_struct(&mut self) -> ParseResult<Span> {
664        match &self.current {
665            Some((Token::Struct | Token::Sigma, span)) => {
666                let span = *span;
667                self.advance();
668                Ok(span)
669            }
670            Some((token, span)) => Err(ParseError::UnexpectedToken {
671                expected: "struct or Σ".to_string(),
672                found: token.clone(),
673                span: *span,
674            }),
675            None => Err(ParseError::UnexpectedEof),
676        }
677    }
678
679    /// Expect fn keyword (Token::Fn or Token::Lambda for λ)
680    pub(crate) fn expect_fn(&mut self) -> ParseResult<Span> {
681        match &self.current {
682            Some((Token::Fn | Token::Lambda, span)) => {
683                let span = *span;
684                self.advance();
685                Ok(span)
686            }
687            Some((token, span)) => Err(ParseError::UnexpectedToken {
688                expected: "fn or λ".to_string(),
689                found: token.clone(),
690                span: *span,
691            }),
692            None => Err(ParseError::UnexpectedEof),
693        }
694    }
695
696    /// Expect trait keyword (Token::Trait or Token::Theta for Θ)
697    pub(crate) fn expect_trait(&mut self) -> ParseResult<Span> {
698        match &self.current {
699            Some((Token::Trait | Token::Theta, span)) => {
700                let span = *span;
701                self.advance();
702                Ok(span)
703            }
704            Some((token, span)) => Err(ParseError::UnexpectedToken {
705                expected: "trait or Θ".to_string(),
706                found: token.clone(),
707                span: *span,
708            }),
709            None => Err(ParseError::UnexpectedEof),
710        }
711    }
712
713    pub(crate) fn check(&self, expected: &Token) -> bool {
714        matches!(&self.current, Some((token, _)) if std::mem::discriminant(token) == std::mem::discriminant(expected))
715    }
716
717    /// Peek at the next token (after current) without consuming anything.
718    pub(crate) fn peek_next(&mut self) -> Option<&Token> {
719        self.lexer.peek().map(|(t, _)| t)
720    }
721
722    /// Peek n tokens ahead (0 = next token after current, 1 = token after that, etc.)
723    pub(crate) fn peek_n(&mut self, n: usize) -> Option<&Token> {
724        self.lexer.peek_n(n).map(|(t, _)| t)
725    }
726
727    pub(crate) fn consume_if(&mut self, expected: &Token) -> bool {
728        if self.check(expected) {
729            self.advance();
730            true
731        } else {
732            false
733        }
734    }
735
736    /// Check for mut keyword (Token::Mut or Token::Delta for Δ)
737    pub(crate) fn check_mut(&self) -> bool {
738        matches!(self.current_token(), Some(Token::Mut) | Some(Token::Delta))
739    }
740
741    /// Consume mut keyword if present (Token::Mut or Token::Delta for Δ)
742    pub(crate) fn consume_if_mut(&mut self) -> bool {
743        if self.check_mut() {
744            self.advance();
745            true
746        } else {
747            false
748        }
749    }
750
751    /// Check for self keyword (Token::SelfLower or Token::Xi for ξ)
752    pub(crate) fn check_self(&self) -> bool {
753        matches!(self.current_token(), Some(Token::SelfLower) | Some(Token::Xi))
754    }
755
756    /// Check for path separator (Token::ColonColon or Token::MiddleDot for ·)
757    pub(crate) fn check_path_sep(&self) -> bool {
758        matches!(self.current_token(), Some(Token::ColonColon) | Some(Token::MiddleDot))
759    }
760
761    /// Consume path separator if present
762    pub(crate) fn consume_if_path_sep(&mut self) -> bool {
763        if self.check_path_sep() {
764            self.advance();
765            true
766        } else {
767            false
768        }
769    }
770
771    /// Check for as keyword (Token::As or Token::Arrow for →)
772    pub(crate) fn check_as(&self) -> bool {
773        matches!(self.current_token(), Some(Token::As) | Some(Token::Arrow))
774    }
775
776    /// Consume as keyword if present (Token::As or Token::Arrow for →)
777    pub(crate) fn consume_if_as(&mut self) -> bool {
778        if self.check_as() {
779            self.advance();
780            true
781        } else {
782            false
783        }
784    }
785
786    /// Skip any comments
787    pub(crate) fn skip_comments(&mut self) {
788        while matches!(
789            self.current_token(),
790            Some(Token::LineComment(_) | Token::TildeComment(_) | Token::BlockComment(_))
791                | Some(Token::DocComment(_))
792        ) {
793            self.advance();
794        }
795    }
796
797    /// Check if the current token is `>`, including pending `>` from split `>>`.
798    pub(crate) fn check_gt(&self) -> bool {
799        self.pending_gt.is_some() || self.check(&Token::Gt)
800    }
801
802    /// Expect a `>` token, handling the case where `>>` (Shr) needs to be split.
803    /// This is necessary for nested generics like `Vec<Option<T>>`.
804    pub(crate) fn expect_gt(&mut self) -> ParseResult<Span> {
805        // First check if we have a pending `>` from a previous split
806        if let Some(span) = self.pending_gt.take() {
807            return Ok(span);
808        }
809
810        match &self.current {
811            Some((Token::Gt, span)) => {
812                let span = *span;
813                self.advance();
814                Ok(span)
815            }
816            Some((Token::Shr, span)) => {
817                // Split `>>` into two `>` tokens
818                // Take the first `>` now and save the second for later
819                let span = *span;
820                self.pending_gt = Some(span);
821                self.advance();
822                Ok(span)
823            }
824            Some((token, span)) => Err(ParseError::UnexpectedToken {
825                expected: "Gt".to_string(),
826                found: token.clone(),
827                span: *span,
828            }),
829            None => Err(ParseError::UnexpectedEof),
830        }
831    }
832
833    /// Consume a `>` if present, handling pending `>` from split `>>`.
834    fn consume_gt(&mut self) -> bool {
835        if self.pending_gt.is_some() {
836            self.pending_gt = None;
837            return true;
838        }
839        if self.check(&Token::Gt) {
840            self.advance();
841            return true;
842        }
843        // Also handle `>>` - split it and return first `>`
844        if self.check(&Token::Shr) {
845            let span = self.current_span();
846            self.pending_gt = Some(span);
847            self.advance();
848            return true;
849        }
850        false
851    }
852
853    /// Check if the current token can start a new item.
854    /// Used to make semicolons optional in Sigil.
855    fn can_start_item(&self) -> bool {
856        matches!(
857            self.current_token(),
858            Some(
859                Token::Pub
860                    | Token::Fn | Token::Lambda  // rite or λ
861                    | Token::Async | Token::Hourglass  // async or ⧗
862                    | Token::Struct | Token::Sigma  // sigil or Σ
863                    | Token::Enum  // ᛈ
864                    | Token::Trait | Token::Theta  // aspect or Θ
865                    | Token::Impl  // ⊢
866                    | Token::Type
867                    | Token::Mod
868                    | Token::Use
869                    | Token::Const
870                    | Token::Static
871                    | Token::Actor
872                    | Token::Extern
873                    | Token::Hash
874                    | Token::At
875                    | Token::Naked
876                    | Token::Packed
877                    | Token::LineComment(_) | Token::TildeComment(_) | Token::BlockComment(_)
878                    | Token::DocComment(_)
879                    // Plurality keywords
880                    | Token::Alter
881                    | Token::Headspace
882                    | Token::Reality
883                    | Token::CoCon
884            )
885        ) || (matches!(self.current_token(), Some(Token::On)) && self.peek_next_is_trigger())
886    }
887
888    /// Check if peek is the Trigger token (for "on trigger" detection)
889    fn peek_next_is_trigger(&self) -> bool {
890        // This is a workaround since we can't mutably borrow in can_start_item
891        false // Will be true when "on trigger" is seen
892    }
893
894    /// Check if the current token can start a new statement in a block.
895    /// Used to make semicolons optional in Sigil's advanced syntax.
896    fn can_start_stmt(&self) -> bool {
897        // Check for keywords that can be used as identifiers (expressions)
898        if let Some(token) = self.current_token() {
899            if Self::keyword_as_ident(token).is_some() {
900                return true;
901            }
902        }
903        matches!(
904            self.current_token(),
905            Some(
906                Token::Let  // ≔
907                    | Token::If  // ⎇
908                    | Token::Match  // ⌥
909                    | Token::Loop | Token::Infinity  // forever or ∞
910                    | Token::While  // ⟳
911                    | Token::For | Token::ForAll  // each or ∀
912                    | Token::Return  // ⤺
913                    | Token::Break  // ⊲
914                    | Token::Continue  // ⊳
915                    | Token::Ident(_)
916                    | Token::SelfLower | Token::Xi  // this or ξ
917                    | Token::SelfUpper  // This or Ξ (also Xi)
918                    | Token::LParen
919                    | Token::LBracket
920                    | Token::LBrace
921                    // Literals can start expression statements (e.g., final return value)
922                    | Token::StringLit(_)
923                    | Token::IntLit(_)
924                    | Token::FloatLit(_)
925                    | Token::True | Token::Top  // yea or ⊤
926                    | Token::False | Token::Bottom  // nay or ⊥
927                    | Token::LineComment(_) | Token::TildeComment(_) | Token::BlockComment(_)
928                    | Token::DocComment(_)
929            )
930        ) || self.can_start_item()
931    }
932
933    /// Consume semicolon if present, or skip if next token can start an item.
934    /// This makes semicolons optional in Sigil's advanced syntax.
935    fn expect_semi_or_item_start(&mut self) -> ParseResult<()> {
936        if self.consume_if(&Token::Semi) {
937            return Ok(());
938        }
939        if self.can_start_item() || self.is_eof() || self.check(&Token::RBrace) {
940            // Semicolon is optional before a new item, EOF, or closing brace
941            return Ok(());
942        }
943        let span = self.current_span();
944        Err(ParseError::UnexpectedToken {
945            expected: "`;` or new item".to_string(),
946            found: self.current_token().cloned().unwrap_or(Token::Semi),
947            span,
948        })
949    }
950
951    // === Item parsing ===
952
953    fn parse_item(&mut self) -> ParseResult<Spanned<Item>> {
954        let start_span = self.current_span();
955
956        // Collect outer attributes (#[...] or @[...])
957        let mut outer_attrs = Vec::new();
958        while self.check(&Token::Hash) || self.check(&Token::At) {
959            outer_attrs.push(self.parse_outer_attribute()?);
960        }
961
962        let visibility = self.parse_visibility()?;
963
964        let item = match self.current_token() {
965            Some(Token::Fn) | Some(Token::Lambda) | Some(Token::Async) | Some(Token::Hourglass) => {
966                Item::Function(self.parse_function_with_attrs(visibility, outer_attrs)?)
967            }
968            Some(Token::Struct) | Some(Token::Sigma) => {
969                Item::Struct(self.parse_struct_with_attrs(visibility, outer_attrs)?)
970            }
971            Some(Token::Enum) => Item::Enum(self.parse_enum(visibility)?),
972            Some(Token::Trait) | Some(Token::Theta) => Item::Trait(self.parse_trait(visibility)?),
973            Some(Token::Impl) => Item::Impl(self.parse_impl()?),
974            Some(Token::Unsafe) => {
975                // unsafe impl, unsafe fn, unsafe trait
976                self.advance(); // consume 'unsafe'
977                match self.current_token() {
978                    Some(Token::Impl) => Item::Impl(self.parse_impl()?),
979                    Some(Token::Fn) | Some(Token::Async) => {
980                        Item::Function(self.parse_function_with_attrs(visibility, outer_attrs)?)
981                    }
982                    Some(Token::Trait) => Item::Trait(self.parse_trait(visibility)?),
983                    Some(t) => {
984                        return Err(ParseError::UnexpectedToken {
985                            expected: "impl, fn, or trait after unsafe".to_string(),
986                            found: t.clone(),
987                            span: self.current_span(),
988                        })
989                    }
990                    None => return Err(ParseError::UnexpectedEof),
991                }
992            }
993            Some(Token::Type) => Item::TypeAlias(self.parse_type_alias(visibility)?),
994            Some(Token::Mod) => Item::Module(self.parse_module(visibility)?),
995            Some(Token::Use) => Item::Use(self.parse_use(visibility)?),
996            Some(Token::Const) => {
997                // Check if this is `const fn` (const function) or just `const X: T = ...`
998                if self
999                    .peek_next()
1000                    .map(|t| matches!(t, Token::Fn | Token::Async))
1001                    == Some(true)
1002                {
1003                    Item::Function(self.parse_function_with_attrs(visibility, outer_attrs)?)
1004                } else {
1005                    Item::Const(self.parse_const(visibility)?)
1006                }
1007            }
1008            Some(Token::Static) => Item::Static(self.parse_static(visibility)?),
1009            Some(Token::Actor) => Item::Actor(self.parse_actor(visibility)?),
1010            Some(Token::Extern) => Item::ExternBlock(self.parse_extern_block()?),
1011            Some(Token::Macro) | Some(Token::MacroRules) => {
1012                Item::Macro(self.parse_macro_def(visibility)?)
1013            }
1014            Some(Token::Naked) => {
1015                // naked fn -> function with naked attribute
1016                Item::Function(self.parse_function_with_attrs(visibility, outer_attrs)?)
1017            }
1018            Some(Token::Packed) => {
1019                // packed struct -> struct with packed attribute
1020                Item::Struct(self.parse_struct_with_attrs(visibility, outer_attrs)?)
1021            }
1022            // Plurality items (DAEMONIORUM extensions)
1023            Some(Token::Alter) => {
1024                use crate::plurality::PluralityParser;
1025                Item::Plurality(crate::plurality::PluralityItem::Alter(
1026                    self.parse_alter_def(visibility)?,
1027                ))
1028            }
1029            Some(Token::Headspace) => {
1030                use crate::plurality::PluralityParser;
1031                Item::Plurality(crate::plurality::PluralityItem::Headspace(
1032                    self.parse_headspace_def(visibility)?,
1033                ))
1034            }
1035            Some(Token::Reality) => {
1036                use crate::plurality::PluralityParser;
1037                Item::Plurality(crate::plurality::PluralityItem::Reality(
1038                    self.parse_reality_def(visibility)?,
1039                ))
1040            }
1041            Some(Token::CoCon) => {
1042                use crate::plurality::PluralityParser;
1043                Item::Plurality(crate::plurality::PluralityItem::CoConChannel(
1044                    self.parse_cocon_channel()?,
1045                ))
1046            }
1047            Some(Token::On) => {
1048                // Check if this is a trigger handler: "on trigger ..."
1049                if self.peek_next() == Some(&Token::Trigger) {
1050                    use crate::plurality::PluralityParser;
1051                    Item::Plurality(crate::plurality::PluralityItem::TriggerHandler(
1052                        self.parse_trigger_handler()?,
1053                    ))
1054                } else {
1055                    return Err(ParseError::UnexpectedToken {
1056                        expected: "item".to_string(),
1057                        found: Token::On,
1058                        span: self.current_span(),
1059                    });
1060                }
1061            }
1062            // Macro invocation at item level: `name! { ... }` or `path::to::macro! { ... }`
1063            Some(Token::Ident(_)) => {
1064                // Check if this is a macro invocation (next token after possible path is !)
1065                if self.looks_like_macro_invocation() {
1066                    Item::MacroInvocation(self.parse_macro_invocation()?)
1067                } else {
1068                    return Err(ParseError::UnexpectedToken {
1069                        expected: "item".to_string(),
1070                        found: self.current_token().unwrap().clone(),
1071                        span: self.current_span(),
1072                    });
1073                }
1074            }
1075            Some(token) => {
1076                return Err(ParseError::UnexpectedToken {
1077                    expected: "item".to_string(),
1078                    found: token.clone(),
1079                    span: self.current_span(),
1080                });
1081            }
1082            None => return Err(ParseError::UnexpectedEof),
1083        };
1084
1085        let end_span = self.current_span();
1086        Ok(Spanned::new(item, start_span.merge(end_span)))
1087    }
1088
1089    pub(crate) fn parse_visibility(&mut self) -> ParseResult<Visibility> {
1090        if self.consume_if(&Token::Pub) {
1091            Ok(Visibility::Public)
1092        } else {
1093            Ok(Visibility::Private)
1094        }
1095    }
1096
1097    fn parse_function(&mut self, visibility: Visibility) -> ParseResult<Function> {
1098        self.parse_function_with_attrs(visibility, Vec::new())
1099    }
1100
1101    fn parse_function_with_attrs(
1102        &mut self,
1103        visibility: Visibility,
1104        outer_attrs: Vec<Attribute>,
1105    ) -> ParseResult<Function> {
1106        // Parse function attributes from outer attributes
1107        let mut attrs = self.process_function_attrs(&outer_attrs);
1108
1109        // Check for naked keyword before fn
1110        if self.consume_if(&Token::Naked) {
1111            attrs.naked = true;
1112        }
1113
1114        // Check for unsafe keyword before fn
1115        let is_unsafe = self.consume_if(&Token::Unsafe);
1116
1117        // Check for const keyword before fn
1118        let is_const = self.consume_if(&Token::Const);
1119
1120        let is_async = self.consume_if(&Token::Async);
1121        self.expect_fn()?;
1122
1123        let mut name = self.parse_ident()?;
1124
1125        // Parse optional evidentiality marker on function name: fn load~<T>() or fn predict◊()
1126        // parse_ident only consumes unambiguous markers (~, ◊, ‽), so we also check for ! and ?
1127        if let Some(ev) = self.parse_evidentiality_opt() {
1128            // Store in the name's evidentiality field if not already set
1129            if name.evidentiality.is_none() {
1130                name.evidentiality = Some(ev);
1131            }
1132        }
1133
1134        // Parse optional aspect suffix: ·ing, ·ed, ·able, ·ive
1135        let aspect = match self.current_token() {
1136            Some(Token::AspectProgressive) => {
1137                self.advance();
1138                Some(Aspect::Progressive)
1139            }
1140            Some(Token::AspectPerfective) => {
1141                self.advance();
1142                Some(Aspect::Perfective)
1143            }
1144            Some(Token::AspectPotential) => {
1145                self.advance();
1146                Some(Aspect::Potential)
1147            }
1148            Some(Token::AspectResultative) => {
1149                self.advance();
1150                Some(Aspect::Resultative)
1151            }
1152            _ => None,
1153        };
1154
1155        let generics = self.parse_generics_opt()?;
1156
1157        self.expect(Token::LParen)?;
1158        let params = self.parse_params()?;
1159        self.expect(Token::RParen)?;
1160
1161        let return_type = if self.consume_if(&Token::Arrow) {
1162            Some(self.parse_type()?)
1163        } else {
1164            None
1165        };
1166
1167        // Handle async marker after return type: -> Type⌛
1168        // This is an alternative async syntax: fn foo() -> Result⌛ { ... }
1169        let is_async = is_async || self.consume_if(&Token::Hourglass);
1170
1171        let where_clause = self.parse_where_clause_opt()?;
1172
1173        let body = if self.check(&Token::LBrace) {
1174            Some(self.parse_block()?)
1175        } else {
1176            // Semicolon is optional for trait method signatures when followed by
1177            // another item, a doc comment, or closing brace (Sigil style)
1178            if !self.consume_if(&Token::Semi) {
1179                // If no semicolon, we must be at a valid termination point:
1180                // - Next function/const/type declaration
1181                // - Doc comment (next trait item)
1182                // - Closing brace (end of trait/impl)
1183                // Otherwise it's an error
1184                let valid_terminator = matches!(
1185                    self.current_token(),
1186                    Some(Token::Fn)
1187                        | Some(Token::Async)
1188                        | Some(Token::Unsafe)
1189                        | Some(Token::Const)
1190                        | Some(Token::Type)
1191                        | Some(Token::Pub)
1192                        | Some(Token::DocComment(_))
1193                        | Some(Token::LineComment(_))
1194                        | Some(Token::BlockComment(_))
1195                        | Some(Token::TildeComment(_))
1196                        | Some(Token::RBrace)
1197                        | Some(Token::Hash)
1198                );
1199                if !valid_terminator {
1200                    return match self.current_token().cloned() {
1201                        Some(token) => Err(ParseError::UnexpectedToken {
1202                            expected: "Semi".to_string(),
1203                            found: token,
1204                            span: self.current_span(),
1205                        }),
1206                        None => Err(ParseError::UnexpectedEof),
1207                    };
1208                }
1209            }
1210            None
1211        };
1212
1213        Ok(Function {
1214            visibility,
1215            is_async,
1216            is_const,
1217            is_unsafe,
1218            attrs,
1219            name,
1220            aspect,
1221            generics,
1222            params,
1223            return_type,
1224            where_clause,
1225            body,
1226        })
1227    }
1228
1229    /// Process outer attributes into FunctionAttrs.
1230    fn process_function_attrs(&self, attrs: &[Attribute]) -> FunctionAttrs {
1231        let mut func_attrs = FunctionAttrs::default();
1232
1233        for attr in attrs {
1234            match attr.name.name.as_str() {
1235                "panic_handler" => func_attrs.panic_handler = true,
1236                "entry" => func_attrs.entry = true,
1237                "no_mangle" => func_attrs.no_mangle = true,
1238                "export" => func_attrs.export = true,
1239                "cold" => func_attrs.cold = true,
1240                "hot" => func_attrs.hot = true,
1241                "test" => func_attrs.test = true,
1242                "naked" => func_attrs.naked = true,
1243                "inline" => {
1244                    func_attrs.inline = Some(match &attr.args {
1245                        Some(AttrArgs::Paren(args)) => {
1246                            if let Some(AttrArg::Ident(ident)) = args.first() {
1247                                match ident.name.as_str() {
1248                                    "always" => InlineHint::Always,
1249                                    "never" => InlineHint::Never,
1250                                    _ => InlineHint::Hint,
1251                                }
1252                            } else {
1253                                InlineHint::Hint
1254                            }
1255                        }
1256                        _ => InlineHint::Hint,
1257                    });
1258                }
1259                "link_section" => {
1260                    if let Some(AttrArgs::Eq(value)) = &attr.args {
1261                        if let Expr::Literal(Literal::String(s)) = value.as_ref() {
1262                            func_attrs.link_section = Some(s.clone());
1263                        }
1264                    }
1265                }
1266                "interrupt" => {
1267                    if let Some(AttrArgs::Paren(args)) = &attr.args {
1268                        if let Some(AttrArg::Literal(Literal::Int { value, base, .. })) =
1269                            args.first()
1270                        {
1271                            let num = Self::parse_int_value(value, *base) as u32;
1272                            func_attrs.interrupt = Some(num);
1273                        }
1274                    }
1275                }
1276                "align" => {
1277                    if let Some(AttrArgs::Paren(args)) = &attr.args {
1278                        if let Some(AttrArg::Literal(Literal::Int { value, base, .. })) =
1279                            args.first()
1280                        {
1281                            let align = Self::parse_int_value(value, *base) as usize;
1282                            func_attrs.align = Some(align);
1283                        }
1284                    }
1285                }
1286                _ => {
1287                    // Store unrecognized attributes
1288                    func_attrs.outer_attrs.push(attr.clone());
1289                }
1290            }
1291        }
1292
1293        func_attrs
1294    }
1295
1296    fn parse_struct_with_attrs(
1297        &mut self,
1298        visibility: Visibility,
1299        outer_attrs: Vec<Attribute>,
1300    ) -> ParseResult<StructDef> {
1301        // Parse struct attributes
1302        let mut attrs = StructAttrs::default();
1303        attrs.outer_attrs = outer_attrs.clone();
1304
1305        // Process derive attributes
1306        for attr in &outer_attrs {
1307            if attr.name.name == "derive" {
1308                if let Some(AttrArgs::Paren(args)) = &attr.args {
1309                    for arg in args {
1310                        if let AttrArg::Ident(ident) = arg {
1311                            let derive = Self::parse_derive_trait(&ident.name)?;
1312                            attrs.derives.push(derive);
1313                        }
1314                    }
1315                }
1316            } else if attr.name.name == "simd" {
1317                attrs.simd = true;
1318            } else if attr.name.name == "repr" {
1319                if let Some(AttrArgs::Paren(args)) = &attr.args {
1320                    for arg in args {
1321                        if let AttrArg::Ident(ident) = arg {
1322                            attrs.repr = Some(match ident.name.as_str() {
1323                                "C" => StructRepr::C,
1324                                "transparent" => StructRepr::Transparent,
1325                                "packed" => {
1326                                    attrs.packed = true;
1327                                    StructRepr::C // packed implies C repr
1328                                }
1329                                other => StructRepr::Int(other.to_string()),
1330                            });
1331                        } else if let AttrArg::Nested(nested) = arg {
1332                            if nested.name.name == "align" {
1333                                if let Some(AttrArgs::Paren(align_args)) = &nested.args {
1334                                    if let Some(AttrArg::Literal(Literal::Int { value, .. })) =
1335                                        align_args.first()
1336                                    {
1337                                        if let Ok(n) = value.parse::<usize>() {
1338                                            attrs.align = Some(n);
1339                                        }
1340                                    }
1341                                }
1342                            }
1343                        }
1344                    }
1345                }
1346            }
1347        }
1348
1349        // Check for packed keyword before struct
1350        if self.consume_if(&Token::Packed) {
1351            attrs.packed = true;
1352        }
1353
1354        self.expect_struct()?;
1355        let name = self.parse_ident()?;
1356
1357        // Evidentiality markers can appear BEFORE or AFTER generics:
1358        // - struct Foo! { ... } - newtype/verified struct
1359        // - struct Bar<T>~ { ... } - reported struct
1360        // - struct Gradient!<S, D, Dev> { ... } - verified struct with generics after evidentiality
1361        // Check for evidentiality BEFORE generics: struct Type!<...>
1362        let _evidentiality_before = self.parse_evidentiality_opt();
1363
1364        let generics = self.parse_generics_opt()?;
1365
1366        // Also check for evidentiality AFTER generics: struct Type<T>!
1367        let _evidentiality_after = self.parse_evidentiality_opt();
1368
1369        // Optional where clause for struct bounds (parsed but not yet stored in AST)
1370        let _ = self.parse_where_clause_opt()?;
1371
1372        let fields = if self.check(&Token::LBrace) {
1373            self.expect(Token::LBrace)?;
1374            let fields = self.parse_field_defs()?;
1375            self.expect(Token::RBrace)?;
1376            StructFields::Named(fields)
1377        } else if self.check(&Token::LParen) {
1378            self.expect(Token::LParen)?;
1379            let types = self.parse_tuple_struct_fields()?;
1380            self.expect(Token::RParen)?;
1381            // Semicolon is optional in Sigil's advanced syntax
1382            self.expect_semi_or_item_start()?;
1383            StructFields::Tuple(types)
1384        } else {
1385            // Semicolon is optional in Sigil's advanced syntax
1386            self.expect_semi_or_item_start()?;
1387            StructFields::Unit
1388        };
1389
1390        Ok(StructDef {
1391            visibility,
1392            attrs,
1393            name,
1394            generics,
1395            fields,
1396        })
1397    }
1398
1399    fn parse_derive_trait(name: &str) -> ParseResult<DeriveTrait> {
1400        match name {
1401            "Debug" => Ok(DeriveTrait::Debug),
1402            "Clone" => Ok(DeriveTrait::Clone),
1403            "Copy" => Ok(DeriveTrait::Copy),
1404            "Default" => Ok(DeriveTrait::Default),
1405            "PartialEq" => Ok(DeriveTrait::PartialEq),
1406            "Eq" => Ok(DeriveTrait::Eq),
1407            "PartialOrd" => Ok(DeriveTrait::PartialOrd),
1408            "Ord" => Ok(DeriveTrait::Ord),
1409            "Hash" => Ok(DeriveTrait::Hash),
1410            // ECS traits
1411            "Component" => Ok(DeriveTrait::Component),
1412            "Resource" => Ok(DeriveTrait::Resource),
1413            "Bundle" => Ok(DeriveTrait::Bundle),
1414            // Serde traits
1415            "Serialize" => Ok(DeriveTrait::Serialize),
1416            "Deserialize" => Ok(DeriveTrait::Deserialize),
1417            // Custom derive
1418            _ => Ok(DeriveTrait::Custom(name.to_string())),
1419        }
1420    }
1421
1422    fn parse_enum(&mut self, visibility: Visibility) -> ParseResult<EnumDef> {
1423        self.expect(Token::Enum)?;
1424        let name = self.parse_ident()?;
1425        let generics = self.parse_generics_opt()?;
1426
1427        self.expect(Token::LBrace)?;
1428        let mut variants = Vec::new();
1429        while !self.check(&Token::RBrace) && !self.is_eof() {
1430            // Skip doc comments, line comments, and attributes before variants
1431            while matches!(
1432                self.current_token(),
1433                Some(Token::DocComment(_))
1434                    | Some(Token::LineComment(_) | Token::TildeComment(_) | Token::BlockComment(_))
1435            ) {
1436                self.advance();
1437            }
1438            // Skip any outer attributes (#[...] or @[...])
1439            while self.check(&Token::Hash) || self.check(&Token::At) {
1440                self.parse_outer_attribute()?;
1441            }
1442            // Skip any additional comments after attributes
1443            while matches!(
1444                self.current_token(),
1445                Some(Token::DocComment(_))
1446                    | Some(Token::LineComment(_) | Token::TildeComment(_) | Token::BlockComment(_))
1447            ) {
1448                self.advance();
1449            }
1450            if self.check(&Token::RBrace) {
1451                break;
1452            }
1453            variants.push(self.parse_enum_variant()?);
1454            if !self.consume_if(&Token::Comma) {
1455                break;
1456            }
1457            // Skip trailing comments after comma
1458            while matches!(
1459                self.current_token(),
1460                Some(Token::DocComment(_))
1461                    | Some(Token::LineComment(_) | Token::TildeComment(_) | Token::BlockComment(_))
1462            ) {
1463                self.advance();
1464            }
1465        }
1466        self.expect(Token::RBrace)?;
1467
1468        Ok(EnumDef {
1469            visibility,
1470            name,
1471            generics,
1472            variants,
1473        })
1474    }
1475
1476    fn parse_enum_variant(&mut self) -> ParseResult<EnumVariant> {
1477        let name = self.parse_ident()?;
1478
1479        let fields = if self.check(&Token::LBrace) {
1480            self.expect(Token::LBrace)?;
1481            let fields = self.parse_field_defs()?;
1482            self.expect(Token::RBrace)?;
1483            StructFields::Named(fields)
1484        } else if self.check(&Token::LParen) {
1485            self.expect(Token::LParen)?;
1486            let types = self.parse_attributed_type_list()?;
1487            self.expect(Token::RParen)?;
1488            StructFields::Tuple(types)
1489        } else {
1490            StructFields::Unit
1491        };
1492
1493        let discriminant = if self.consume_if(&Token::Eq) {
1494            Some(self.parse_expr()?)
1495        } else {
1496            None
1497        };
1498
1499        Ok(EnumVariant {
1500            name,
1501            fields,
1502            discriminant,
1503        })
1504    }
1505
1506    fn parse_trait(&mut self, visibility: Visibility) -> ParseResult<TraitDef> {
1507        self.expect_trait()?;
1508        let name = self.parse_ident()?;
1509        let generics = self.parse_generics_opt()?;
1510
1511        let supertraits = if self.consume_if(&Token::Colon) {
1512            self.parse_type_bounds()?
1513        } else {
1514            vec![]
1515        };
1516
1517        self.expect(Token::LBrace)?;
1518        let mut items = Vec::new();
1519        while !self.check(&Token::RBrace) && !self.is_eof() {
1520            // Skip doc comments and line comments before trait items
1521            while matches!(
1522                self.current_token(),
1523                Some(Token::DocComment(_))
1524                    | Some(Token::LineComment(_) | Token::TildeComment(_) | Token::BlockComment(_))
1525            ) {
1526                self.advance();
1527            }
1528            if self.check(&Token::RBrace) {
1529                break;
1530            }
1531            items.push(self.parse_trait_item()?);
1532        }
1533        self.expect(Token::RBrace)?;
1534
1535        Ok(TraitDef {
1536            visibility,
1537            name,
1538            generics,
1539            supertraits,
1540            items,
1541        })
1542    }
1543
1544    fn parse_trait_item(&mut self) -> ParseResult<TraitItem> {
1545        let visibility = self.parse_visibility()?;
1546
1547        match self.current_token() {
1548            Some(Token::Fn) | Some(Token::Lambda) | Some(Token::Async) | Some(Token::Hourglass) | Some(Token::Unsafe) => {
1549                Ok(TraitItem::Function(self.parse_function(visibility)?))
1550            }
1551            Some(Token::Type) => {
1552                self.advance();
1553                let name = self.parse_ident()?;
1554                let bounds = if self.consume_if(&Token::Colon) {
1555                    self.parse_type_bounds()?
1556                } else {
1557                    vec![]
1558                };
1559                self.expect(Token::Semi)?;
1560                Ok(TraitItem::Type { name, bounds })
1561            }
1562            Some(Token::Const) => {
1563                // Check if this is `const fn` or just `const NAME: TYPE;`
1564                if self
1565                    .peek_next()
1566                    .map(|t| matches!(t, Token::Fn | Token::Lambda | Token::Async | Token::Hourglass))
1567                    == Some(true)
1568                {
1569                    Ok(TraitItem::Function(self.parse_function(visibility)?))
1570                } else {
1571                    self.advance();
1572                    let name = self.parse_ident()?;
1573                    self.expect(Token::Colon)?;
1574                    let ty = self.parse_type()?;
1575                    self.expect(Token::Semi)?;
1576                    Ok(TraitItem::Const { name, ty })
1577                }
1578            }
1579            Some(token) => Err(ParseError::UnexpectedToken {
1580                expected: "trait item".to_string(),
1581                found: token.clone(),
1582                span: self.current_span(),
1583            }),
1584            None => Err(ParseError::UnexpectedEof),
1585        }
1586    }
1587
1588    fn parse_impl(&mut self) -> ParseResult<ImplBlock> {
1589        self.expect(Token::Impl)?;
1590        let generics = self.parse_generics_opt()?;
1591
1592        // Parse either `Type : Trait` or just `Type`
1593        // Sigil syntax: ⊢ Type : Aspect (type first, then aspect/trait)
1594        let first_type = self.parse_type()?;
1595
1596        let (trait_, self_ty) = if self.consume_if(&Token::Colon) {
1597            // New Sigil syntax: ⊢ Type : Trait
1598            let trait_type = self.parse_type()?;
1599            let trait_path = match trait_type {
1600                TypeExpr::Path(p) => p,
1601                _ => return Err(ParseError::Custom("expected aspect path".to_string())),
1602            };
1603            (Some(trait_path), first_type)
1604        } else {
1605            (None, first_type)
1606        };
1607
1608        // Optional where clause for impl bounds (parsed but not yet stored in AST)
1609        let _ = self.parse_where_clause_opt()?;
1610
1611        self.expect(Token::LBrace)?;
1612        let mut items = Vec::new();
1613        while !self.check(&Token::RBrace) && !self.is_eof() {
1614            // Skip doc comments, line comments, and attributes before impl items
1615            while matches!(
1616                self.current_token(),
1617                Some(Token::DocComment(_))
1618                    | Some(Token::LineComment(_) | Token::TildeComment(_) | Token::BlockComment(_))
1619                    | Some(Token::Hash)
1620            ) {
1621                if self.check(&Token::Hash) {
1622                    // Skip attribute: #[...] or #![...]
1623                    self.advance();
1624                    self.consume_if(&Token::Bang);
1625                    if self.consume_if(&Token::LBracket) {
1626                        let mut depth = 1;
1627                        while depth > 0 && !self.is_eof() {
1628                            match self.current_token() {
1629                                Some(Token::LBracket) => depth += 1,
1630                                Some(Token::RBracket) => depth -= 1,
1631                                _ => {}
1632                            }
1633                            self.advance();
1634                        }
1635                    }
1636                } else {
1637                    self.advance();
1638                }
1639            }
1640            if self.check(&Token::RBrace) {
1641                break;
1642            }
1643            items.push(self.parse_impl_item()?);
1644        }
1645        self.expect(Token::RBrace)?;
1646
1647        Ok(ImplBlock {
1648            generics,
1649            trait_,
1650            self_ty,
1651            items,
1652        })
1653    }
1654
1655    fn parse_impl_item(&mut self) -> ParseResult<ImplItem> {
1656        // Parse outer attributes (#[...] or @[...])
1657        let mut outer_attrs = Vec::new();
1658        while self.check(&Token::Hash) || self.check(&Token::At) {
1659            outer_attrs.push(self.parse_outer_attribute()?);
1660        }
1661
1662        let visibility = self.parse_visibility()?;
1663
1664        match self.current_token() {
1665            Some(Token::Fn) | Some(Token::Lambda) | Some(Token::Async) | Some(Token::Hourglass) | Some(Token::Unsafe) => Ok(ImplItem::Function(
1666                self.parse_function_with_attrs(visibility, outer_attrs)?,
1667            )),
1668            Some(Token::Type) => Ok(ImplItem::Type(self.parse_type_alias(visibility)?)),
1669            Some(Token::Const) => {
1670                // Check if this is `const fn` or just `const`
1671                if self
1672                    .peek_next()
1673                    .map(|t| matches!(t, Token::Fn | Token::Lambda | Token::Async | Token::Hourglass))
1674                    == Some(true)
1675                {
1676                    Ok(ImplItem::Function(
1677                        self.parse_function_with_attrs(visibility, outer_attrs)?,
1678                    ))
1679                } else {
1680                    Ok(ImplItem::Const(self.parse_const(visibility)?))
1681                }
1682            }
1683            Some(token) => Err(ParseError::UnexpectedToken {
1684                expected: "impl item".to_string(),
1685                found: token.clone(),
1686                span: self.current_span(),
1687            }),
1688            None => Err(ParseError::UnexpectedEof),
1689        }
1690    }
1691
1692    fn parse_type_alias(&mut self, visibility: Visibility) -> ParseResult<TypeAlias> {
1693        self.expect(Token::Type)?;
1694        let name = self.parse_ident()?;
1695        let generics = self.parse_generics_opt()?;
1696        // Handle evidentiality marker after name: type Weights~ = ...
1697        let _evidentiality = self.parse_evidentiality_opt();
1698        self.expect(Token::Eq)?;
1699        let ty = self.parse_type()?;
1700        // Semicolon is optional for type aliases (especially after inline struct types)
1701        self.consume_if(&Token::Semi);
1702
1703        Ok(TypeAlias {
1704            visibility,
1705            name,
1706            generics,
1707            ty,
1708        })
1709    }
1710
1711    fn parse_module(&mut self, visibility: Visibility) -> ParseResult<Module> {
1712        self.expect(Token::Mod)?;
1713        let name = self.parse_ident()?;
1714
1715        let items = if self.check(&Token::LBrace) {
1716            self.expect(Token::LBrace)?;
1717            let mut items = Vec::new();
1718            while !self.check(&Token::RBrace) && !self.is_eof() {
1719                // Skip doc comments and line comments before items
1720                while matches!(
1721                    self.current_token(),
1722                    Some(Token::DocComment(_))
1723                        | Some(
1724                            Token::LineComment(_) | Token::TildeComment(_) | Token::BlockComment(_)
1725                        )
1726                ) {
1727                    self.advance();
1728                }
1729                if self.check(&Token::RBrace) {
1730                    break;
1731                }
1732                items.push(self.parse_item()?);
1733            }
1734            self.expect(Token::RBrace)?;
1735            Some(items)
1736        } else {
1737            // Semicolon is optional in Sigil's advanced syntax
1738            self.expect_semi_or_item_start()?;
1739            None
1740        };
1741
1742        Ok(Module {
1743            visibility,
1744            name,
1745            items,
1746        })
1747    }
1748
1749    fn parse_use(&mut self, visibility: Visibility) -> ParseResult<UseDecl> {
1750        self.expect(Token::Use)?;
1751        let tree = self.parse_use_tree()?;
1752        // Semicolon is optional in Sigil's advanced syntax
1753        self.expect_semi_or_item_start()?;
1754
1755        Ok(UseDecl { visibility, tree })
1756    }
1757
1758    fn parse_use_tree(&mut self) -> ParseResult<UseTree> {
1759        if self.consume_if(&Token::Star) {
1760            return Ok(UseTree::Glob);
1761        }
1762
1763        if self.check(&Token::LBrace) {
1764            self.expect(Token::LBrace)?;
1765            let mut trees = Vec::new();
1766            while !self.check(&Token::RBrace) {
1767                // Skip comments and attributes inside use groups: #[cfg(...)]
1768                loop {
1769                    if matches!(
1770                        self.current_token(),
1771                        Some(Token::DocComment(_))
1772                            | Some(
1773                                Token::LineComment(_)
1774                                    | Token::TildeComment(_)
1775                                    | Token::BlockComment(_)
1776                            )
1777                    ) {
1778                        self.advance();
1779                    } else if self.check(&Token::Hash) {
1780                        // Skip attribute: #[...]
1781                        self.skip_attribute()?;
1782                    } else {
1783                        break;
1784                    }
1785                }
1786                if self.check(&Token::RBrace) {
1787                    break;
1788                }
1789                trees.push(self.parse_use_tree()?);
1790                if !self.consume_if(&Token::Comma) {
1791                    break;
1792                }
1793                // Skip comments and attributes after comma
1794                loop {
1795                    if matches!(
1796                        self.current_token(),
1797                        Some(Token::DocComment(_))
1798                            | Some(
1799                                Token::LineComment(_)
1800                                    | Token::TildeComment(_)
1801                                    | Token::BlockComment(_)
1802                            )
1803                    ) {
1804                        self.advance();
1805                    } else if self.check(&Token::Hash) {
1806                        // Skip attribute: #[...]
1807                        self.skip_attribute()?;
1808                    } else {
1809                        break;
1810                    }
1811                }
1812            }
1813            self.expect(Token::RBrace)?;
1814            return Ok(UseTree::Group(trees));
1815        }
1816
1817        // Handle special keywords that can appear as path segments: crate, super, self
1818        let name = if self.check(&Token::Crate) {
1819            let span = self.current_span();
1820            self.advance();
1821            Ident {
1822                name: "crate".to_string(),
1823                evidentiality: None,
1824                affect: None,
1825                span,
1826            }
1827        } else if self.check(&Token::Super) {
1828            let span = self.current_span();
1829            self.advance();
1830            Ident {
1831                name: "super".to_string(),
1832                evidentiality: None,
1833                affect: None,
1834                span,
1835            }
1836        } else if self.check_self() {
1837            // this or ξ (self)
1838            let span = self.current_span();
1839            self.advance();
1840            Ident {
1841                name: "self".to_string(),
1842                evidentiality: None,
1843                affect: None,
1844                span,
1845            }
1846        } else if self.check(&Token::Sqrt) {
1847            // Handle sacred constant √2, √3, etc.
1848            let span = self.current_span();
1849            self.advance();
1850            // Check for following integer (e.g., √2)
1851            if let Some(Token::IntLit(n)) = self.current_token().cloned() {
1852                let merged_span = span.merge(self.current_span());
1853                self.advance();
1854                Ident {
1855                    name: format!("√{}", n),
1856                    evidentiality: None,
1857                    affect: None,
1858                    span: merged_span,
1859                }
1860            } else {
1861                Ident {
1862                    name: "√".to_string(),
1863                    evidentiality: None,
1864                    affect: None,
1865                    span,
1866                }
1867            }
1868        } else if self.check(&Token::Phi) {
1869            // Handle φ (golden ratio) as import name
1870            let span = self.current_span();
1871            self.advance();
1872            Ident {
1873                name: "φ".to_string(),
1874                evidentiality: None,
1875                affect: None,
1876                span,
1877            }
1878        } else {
1879            self.parse_ident()?
1880        };
1881
1882        // Handle macro import or evidentiality suffix: Gradients!, MomentEstimate~
1883        // These are valid in use statements for macro types or evidential type aliases
1884        let _evidentiality = self.parse_evidentiality_opt();
1885
1886        // Check for path continuation with · or ::
1887        if self.consume_if(&Token::MiddleDot) || self.consume_if(&Token::ColonColon) {
1888            let suffix = self.parse_use_tree()?;
1889            return Ok(UseTree::Path {
1890                prefix: name,
1891                suffix: Box::new(suffix),
1892            });
1893        }
1894
1895        // Check for rename (as or →)
1896        if self.consume_if_as() {
1897            // Allow underscore as alias: `use foo::Bar as _`
1898            if self.check(&Token::Underscore) {
1899                let span = self.current_span();
1900                self.advance();
1901                let alias = Ident {
1902                    name: "_".to_string(),
1903                    evidentiality: None,
1904                    affect: None,
1905                    span,
1906                };
1907                return Ok(UseTree::Rename { name, alias });
1908            }
1909            let alias = self.parse_ident()?;
1910            return Ok(UseTree::Rename { name, alias });
1911        }
1912
1913        Ok(UseTree::Name(name))
1914    }
1915
1916    fn parse_const(&mut self, visibility: Visibility) -> ParseResult<ConstDef> {
1917        self.expect(Token::Const)?;
1918        let name = self.parse_ident()?;
1919        self.expect(Token::Colon)?;
1920        let ty = self.parse_type()?;
1921        self.expect(Token::Eq)?;
1922        let value = self.parse_expr()?;
1923        // Semicolon is optional in Sigil's advanced syntax
1924        self.expect_semi_or_item_start()?;
1925
1926        Ok(ConstDef {
1927            visibility,
1928            name,
1929            ty,
1930            value,
1931        })
1932    }
1933
1934    fn parse_static(&mut self, visibility: Visibility) -> ParseResult<StaticDef> {
1935        self.expect(Token::Static)?;
1936        let mutable = self.consume_if_mut();
1937        let name = self.parse_ident()?;
1938        self.expect(Token::Colon)?;
1939        let ty = self.parse_type()?;
1940        self.expect(Token::Eq)?;
1941        let value = self.parse_expr()?;
1942        // Semicolon is optional in Sigil's advanced syntax
1943        self.expect_semi_or_item_start()?;
1944
1945        Ok(StaticDef {
1946            visibility,
1947            mutable,
1948            name,
1949            ty,
1950            value,
1951        })
1952    }
1953
1954    /// Parse a macro definition: `macro name { ... }` or `macro name(...) { ... }`
1955    /// Also supports Rust-style: `macro_rules! name { ... }`
1956    fn parse_macro_def(&mut self, visibility: Visibility) -> ParseResult<MacroDef> {
1957        // Handle both `macro` and `macro_rules` keywords
1958        let is_macro_rules = self.check(&Token::MacroRules);
1959        if is_macro_rules {
1960            self.advance(); // consume 'macro_rules'
1961            self.expect(Token::Bang)?; // consume '!'
1962        } else {
1963            self.expect(Token::Macro)?;
1964        }
1965
1966        let name = self.parse_ident()?;
1967
1968        // Collect the entire macro body as a string (we don't interpret macros)
1969        // Could be: macro name { ... } or macro name(...) { ... } or macro name($arg:ty) { ... }
1970        let mut body = String::new();
1971        let mut depth = 0;
1972
1973        // Check for optional parameter list (parentheses)
1974        if self.check(&Token::LParen) {
1975            body.push('(');
1976            self.advance();
1977            depth = 1;
1978            while depth > 0 && !self.is_eof() {
1979                match self.current_token() {
1980                    Some(Token::LParen) => {
1981                        depth += 1;
1982                        body.push('(');
1983                    }
1984                    Some(Token::RParen) => {
1985                        depth -= 1;
1986                        if depth > 0 {
1987                            body.push(')');
1988                        }
1989                    }
1990                    Some(tok) => {
1991                        body.push_str(&format!("{:?} ", tok));
1992                    }
1993                    None => break,
1994                }
1995                self.advance();
1996            }
1997            body.push(')');
1998        }
1999
2000        // Expect the body in braces
2001        self.expect(Token::LBrace)?;
2002        body.push('{');
2003        depth = 1;
2004        while depth > 0 && !self.is_eof() {
2005            match self.current_token() {
2006                Some(Token::LBrace) => {
2007                    depth += 1;
2008                    body.push('{');
2009                }
2010                Some(Token::RBrace) => {
2011                    depth -= 1;
2012                    if depth > 0 {
2013                        body.push('}');
2014                    }
2015                }
2016                Some(Token::LineComment(s)) => {
2017                    body.push_str(&format!("//{}", s));
2018                }
2019                Some(tok) => {
2020                    body.push_str(&format!("{:?} ", tok));
2021                }
2022                None => break,
2023            }
2024            self.advance();
2025        }
2026        body.push('}');
2027
2028        Ok(MacroDef {
2029            visibility,
2030            name,
2031            rules: body,
2032        })
2033    }
2034
2035    /// Check if the current position looks like a macro invocation (ident! or path::ident!)
2036    fn looks_like_macro_invocation(&mut self) -> bool {
2037        // Check if current is identifier
2038        if !matches!(self.current_token(), Some(Token::Ident(_))) {
2039            return false;
2040        }
2041        // Scan ahead for pattern: (ident (:: ident)*) !
2042        // Position 0 = first token after current (peek_n(0)), etc.
2043        let mut pos = 0;
2044        loop {
2045            match self.peek_n(pos) {
2046                Some(Token::Bang) => return true,
2047                Some(Token::ColonColon) => {
2048                    pos += 1;
2049                    // Next should be an identifier
2050                    match self.peek_n(pos) {
2051                        Some(Token::Ident(_)) => {
2052                            pos += 1;
2053                            continue;
2054                        }
2055                        _ => return false,
2056                    }
2057                }
2058                _ => return false,
2059            }
2060        }
2061    }
2062
2063    /// Parse a macro invocation: `name! { ... }` or `path::to::macro! { ... }`
2064    fn parse_macro_invocation(&mut self) -> ParseResult<MacroInvocation> {
2065        use crate::ast::{MacroDelimiter, MacroInvocation};
2066
2067        // Parse the path (macro name, potentially with ::)
2068        let path = self.parse_type_path()?;
2069
2070        // Expect !
2071        self.expect(Token::Bang)?;
2072
2073        // Determine delimiter and parse body
2074        let (delimiter, open_tok, close_tok) = match self.current_token() {
2075            Some(Token::LBrace) => (MacroDelimiter::Brace, Token::LBrace, Token::RBrace),
2076            Some(Token::LParen) => (MacroDelimiter::Paren, Token::LParen, Token::RParen),
2077            Some(Token::LBracket) => (MacroDelimiter::Bracket, Token::LBracket, Token::RBracket),
2078            Some(tok) => {
2079                return Err(ParseError::UnexpectedToken {
2080                    expected: "macro delimiter ('{', '(', or '[')".to_string(),
2081                    found: tok.clone(),
2082                    span: self.current_span(),
2083                });
2084            }
2085            None => return Err(ParseError::UnexpectedEof),
2086        };
2087
2088        self.advance(); // consume opening delimiter
2089
2090        // Collect body tokens as string
2091        let mut body = String::new();
2092        let mut depth = 1;
2093
2094        while depth > 0 && !self.is_eof() {
2095            let tok = self.current_token().cloned();
2096            match &tok {
2097                Some(t) if *t == open_tok => {
2098                    depth += 1;
2099                    body.push_str(&format!("{:?} ", t));
2100                }
2101                Some(t) if *t == close_tok => {
2102                    depth -= 1;
2103                    if depth > 0 {
2104                        body.push_str(&format!("{:?} ", t));
2105                    }
2106                }
2107                Some(Token::LineComment(s)) => {
2108                    body.push_str(&format!("//{}\n", s));
2109                }
2110                Some(t) => {
2111                    body.push_str(&format!("{:?} ", t));
2112                }
2113                None => break,
2114            }
2115            self.advance();
2116        }
2117
2118        // For () and [] delimited macros at item level, consume trailing semicolon
2119        if delimiter != MacroDelimiter::Brace {
2120            self.consume_if(&Token::Semi);
2121        }
2122
2123        Ok(MacroInvocation {
2124            path,
2125            delimiter,
2126            tokens: body,
2127        })
2128    }
2129
2130    fn parse_actor(&mut self, visibility: Visibility) -> ParseResult<ActorDef> {
2131        self.expect(Token::Actor)?;
2132        let name = self.parse_ident()?;
2133        let generics = self.parse_generics_opt()?;
2134
2135        self.expect(Token::LBrace)?;
2136
2137        let mut state = Vec::new();
2138        let mut handlers = Vec::new();
2139
2140        while !self.check(&Token::RBrace) && !self.is_eof() {
2141            if self.check(&Token::On) {
2142                handlers.push(self.parse_message_handler()?);
2143            } else {
2144                // Parse state field
2145                let vis = self.parse_visibility()?;
2146                let field_name = self.parse_ident()?;
2147                self.expect(Token::Colon)?;
2148                let ty = self.parse_type()?;
2149
2150                // Optional default value
2151                let default = if self.consume_if(&Token::Eq) {
2152                    Some(self.parse_expr()?)
2153                } else {
2154                    None
2155                };
2156
2157                if !self.check(&Token::RBrace) && !self.check(&Token::On) {
2158                    self.consume_if(&Token::Comma);
2159                }
2160
2161                state.push(FieldDef {
2162                    visibility: vis,
2163                    name: field_name,
2164                    ty,
2165                    default,
2166                });
2167            }
2168        }
2169
2170        self.expect(Token::RBrace)?;
2171
2172        Ok(ActorDef {
2173            visibility,
2174            name,
2175            generics,
2176            state,
2177            handlers,
2178        })
2179    }
2180
2181    /// Parse an extern block: `extern "C" { ... }`
2182    fn parse_extern_block(&mut self) -> ParseResult<ExternBlock> {
2183        self.expect(Token::Extern)?;
2184
2185        // Parse ABI string (default to "C")
2186        let abi = if let Some(Token::StringLit(s)) = self.current_token().cloned() {
2187            self.advance();
2188            s
2189        } else {
2190            "C".to_string()
2191        };
2192
2193        self.expect(Token::LBrace)?;
2194
2195        let mut items = Vec::new();
2196
2197        while !self.check(&Token::RBrace) && !self.is_eof() {
2198            let visibility = self.parse_visibility()?;
2199
2200            match self.current_token() {
2201                Some(Token::Fn) => {
2202                    items.push(ExternItem::Function(
2203                        self.parse_extern_function(visibility)?,
2204                    ));
2205                }
2206                Some(Token::Static) => {
2207                    items.push(ExternItem::Static(self.parse_extern_static(visibility)?));
2208                }
2209                Some(token) => {
2210                    return Err(ParseError::UnexpectedToken {
2211                        expected: "fn or static".to_string(),
2212                        found: token.clone(),
2213                        span: self.current_span(),
2214                    });
2215                }
2216                None => return Err(ParseError::UnexpectedEof),
2217            }
2218        }
2219
2220        self.expect(Token::RBrace)?;
2221
2222        Ok(ExternBlock { abi, items })
2223    }
2224
2225    /// Parse an extern function declaration (no body).
2226    fn parse_extern_function(&mut self, visibility: Visibility) -> ParseResult<ExternFunction> {
2227        self.expect_fn()?;
2228        let name = self.parse_ident()?;
2229
2230        // Handle evidentiality marker after function name: fn load_safetensors~(...)
2231        let _evidentiality = self.parse_evidentiality_opt();
2232
2233        self.expect(Token::LParen)?;
2234
2235        let mut params = Vec::new();
2236        let mut variadic = false;
2237
2238        while !self.check(&Token::RParen) && !self.is_eof() {
2239            // Check for variadic: ...
2240            if self.check(&Token::DotDot) {
2241                self.advance();
2242                if self.consume_if(&Token::Dot) {
2243                    variadic = true;
2244                    break;
2245                }
2246            }
2247
2248            let pattern = self.parse_pattern()?;
2249            self.expect(Token::Colon)?;
2250            let ty = self.parse_type()?;
2251
2252            params.push(Param { pattern, ty });
2253
2254            if !self.check(&Token::RParen) {
2255                self.expect(Token::Comma)?;
2256            }
2257        }
2258
2259        self.expect(Token::RParen)?;
2260
2261        // Return type
2262        let return_type = if self.consume_if(&Token::Arrow) {
2263            Some(self.parse_type()?)
2264        } else {
2265            None
2266        };
2267
2268        // Extern functions end with semicolon, not a body
2269        self.expect(Token::Semi)?;
2270
2271        Ok(ExternFunction {
2272            visibility,
2273            name,
2274            params,
2275            return_type,
2276            variadic,
2277        })
2278    }
2279
2280    /// Parse an extern static declaration.
2281    fn parse_extern_static(&mut self, visibility: Visibility) -> ParseResult<ExternStatic> {
2282        self.expect(Token::Static)?;
2283        let mutable = self.consume_if_mut();
2284        let name = self.parse_ident()?;
2285        self.expect(Token::Colon)?;
2286        let ty = self.parse_type()?;
2287        self.expect(Token::Semi)?;
2288
2289        Ok(ExternStatic {
2290            visibility,
2291            mutable,
2292            name,
2293            ty,
2294        })
2295    }
2296
2297    fn parse_message_handler(&mut self) -> ParseResult<MessageHandler> {
2298        self.expect(Token::On)?;
2299        let message = self.parse_ident()?;
2300
2301        self.expect(Token::LParen)?;
2302        let params = self.parse_params()?;
2303        self.expect(Token::RParen)?;
2304
2305        let return_type = if self.consume_if(&Token::Arrow) {
2306            Some(self.parse_type()?)
2307        } else {
2308            None
2309        };
2310
2311        let body = self.parse_block()?;
2312
2313        Ok(MessageHandler {
2314            message,
2315            params,
2316            return_type,
2317            body,
2318        })
2319    }
2320
2321    // === Type parsing ===
2322
2323    pub(crate) fn parse_type(&mut self) -> ParseResult<TypeExpr> {
2324        // Check for PREFIX evidentiality: !T, ?T, ~T, ‽T (Sigil-style)
2325        if let Some(ev) = self.parse_evidentiality_prefix_opt() {
2326            let inner = self.parse_type()?;
2327            return Ok(TypeExpr::Evidential {
2328                inner: Box::new(inner),
2329                evidentiality: ev,
2330                error_type: None,
2331            });
2332        }
2333
2334        let mut base = self.parse_type_base()?;
2335
2336        // Check if parse_ident already consumed evidentiality on the type name (e.g., Tensor◊)
2337        // If so, we need to extract it and wrap the type properly
2338        // But DON'T return early - there may be additional evidentiality after generics (e.g., Type~<T>!)
2339        let path_evidentiality = if let TypeExpr::Path(ref mut path) = base {
2340            if let Some(last_seg) = path.segments.last_mut() {
2341                last_seg.ident.evidentiality.take()
2342            } else {
2343                None
2344            }
2345        } else {
2346            None
2347        };
2348        if let Some(ev) = path_evidentiality {
2349            base = TypeExpr::Evidential {
2350                inner: Box::new(base),
2351                evidentiality: ev,
2352                error_type: None,
2353            };
2354        }
2355
2356        // Check for evidentiality suffix: T?, T!, T~, T?[Error], T![Error], T~[Error]
2357        if let Some(ev) = self.parse_evidentiality_opt() {
2358            // Check for generics after evidentiality: Type!<T>, Type?<T>
2359            // Pattern: Gradient!<S, D, Dev> where ! is evidentiality, <...> are generics
2360            let base = if self.check(&Token::Lt) && self.peek_looks_like_generic_arg() {
2361                // Apply generics to the inner path type
2362                if let TypeExpr::Path(mut path) = base {
2363                    self.advance(); // consume <
2364                    let types = self.parse_type_list()?;
2365                    self.expect_gt()?;
2366                    // Add generics to the last segment
2367                    if let Some(last) = path.segments.last_mut() {
2368                        last.generics = Some(types);
2369                    }
2370                    TypeExpr::Path(path)
2371                } else {
2372                    base
2373                }
2374            } else {
2375                base
2376            };
2377
2378            // Check for optional error type bracket: ?[ErrorType]
2379            let error_type = if self.check(&Token::LBracket) {
2380                self.advance(); // consume [
2381                let err_ty = self.parse_type()?;
2382                self.expect(Token::RBracket)?; // consume ]
2383                Some(Box::new(err_ty))
2384            } else {
2385                None
2386            };
2387
2388            let mut result = TypeExpr::Evidential {
2389                inner: Box::new(base),
2390                evidentiality: ev,
2391                error_type,
2392            };
2393
2394            // Check for additional evidentiality suffix: Type~<T>! (chained evidentiality)
2395            if let Some(ev2) = self.parse_evidentiality_opt() {
2396                result = TypeExpr::Evidential {
2397                    inner: Box::new(result),
2398                    evidentiality: ev2,
2399                    error_type: None,
2400                };
2401            }
2402
2403            return Ok(result);
2404        }
2405
2406        Ok(base)
2407    }
2408
2409    /// Parse PREFIX evidentiality marker: !T, ?T, ~T, ◊T, ‽T
2410    /// Only consumes the token if followed by valid type start
2411    fn parse_evidentiality_prefix_opt(&mut self) -> Option<Evidentiality> {
2412        match self.current_token() {
2413            Some(Token::Bang) => {
2414                // Check if this is prefix evidentiality or something else
2415                // Peek to see if next token could be a type
2416                if self.peek_is_type_start() {
2417                    self.advance();
2418                    Some(Evidentiality::Known)
2419                } else {
2420                    None
2421                }
2422            }
2423            Some(Token::Question) => {
2424                if self.peek_is_type_start() {
2425                    self.advance();
2426                    Some(Evidentiality::Uncertain)
2427                } else {
2428                    None
2429                }
2430            }
2431            Some(Token::Tilde) => {
2432                if self.peek_is_type_start() {
2433                    self.advance();
2434                    Some(Evidentiality::Reported)
2435                } else {
2436                    None
2437                }
2438            }
2439            Some(Token::Lozenge) => {
2440                if self.peek_is_type_start() {
2441                    self.advance();
2442                    Some(Evidentiality::Predicted)
2443                } else {
2444                    None
2445                }
2446            }
2447            Some(Token::Interrobang) => {
2448                if self.peek_is_type_start() {
2449                    self.advance();
2450                    Some(Evidentiality::Paradox)
2451                } else {
2452                    None
2453                }
2454            }
2455            _ => None,
2456        }
2457    }
2458
2459    /// Check if the next token (after current) could start a type
2460    fn peek_is_type_start(&mut self) -> bool {
2461        match self.peek_next() {
2462            Some(Token::Ident(_)) => true,
2463            Some(Token::SelfUpper) => true,
2464            Some(Token::Amp) => true,
2465            Some(Token::AndAnd) => true, // Double reference: &&T
2466            Some(Token::Star) => true,
2467            Some(Token::LBracket) => true,
2468            Some(Token::LParen) => true,
2469            Some(Token::Fn) => true,
2470            Some(Token::Underscore) => true,
2471            Some(Token::Simd) => true,
2472            Some(Token::Atomic) => true,
2473            // Nested prefix evidentiality: !!T, !?T, etc.
2474            Some(Token::Bang) => true,
2475            Some(Token::Question) => true,
2476            Some(Token::Tilde) => true,
2477            Some(Token::Interrobang) => true,
2478            _ => false,
2479        }
2480    }
2481
2482    fn parse_type_base(&mut self) -> ParseResult<TypeExpr> {
2483        match self.current_token() {
2484            Some(Token::AndAnd) => {
2485                // Double reference: &&T -> &(&T)
2486                self.advance();
2487                // Check for optional lifetime on inner reference: &&'a T
2488                let lifetime = if let Some(Token::Lifetime(lt)) = self.current_token().cloned() {
2489                    self.advance();
2490                    Some(lt)
2491                } else {
2492                    None
2493                };
2494                let mutable = self.consume_if_mut();
2495                let inner = self.parse_type()?;
2496                // Inner reference
2497                let inner_ref = TypeExpr::Reference {
2498                    lifetime,
2499                    mutable,
2500                    inner: Box::new(inner),
2501                };
2502                // Outer reference (immutable, no lifetime)
2503                Ok(TypeExpr::Reference {
2504                    lifetime: None,
2505                    mutable: false,
2506                    inner: Box::new(inner_ref),
2507                })
2508            }
2509            Some(Token::Amp) => {
2510                self.advance();
2511                // Check for optional lifetime: &'a T or &'static T
2512                let lifetime = if let Some(Token::Lifetime(lt)) = self.current_token().cloned() {
2513                    self.advance();
2514                    Some(lt)
2515                } else {
2516                    None
2517                };
2518                let mutable = self.consume_if_mut();
2519                let inner = self.parse_type()?;
2520                Ok(TypeExpr::Reference {
2521                    lifetime,
2522                    mutable,
2523                    inner: Box::new(inner),
2524                })
2525            }
2526            Some(Token::Star) => {
2527                self.advance();
2528                // Raw pointer: *const T, *mut T, or *!T (evidential pointer)
2529                // Make const/mut optional to support Sigil's *!T syntax
2530                let mutable = if self.consume_if(&Token::Const) {
2531                    false
2532                } else if self.consume_if_mut() {
2533                    true
2534                } else {
2535                    // No const/mut - default to immutable (for *!T style)
2536                    false
2537                };
2538                let inner = self.parse_type()?;
2539                Ok(TypeExpr::Pointer {
2540                    mutable,
2541                    inner: Box::new(inner),
2542                })
2543            }
2544            Some(Token::Linear) => {
2545                // Linear type: `linear T` - value can only be used once
2546                self.advance();
2547                let inner = self.parse_type()?;
2548                Ok(TypeExpr::Linear(Box::new(inner)))
2549            }
2550            Some(Token::LBracket) => {
2551                self.advance();
2552                // Check for empty brackets or array/shape syntax
2553                if self.check(&Token::RBracket) {
2554                    // Empty array/scalar shape: [] - used for scalar tensors (0-dimensional)
2555                    self.advance();
2556                    // Return as an empty const expression (empty array literal)
2557                    return Ok(TypeExpr::ConstExpr(Box::new(Expr::Array(vec![]))));
2558                }
2559                // Use parse_type_or_lifetime to handle const generic literals like [2, 4]
2560                let first = self.parse_type_or_lifetime()?;
2561                if self.consume_if(&Token::Semi) {
2562                    // Fixed-size array: [Type; size]
2563                    let size = self.parse_expr()?;
2564                    self.expect(Token::RBracket)?;
2565                    Ok(TypeExpr::Array {
2566                        element: Box::new(first),
2567                        size: Box::new(size),
2568                    })
2569                } else if self.consume_if(&Token::Comma) {
2570                    // Multi-element array shape: [A, B, C] or [D, HD/2] for tensor shapes
2571                    // Parse as const expressions to support arithmetic like HD/2
2572                    let first_expr = match first {
2573                        TypeExpr::Path(path) => Expr::Path(path),
2574                        TypeExpr::ConstExpr(expr) => *expr,
2575                        _ => Expr::Path(TypePath {
2576                            segments: vec![PathSegment {
2577                                ident: Ident {
2578                                    name: format!("{:?}", first),
2579                                    evidentiality: None,
2580                                    affect: None,
2581                                    span: Span::new(0, 0),
2582                                },
2583                                generics: None,
2584                            }],
2585                        }),
2586                    };
2587                    let mut elem_exprs = vec![first_expr];
2588                    while !self.check(&Token::RBracket) && !self.is_eof() {
2589                        // Parse dimension as const expression to support HD/2, N*2, etc.
2590                        let dim_expr = self.parse_array_dim_expr()?;
2591                        elem_exprs.push(dim_expr);
2592                        if !self.consume_if(&Token::Comma) {
2593                            break;
2594                        }
2595                    }
2596                    self.expect(Token::RBracket)?;
2597                    Ok(TypeExpr::ConstExpr(Box::new(Expr::Array(elem_exprs))))
2598                } else if matches!(
2599                    self.current_token(),
2600                    Some(Token::Slash)
2601                        | Some(Token::Star)
2602                        | Some(Token::Plus)
2603                        | Some(Token::Minus)
2604                        | Some(Token::Percent)
2605                ) {
2606                    // Dimension expression with arithmetic: [HD/2], [H * HD, D], etc.
2607                    // Convert first to expression and continue parsing as arithmetic
2608                    let first_expr = match first {
2609                        TypeExpr::Path(path) => Expr::Path(path),
2610                        TypeExpr::ConstExpr(expr) => *expr,
2611                        _ => Expr::Path(TypePath {
2612                            segments: vec![PathSegment {
2613                                ident: Ident {
2614                                    name: format!("{:?}", first),
2615                                    evidentiality: None,
2616                                    affect: None,
2617                                    span: Span::new(0, 0),
2618                                },
2619                                generics: None,
2620                            }],
2621                        }),
2622                    };
2623                    // Now parse the operator and rest of expression
2624                    let op = match self.current_token() {
2625                        Some(Token::Slash) => BinOp::Div,
2626                        Some(Token::Star) => BinOp::Mul,
2627                        Some(Token::Plus) => BinOp::Add,
2628                        Some(Token::Minus) => BinOp::Sub,
2629                        Some(Token::Percent) => BinOp::Rem,
2630                        _ => unreachable!(),
2631                    };
2632                    self.advance(); // consume operator
2633                    let right = self.parse_const_expr_primary()?;
2634                    let expr = Expr::Binary {
2635                        left: Box::new(first_expr),
2636                        op,
2637                        right: Box::new(right),
2638                    };
2639
2640                    // Check for more dimensions after the arithmetic: [H * HD, D]
2641                    if self.consume_if(&Token::Comma) {
2642                        let mut elem_exprs = vec![expr];
2643                        while !self.check(&Token::RBracket) && !self.is_eof() {
2644                            let dim_expr = self.parse_array_dim_expr()?;
2645                            elem_exprs.push(dim_expr);
2646                            if !self.consume_if(&Token::Comma) {
2647                                break;
2648                            }
2649                        }
2650                        self.expect(Token::RBracket)?;
2651                        Ok(TypeExpr::ConstExpr(Box::new(Expr::Array(elem_exprs))))
2652                    } else {
2653                        self.expect(Token::RBracket)?;
2654                        Ok(TypeExpr::ConstExpr(Box::new(Expr::Array(vec![expr]))))
2655                    }
2656                } else {
2657                    // Slice: [Type]
2658                    self.expect(Token::RBracket)?;
2659                    Ok(TypeExpr::Slice(Box::new(first)))
2660                }
2661            }
2662            Some(Token::LParen) => {
2663                self.advance();
2664                if self.check(&Token::RParen) {
2665                    self.advance();
2666                    return Ok(TypeExpr::Tuple(vec![]));
2667                }
2668                let types = self.parse_type_list()?;
2669                self.expect(Token::RParen)?;
2670                Ok(TypeExpr::Tuple(types))
2671            }
2672            Some(Token::Fn) => {
2673                self.advance();
2674                self.expect(Token::LParen)?;
2675                let params = self.parse_type_list()?;
2676                self.expect(Token::RParen)?;
2677                let return_type = if self.consume_if(&Token::Arrow) {
2678                    Some(Box::new(self.parse_type()?))
2679                } else {
2680                    None
2681                };
2682                Ok(TypeExpr::Function {
2683                    params,
2684                    return_type,
2685                })
2686            }
2687            Some(Token::Impl) => {
2688                // impl Trait - opaque return type
2689                self.advance();
2690                // Parse trait bounds: impl Trait + OtherTrait + 'lifetime
2691                let bounds = self.parse_type_bounds()?;
2692                Ok(TypeExpr::ImplTrait(bounds))
2693            }
2694            Some(Token::Bang) => {
2695                self.advance();
2696                Ok(TypeExpr::Never)
2697            }
2698            Some(Token::Underscore) => {
2699                self.advance();
2700                Ok(TypeExpr::Infer)
2701            }
2702            Some(Token::Lt) => {
2703                // Qualified path: <Type as Trait>::AssociatedType
2704                // or: <Type>::AssociatedType (inherent associated type)
2705                self.advance(); // consume <
2706                let base_type = self.parse_type()?;
2707
2708                // Check for "as Trait" clause (as or →)
2709                let trait_path = if self.consume_if_as() {
2710                    Some(self.parse_type_path()?)
2711                } else {
2712                    None
2713                };
2714
2715                self.expect_gt()?; // consume >
2716                // must have :: or · after >
2717                if !self.consume_if(&Token::ColonColon) && !self.consume_if(&Token::MiddleDot) {
2718                    return match &self.current {
2719                        Some((token, span)) => Err(ParseError::UnexpectedToken {
2720                            expected: "ColonColon or MiddleDot".to_string(),
2721                            found: token.clone(),
2722                            span: *span,
2723                        }),
2724                        None => Err(ParseError::UnexpectedEof),
2725                    };
2726                }
2727
2728                // Parse the associated type/const path
2729                let mut segments = vec![self.parse_path_segment()?];
2730                while self.consume_if(&Token::ColonColon) || self.consume_if(&Token::MiddleDot) {
2731                    segments.push(self.parse_path_segment()?);
2732                }
2733
2734                Ok(TypeExpr::QualifiedPath {
2735                    self_type: Box::new(base_type),
2736                    trait_path,
2737                    item_path: TypePath { segments },
2738                })
2739            }
2740            Some(Token::SelfUpper) => {
2741                let span = self.current_span();
2742                self.advance();
2743                let mut segments = vec![PathSegment {
2744                    ident: Ident {
2745                        name: "Self".to_string(),
2746                        evidentiality: None,
2747                        affect: None,
2748                        span,
2749                    },
2750                    generics: None,
2751                }];
2752                // Continue parsing path: Self::AssociatedType, Self::Nested::Type
2753                while self.consume_if(&Token::ColonColon) || self.consume_if(&Token::MiddleDot) {
2754                    // Check for turbofish: Self::<T>
2755                    if self.check(&Token::Lt) {
2756                        self.advance();
2757                        let types = self.parse_type_list()?;
2758                        self.expect_gt()?;
2759                        if let Some(last) = segments.last_mut() {
2760                            last.generics = Some(types);
2761                        }
2762                        continue;
2763                    }
2764                    segments.push(self.parse_path_segment()?);
2765                }
2766                Ok(TypeExpr::Path(TypePath { segments }))
2767            }
2768            Some(Token::Simd) => {
2769                self.advance();
2770                self.expect(Token::Lt)?;
2771                let element = self.parse_type()?;
2772                self.expect(Token::Comma)?;
2773                let lanes = match self.current_token() {
2774                    Some(Token::IntLit(s)) => {
2775                        let n = s
2776                            .parse::<u8>()
2777                            .map_err(|_| ParseError::Custom("invalid lane count".to_string()))?;
2778                        self.advance();
2779                        n
2780                    }
2781                    _ => return Err(ParseError::Custom("expected lane count".to_string())),
2782                };
2783                self.expect_gt()?;
2784                Ok(TypeExpr::Simd {
2785                    element: Box::new(element),
2786                    lanes,
2787                })
2788            }
2789            Some(Token::Atomic) => {
2790                self.advance();
2791                self.expect(Token::Lt)?;
2792                let inner = self.parse_type()?;
2793                self.expect_gt()?;
2794                Ok(TypeExpr::Atomic(Box::new(inner)))
2795            }
2796            Some(Token::Dyn) => {
2797                // Parse trait object: dyn Trait or dyn Trait + Send + 'static
2798                self.advance();
2799                let bounds = self.parse_type_bounds()?;
2800                Ok(TypeExpr::TraitObject(bounds))
2801            }
2802            Some(Token::Struct) | Some(Token::Sigma) => {
2803                // Inline struct type: struct { field: Type, ... } or Σ { ... }
2804                self.advance();
2805                self.expect(Token::LBrace)?;
2806                let mut fields = Vec::new();
2807                while !self.check(&Token::RBrace) && !self.is_eof() {
2808                    // Skip comments, doc comments, and attributes
2809                    while matches!(
2810                        self.current_token(),
2811                        Some(Token::DocComment(_))
2812                            | Some(
2813                                Token::LineComment(_)
2814                                    | Token::TildeComment(_)
2815                                    | Token::BlockComment(_)
2816                            )
2817                            | Some(Token::Hash)
2818                    ) {
2819                        if self.check(&Token::Hash) {
2820                            // Skip attribute: #[...]
2821                            self.advance();
2822                            if self.consume_if(&Token::LBracket) {
2823                                let mut depth = 1;
2824                                while depth > 0 && !self.is_eof() {
2825                                    match self.current_token() {
2826                                        Some(Token::LBracket) => depth += 1,
2827                                        Some(Token::RBracket) => depth -= 1,
2828                                        _ => {}
2829                                    }
2830                                    self.advance();
2831                                }
2832                            }
2833                        } else {
2834                            self.advance();
2835                        }
2836                    }
2837                    if self.check(&Token::RBrace) {
2838                        break;
2839                    }
2840                    // Parse optional visibility
2841                    let visibility = self.parse_visibility()?;
2842                    let name = self.parse_ident()?;
2843                    self.expect(Token::Colon)?;
2844                    let ty = self.parse_type()?;
2845                    fields.push(FieldDef {
2846                        visibility,
2847                        name,
2848                        ty,
2849                        default: None,
2850                    });
2851                    if !self.consume_if(&Token::Comma) {
2852                        break;
2853                    }
2854                }
2855                self.expect(Token::RBrace)?;
2856                Ok(TypeExpr::InlineStruct { fields })
2857            }
2858            Some(Token::Enum) => {
2859                // Inline enum type: enum { Variant1, Variant2(Type), ... }
2860                self.advance();
2861                self.expect(Token::LBrace)?;
2862                let mut variants = Vec::new();
2863                while !self.check(&Token::RBrace) && !self.is_eof() {
2864                    // Skip comments and doc comments
2865                    while matches!(
2866                        self.current_token(),
2867                        Some(Token::DocComment(_))
2868                            | Some(
2869                                Token::LineComment(_)
2870                                    | Token::TildeComment(_)
2871                                    | Token::BlockComment(_)
2872                            )
2873                    ) {
2874                        self.advance();
2875                    }
2876                    if self.check(&Token::RBrace) {
2877                        break;
2878                    }
2879                    // Parse variant name
2880                    let name = self.parse_ident()?;
2881                    // Parse optional fields
2882                    let fields = if self.check(&Token::LParen) {
2883                        self.advance();
2884                        let mut types = Vec::new();
2885                        while !self.check(&Token::RParen) && !self.is_eof() {
2886                            types.push(self.parse_type()?);
2887                            if !self.consume_if(&Token::Comma) {
2888                                break;
2889                            }
2890                        }
2891                        self.expect(Token::RParen)?;
2892                        StructFields::Tuple(types)
2893                    } else if self.check(&Token::LBrace) {
2894                        self.advance();
2895                        let mut fields = Vec::new();
2896                        while !self.check(&Token::RBrace) && !self.is_eof() {
2897                            let name = self.parse_ident()?;
2898                            self.expect(Token::Colon)?;
2899                            let ty = self.parse_type()?;
2900                            fields.push(FieldDef {
2901                                visibility: Visibility::Private,
2902                                name,
2903                                ty,
2904                                default: None,
2905                            });
2906                            if !self.consume_if(&Token::Comma) {
2907                                break;
2908                            }
2909                        }
2910                        self.expect(Token::RBrace)?;
2911                        StructFields::Named(fields)
2912                    } else {
2913                        StructFields::Unit
2914                    };
2915                    // Parse optional discriminant: N = -1
2916                    let discriminant = if self.consume_if(&Token::Eq) {
2917                        Some(self.parse_expr()?)
2918                    } else {
2919                        None
2920                    };
2921                    variants.push(EnumVariant {
2922                        name,
2923                        fields,
2924                        discriminant,
2925                    });
2926                    if !self.consume_if(&Token::Comma) {
2927                        break;
2928                    }
2929                }
2930                self.expect(Token::RBrace)?;
2931                Ok(TypeExpr::InlineEnum { variants })
2932            }
2933            // Handle crate::, self::, super:: path prefixes in types
2934            Some(Token::Crate) | Some(Token::SelfLower) | Some(Token::Xi) | Some(Token::Super) | Some(Token::IntensityUp) => {
2935                let keyword = self.current_token().cloned();
2936                let span = self.current_span();
2937                self.advance();
2938
2939                // Build the first segment from the keyword
2940                let keyword_name = match keyword {
2941                    Some(Token::Crate) => "crate",
2942                    Some(Token::SelfLower) | Some(Token::Xi) => "self",  // this or ξ
2943                    Some(Token::Super) | Some(Token::IntensityUp) => "super",  // above or ↑
2944                    _ => unreachable!(),
2945                };
2946                let first_segment = PathSegment {
2947                    ident: Ident {
2948                        name: keyword_name.to_string(),
2949                        evidentiality: None,
2950                        affect: None,
2951                        span,
2952                    },
2953                    generics: None,
2954                };
2955
2956                let mut segments = vec![first_segment];
2957
2958                // Continue parsing path: crate::module::Type
2959                while self.consume_if(&Token::ColonColon) || self.consume_if(&Token::MiddleDot) {
2960                    // Check for turbofish: crate::<T> (unlikely but possible)
2961                    if self.check(&Token::Lt) {
2962                        self.advance();
2963                        let types = self.parse_type_list()?;
2964                        self.expect_gt()?;
2965                        if let Some(last) = segments.last_mut() {
2966                            last.generics = Some(types);
2967                        }
2968                        continue;
2969                    }
2970                    segments.push(self.parse_path_segment()?);
2971                }
2972                Ok(TypeExpr::Path(TypePath { segments }))
2973            }
2974            _ => {
2975                let path = self.parse_type_path()?;
2976                Ok(TypeExpr::Path(path))
2977            }
2978        }
2979    }
2980
2981    fn parse_type_path(&mut self) -> ParseResult<TypePath> {
2982        let mut segments = Vec::new();
2983        segments.push(self.parse_path_segment()?);
2984
2985        // Don't continue parsing path if there's a pending `>` from split `>>`
2986        // This handles cases like `<T as Trait<U>>::Assoc` where `>>` is split
2987        // and the `::Assoc` belongs to the outer qualified path, not the trait path
2988        while !self.pending_gt.is_some()
2989            && (self.consume_if(&Token::ColonColon) || self.consume_if(&Token::MiddleDot))
2990        {
2991            // Check for turbofish syntax: path::<Type> instead of path::segment
2992            if self.check(&Token::Lt) {
2993                // Parse turbofish generics for the last segment
2994                // Temporarily exit condition context - turbofish is always type context
2995                let was_in_condition = self.in_condition;
2996                self.in_condition = false;
2997                self.advance(); // consume <
2998                let types = self.parse_type_list()?;
2999                self.expect_gt()?;
3000                self.in_condition = was_in_condition;
3001                // Update the last segment with these generics
3002                if let Some(last) = segments.last_mut() {
3003                    last.generics = Some(types);
3004                }
3005                // Continue parsing - there may be more segments after turbofish
3006                // e.g., Option::<T>::None or Vec::<T>::new()
3007                continue;
3008            }
3009            segments.push(self.parse_path_segment()?);
3010        }
3011
3012        Ok(TypePath { segments })
3013    }
3014
3015    fn parse_path_segment(&mut self) -> ParseResult<PathSegment> {
3016        // Handle both identifiers and numeric indices (for tuple field access like tuple·0)
3017        let ident = if let Some(Token::IntLit(idx)) = self.current_token().cloned() {
3018            let span = self.current_span();
3019            self.advance();
3020            Ident {
3021                name: idx,
3022                evidentiality: None,
3023                affect: None,
3024                span,
3025            }
3026        } else {
3027            self.parse_ident()?
3028        };
3029
3030        // Special case: Fn(T) -> R, FnMut(T) -> R, FnOnce(T) -> R trait syntax
3031        // These are function trait bounds with parenthesis-style generics
3032        let is_fn_trait = matches!(ident.name.as_str(), "Fn" | "FnMut" | "FnOnce");
3033        if is_fn_trait && self.check(&Token::LParen) {
3034            self.advance(); // consume (
3035            let param_types = self.parse_type_list()?;
3036            self.expect(Token::RParen)?;
3037            // Check for optional return type: -> R
3038            let return_type = if self.consume_if(&Token::Arrow) {
3039                Some(self.parse_type()?)
3040            } else {
3041                None
3042            };
3043            // Build a tuple type for params and optional return as generics
3044            // Fn(A, B) -> R becomes Fn<(A, B), R>
3045            let mut generics = vec![TypeExpr::Tuple(param_types)];
3046            if let Some(ret) = return_type {
3047                generics.push(ret);
3048            }
3049            return Ok(PathSegment {
3050                ident,
3051                generics: Some(generics),
3052            });
3053        }
3054
3055        // Don't parse generics in condition context (< is comparison, not generics)
3056        // Also check that what follows < looks like a type, not an expression like `self`
3057        // Support both <T> and [T] syntax for type generics (Sigil alternative syntax)
3058        let generics = if !self.is_in_condition()
3059            && self.check(&Token::Lt)
3060            && self.peek_looks_like_generic_arg()
3061        {
3062            self.advance(); // consume <
3063            let types = self.parse_type_list()?;
3064            // Use expect_gt() to handle nested generics with `>>`
3065            self.expect_gt()?;
3066            Some(types)
3067        } else if self.check(&Token::LBracket) && self.peek_looks_like_bracket_generic() {
3068            // Alternative syntax: Type[T] instead of Type<T>
3069            self.advance(); // consume [
3070            let types = self.parse_type_list()?;
3071            self.expect(Token::RBracket)?;
3072            Some(types)
3073        } else {
3074            None
3075        };
3076
3077        Ok(PathSegment { ident, generics })
3078    }
3079
3080    /// Check if [...] after identifier looks like a generic type argument rather than an array
3081    fn peek_looks_like_bracket_generic(&mut self) -> bool {
3082        // Peek after [ to check if it looks like a type parameter
3083        // Be conservative - index expressions like `array[pos + 2..]` should not be treated as generics
3084        match self.peek_next().cloned() {
3085            // For identifiers, use 2-token lookahead to see if it's a type or expression
3086            Some(Token::Ident(name)) => {
3087                // Check what follows the identifier
3088                // Only treat as generic if the identifier looks like a type name (uppercase)
3089                let is_type_name = name.chars().next().map_or(false, |c| c.is_uppercase());
3090                match self.peek_n(1) {
3091                    // [T] - only treat as generic if T looks like a type name (uppercase)
3092                    // This distinguishes HashMap[String] (generic) from array[index] (indexing)
3093                    Some(Token::RBracket) => is_type_name,
3094                    Some(Token::Comma) => is_type_name, // [T, U] - but not [a, b] which is array
3095                    Some(Token::ColonColon) => true,    // [T::U]
3096                    Some(Token::Lt) => is_type_name,    // [T<U>]
3097                    Some(Token::LBracket) => is_type_name, // [T[U]] but not [a[b]] (nested index)
3098                    // Evidentiality markers: [T!], [T?], [T~], [T◊], [T‽]
3099                    Some(Token::Question) => true,
3100                    Some(Token::Bang) => true,
3101                    Some(Token::Tilde) => true,
3102                    Some(Token::Lozenge) => true,
3103                    Some(Token::Interrobang) => true,
3104                    // Associated type binding: [Output = Type]
3105                    Some(Token::Eq) => true,
3106                    // Expression operators indicate index expression, not generics
3107                    Some(Token::Plus) => false,     // [pos + 2]
3108                    Some(Token::Minus) => false,    // [len - 1]
3109                    Some(Token::Star) => false,     // [i * 2]
3110                    Some(Token::Slash) => false,    // [i / 2]
3111                    Some(Token::DotDot) => false,   // [pos..] range
3112                    Some(Token::DotDotEq) => false, // [0..=n]
3113                    _ => false,                     // Default to not treating as generics
3114                }
3115            }
3116            Some(Token::SelfUpper) => true, // [Self]
3117            Some(Token::Amp) => true,       // [&T]
3118            // Don't treat [*expr] as generic - could be dereference in index
3119            Some(Token::Star) => false,
3120            Some(Token::Fn) => true, // [fn(...)]
3121            Some(Token::LParen) => {
3122                // [()] could be tuple type generic or parenthesized expression index
3123                // Look inside the parens to decide:
3124                // - [()] empty tuple - likely type
3125                // - [(T, U)] uppercase identifiers - likely type
3126                // - [(expr)] lowercase identifier or expression - likely index
3127                match self.peek_n(1) {
3128                    Some(Token::RParen) => true, // [()] empty tuple type
3129                    Some(Token::Ident(name)) => {
3130                        // If identifier starts uppercase, likely a type
3131                        // If lowercase followed by expression ops like 'as', it's an expression
3132                        if name.chars().next().map_or(false, |c| c.is_uppercase()) {
3133                            true // [(Type...)]
3134                        } else {
3135                            // Check what follows the lowercase identifier
3136                            match self.peek_n(2) {
3137                                Some(Token::As) | Some(Token::Arrow) => false, // [(n as T)] or [(n → T)] cast expression
3138                                Some(Token::Plus) => false,     // [(a + b)]
3139                                Some(Token::Minus) => false,    // [(a - b)]
3140                                Some(Token::Star) => false,     // [(a * b)]
3141                                Some(Token::Slash) => false,    // [(a / b)]
3142                                Some(Token::Dot) => false,      // [(a.b)]
3143                                Some(Token::LBracket) => false, // [(a[i])]
3144                                Some(Token::LParen) => false,   // [(f())]
3145                                Some(Token::RParen) => false, // [(x)] single lowercase var - expression
3146                                Some(Token::Comma) => true, // [(a, b)] could be tuple type, try it
3147                                _ => false,                 // Default to expression (index)
3148                            }
3149                        }
3150                    }
3151                    _ => false, // Default to not treating as generics
3152                }
3153            }
3154            Some(Token::Dyn) => true,  // [dyn Trait]
3155            Some(Token::Impl) => true, // [impl Trait]
3156            // Path-starting keywords that indicate type paths
3157            Some(Token::Crate) => true, // [crate::Type]
3158            Some(Token::Super) | Some(Token::IntensityUp) => true, // [super::Type] or ↑::Type
3159            // Literals indicate expressions, not types
3160            Some(Token::IntLit(_)) => false,
3161            Some(Token::FloatLit(_)) => false,
3162            Some(Token::SelfLower) | Some(Token::Xi) => false, // [this.x] or [ξ.x] - expression
3163            // Could be array: [expr; size] or [type; size]
3164            // If it's for generics, there won't be a semicolon
3165            _ => false,
3166        }
3167    }
3168
3169    /// Check if what follows < looks like it could be a generic type argument
3170    /// This helps disambiguate `foo<T>` (generics) from `foo < bar` (comparison)
3171    /// We are conservative: only treat as generics if it's clearly a type context
3172    /// Note: When called, self.current is at the < token
3173    fn peek_looks_like_generic_arg(&mut self) -> bool {
3174        // Use peek_next (peek_n(0)) to see what's after <
3175        match self.peek_next().cloned() {
3176            // Clear type starts that don't look like expressions
3177            Some(Token::Amp) => true, // &T - references are type-like
3178            Some(Token::Star) => {
3179                // *const T or *mut T - pointer types
3180                // *expr - dereference (not a type)
3181                // Look at what follows * to distinguish
3182                match self.peek_n(1) {
3183                    Some(Token::Const) => true, // *const T - pointer type
3184                    Some(Token::Mut) | Some(Token::Delta) => true,   // *mut/*Δ T - pointer type
3185                    _ => false,                 // *expr - dereference, not a type
3186                }
3187            }
3188            Some(Token::LBracket) => true,    // [T] - slices
3189            Some(Token::LParen) => true,      // () - tuple types including unit
3190            Some(Token::Fn) => true,          // fn() - function types
3191            Some(Token::Simd) => true,        // simd<T, N>
3192            Some(Token::Atomic) => true,      // atomic<T>
3193            Some(Token::Dyn) => true,         // dyn Trait - trait objects
3194            Some(Token::Impl) => true,        // impl Trait - existential types
3195            Some(Token::SelfUpper) => true,   // This is a type
3196            Some(Token::Crate) => true,       // crate::Type - path starting with crate
3197            Some(Token::Super) | Some(Token::IntensityUp) => true, // above/↑ - path starting with super
3198            Some(Token::Lifetime(_)) => true, // 'a, 'static - lifetime type args
3199            Some(Token::Underscore) => true,  // _ - inferred type
3200            // Evidentiality prefixes on types: !T, ?T, ~T
3201            Some(Token::Bang) => true,
3202            Some(Token::Question) => true,
3203            Some(Token::Tilde) => true,
3204            Some(Token::Interrobang) => true,
3205            // For identifiers, we need 2-token lookahead to see what follows
3206            Some(Token::Ident(name)) => {
3207                // peek_n(1) looks at the token after the identifier
3208                // (peek_n(0) = token after <, peek_n(1) = token after that)
3209                let is_type_like = name.chars().next().map_or(false, |c| c.is_uppercase())
3210                    || matches!(
3211                        name.as_str(),
3212                        // Primitive types are lowercase but are type names
3213                        "u8" | "u16"
3214                            | "u32"
3215                            | "u64"
3216                            | "u128"
3217                            | "usize"
3218                            | "i8"
3219                            | "i16"
3220                            | "i32"
3221                            | "i64"
3222                            | "i128"
3223                            | "isize"
3224                            | "f32"
3225                            | "f64"
3226                            | "bool"
3227                            | "char"
3228                            | "str"
3229                    );
3230                match self.peek_n(1) {
3231                    // Only treat as generic if clearly followed by generic-context tokens
3232                    Some(Token::Gt) => true,
3233                    Some(Token::Shr) => true, // >> which may close nested generics
3234                    // For comma: only treat as generic if identifier looks like a type name
3235                    // This distinguishes `HashMap<K, V>` (generic) from `x < y,` (comparison in match)
3236                    Some(Token::Comma) => is_type_like,
3237                    Some(Token::ColonColon) => true, // T::U path
3238                    Some(Token::MiddleDot) => true,  // T·U path (Sigil-style)
3239                    Some(Token::Lt) => true,         // T<U> nested generic
3240                    Some(Token::LBracket) => true,   // T[U] bracket generic
3241                    // Evidentiality markers after type name: T?, T!, T~, T◊, T‽
3242                    Some(Token::Question) => true,
3243                    Some(Token::Bang) => true,
3244                    Some(Token::Tilde) => true,
3245                    Some(Token::Lozenge) => true,
3246                    Some(Token::Interrobang) => true,
3247                    // Associated type bindings: <Item = Type>
3248                    Some(Token::Eq) => true,
3249                    // Trait bounds: <T: Trait>
3250                    Some(Token::Colon) => true,
3251                    _ => false,
3252                }
3253            }
3254            // NOT a type - likely comparison with expression
3255            Some(Token::SelfLower) | Some(Token::Xi) => false, // this/ξ is an expression
3256            // Integer literals in generics: const generic values like Type<50257, 1024>
3257            // Only treat as generic if followed by comma or closing >
3258            Some(Token::IntLit(_)) => {
3259                match self.peek_n(1) {
3260                    Some(Token::Comma) => true, // <50257, 1024, ...>
3261                    Some(Token::Gt) => true,    // <50257>
3262                    Some(Token::Shr) => true,   // <50257>> nested
3263                    _ => false,                 // <5 + x> - comparison
3264                }
3265            }
3266            Some(Token::FloatLit(_)) => false,
3267            Some(Token::StringLit(_)) => false,
3268            Some(Token::True) | Some(Token::False) | Some(Token::Top) | Some(Token::Bottom) => false, // yea/nay/⊤/⊥
3269            Some(Token::Null) => false,
3270            _ => false, // Default to not parsing as generics if uncertain
3271        }
3272    }
3273
3274    /// Check if the token after | looks like a pipe operation
3275    /// This distinguishes `expr|τ{...}` (pipe) from `a | b` (bitwise OR)
3276    fn peek_looks_like_pipe_op(&mut self) -> bool {
3277        match self.peek_next() {
3278            // Greek letters for morpheme operations
3279            Some(Token::Tau) => true,         // |τ{...} transform
3280            Some(Token::Phi) => true,         // |φ{...} filter
3281            Some(Token::Sigma) => true,       // |σ sort
3282            Some(Token::Rho) => true,         // |ρ+ reduce
3283            Some(Token::Pi) => true,          // |Π product
3284            Some(Token::Alpha) => true,       // |α first
3285            Some(Token::Omega) => true,       // |ω last
3286            Some(Token::Mu) => true,          // |μ middle
3287            Some(Token::Chi) => true,         // |χ choice
3288            Some(Token::Nu) => true,          // |ν nth
3289            Some(Token::Xi) => true,          // |ξ slice
3290            Some(Token::Delta) => true,       // |δ diff
3291            Some(Token::Iota) => true,        // |⍳ enumerate
3292            Some(Token::ForAll) => true,      // |∀ forall
3293            Some(Token::Exists) => true,      // |∃ exists
3294            Some(Token::Compose) => true,     // |∘ compose
3295            Some(Token::Bowtie) => true,      // |⋈ zip/join
3296            Some(Token::Integral) => true,    // |∫ scan
3297            Some(Token::Partial) => true,     // |∂ diff
3298            Some(Token::Nabla) => true,       // |∇ gradient
3299            Some(Token::GradeUp) => true,     // |⍋ sort ascending
3300            Some(Token::GradeDown) => true,   // |⍒ sort descending
3301            Some(Token::Rotate) => true,      // |⌽ reverse
3302            Some(Token::CycleArrow) => true,  // |↻ cycle
3303            Some(Token::QuadDiamond) => true, // |⌺ windows
3304            Some(Token::SquaredPlus) => true, // |⊞ chunks
3305            Some(Token::ElementSmallVerticalBar) => true, // |⋳ flatten
3306            Some(Token::Union) => true,       // |∪ unique
3307            // Keywords for pipe operations
3308            Some(Token::Match) => true,  // |match{...}
3309            Some(Token::Send) => true,   // |send{...}
3310            Some(Token::Recv) => true,   // |recv
3311            Some(Token::Stream) => true, // |stream{...}
3312            // Protocol tokens
3313            Some(Token::ProtoSend) => true,   // |⇒{...}
3314            Some(Token::ProtoRecv) => true,   // |⇐
3315            Some(Token::ProtoStream) => true, // |≋{...}
3316            // Other pipe operation keywords
3317            Some(Token::Header) => true,      // |header{...}
3318            Some(Token::Body) => true,        // |body{...}
3319            Some(Token::Interrobang) => true, // |‽
3320            // Holographic operators
3321            Some(Token::Lozenge) => true,     // |◊ or |◊method - possibility
3322            Some(Token::BoxSymbol) => true,   // |□ or |□method - necessity
3323            // Identifier could be pipe method: |collect, |take, etc.
3324            // But identifiers NOT followed by `(` or `{` are likely bitwise OR operands
3325            Some(Token::Ident(name)) => {
3326                // Some pipe methods don't require parentheses
3327                let no_args_pipe_methods = [
3328                    "collect", "observe", "len", "first", "last", "reverse",
3329                    "iter", "into_iter", "enumerate", "sum", "product",
3330                    "min", "max", "count", "flatten", "unique",
3331                    // Quantum gates
3332                    "H", "X", "Y", "Z", "S", "T", "measure",
3333                    "H_all", "measure_all",
3334                    // Neural network activations and tensor operations
3335                    "relu", "softmax", "reshape", "backward",
3336                ];
3337                if no_args_pipe_methods.contains(&name.as_str()) {
3338                    return true;
3339                }
3340                // Only treat as pipe method if followed by explicit call syntax
3341                // peek_next() gave us the Ident, peek_n(1) gives us the token after it
3342                // Also handle evidentiality markers: |validate!{...} where ! precedes {
3343                let after_ident = self.peek_n(1);
3344                match after_ident {
3345                    Some(Token::LParen) | Some(Token::LBrace) => true,
3346                    // Evidentiality markers followed by call syntax
3347                    Some(Token::Bang)
3348                    | Some(Token::Question)
3349                    | Some(Token::Tilde)
3350                    | Some(Token::Lozenge) => {
3351                        matches!(self.peek_n(2), Some(Token::LParen) | Some(Token::LBrace))
3352                    }
3353                    _ => false,
3354                }
3355            }
3356            // Reference expression: |&self.field for piping to borrows
3357            Some(Token::Amp) => true,
3358            // Direct closure: |{x => body}
3359            Some(Token::LBrace) => true,
3360            // Everything else is likely bitwise OR
3361            _ => false,
3362        }
3363    }
3364
3365    fn parse_type_list(&mut self) -> ParseResult<Vec<TypeExpr>> {
3366        let mut types = Vec::new();
3367        // Check for empty list - also check Shr (>>) for nested generics
3368        if !self.check(&Token::RParen)
3369            && !self.check(&Token::RBracket)
3370            && !self.check(&Token::Gt)
3371            && !self.check(&Token::Shr)
3372            && self.pending_gt.is_none()
3373        {
3374            // Use parse_type_or_lifetime to handle generic args like <'a, T>
3375            types.push(self.parse_type_or_lifetime()?);
3376            // Continue parsing more types while we see commas
3377            // But check for pending_gt BEFORE consuming comma to avoid eating param separators
3378            while !self.pending_gt.is_some()
3379                && !self.check(&Token::Gt)
3380                && !self.check(&Token::Shr)
3381                && self.consume_if(&Token::Comma)
3382            {
3383                // Trailing comma check
3384                if self.check(&Token::RParen)
3385                    || self.check(&Token::RBracket)
3386                    || self.check(&Token::Gt)
3387                    || self.check(&Token::Shr)
3388                {
3389                    break;
3390                }
3391                types.push(self.parse_type_or_lifetime()?);
3392            }
3393        }
3394        Ok(types)
3395    }
3396
3397    /// Parse a type list that may have attributes before each type
3398    /// e.g., `(#[from] Error, #[source] io::Error)`
3399    fn parse_attributed_type_list(&mut self) -> ParseResult<Vec<TypeExpr>> {
3400        let mut types = Vec::new();
3401        if !self.check(&Token::RParen) {
3402            loop {
3403                // Skip any attributes before the type
3404                while self.check(&Token::Hash) {
3405                    self.advance();
3406                    self.consume_if(&Token::Bang); // for #![...]
3407                    if self.consume_if(&Token::LBracket) {
3408                        let mut depth = 1;
3409                        while depth > 0 && !self.is_eof() {
3410                            match self.current_token() {
3411                                Some(Token::LBracket) => depth += 1,
3412                                Some(Token::RBracket) => depth -= 1,
3413                                _ => {}
3414                            }
3415                            self.advance();
3416                        }
3417                    }
3418                }
3419                // Parse the type
3420                types.push(self.parse_type()?);
3421                if !self.consume_if(&Token::Comma) {
3422                    break;
3423                }
3424            }
3425        }
3426        Ok(types)
3427    }
3428
3429    /// Parse tuple struct fields, which may have optional `pub` visibility before each type
3430    /// e.g., `struct Foo(pub String, i32)` or `struct Bar(pub(crate) Type)`
3431    fn parse_tuple_struct_fields(&mut self) -> ParseResult<Vec<TypeExpr>> {
3432        let mut types = Vec::new();
3433        if !self.check(&Token::RParen) {
3434            loop {
3435                // Skip optional visibility modifier (pub, pub(crate), pub(super), etc.)
3436                if self.check(&Token::Pub) {
3437                    self.advance();
3438                    // Handle pub(crate), pub(super), pub(self), pub(in path)
3439                    if self.check(&Token::LParen) {
3440                        self.advance();
3441                        // Skip tokens until matching RParen
3442                        let mut depth = 1;
3443                        while depth > 0 {
3444                            match self.current_token() {
3445                                Some(Token::LParen) => depth += 1,
3446                                Some(Token::RParen) => depth -= 1,
3447                                None => break,
3448                                _ => {}
3449                            }
3450                            self.advance();
3451                        }
3452                    }
3453                }
3454                // Parse the type
3455                types.push(self.parse_type()?);
3456                if !self.consume_if(&Token::Comma) {
3457                    break;
3458                }
3459                // Check for trailing comma
3460                if self.check(&Token::RParen) {
3461                    break;
3462                }
3463            }
3464        }
3465        Ok(types)
3466    }
3467
3468    fn parse_type_bounds(&mut self) -> ParseResult<Vec<TypeExpr>> {
3469        let mut bounds = Vec::new();
3470
3471        // Handle empty bounds: `T: ,` or `[(); K]: ,` (just checking type is well-formed)
3472        if self.check(&Token::Comma) || self.check(&Token::LBrace) || self.check(&Token::Semi) {
3473            return Ok(bounds);
3474        }
3475
3476        bounds.push(self.parse_type_or_lifetime()?);
3477        while self.consume_if(&Token::Plus) {
3478            bounds.push(self.parse_type_or_lifetime()?);
3479        }
3480        Ok(bounds)
3481    }
3482
3483    /// Parse either a type or a lifetime (for trait bounds like `T: Trait + 'static`)
3484    /// Also handles HRTB: `for<'de> Deserialize<'de>`
3485    /// Also handles associated type bindings: `Output = Type`
3486    fn parse_type_or_lifetime(&mut self) -> ParseResult<TypeExpr> {
3487        if let Some(Token::Lifetime(name)) = self.current_token().cloned() {
3488            self.advance();
3489            Ok(TypeExpr::Lifetime(name))
3490        } else if self.check(&Token::For) {
3491            // Higher-ranked trait bound: for<'a, 'b> Trait<'a, 'b>
3492            self.advance(); // consume 'for'
3493            self.expect(Token::Lt)?; // <
3494            let mut lifetimes = Vec::new();
3495            if let Some(Token::Lifetime(lt)) = self.current_token().cloned() {
3496                lifetimes.push(lt);
3497                self.advance();
3498                while self.consume_if(&Token::Comma) {
3499                    if let Some(Token::Lifetime(lt)) = self.current_token().cloned() {
3500                        lifetimes.push(lt);
3501                        self.advance();
3502                    } else {
3503                        break;
3504                    }
3505                }
3506            }
3507            self.expect_gt()?; // >
3508            let bound = self.parse_type()?;
3509            Ok(TypeExpr::Hrtb {
3510                lifetimes,
3511                bound: Box::new(bound),
3512            })
3513        } else if matches!(self.current_token(), Some(Token::Ident(_)))
3514            && self.peek_next() == Some(&Token::Eq)
3515        {
3516            // Associated type binding: `Output = Type`
3517            let name = self.parse_ident()?;
3518            self.expect(Token::Eq)?;
3519            let ty = self.parse_type()?;
3520            Ok(TypeExpr::AssocTypeBinding {
3521                name,
3522                ty: Box::new(ty),
3523            })
3524        } else if matches!(
3525            self.current_token(),
3526            Some(Token::IntLit(_))
3527                | Some(Token::HexLit(_))
3528                | Some(Token::BinaryLit(_))
3529                | Some(Token::OctalLit(_))
3530        ) {
3531            // Const generic: numeric literal or expression in type position like `<32>` or `<3 * D>`
3532            // Parse as expression to handle `3 * D`, `N + 1`, etc.
3533            let expr = self.parse_const_expr_simple()?;
3534            Ok(TypeExpr::ConstExpr(Box::new(expr)))
3535        } else if self.check(&Token::LBrace) {
3536            // Const block expression: `<{N + 1}>`
3537            self.advance();
3538            let expr = self.parse_expr()?;
3539            self.expect(Token::RBrace)?;
3540            Ok(TypeExpr::ConstExpr(Box::new(expr)))
3541        } else {
3542            self.parse_type()
3543        }
3544    }
3545
3546    /// Parse an array dimension expression like `HD/2`, `N*2`, `MAX_SEQ`, or `{ const { if ... } }`
3547    /// Used for tensor shape dimensions: [A, B, HD/2]
3548    fn parse_array_dim_expr(&mut self) -> ParseResult<Expr> {
3549        // Handle const block: { const { ... } } or just { expr }
3550        if self.check(&Token::LBrace) {
3551            self.advance();
3552            let expr = self.parse_expr()?;
3553            self.expect(Token::RBrace)?;
3554            return Ok(expr);
3555        }
3556        // Parse as const expression (identifier or literal followed by optional arithmetic)
3557        self.parse_const_expr_simple()
3558    }
3559
3560    /// Parse a simple const expression for use in type positions like `[3 * D, D]`
3561    /// Handles simple arithmetic: literals, identifiers, and +-*/ operations
3562    /// Stops at: comma, >, ], ), ;
3563    fn parse_const_expr_simple(&mut self) -> ParseResult<Expr> {
3564        let mut lhs = self.parse_const_expr_primary()?;
3565
3566        loop {
3567            match self.current_token() {
3568                Some(Token::Star) => {
3569                    self.advance();
3570                    let rhs = self.parse_const_expr_primary()?;
3571                    lhs = Expr::Binary {
3572                        op: BinOp::Mul,
3573                        left: Box::new(lhs),
3574                        right: Box::new(rhs),
3575                    };
3576                }
3577                Some(Token::Plus) => {
3578                    self.advance();
3579                    let rhs = self.parse_const_expr_primary()?;
3580                    lhs = Expr::Binary {
3581                        op: BinOp::Add,
3582                        left: Box::new(lhs),
3583                        right: Box::new(rhs),
3584                    };
3585                }
3586                Some(Token::Minus) => {
3587                    self.advance();
3588                    let rhs = self.parse_const_expr_primary()?;
3589                    lhs = Expr::Binary {
3590                        op: BinOp::Sub,
3591                        left: Box::new(lhs),
3592                        right: Box::new(rhs),
3593                    };
3594                }
3595                Some(Token::Slash) => {
3596                    self.advance();
3597                    let rhs = self.parse_const_expr_primary()?;
3598                    lhs = Expr::Binary {
3599                        op: BinOp::Div,
3600                        left: Box::new(lhs),
3601                        right: Box::new(rhs),
3602                    };
3603                }
3604                _ => break,
3605            }
3606        }
3607        Ok(lhs)
3608    }
3609
3610    /// Parse a primary element for const expressions
3611    fn parse_const_expr_primary(&mut self) -> ParseResult<Expr> {
3612        match self.current_token().cloned() {
3613            Some(Token::IntLit(_))
3614            | Some(Token::HexLit(_))
3615            | Some(Token::BinaryLit(_))
3616            | Some(Token::OctalLit(_)) => {
3617                let lit = self.parse_literal()?;
3618                Ok(Expr::Literal(lit))
3619            }
3620            Some(Token::Ident(_)) => {
3621                let path = self.parse_type_path()?;
3622                Ok(Expr::Path(path))
3623            }
3624            Some(Token::Underscore) => {
3625                // Inferred dimension: [_, N] means first dimension is inferred
3626                let span = self.current_span();
3627                self.advance();
3628                Ok(Expr::Path(TypePath {
3629                    segments: vec![PathSegment {
3630                        ident: Ident {
3631                            name: "_".to_string(),
3632                            evidentiality: None,
3633                            affect: None,
3634                            span,
3635                        },
3636                        generics: None,
3637                    }],
3638                }))
3639            }
3640            Some(Token::LParen) => {
3641                self.advance();
3642                let expr = self.parse_const_expr_simple()?;
3643                self.expect(Token::RParen)?;
3644                Ok(expr)
3645            }
3646            _ => Err(ParseError::Custom("expected const expression".to_string())),
3647        }
3648    }
3649
3650    // === Expression parsing (Pratt parser) ===
3651
3652    pub fn parse_expr(&mut self) -> ParseResult<Expr> {
3653        // Skip leading comments (line comments, doc comments)
3654        self.skip_comments();
3655        let lhs = self.parse_expr_bp(0)?;
3656
3657        // Check for assignment: expr = value
3658        if self.consume_if(&Token::Eq) {
3659            let value = self.parse_expr()?;
3660            return Ok(Expr::Assign {
3661                target: Box::new(lhs),
3662                value: Box::new(value),
3663            });
3664        }
3665
3666        // Check for compound assignment: expr += value, expr -= value, etc.
3667        // Desugar to: expr = expr op value
3668        let compound_op = match self.current_token() {
3669            Some(Token::PlusEq) => Some(BinOp::Add),
3670            Some(Token::MinusEq) => Some(BinOp::Sub),
3671            Some(Token::StarEq) => Some(BinOp::Mul),
3672            Some(Token::SlashEq) => Some(BinOp::Div),
3673            Some(Token::PercentEq) => Some(BinOp::Rem),
3674            Some(Token::ShlEq) => Some(BinOp::Shl),
3675            Some(Token::ShrEq) => Some(BinOp::Shr),
3676            Some(Token::PipeEq) => Some(BinOp::BitOr),
3677            Some(Token::AmpEq) => Some(BinOp::BitAnd),
3678            Some(Token::CaretEq) => Some(BinOp::BitXor),
3679            _ => None,
3680        };
3681
3682        if let Some(op) = compound_op {
3683            self.advance();
3684            let rhs = self.parse_expr()?;
3685            // Desugar: lhs op= rhs  ->  lhs = lhs op rhs
3686            let binary = Expr::Binary {
3687                left: Box::new(lhs.clone()),
3688                op,
3689                right: Box::new(rhs),
3690            };
3691            return Ok(Expr::Assign {
3692                target: Box::new(lhs),
3693                value: Box::new(binary),
3694            });
3695        }
3696
3697        // Check for Legion compound operators: ⊕=, ∂=, ⫰=
3698        match self.current_token() {
3699            Some(Token::DirectSumEq) => {
3700                // Superposition: field∿ ⊕= pattern
3701                self.advance();
3702                let pattern = self.parse_expr()?;
3703                return Ok(Expr::LegionSuperposition {
3704                    field: Box::new(lhs),
3705                    pattern: Box::new(pattern),
3706                });
3707            }
3708            Some(Token::PartialEq_) => {
3709                // Decay: field∿ ∂= rate
3710                self.advance();
3711                let rate = self.parse_expr()?;
3712                return Ok(Expr::LegionDecay {
3713                    field: Box::new(lhs),
3714                    rate: Box::new(rate),
3715                });
3716            }
3717            Some(Token::InterfereEq) => {
3718                // Interference assign (rare, but supported)
3719                self.advance();
3720                let query = self.parse_expr()?;
3721                return Ok(Expr::LegionInterference {
3722                    query: Box::new(query),
3723                    field: Box::new(lhs),
3724                });
3725            }
3726            _ => {}
3727        }
3728
3729        Ok(lhs)
3730    }
3731
3732    fn parse_expr_bp(&mut self, min_bp: u8) -> ParseResult<Expr> {
3733        let mut lhs = self.parse_prefix_expr()?;
3734
3735        loop {
3736            // Skip comments between binary operators - allows line-continuation style:
3737            // let x = foo()
3738            //     // comment
3739            //     && bar()
3740            self.skip_comments();
3741
3742            // Check for pipe operator - but only if followed by pipe operation token
3743            // Otherwise treat | as bitwise OR for Rust-style code
3744            if self.check(&Token::Pipe) && self.peek_looks_like_pipe_op() {
3745                lhs = self.parse_pipe_chain(lhs)?;
3746                // After pipe chain, check for postfix operators like ? and method calls
3747                lhs = self.parse_postfix_after_pipe(lhs)?;
3748                continue;
3749            }
3750
3751            // Check for binary operators
3752            let op = match self.current_token() {
3753                // Bitwise OR - only reached if not a pipe operation
3754                Some(Token::Pipe) => BinOp::BitOr,
3755                Some(Token::OrOr) | Some(Token::LogicOr) => BinOp::Or,  // || or ∨
3756                Some(Token::AndAnd) | Some(Token::LogicAnd) => BinOp::And,  // && or ∧
3757                Some(Token::EqEq) => BinOp::Eq,
3758                Some(Token::NotEq) => BinOp::Ne,
3759                Some(Token::Lt) => BinOp::Lt,
3760                Some(Token::LtEq) => BinOp::Le,
3761                Some(Token::Gt) => BinOp::Gt,
3762                Some(Token::GtEq) => BinOp::Ge,
3763                Some(Token::Plus) => BinOp::Add,
3764                Some(Token::Minus) => BinOp::Sub,
3765                Some(Token::Star) => BinOp::Mul,
3766                Some(Token::Slash) => BinOp::Div,
3767                Some(Token::Percent) => BinOp::Rem,
3768                Some(Token::StarStar) => BinOp::Pow,
3769                Some(Token::Amp) => BinOp::BitAnd,
3770                Some(Token::Caret) => BinOp::BitXor,
3771                Some(Token::Shl) => BinOp::Shl,
3772                Some(Token::Shr) => BinOp::Shr,
3773                Some(Token::PlusPlus) => BinOp::Concat,
3774                // Matrix multiplication
3775                Some(Token::At) => BinOp::MatMul,
3776                // Unicode bitwise operators
3777                Some(Token::BitwiseAndSymbol) => BinOp::BitAnd, // ⋏
3778                Some(Token::BitwiseOrSymbol) => BinOp::BitOr,   // ⋎
3779                // Note: ∧ and ∨ logic operators handled above with && and ||
3780                // Tensor/array operators
3781                Some(Token::CircledDot) => BinOp::Hadamard, // ⊙ element-wise multiply
3782                Some(Token::Tensor) => BinOp::TensorProd,   // ⊗ tensor product
3783                Some(Token::Gpu) => BinOp::Convolve,        // ⊛ convolution/merge
3784                // Legion operators handled specially below
3785                Some(Token::Interfere)
3786                | Some(Token::Distribute)
3787                | Some(Token::Broadcast)
3788                | Some(Token::Gather)
3789                | Some(Token::Consensus)
3790                | Some(Token::ConfidenceHigh) => {
3791                    // Handle Legion operators specially
3792                    lhs = self.parse_legion_operator(lhs)?;
3793                    continue;
3794                }
3795                _ => {
3796                    // Check for range operators: .. and ..=
3797                    // Range has very low precedence (lower than all binary ops)
3798                    // Only parse range if min_bp is low enough (i.e., we're not inside
3799                    // a higher-precedence expression like i+1..)
3800                    // Range binding power is 0 - lower than any binary operator
3801                    if min_bp == 0 && (self.check(&Token::DotDot) || self.check(&Token::DotDotEq)) {
3802                        let inclusive = self.consume_if(&Token::DotDotEq);
3803                        if !inclusive {
3804                            self.advance(); // consume ..
3805                        }
3806                        // Parse end of range (optional for open ranges like `0..`)
3807                        let end = if self.check(&Token::Semi)
3808                            || self.check(&Token::RBrace)
3809                            || self.check(&Token::Comma)
3810                            || self.check(&Token::RParen)
3811                            || self.check(&Token::RBracket)
3812                            || self.check(&Token::LBrace)
3813                        {
3814                            None
3815                        } else {
3816                            Some(Box::new(self.parse_expr_bp(0)?))
3817                        };
3818                        lhs = Expr::Range {
3819                            start: Some(Box::new(lhs)),
3820                            end,
3821                            inclusive,
3822                        };
3823                        continue;
3824                    }
3825                    break;
3826                }
3827            };
3828
3829            let (l_bp, r_bp) = infix_binding_power(op);
3830            if l_bp < min_bp {
3831                break;
3832            }
3833
3834            self.advance();
3835            // Skip comments before RHS - allows:
3836            // a ||  // comment
3837            //   b
3838            self.skip_comments();
3839            let rhs = self.parse_expr_bp(r_bp)?;
3840
3841            lhs = Expr::Binary {
3842                left: Box::new(lhs),
3843                op,
3844                right: Box::new(rhs),
3845            };
3846        }
3847
3848        Ok(lhs)
3849    }
3850
3851    fn parse_prefix_expr(&mut self) -> ParseResult<Expr> {
3852        match self.current_token() {
3853            Some(Token::Minus) => {
3854                self.advance();
3855                let expr = self.parse_prefix_expr()?;
3856                Ok(Expr::Unary {
3857                    op: UnaryOp::Neg,
3858                    expr: Box::new(expr),
3859                })
3860            }
3861            Some(Token::Bang) | Some(Token::LogicNot) => {
3862                self.advance();
3863                let expr = self.parse_prefix_expr()?;
3864                Ok(Expr::Unary {
3865                    op: UnaryOp::Not,
3866                    expr: Box::new(expr),
3867                })
3868            }
3869            Some(Token::Star) => {
3870                self.advance();
3871                let expr = self.parse_prefix_expr()?;
3872                Ok(Expr::Unary {
3873                    op: UnaryOp::Deref,
3874                    expr: Box::new(expr),
3875                })
3876            }
3877            // Double dereference: **expr
3878            Some(Token::StarStar) => {
3879                self.advance();
3880                let inner = self.parse_prefix_expr()?;
3881                // Desugar **x to *(*x)
3882                let first_deref = Expr::Unary {
3883                    op: UnaryOp::Deref,
3884                    expr: Box::new(inner),
3885                };
3886                Ok(Expr::Unary {
3887                    op: UnaryOp::Deref,
3888                    expr: Box::new(first_deref),
3889                })
3890            }
3891            Some(Token::Amp) => {
3892                self.advance();
3893                let op = if self.consume_if_mut() {
3894                    UnaryOp::RefMut
3895                } else {
3896                    UnaryOp::Ref
3897                };
3898                let expr = self.parse_prefix_expr()?;
3899                Ok(Expr::Unary {
3900                    op,
3901                    expr: Box::new(expr),
3902                })
3903            }
3904            // Prefix evidentiality markers: ?expr, ~expr, ‽expr
3905            Some(Token::Question) => {
3906                self.advance();
3907                let expr = self.parse_prefix_expr()?;
3908                Ok(Expr::Evidential {
3909                    expr: Box::new(expr),
3910                    evidentiality: Evidentiality::Uncertain,
3911                })
3912            }
3913            Some(Token::Tilde) => {
3914                self.advance();
3915                let expr = self.parse_prefix_expr()?;
3916                Ok(Expr::Evidential {
3917                    expr: Box::new(expr),
3918                    evidentiality: Evidentiality::Reported,
3919                })
3920            }
3921            Some(Token::Interrobang) => {
3922                self.advance();
3923                let expr = self.parse_prefix_expr()?;
3924                Ok(Expr::Evidential {
3925                    expr: Box::new(expr),
3926                    evidentiality: Evidentiality::Paradox,
3927                })
3928            }
3929            // Move closure: move |params| body or move || body
3930            Some(Token::Move) => {
3931                self.advance();
3932                self.parse_pipe_closure_with_move(true)
3933            }
3934            // Pipe-style closure: |params| body or || body or ∨ body
3935            Some(Token::Pipe) | Some(Token::OrOr) | Some(Token::LogicOr) => self.parse_pipe_closure_with_move(false),
3936            _ => self.parse_postfix_expr(),
3937        }
3938    }
3939
3940    /// Parse a pipe-style closure: |params| body or || body or ∨ body or move |params| body
3941    fn parse_pipe_closure_with_move(&mut self, is_move: bool) -> ParseResult<Expr> {
3942        let params = if self.consume_if(&Token::OrOr) || self.consume_if(&Token::LogicOr) {
3943            // || body or ∨ body - no parameters
3944            Vec::new()
3945        } else {
3946            // |params| body
3947            self.expect(Token::Pipe)?;
3948            let mut params = Vec::new();
3949            if !self.check(&Token::Pipe) {
3950                loop {
3951                    // Parse parameter pattern (possibly with type)
3952                    let pattern = self.parse_pattern()?;
3953                    let ty = if self.consume_if(&Token::Colon) {
3954                        Some(self.parse_type()?)
3955                    } else {
3956                        None
3957                    };
3958                    params.push(ClosureParam { pattern, ty });
3959                    if !self.consume_if(&Token::Comma) {
3960                        break;
3961                    }
3962                    if self.check(&Token::Pipe) {
3963                        break;
3964                    }
3965                }
3966            }
3967            self.expect(Token::Pipe)?;
3968            params
3969        };
3970
3971        // Optional return type annotation: |params| -> Type { body }
3972        let return_type = if self.consume_if(&Token::Arrow) {
3973            Some(self.parse_type()?)
3974        } else {
3975            None
3976        };
3977
3978        let body = self.parse_expr()?;
3979        Ok(Expr::Closure {
3980            params,
3981            return_type,
3982            body: Box::new(body),
3983            is_move,
3984        })
3985    }
3986
3987    /// Parse macro tokens: collects all tokens inside matching delimiters
3988    fn parse_macro_tokens(&mut self) -> ParseResult<String> {
3989        // Determine delimiter type
3990        let (open, close) = match self.current_token() {
3991            Some(Token::LParen) => (Token::LParen, Token::RParen),
3992            Some(Token::LBracket) => (Token::LBracket, Token::RBracket),
3993            Some(Token::LBrace) => (Token::LBrace, Token::RBrace),
3994            _ => {
3995                return Err(ParseError::Custom(
3996                    "expected '(', '[', or '{' for macro invocation".to_string(),
3997                ))
3998            }
3999        };
4000
4001        self.advance(); // consume opening delimiter
4002        let mut tokens = String::new();
4003        let mut depth = 1;
4004
4005        while depth > 0 && !self.is_eof() {
4006            if self.check(&open) {
4007                depth += 1;
4008            } else if self.check(&close) {
4009                depth -= 1;
4010                if depth == 0 {
4011                    break;
4012                }
4013            }
4014
4015            // Collect token text (approximate - this is a simplified approach)
4016            if let Some((token, span)) = &self.current {
4017                // Get the source slice for this token
4018                let token_str = match token {
4019                    Token::Ident(s) => s.clone(),
4020                    Token::IntLit(s) => s.clone(),
4021                    Token::FloatLit(s) => s.clone(),
4022                    Token::StringLit(s) => {
4023                        format!("\"{}\"", s.replace('\\', "\\\\").replace('"', "\\\""))
4024                    }
4025                    Token::CharLit(c) => format!("'{}'", c),
4026                    Token::Comma => ",".to_string(),
4027                    Token::Colon => ":".to_string(),
4028                    Token::ColonColon => "::".to_string(),
4029                    Token::Dot => ".".to_string(),
4030                    Token::DotDot => "..".to_string(),
4031                    Token::Semi => ";".to_string(),
4032                    Token::LParen => "(".to_string(),
4033                    Token::RParen => ")".to_string(),
4034                    Token::LBrace => "{".to_string(),
4035                    Token::RBrace => "}".to_string(),
4036                    Token::LBracket => "[".to_string(),
4037                    Token::RBracket => "]".to_string(),
4038                    Token::Lt => "<".to_string(),
4039                    Token::Gt => ">".to_string(),
4040                    Token::Eq => "=".to_string(),
4041                    Token::FatArrow => "=>".to_string(),
4042                    Token::Bang => "!".to_string(),
4043                    Token::Question => "?".to_string(),
4044                    Token::Amp => "&".to_string(),
4045                    Token::Pipe => "|".to_string(),
4046                    Token::Underscore => "_".to_string(),
4047                    Token::Plus => "+".to_string(),
4048                    Token::Minus => "-".to_string(),
4049                    Token::Star => "*".to_string(),
4050                    Token::Slash => "/".to_string(),
4051                    Token::Percent => "%".to_string(),
4052                    Token::EqEq => "==".to_string(),
4053                    Token::NotEq => "!=".to_string(),
4054                    Token::LtEq => "<=".to_string(),
4055                    Token::GtEq => ">=".to_string(),
4056                    Token::AndAnd => "&&".to_string(),
4057                    Token::OrOr => "||".to_string(),
4058                    Token::Arrow => "->".to_string(),
4059                    Token::Hash => "#".to_string(),
4060                    Token::At => "@".to_string(),
4061                    Token::Tilde => "~".to_string(),
4062                    // Keywords
4063                    Token::SelfLower => "self".to_string(),
4064                    Token::SelfUpper => "Self".to_string(),
4065                    Token::Let => "let".to_string(),
4066                    Token::Mut => "mut".to_string(),
4067                    Token::Fn => "fn".to_string(),
4068                    Token::If => "if".to_string(),
4069                    Token::Else => "else".to_string(),
4070                    Token::Match => "match".to_string(),
4071                    Token::For => "for".to_string(),
4072                    Token::While => "while".to_string(),
4073                    Token::Loop => "loop".to_string(),
4074                    Token::Break => "break".to_string(),
4075                    Token::Continue => "continue".to_string(),
4076                    Token::Return => "return".to_string(),
4077                    Token::Struct => "struct".to_string(),
4078                    Token::Enum => "enum".to_string(),
4079                    Token::Impl => "impl".to_string(),
4080                    Token::Trait => "trait".to_string(),
4081                    Token::Type => "type".to_string(),
4082                    Token::Pub => "pub".to_string(),
4083                    Token::Mod => "mod".to_string(),
4084                    Token::Use => "use".to_string(),
4085                    Token::As => "as".to_string(),
4086                    Token::In => "in".to_string(),
4087                    Token::True => "true".to_string(),
4088                    Token::False => "false".to_string(),
4089                    Token::Null => "null".to_string(),
4090                    Token::Const => "const".to_string(),
4091                    Token::Static => "static".to_string(),
4092                    Token::Async => "async".to_string(),
4093                    Token::Await => "await".to_string(),
4094                    Token::Move => "move".to_string(),
4095                    Token::Ref => "ref".to_string(),
4096                    Token::Where => "where".to_string(),
4097                    Token::Dyn => "dyn".to_string(),
4098                    Token::Super => "super".to_string(),
4099                    Token::Crate => "crate".to_string(),
4100                    _ => format!("{:?}", token),
4101                };
4102                // Don't add space before . :: ( [ { ) ] } , ;
4103                let suppress_space_before = matches!(
4104                    token,
4105                    Token::Dot
4106                        | Token::ColonColon
4107                        | Token::LParen
4108                        | Token::LBracket
4109                        | Token::LBrace
4110                        | Token::RParen
4111                        | Token::RBracket
4112                        | Token::RBrace
4113                        | Token::Comma
4114                        | Token::Semi
4115                );
4116                if !tokens.is_empty()
4117                    && !suppress_space_before
4118                    && !tokens.ends_with('.')
4119                    && !tokens.ends_with("::")
4120                    && !tokens.ends_with('(')
4121                    && !tokens.ends_with('[')
4122                    && !tokens.ends_with('{')
4123                {
4124                    tokens.push(' ');
4125                }
4126                tokens.push_str(&token_str);
4127            }
4128            self.advance();
4129        }
4130
4131        self.expect(close)?;
4132        Ok(tokens)
4133    }
4134
4135    /// Check if an expression is a block-ending expression that should not be callable.
4136    /// Block expressions like if/while/match/loop/for return values but should not
4137    /// be directly called like functions.
4138    fn is_non_callable_expr(expr: &Expr) -> bool {
4139        matches!(
4140            expr,
4141            Expr::If { .. }
4142                | Expr::While { .. }
4143                | Expr::Match { .. }
4144                | Expr::Loop { .. }
4145                | Expr::For { .. }
4146                | Expr::Block(_)
4147        )
4148    }
4149
4150    fn parse_postfix_expr(&mut self) -> ParseResult<Expr> {
4151        let mut expr = self.parse_primary_expr()?;
4152
4153        loop {
4154            // Skip comments between postfix operations - allows line-continuation:
4155            // foo()
4156            //     // comment
4157            //     .bar()
4158            self.skip_comments();
4159
4160            match self.current_token() {
4161                Some(Token::LParen) => {
4162                    // Don't treat block-ending expressions as callable
4163                    // This prevents parsing `if {...} (...)` as a call expression
4164                    if Self::is_non_callable_expr(&expr) {
4165                        break;
4166                    }
4167                    self.advance();
4168                    let args = self.parse_expr_list()?;
4169                    self.expect(Token::RParen)?;
4170                    expr = Expr::Call {
4171                        func: Box::new(expr),
4172                        args,
4173                    };
4174                }
4175                Some(Token::LBracket) => {
4176                    self.advance();
4177                    // Support multi-dimensional indexing: arr[.., 0] or arr[i, j, k]
4178                    let first = self.parse_expr()?;
4179                    if self.consume_if(&Token::Comma) {
4180                        // Multi-dimensional index: create tuple of indices
4181                        let mut indices = vec![first];
4182                        while !self.check(&Token::RBracket) && !self.is_eof() {
4183                            indices.push(self.parse_expr()?);
4184                            if !self.consume_if(&Token::Comma) {
4185                                break;
4186                            }
4187                        }
4188                        self.expect(Token::RBracket)?;
4189                        // Represent as index with a tuple expression
4190                        expr = Expr::Index {
4191                            expr: Box::new(expr),
4192                            index: Box::new(Expr::Tuple(indices)),
4193                        };
4194                    } else {
4195                        self.expect(Token::RBracket)?;
4196                        expr = Expr::Index {
4197                            expr: Box::new(expr),
4198                            index: Box::new(first),
4199                        };
4200                    }
4201                }
4202                Some(Token::Dot) => {
4203                    self.advance();
4204                    // Handle `.⌛` as await syntax (alternative to `expr⌛`)
4205                    if self.check(&Token::Hourglass) {
4206                        self.advance();
4207                        let evidentiality = self.parse_evidentiality_opt();
4208                        expr = Expr::Await {
4209                            expr: Box::new(expr),
4210                            evidentiality,
4211                        };
4212                        continue;
4213                    }
4214                    // Handle both named fields (`.field`) and tuple indices (`.0`, `.1`)
4215                    let field = if let Some(Token::IntLit(idx)) = self.current_token() {
4216                        let idx = idx.clone();
4217                        let span = self.current_span();
4218                        self.advance();
4219                        Ident {
4220                            name: idx,
4221                            evidentiality: None,
4222                            affect: None,
4223                            span,
4224                        }
4225                    } else {
4226                        self.parse_ident()?
4227                    };
4228                    // Check for turbofish syntax: method::<Type>(args) or method·<Type>(args)
4229                    if self.consume_if(&Token::ColonColon) || self.consume_if(&Token::MiddleDot) {
4230                        // Already consumed :: or ·
4231                        self.expect(Token::Lt)?;
4232                        // Temporarily exit condition context - turbofish is type context
4233                        let was_in_condition = self.in_condition;
4234                        self.in_condition = false;
4235                        let type_args = self.parse_type_list()?;
4236                        self.expect_gt()?;
4237                        self.in_condition = was_in_condition;
4238                        self.expect(Token::LParen)?;
4239                        let args = self.parse_expr_list()?;
4240                        self.expect(Token::RParen)?;
4241                        expr = Expr::MethodCall {
4242                            receiver: Box::new(expr),
4243                            method: field,
4244                            type_args: Some(type_args),
4245                            args,
4246                        };
4247                    } else if self.check(&Token::LParen) {
4248                        self.advance();
4249                        let args = self.parse_expr_list()?;
4250                        self.expect(Token::RParen)?;
4251                        expr = Expr::MethodCall {
4252                            receiver: Box::new(expr),
4253                            method: field,
4254                            type_args: None,
4255                            args,
4256                        };
4257                    } else {
4258                        // Consume optional unambiguous evidentiality markers after field: self.field◊, self.field~
4259                        // Note: don't consume ! or ? here as they have other meanings (! = not, ? = try)
4260                        while self.check(&Token::Tilde) || self.check(&Token::Lozenge) {
4261                            self.advance();
4262                        }
4263                        expr = Expr::Field {
4264                            expr: Box::new(expr),
4265                            field,
4266                        };
4267                    }
4268                }
4269                Some(Token::Question) => {
4270                    // Check if this is Type? { ... } struct literal with evidentiality
4271                    // vs expr? try operator
4272                    if self.peek_next() == Some(&Token::LBrace) && !self.is_in_condition() {
4273                        if let Expr::Path(ref path) = expr {
4274                            let path = path.clone();
4275                            self.advance(); // consume ?
4276                            self.advance(); // consume {
4277                            let (fields, rest) = self.parse_struct_fields()?;
4278                            self.expect(Token::RBrace)?;
4279                            expr = Expr::Struct { path, fields, rest };
4280                            continue;
4281                        }
4282                    }
4283                    // Not a struct literal - treat as try operator
4284                    self.advance();
4285                    expr = Expr::Try(Box::new(expr));
4286                }
4287                // Cast expression: expr as Type (or expr → Type)
4288                Some(Token::As) | Some(Token::Arrow) => {
4289                    self.advance();
4290                    let ty = self.parse_type()?;
4291                    expr = Expr::Cast {
4292                        expr: Box::new(expr),
4293                        ty,
4294                    };
4295                }
4296                Some(Token::Bang) => {
4297                    // Check for macro invocation: path!(...)  path![...]  path!{...}
4298                    if let Expr::Path(path) = &expr {
4299                        let peeked = self.peek_next();
4300                        // Peek at next token to see if it's a macro delimiter
4301                        let is_macro = match peeked {
4302                            Some(Token::LParen) | Some(Token::LBracket) | Some(Token::LBrace) => {
4303                                true
4304                            }
4305                            _ => false,
4306                        };
4307                        if is_macro {
4308                            self.advance(); // consume !
4309                            let tokens = self.parse_macro_tokens()?;
4310                            expr = Expr::Macro {
4311                                path: path.clone(),
4312                                tokens,
4313                            };
4314                            continue;
4315                        }
4316                    }
4317                    // Not a macro, check for evidentiality
4318                    if let Some(ev) = self.parse_evidentiality_opt() {
4319                        expr = Expr::Evidential {
4320                            expr: Box::new(expr),
4321                            evidentiality: ev,
4322                        };
4323                    } else {
4324                        break;
4325                    }
4326                }
4327                Some(Token::Tilde) | Some(Token::Interrobang) | Some(Token::Lozenge) => {
4328                    if let Some(ev) = self.parse_evidentiality_opt() {
4329                        // After evidentiality marker, check for struct literal: Type~ { ... }
4330                        // The evidentiality attaches to the struct type
4331                        if self.check(&Token::LBrace) && !self.is_in_condition() {
4332                            if let Expr::Path(ref path) = expr {
4333                                let path = path.clone();
4334                                self.advance(); // consume {
4335                                let (fields, rest) = self.parse_struct_fields()?;
4336                                self.expect(Token::RBrace)?;
4337                                expr = Expr::Struct { path, fields, rest };
4338                                continue;
4339                            }
4340                        }
4341                        // Wrap in Evidential for non-struct cases
4342                        expr = Expr::Evidential {
4343                            expr: Box::new(expr),
4344                            evidentiality: ev,
4345                        };
4346                    } else {
4347                        break;
4348                    }
4349                }
4350                Some(Token::ColonColon) => {
4351                    // Qualified path call: Type::method() or path!::method()
4352                    self.advance(); // consume ::
4353                    let method = self.parse_ident()?;
4354                    // Check for turbofish: Type::method::<T>()
4355                    let type_args = if self.check(&Token::ColonColon) {
4356                        self.advance();
4357                        self.expect(Token::Lt)?;
4358                        let types = self.parse_type_list()?;
4359                        self.expect_gt()?;
4360                        Some(types)
4361                    } else {
4362                        None
4363                    };
4364                    if self.check(&Token::LParen) {
4365                        self.advance();
4366                        let args = self.parse_expr_list()?;
4367                        self.expect(Token::RParen)?;
4368                        // Treat as a static method call - desugar to path::method(args)
4369                        expr = Expr::MethodCall {
4370                            receiver: Box::new(expr),
4371                            method,
4372                            type_args,
4373                            args,
4374                        };
4375                    } else {
4376                        // Field access style: Type::CONST
4377                        expr = Expr::Field {
4378                            expr: Box::new(expr),
4379                            field: method,
4380                        };
4381                    }
4382                }
4383                Some(Token::Hourglass) => {
4384                    self.advance();
4385                    // Check for optional evidentiality marker: ⌛? ⌛! ⌛~ ⌛◊ ⌛‽
4386                    let evidentiality = match self.current_token() {
4387                        Some(Token::Question) => {
4388                            self.advance();
4389                            Some(Evidentiality::Uncertain)
4390                        }
4391                        Some(Token::Bang) => {
4392                            self.advance();
4393                            Some(Evidentiality::Known)
4394                        }
4395                        Some(Token::Tilde) => {
4396                            self.advance();
4397                            Some(Evidentiality::Reported)
4398                        }
4399                        Some(Token::Lozenge) => {
4400                            self.advance();
4401                            Some(Evidentiality::Predicted)
4402                        }
4403                        Some(Token::Interrobang) => {
4404                            self.advance();
4405                            Some(Evidentiality::Paradox)
4406                        }
4407                        _ => None,
4408                    };
4409                    expr = Expr::Await {
4410                        expr: Box::new(expr),
4411                        evidentiality,
4412                    };
4413                }
4414                // Incorporation: expr·verb·noun·action
4415                // Polysynthetic noun incorporation using middle dot
4416                Some(Token::MiddleDot) => {
4417                    // Convert current expr to first segment, then parse chain
4418                    let first_segment = self.expr_to_incorporation_segment(expr.clone())?;
4419                    let mut segments = vec![first_segment];
4420
4421                    while self.consume_if(&Token::MiddleDot) {
4422                        // Handle both named methods and tuple indices: ·method() or ·0
4423                        let name = if let Some(Token::IntLit(idx)) = self.current_token().cloned() {
4424                            let span = self.current_span();
4425                            self.advance();
4426                            Ident {
4427                                name: idx,
4428                                evidentiality: None,
4429                                affect: None,
4430                                span,
4431                            }
4432                        } else {
4433                            self.parse_ident()?
4434                        };
4435                        // Handle bracket generics on method: ·method[Type]()
4436                        if self.check(&Token::LBracket) && self.peek_looks_like_bracket_generic() {
4437                            self.advance(); // consume [
4438                            let _generics = self.parse_type_list()?;
4439                            self.expect(Token::RBracket)?;
4440                            // Generics are parsed but currently ignored in incorporation segments
4441                        }
4442                        // Handle angle bracket generics: ·method<Type>()
4443                        if self.check(&Token::Lt) && self.peek_looks_like_generic_arg() {
4444                            self.advance(); // consume <
4445                            let _generics = self.parse_type_list()?;
4446                            self.expect_gt()?;
4447                        }
4448                        let args = if self.check(&Token::LParen) {
4449                            self.advance();
4450                            let args = self.parse_expr_list()?;
4451                            self.expect(Token::RParen)?;
4452                            Some(args)
4453                        } else {
4454                            None
4455                        };
4456                        segments.push(IncorporationSegment { name, args });
4457                    }
4458
4459                    expr = Expr::Incorporation { segments };
4460                }
4461                _ => break,
4462            }
4463        }
4464
4465        Ok(expr)
4466    }
4467
4468    fn parse_primary_expr(&mut self) -> ParseResult<Expr> {
4469        match self.current_token().cloned() {
4470            Some(Token::IntLit(s)) => {
4471                self.advance();
4472                Ok(Expr::Literal(Literal::Int {
4473                    value: s,
4474                    base: NumBase::Decimal,
4475                    suffix: None,
4476                }))
4477            }
4478            Some(Token::BinaryLit(s)) => {
4479                self.advance();
4480                Ok(Expr::Literal(Literal::Int {
4481                    value: s,
4482                    base: NumBase::Binary,
4483                    suffix: None,
4484                }))
4485            }
4486            Some(Token::OctalLit(s)) => {
4487                self.advance();
4488                Ok(Expr::Literal(Literal::Int {
4489                    value: s,
4490                    base: NumBase::Octal,
4491                    suffix: None,
4492                }))
4493            }
4494            Some(Token::HexLit(s)) => {
4495                self.advance();
4496                Ok(Expr::Literal(Literal::Int {
4497                    value: s,
4498                    base: NumBase::Hex,
4499                    suffix: None,
4500                }))
4501            }
4502            Some(Token::VigesimalLit(s)) => {
4503                self.advance();
4504                Ok(Expr::Literal(Literal::Int {
4505                    value: s,
4506                    base: NumBase::Vigesimal,
4507                    suffix: None,
4508                }))
4509            }
4510            Some(Token::SexagesimalLit(s)) => {
4511                self.advance();
4512                Ok(Expr::Literal(Literal::Int {
4513                    value: s,
4514                    base: NumBase::Sexagesimal,
4515                    suffix: None,
4516                }))
4517            }
4518            Some(Token::DuodecimalLit(s)) => {
4519                self.advance();
4520                Ok(Expr::Literal(Literal::Int {
4521                    value: s,
4522                    base: NumBase::Duodecimal,
4523                    suffix: None,
4524                }))
4525            }
4526            Some(Token::FloatLit(s)) => {
4527                self.advance();
4528                Ok(Expr::Literal(Literal::Float {
4529                    value: s,
4530                    suffix: None,
4531                }))
4532            }
4533            Some(Token::StringLit(s)) => {
4534                self.advance();
4535                Ok(Expr::Literal(Literal::String(s)))
4536            }
4537            Some(Token::MultiLineStringLit(s)) => {
4538                self.advance();
4539                Ok(Expr::Literal(Literal::MultiLineString(s)))
4540            }
4541            Some(Token::RawStringLit(s)) | Some(Token::RawStringDelimited(s)) => {
4542                self.advance();
4543                Ok(Expr::Literal(Literal::RawString(s)))
4544            }
4545            // Full range expression: `..` or `..=` (with optional end)
4546            // Handles cases like `.drain(..)` and `[..]`
4547            Some(Token::DotDot) | Some(Token::DotDotEq) => {
4548                let inclusive = self.consume_if(&Token::DotDotEq);
4549                if !inclusive {
4550                    self.advance(); // consume ..
4551                }
4552                // Check if there's an end expression
4553                let end = if self.check(&Token::RParen)
4554                    || self.check(&Token::RBracket)
4555                    || self.check(&Token::Comma)
4556                    || self.check(&Token::Semi)
4557                    || self.check(&Token::RBrace)
4558                {
4559                    None
4560                } else {
4561                    Some(Box::new(self.parse_expr()?))
4562                };
4563                Ok(Expr::Range {
4564                    start: None,
4565                    end,
4566                    inclusive,
4567                })
4568            }
4569            Some(Token::ByteStringLit(bytes)) => {
4570                self.advance();
4571                Ok(Expr::Literal(Literal::ByteString(bytes)))
4572            }
4573            Some(Token::InterpolatedStringLit(s)) => {
4574                self.advance();
4575                // Parse the interpolation parts
4576                let parts = self.parse_interpolation_parts(&s)?;
4577                Ok(Expr::Literal(Literal::InterpolatedString { parts }))
4578            }
4579            Some(Token::SigilStringSql(s)) => {
4580                self.advance();
4581                Ok(Expr::Literal(Literal::SigilStringSql(s)))
4582            }
4583            Some(Token::SigilStringRoute(s)) => {
4584                self.advance();
4585                Ok(Expr::Literal(Literal::SigilStringRoute(s)))
4586            }
4587            Some(Token::CharLit(c)) => {
4588                self.advance();
4589                Ok(Expr::Literal(Literal::Char(c)))
4590            }
4591            Some(Token::ByteCharLit(b)) => {
4592                self.advance();
4593                Ok(Expr::Literal(Literal::ByteChar(b)))
4594            }
4595            Some(Token::True) | Some(Token::Top) => {
4596                self.advance();
4597                Ok(Expr::Literal(Literal::Bool(true)))
4598            }
4599            Some(Token::False) | Some(Token::Bottom) => {
4600                self.advance();
4601                Ok(Expr::Literal(Literal::Bool(false)))
4602            }
4603            Some(Token::Null) => {
4604                self.advance();
4605                Ok(Expr::Literal(Literal::Null))
4606            }
4607            Some(Token::Empty) => {
4608                self.advance();
4609                Ok(Expr::Literal(Literal::Empty))
4610            }
4611            Some(Token::Infinity) => {
4612                // Check if this is ∞ { ... } (loop) or just ∞ (infinity literal)
4613                if matches!(self.peek_next(), Some(Token::LBrace)) {
4614                    // It's a loop: ∞ { body }
4615                    self.advance();
4616                    let body = self.parse_block()?;
4617                    Ok(Expr::Loop { label: None, body })
4618                } else {
4619                    // It's an infinity literal
4620                    self.advance();
4621                    Ok(Expr::Literal(Literal::Infinity))
4622                }
4623            }
4624            Some(Token::Circle) => {
4625                self.advance();
4626                Ok(Expr::Literal(Literal::Circle))
4627            }
4628            Some(Token::LParen) => {
4629                self.advance();
4630                if self.check(&Token::RParen) {
4631                    self.advance();
4632                    return Ok(Expr::Tuple(vec![]));
4633                }
4634                let expr = self.parse_expr()?;
4635                if self.consume_if(&Token::Comma) {
4636                    let mut exprs = vec![expr];
4637                    while !self.check(&Token::RParen) {
4638                        exprs.push(self.parse_expr()?);
4639                        if !self.consume_if(&Token::Comma) {
4640                            break;
4641                        }
4642                    }
4643                    self.expect(Token::RParen)?;
4644                    Ok(Expr::Tuple(exprs))
4645                } else {
4646                    self.expect(Token::RParen)?;
4647                    Ok(expr)
4648                }
4649            }
4650            Some(Token::LBracket) => {
4651                self.advance();
4652                // Check for empty array
4653                if self.check(&Token::RBracket) {
4654                    self.advance();
4655                    return Ok(Expr::Array(vec![]));
4656                }
4657                // Parse first expression
4658                let first = self.parse_expr()?;
4659                // Check for repeat syntax: [value; count]
4660                if self.consume_if(&Token::Semi) {
4661                    let count = self.parse_expr()?;
4662                    self.expect(Token::RBracket)?;
4663                    return Ok(Expr::ArrayRepeat {
4664                        value: Box::new(first),
4665                        count: Box::new(count),
4666                    });
4667                }
4668                // Otherwise, parse as regular array literal
4669                let mut exprs = vec![first];
4670                while self.consume_if(&Token::Comma) {
4671                    // Skip comments after comma (for trailing comments)
4672                    self.skip_comments();
4673                    if self.check(&Token::RBracket) {
4674                        break; // trailing comma
4675                    }
4676                    exprs.push(self.parse_expr()?);
4677                }
4678                self.skip_comments();
4679                self.expect(Token::RBracket)?;
4680                Ok(Expr::Array(exprs))
4681            }
4682            Some(Token::LBrace) => {
4683                // Could be block or closure
4684                self.parse_block_or_closure()
4685            }
4686            Some(Token::If) => self.parse_if_expr(),
4687            Some(Token::Match) => self.parse_match_expr(),
4688            Some(Token::Unsafe) => {
4689                self.advance();
4690                let block = self.parse_block()?;
4691                Ok(Expr::Unsafe(block))
4692            }
4693            Some(Token::Async) => {
4694                self.advance();
4695                let is_move = self.consume_if(&Token::Move);
4696                let block = self.parse_block()?;
4697                Ok(Expr::Async { block, is_move })
4698            }
4699            Some(Token::Const) => {
4700                // Const block expression: `const { expr }` - compile-time evaluated block
4701                // For now, parse as a regular block expression
4702                self.advance();
4703                let block = self.parse_block()?;
4704                Ok(Expr::Block(block))
4705            }
4706            Some(Token::Lifetime(name)) => {
4707                // Labeled loop: 'label: loop/while/for { ... }
4708                let span = self.current_span();
4709                let label = Ident {
4710                    name: name.clone(),
4711                    evidentiality: None,
4712                    affect: None,
4713                    span,
4714                };
4715                self.advance();
4716                self.expect(Token::Colon)?;
4717                match self.current_token().cloned() {
4718                    Some(Token::Loop) | Some(Token::Infinity) => {
4719                        self.advance();
4720                        let body = self.parse_block()?;
4721                        Ok(Expr::Loop {
4722                            label: Some(label),
4723                            body,
4724                        })
4725                    }
4726                    Some(Token::While) => {
4727                        self.advance();
4728                        // Handle while-let: `while let pattern = expr { ... }`
4729                        let condition = if self.consume_if(&Token::Let) {
4730                            let pattern = self.parse_pattern()?;
4731                            self.expect(Token::Eq)?;
4732                            let value = self.parse_condition()?;
4733                            Expr::Let {
4734                                pattern,
4735                                value: Box::new(value),
4736                            }
4737                        } else {
4738                            self.parse_condition()?
4739                        };
4740                        let body = self.parse_block()?;
4741                        Ok(Expr::While {
4742                            label: Some(label),
4743                            condition: Box::new(condition),
4744                            body,
4745                        })
4746                    }
4747                    Some(Token::For) | Some(Token::ForAll) => {
4748                        self.advance();
4749                        let pattern = self.parse_pattern()?;
4750                        // Accept both 'in' and '∈' for element-of
4751                        if !self.consume_if(&Token::In) && !self.consume_if(&Token::ElementOf) {
4752                            return Err(ParseError::UnexpectedToken {
4753                                expected: "in or ∈".to_string(),
4754                                found: self.current_token().cloned().unwrap_or(Token::Null),
4755                                span: self.current_span(),
4756                            });
4757                        }
4758                        let iter = self.parse_condition()?;
4759                        let body = self.parse_block()?;
4760                        Ok(Expr::For {
4761                            label: Some(label),
4762                            pattern,
4763                            iter: Box::new(iter),
4764                            body,
4765                        })
4766                    }
4767                    other => Err(ParseError::UnexpectedToken {
4768                        expected: "loop/∞, while/⟳, or for/∀ after label".to_string(),
4769                        found: other.unwrap_or(Token::Null),
4770                        span: self.current_span(),
4771                    }),
4772                }
4773            }
4774            Some(Token::Loop) | Some(Token::Infinity) => {
4775                self.advance();
4776                let body = self.parse_block()?;
4777                Ok(Expr::Loop { label: None, body })
4778            }
4779            Some(Token::While) => {
4780                self.advance();
4781                // Handle while-let: `while let pattern = expr { ... }`
4782                let condition = if self.consume_if(&Token::Let) {
4783                    let pattern = self.parse_pattern()?;
4784                    self.expect(Token::Eq)?;
4785                    let value = self.parse_condition()?;
4786                    Expr::Let {
4787                        pattern,
4788                        value: Box::new(value),
4789                    }
4790                } else {
4791                    self.parse_condition()?
4792                };
4793                let body = self.parse_block()?;
4794                Ok(Expr::While {
4795                    label: None,
4796                    condition: Box::new(condition),
4797                    body,
4798                })
4799            }
4800            Some(Token::For) | Some(Token::ForAll) => {
4801                self.advance();
4802                let pattern = self.parse_pattern()?;
4803                // Accept both 'in' and '∈' for element-of
4804                if !self.consume_if(&Token::In) && !self.consume_if(&Token::ElementOf) {
4805                    return Err(ParseError::UnexpectedToken {
4806                        expected: "in or ∈".to_string(),
4807                        found: self.current_token().cloned().unwrap_or(Token::Null),
4808                        span: self.current_span(),
4809                    });
4810                }
4811                let iter = self.parse_condition()?;
4812                let body = self.parse_block()?;
4813                Ok(Expr::For {
4814                    label: None,
4815                    pattern,
4816                    iter: Box::new(iter),
4817                    body,
4818                })
4819            }
4820            Some(Token::Return) => {
4821                self.advance();
4822                // Check for terminators: ; } or , (in match arms)
4823                let value = if self.check(&Token::Semi)
4824                    || self.check(&Token::RBrace)
4825                    || self.check(&Token::Comma)
4826                {
4827                    None
4828                } else {
4829                    Some(Box::new(self.parse_expr()?))
4830                };
4831                Ok(Expr::Return(value))
4832            }
4833            Some(Token::Break) | Some(Token::Tensor) => {
4834                self.advance();
4835                // Check for optional label: break 'label or break 'label value
4836                let label = if let Some(Token::Lifetime(name)) = self.current_token().cloned() {
4837                    let span = self.current_span();
4838                    let label = Ident {
4839                        name,
4840                        evidentiality: None,
4841                        affect: None,
4842                        span,
4843                    };
4844                    self.advance();
4845                    Some(label)
4846                } else {
4847                    None
4848                };
4849                // Check for terminators: ; } or , (in match arms)
4850                let value = if self.check(&Token::Semi)
4851                    || self.check(&Token::RBrace)
4852                    || self.check(&Token::Comma)
4853                {
4854                    None
4855                } else {
4856                    Some(Box::new(self.parse_expr()?))
4857                };
4858                Ok(Expr::Break { label, value })
4859            }
4860            Some(Token::Continue) | Some(Token::CycleArrow) => {
4861                self.advance();
4862                // Check for optional label: continue 'label
4863                let label = if let Some(Token::Lifetime(name)) = self.current_token().cloned() {
4864                    let span = self.current_span();
4865                    let label = Ident {
4866                        name,
4867                        evidentiality: None,
4868                        affect: None,
4869                        span,
4870                    };
4871                    self.advance();
4872                    Some(label)
4873                } else {
4874                    None
4875                };
4876                Ok(Expr::Continue { label })
4877            }
4878            // Morphemes as standalone expressions
4879            Some(Token::Tau) | Some(Token::Phi) | Some(Token::Sigma) | Some(Token::Rho)
4880            | Some(Token::Lambda) | Some(Token::Pi) => {
4881                let kind = self.parse_morpheme_kind()?;
4882                if self.check(&Token::LBrace) {
4883                    self.advance();
4884                    self.skip_comments();
4885                    // Check for closure pattern: τ{x => expr} or τ{(a, b) => expr}
4886                    let body = if self.looks_like_morpheme_closure() {
4887                        self.parse_morpheme_closure()?
4888                    } else {
4889                        self.parse_expr()?
4890                    };
4891                    self.expect(Token::RBrace)?;
4892                    Ok(Expr::Morpheme {
4893                        kind,
4894                        body: Box::new(body),
4895                    })
4896                } else {
4897                    // Just the morpheme symbol
4898                    Ok(Expr::Morpheme {
4899                        kind,
4900                        body: Box::new(Expr::Path(TypePath {
4901                            segments: vec![PathSegment {
4902                                ident: Ident {
4903                                    name: "_".to_string(),
4904                                    evidentiality: None,
4905                                    affect: None,
4906                                    span: Span::default(),
4907                                },
4908                                generics: None,
4909                            }],
4910                        })),
4911                    })
4912                }
4913            }
4914            // Sacred constants as expressions
4915            Some(Token::Sqrt) => {
4916                // Handle √2, √3, √5, etc. (square root constants)
4917                let span = self.current_span();
4918                self.advance();
4919                let name = if let Some(Token::IntLit(n)) = self.current_token().cloned() {
4920                    let merged_span = span.merge(self.current_span());
4921                    self.advance();
4922                    (format!("√{}", n), merged_span)
4923                } else {
4924                    ("√".to_string(), span)
4925                };
4926                Ok(Expr::Path(TypePath {
4927                    segments: vec![PathSegment {
4928                        ident: Ident {
4929                            name: name.0,
4930                            evidentiality: None,
4931                            affect: None,
4932                            span: name.1,
4933                        },
4934                        generics: None,
4935                    }],
4936                }))
4937            }
4938            Some(Token::Underscore) => {
4939                // Underscore as placeholder in closures
4940                let span = self.current_span();
4941                self.advance();
4942                Ok(Expr::Path(TypePath {
4943                    segments: vec![PathSegment {
4944                        ident: Ident {
4945                            name: "_".to_string(),
4946                            evidentiality: None,
4947                            affect: None,
4948                            span,
4949                        },
4950                        generics: None,
4951                    }],
4952                }))
4953            }
4954            Some(Token::SelfLower) | Some(Token::Xi) => {
4955                // this/ξ keyword as expression (self)
4956                let span = self.current_span();
4957                self.advance();
4958                Ok(Expr::Path(TypePath {
4959                    segments: vec![PathSegment {
4960                        ident: Ident {
4961                            name: "self".to_string(),
4962                            evidentiality: None,
4963                            affect: None,
4964                            span,
4965                        },
4966                        generics: None,
4967                    }],
4968                }))
4969            }
4970            Some(Token::SelfUpper) => {
4971                // Self keyword as expression (struct constructor or path start)
4972                let span = self.current_span();
4973                self.advance();
4974                let mut segments = vec![PathSegment {
4975                    ident: Ident {
4976                        name: "Self".to_string(),
4977                        evidentiality: None,
4978                        affect: None,
4979                        span,
4980                    },
4981                    generics: None,
4982                }];
4983                // Handle Self::method() and other path continuations
4984                // Support both :: and · (middle dot) as path separators
4985                while self.consume_if(&Token::ColonColon) || self.consume_if(&Token::MiddleDot) {
4986                    // Check for turbofish syntax: Self::method::<Type> or Self·method·<Type>
4987                    if self.check(&Token::Lt) {
4988                        self.advance(); // consume <
4989                        let types = self.parse_type_list()?;
4990                        self.expect_gt()?;
4991                        // Update the last segment with these generics
4992                        if let Some(last) = segments.last_mut() {
4993                            last.generics = Some(types);
4994                        }
4995                        // Continue parsing - there may be more segments after turbofish
4996                        // e.g., Self::<T>::new() or This·<T>·method()
4997                        continue;
4998                    }
4999                    segments.push(self.parse_path_segment()?);
5000                }
5001                let path = TypePath { segments };
5002                // Check for struct literal: Self { ... }
5003                if self.check(&Token::LBrace) && !self.is_in_condition() {
5004                    self.advance();
5005                    let (fields, rest) = self.parse_struct_fields()?;
5006                    self.expect(Token::RBrace)?;
5007                    Ok(Expr::Struct { path, fields, rest })
5008                } else {
5009                    Ok(Expr::Path(path))
5010                }
5011            }
5012            Some(Token::Ident(_)) => {
5013                let path = self.parse_type_path()?;
5014
5015                // Check for struct literal: Name { ... }
5016                // Note: Name! { ... } is treated as a macro invocation, handled in parse_postfix_expr
5017                // This allows html! { ... } and other macros with brace bodies to work correctly
5018                if self.check(&Token::LBrace) && !self.is_in_condition() {
5019                    self.advance();
5020                    let (fields, rest) = self.parse_struct_fields()?;
5021                    self.expect(Token::RBrace)?;
5022                    Ok(Expr::Struct { path, fields, rest })
5023                } else {
5024                    Ok(Expr::Path(path))
5025                }
5026            }
5027            Some(Token::Asm) => self.parse_inline_asm(),
5028            Some(Token::Volatile) => self.parse_volatile_expr(),
5029            Some(Token::Simd) => self.parse_simd_expr(),
5030            Some(Token::Atomic) => self.parse_atomic_expr(),
5031            // Implicit self field access: `.field` desugars to `self.field`
5032            // This allows more concise method bodies:
5033            //   fn increment(mut self) { .count += 1; }
5034            // instead of:
5035            //   fn increment(mut self) { self.count += 1; }
5036            Some(Token::Dot) => {
5037                let dot_span = self.current_span();
5038                self.advance(); // consume .
5039                match self.current_token() {
5040                    Some(Token::Ident(name)) => {
5041                        let field_name = name.clone();
5042                        let field_span = self.current_span();
5043                        self.advance();
5044                        // Create `self.field` expression
5045                        let self_expr = Expr::Path(TypePath {
5046                            segments: vec![PathSegment {
5047                                ident: Ident {
5048                                    name: "self".to_string(),
5049                                    evidentiality: None,
5050                                    affect: None,
5051                                    span: dot_span,
5052                                },
5053                                generics: None,
5054                            }],
5055                        });
5056                        Ok(Expr::Field {
5057                            expr: Box::new(self_expr),
5058                            field: Ident {
5059                                name: field_name,
5060                                evidentiality: None,
5061                                affect: None,
5062                                span: field_span,
5063                            },
5064                        })
5065                    }
5066                    Some(token) => Err(ParseError::UnexpectedToken {
5067                        expected: "identifier after '.' for implicit self field".to_string(),
5068                        found: token.clone(),
5069                        span: self.current_span(),
5070                    }),
5071                    None => Err(ParseError::UnexpectedEof),
5072                }
5073            }
5074            // Handle contextual keywords as identifiers in expressions
5075            Some(ref token) if Self::keyword_as_ident(token).is_some() => {
5076                let path = self.parse_type_path()?;
5077                // Check for struct literal: Name { ... }
5078                // Note: Don't consume ! here - macro invocations (Name!(...)) are handled in parse_postfix_expr
5079                if self.check(&Token::LBrace) && !self.is_in_condition() {
5080                    self.advance();
5081                    let (fields, rest) = self.parse_struct_fields()?;
5082                    self.expect(Token::RBrace)?;
5083                    Ok(Expr::Struct { path, fields, rest })
5084                } else {
5085                    Ok(Expr::Path(path))
5086                }
5087            }
5088            Some(token) => Err(ParseError::UnexpectedToken {
5089                expected: "expression".to_string(),
5090                found: token,
5091                span: self.current_span(),
5092            }),
5093            None => Err(ParseError::UnexpectedEof),
5094        }
5095    }
5096
5097    /// Parse inline assembly: `asm!("template", ...)`
5098    ///
5099    /// Syntax:
5100    /// ```sigil
5101    /// asm!("template {0} {1}",
5102    ///     out("rax") result,
5103    ///     in("rbx") input,
5104    ///     clobber("rcx", "rdx"),
5105    ///     options(volatile, nostack))
5106    /// ```
5107    fn parse_inline_asm(&mut self) -> ParseResult<Expr> {
5108        self.expect(Token::Asm)?;
5109        self.expect(Token::Bang)?;
5110        self.expect(Token::LParen)?;
5111
5112        // Parse template string
5113        let template = match self.current_token().cloned() {
5114            Some(Token::StringLit(s)) => {
5115                self.advance();
5116                s
5117            }
5118            Some(t) => {
5119                return Err(ParseError::UnexpectedToken {
5120                    expected: "assembly template string".to_string(),
5121                    found: t,
5122                    span: self.current_span(),
5123                });
5124            }
5125            None => return Err(ParseError::UnexpectedEof),
5126        };
5127
5128        let mut outputs = Vec::new();
5129        let mut inputs = Vec::new();
5130        let mut clobbers = Vec::new();
5131        let mut options = AsmOptions::default();
5132
5133        // Parse operands and options
5134        while self.consume_if(&Token::Comma) {
5135            if self.check(&Token::RParen) {
5136                break;
5137            }
5138
5139            match self.current_token().cloned() {
5140                Some(Token::Ident(ref name)) if name == "out" => {
5141                    self.advance();
5142                    let operand = self.parse_asm_operand(AsmOperandKind::Output)?;
5143                    outputs.push(operand);
5144                }
5145                // Handle `in` which is a keyword (Token::In)
5146                Some(Token::In) => {
5147                    self.advance();
5148                    let operand = self.parse_asm_operand(AsmOperandKind::Input)?;
5149                    inputs.push(operand);
5150                }
5151                Some(Token::Ident(ref name)) if name == "inout" => {
5152                    self.advance();
5153                    let operand = self.parse_asm_operand(AsmOperandKind::InOut)?;
5154                    outputs.push(operand);
5155                }
5156                Some(Token::Ident(ref name)) if name == "clobber" => {
5157                    self.advance();
5158                    self.expect(Token::LParen)?;
5159                    while !self.check(&Token::RParen) {
5160                        if let Some(Token::StringLit(reg)) = self.current_token().cloned() {
5161                            self.advance();
5162                            clobbers.push(reg);
5163                        } else if let Some(Token::Ident(reg)) = self.current_token().cloned() {
5164                            self.advance();
5165                            clobbers.push(reg);
5166                        }
5167                        if !self.consume_if(&Token::Comma) {
5168                            break;
5169                        }
5170                    }
5171                    self.expect(Token::RParen)?;
5172                }
5173                Some(Token::Ident(ref name)) if name == "options" => {
5174                    self.advance();
5175                    self.expect(Token::LParen)?;
5176                    while !self.check(&Token::RParen) {
5177                        if let Some(Token::Ident(opt)) = self.current_token().cloned() {
5178                            self.advance();
5179                            match opt.as_str() {
5180                                "volatile" => options.volatile = true,
5181                                "nostack" => options.nostack = true,
5182                                "pure" => options.pure_asm = true,
5183                                "readonly" => options.readonly = true,
5184                                "nomem" => options.nomem = true,
5185                                "att_syntax" => options.att_syntax = true,
5186                                _ => {}
5187                            }
5188                        }
5189                        if !self.consume_if(&Token::Comma) {
5190                            break;
5191                        }
5192                    }
5193                    self.expect(Token::RParen)?;
5194                }
5195                _ => break,
5196            }
5197        }
5198
5199        self.expect(Token::RParen)?;
5200
5201        Ok(Expr::InlineAsm(InlineAsm {
5202            template,
5203            outputs,
5204            inputs,
5205            clobbers,
5206            options,
5207        }))
5208    }
5209
5210    /// Parse an assembly operand: `("reg") expr` or `("reg") var => expr`
5211    fn parse_asm_operand(&mut self, kind: AsmOperandKind) -> ParseResult<AsmOperand> {
5212        self.expect(Token::LParen)?;
5213
5214        let constraint = match self.current_token().cloned() {
5215            Some(Token::StringLit(s)) => {
5216                self.advance();
5217                s
5218            }
5219            Some(Token::Ident(s)) => {
5220                self.advance();
5221                s
5222            }
5223            Some(t) => {
5224                return Err(ParseError::UnexpectedToken {
5225                    expected: "register constraint".to_string(),
5226                    found: t,
5227                    span: self.current_span(),
5228                });
5229            }
5230            None => return Err(ParseError::UnexpectedEof),
5231        };
5232
5233        self.expect(Token::RParen)?;
5234
5235        let expr = self.parse_expr()?;
5236
5237        // For inout, check for `=> output`
5238        let output = if kind == AsmOperandKind::InOut && self.consume_if(&Token::FatArrow) {
5239            Some(Box::new(self.parse_expr()?))
5240        } else {
5241            None
5242        };
5243
5244        Ok(AsmOperand {
5245            constraint,
5246            expr,
5247            kind,
5248            output,
5249        })
5250    }
5251
5252    /// Parse volatile memory operations
5253    ///
5254    /// - `volatile read<T>(ptr)` - volatile read from pointer
5255    /// - `volatile write<T>(ptr, value)` - volatile write to pointer
5256    fn parse_volatile_expr(&mut self) -> ParseResult<Expr> {
5257        self.expect(Token::Volatile)?;
5258
5259        match self.current_token().cloned() {
5260            Some(Token::Ident(ref name)) if name == "read" => {
5261                self.advance();
5262
5263                // Optional type parameter <T>
5264                let ty = if self.consume_if(&Token::Lt) {
5265                    let t = self.parse_type()?;
5266                    self.expect_gt()?;
5267                    Some(t)
5268                } else {
5269                    None
5270                };
5271
5272                self.expect(Token::LParen)?;
5273                let ptr = self.parse_expr()?;
5274                self.expect(Token::RParen)?;
5275
5276                Ok(Expr::VolatileRead {
5277                    ptr: Box::new(ptr),
5278                    ty,
5279                })
5280            }
5281            Some(Token::Ident(ref name)) if name == "write" => {
5282                self.advance();
5283
5284                // Optional type parameter <T>
5285                let ty = if self.consume_if(&Token::Lt) {
5286                    let t = self.parse_type()?;
5287                    self.expect_gt()?;
5288                    Some(t)
5289                } else {
5290                    None
5291                };
5292
5293                self.expect(Token::LParen)?;
5294                let ptr = self.parse_expr()?;
5295                self.expect(Token::Comma)?;
5296                let value = self.parse_expr()?;
5297                self.expect(Token::RParen)?;
5298
5299                Ok(Expr::VolatileWrite {
5300                    ptr: Box::new(ptr),
5301                    value: Box::new(value),
5302                    ty,
5303                })
5304            }
5305            Some(t) => Err(ParseError::UnexpectedToken {
5306                expected: "'read' or 'write' after 'volatile'".to_string(),
5307                found: t,
5308                span: self.current_span(),
5309            }),
5310            None => Err(ParseError::UnexpectedEof),
5311        }
5312    }
5313
5314    /// Parse SIMD expressions
5315    ///
5316    /// Syntax:
5317    /// ```sigil
5318    /// simd[1.0, 2.0, 3.0, 4.0]              // SIMD literal
5319    /// simd.splat(1.0, 4)                    // Broadcast value to all lanes
5320    /// simd.add(a, b)                        // SIMD intrinsic
5321    /// simd.shuffle(a, b, [0, 4, 1, 5])      // Shuffle lanes
5322    /// simd.extract(v, 0)                    // Extract element
5323    /// simd.insert(v, 0, val)                // Insert element
5324    /// ```
5325    fn parse_simd_expr(&mut self) -> ParseResult<Expr> {
5326        self.expect(Token::Simd)?;
5327
5328        match self.current_token().cloned() {
5329            Some(Token::LBracket) => {
5330                // SIMD literal: simd[1.0, 2.0, 3.0, 4.0]
5331                self.advance();
5332                let elements = self.parse_expr_list()?;
5333                self.expect(Token::RBracket)?;
5334
5335                // Optional type annotation
5336                let ty = if self.consume_if(&Token::Colon) {
5337                    Some(self.parse_type()?)
5338                } else {
5339                    None
5340                };
5341
5342                Ok(Expr::SimdLiteral { elements, ty })
5343            }
5344            Some(Token::Dot) => {
5345                self.advance();
5346                match self.current_token().cloned() {
5347                    Some(Token::Ident(ref op)) => {
5348                        let op_name = op.clone();
5349                        self.advance();
5350                        self.expect(Token::LParen)?;
5351
5352                        match op_name.as_str() {
5353                            "splat" => {
5354                                let value = self.parse_expr()?;
5355                                self.expect(Token::Comma)?;
5356                                let lanes = match self.current_token() {
5357                                    Some(Token::IntLit(s)) => {
5358                                        let n = s.parse::<u8>().map_err(|_| {
5359                                            ParseError::Custom("invalid lane count".to_string())
5360                                        })?;
5361                                        self.advance();
5362                                        n
5363                                    }
5364                                    _ => {
5365                                        return Err(ParseError::Custom(
5366                                            "expected lane count".to_string(),
5367                                        ))
5368                                    }
5369                                };
5370                                self.expect(Token::RParen)?;
5371                                Ok(Expr::SimdSplat {
5372                                    value: Box::new(value),
5373                                    lanes,
5374                                })
5375                            }
5376                            "shuffle" => {
5377                                let a = self.parse_expr()?;
5378                                self.expect(Token::Comma)?;
5379                                let b = self.parse_expr()?;
5380                                self.expect(Token::Comma)?;
5381                                self.expect(Token::LBracket)?;
5382                                let mut indices = Vec::new();
5383                                loop {
5384                                    match self.current_token() {
5385                                        Some(Token::IntLit(s)) => {
5386                                            let n = s.parse::<u8>().map_err(|_| {
5387                                                ParseError::Custom("invalid index".to_string())
5388                                            })?;
5389                                            indices.push(n);
5390                                            self.advance();
5391                                        }
5392                                        _ => {
5393                                            return Err(ParseError::Custom(
5394                                                "expected index".to_string(),
5395                                            ))
5396                                        }
5397                                    }
5398                                    if !self.consume_if(&Token::Comma) {
5399                                        break;
5400                                    }
5401                                }
5402                                self.expect(Token::RBracket)?;
5403                                self.expect(Token::RParen)?;
5404                                Ok(Expr::SimdShuffle {
5405                                    a: Box::new(a),
5406                                    b: Box::new(b),
5407                                    indices,
5408                                })
5409                            }
5410                            "extract" => {
5411                                let vector = self.parse_expr()?;
5412                                self.expect(Token::Comma)?;
5413                                let index = match self.current_token() {
5414                                    Some(Token::IntLit(s)) => {
5415                                        let n = s.parse::<u8>().map_err(|_| {
5416                                            ParseError::Custom("invalid index".to_string())
5417                                        })?;
5418                                        self.advance();
5419                                        n
5420                                    }
5421                                    _ => {
5422                                        return Err(ParseError::Custom(
5423                                            "expected index".to_string(),
5424                                        ))
5425                                    }
5426                                };
5427                                self.expect(Token::RParen)?;
5428                                Ok(Expr::SimdExtract {
5429                                    vector: Box::new(vector),
5430                                    index,
5431                                })
5432                            }
5433                            "insert" => {
5434                                let vector = self.parse_expr()?;
5435                                self.expect(Token::Comma)?;
5436                                let index = match self.current_token() {
5437                                    Some(Token::IntLit(s)) => {
5438                                        let n = s.parse::<u8>().map_err(|_| {
5439                                            ParseError::Custom("invalid index".to_string())
5440                                        })?;
5441                                        self.advance();
5442                                        n
5443                                    }
5444                                    _ => {
5445                                        return Err(ParseError::Custom(
5446                                            "expected index".to_string(),
5447                                        ))
5448                                    }
5449                                };
5450                                self.expect(Token::Comma)?;
5451                                let value = self.parse_expr()?;
5452                                self.expect(Token::RParen)?;
5453                                Ok(Expr::SimdInsert {
5454                                    vector: Box::new(vector),
5455                                    index,
5456                                    value: Box::new(value),
5457                                })
5458                            }
5459                            _ => {
5460                                // Parse as generic SIMD intrinsic
5461                                let op = Self::parse_simd_op(&op_name)?;
5462                                let args = self.parse_expr_list()?;
5463                                self.expect(Token::RParen)?;
5464                                Ok(Expr::SimdIntrinsic { op, args })
5465                            }
5466                        }
5467                    }
5468                    Some(t) => Err(ParseError::UnexpectedToken {
5469                        expected: "SIMD operation name".to_string(),
5470                        found: t,
5471                        span: self.current_span(),
5472                    }),
5473                    None => Err(ParseError::UnexpectedEof),
5474                }
5475            }
5476            Some(t) => Err(ParseError::UnexpectedToken {
5477                expected: "'[' or '.' after 'simd'".to_string(),
5478                found: t,
5479                span: self.current_span(),
5480            }),
5481            None => Err(ParseError::UnexpectedEof),
5482        }
5483    }
5484
5485    fn parse_simd_op(name: &str) -> ParseResult<SimdOp> {
5486        match name {
5487            "add" => Ok(SimdOp::Add),
5488            "sub" => Ok(SimdOp::Sub),
5489            "mul" => Ok(SimdOp::Mul),
5490            "div" => Ok(SimdOp::Div),
5491            "neg" => Ok(SimdOp::Neg),
5492            "abs" => Ok(SimdOp::Abs),
5493            "min" => Ok(SimdOp::Min),
5494            "max" => Ok(SimdOp::Max),
5495            "eq" => Ok(SimdOp::Eq),
5496            "ne" => Ok(SimdOp::Ne),
5497            "lt" => Ok(SimdOp::Lt),
5498            "le" => Ok(SimdOp::Le),
5499            "gt" => Ok(SimdOp::Gt),
5500            "ge" => Ok(SimdOp::Ge),
5501            "hadd" => Ok(SimdOp::HAdd),
5502            "dot" => Ok(SimdOp::Dot),
5503            "blend" => Ok(SimdOp::Blend),
5504            "load" => Ok(SimdOp::Load),
5505            "store" => Ok(SimdOp::Store),
5506            "load_aligned" => Ok(SimdOp::LoadAligned),
5507            "store_aligned" => Ok(SimdOp::StoreAligned),
5508            "cast" => Ok(SimdOp::Cast),
5509            "widen" => Ok(SimdOp::Widen),
5510            "narrow" => Ok(SimdOp::Narrow),
5511            "sqrt" => Ok(SimdOp::Sqrt),
5512            "rsqrt" => Ok(SimdOp::Rsqrt),
5513            "rcp" => Ok(SimdOp::Rcp),
5514            "floor" => Ok(SimdOp::Floor),
5515            "ceil" => Ok(SimdOp::Ceil),
5516            "round" => Ok(SimdOp::Round),
5517            "and" => Ok(SimdOp::And),
5518            "or" => Ok(SimdOp::Or),
5519            "xor" => Ok(SimdOp::Xor),
5520            "not" => Ok(SimdOp::Not),
5521            "shl" => Ok(SimdOp::Shl),
5522            "shr" => Ok(SimdOp::Shr),
5523            _ => Err(ParseError::Custom(format!(
5524                "unknown SIMD operation: {}",
5525                name
5526            ))),
5527        }
5528    }
5529
5530    /// Parse atomic expressions
5531    ///
5532    /// Syntax:
5533    /// ```sigil
5534    /// atomic.load(ptr, Relaxed)
5535    /// atomic.store(ptr, value, Release)
5536    /// atomic.swap(ptr, value, SeqCst)
5537    /// atomic.compare_exchange(ptr, expected, new, AcqRel, Relaxed)
5538    /// atomic.fetch_add(ptr, value, Acquire)
5539    /// atomic.fence(SeqCst)
5540    /// ```
5541    fn parse_atomic_expr(&mut self) -> ParseResult<Expr> {
5542        self.expect(Token::Atomic)?;
5543        self.expect(Token::Dot)?;
5544
5545        match self.current_token().cloned() {
5546            Some(Token::Ident(ref op)) => {
5547                let op_name = op.clone();
5548                self.advance();
5549
5550                if op_name == "fence" {
5551                    self.expect(Token::LParen)?;
5552                    let ordering = self.parse_memory_ordering()?;
5553                    self.expect(Token::RParen)?;
5554                    return Ok(Expr::AtomicFence { ordering });
5555                }
5556
5557                self.expect(Token::LParen)?;
5558                let ptr = self.parse_expr()?;
5559
5560                let op = Self::parse_atomic_op(&op_name)?;
5561
5562                // Parse value for operations that need it
5563                let value = match op {
5564                    AtomicOp::Load => None,
5565                    _ => {
5566                        self.expect(Token::Comma)?;
5567                        Some(Box::new(self.parse_expr()?))
5568                    }
5569                };
5570
5571                // Parse expected value for compare_exchange
5572                let expected = match op {
5573                    AtomicOp::CompareExchange | AtomicOp::CompareExchangeWeak => {
5574                        self.expect(Token::Comma)?;
5575                        Some(Box::new(self.parse_expr()?))
5576                    }
5577                    _ => None,
5578                };
5579
5580                // Parse memory ordering
5581                self.expect(Token::Comma)?;
5582                let ordering = self.parse_memory_ordering()?;
5583
5584                // Parse failure ordering for compare_exchange
5585                let failure_ordering = match op {
5586                    AtomicOp::CompareExchange | AtomicOp::CompareExchangeWeak => {
5587                        if self.consume_if(&Token::Comma) {
5588                            Some(self.parse_memory_ordering()?)
5589                        } else {
5590                            None
5591                        }
5592                    }
5593                    _ => None,
5594                };
5595
5596                self.expect(Token::RParen)?;
5597
5598                Ok(Expr::AtomicOp {
5599                    op,
5600                    ptr: Box::new(ptr),
5601                    value,
5602                    expected,
5603                    ordering,
5604                    failure_ordering,
5605                })
5606            }
5607            Some(t) => Err(ParseError::UnexpectedToken {
5608                expected: "atomic operation name".to_string(),
5609                found: t,
5610                span: self.current_span(),
5611            }),
5612            None => Err(ParseError::UnexpectedEof),
5613        }
5614    }
5615
5616    fn parse_atomic_op(name: &str) -> ParseResult<AtomicOp> {
5617        match name {
5618            "load" => Ok(AtomicOp::Load),
5619            "store" => Ok(AtomicOp::Store),
5620            "swap" => Ok(AtomicOp::Swap),
5621            "compare_exchange" => Ok(AtomicOp::CompareExchange),
5622            "compare_exchange_weak" => Ok(AtomicOp::CompareExchangeWeak),
5623            "fetch_add" => Ok(AtomicOp::FetchAdd),
5624            "fetch_sub" => Ok(AtomicOp::FetchSub),
5625            "fetch_and" => Ok(AtomicOp::FetchAnd),
5626            "fetch_or" => Ok(AtomicOp::FetchOr),
5627            "fetch_xor" => Ok(AtomicOp::FetchXor),
5628            "fetch_min" => Ok(AtomicOp::FetchMin),
5629            "fetch_max" => Ok(AtomicOp::FetchMax),
5630            _ => Err(ParseError::Custom(format!(
5631                "unknown atomic operation: {}",
5632                name
5633            ))),
5634        }
5635    }
5636
5637    fn parse_memory_ordering(&mut self) -> ParseResult<MemoryOrdering> {
5638        match self.current_token() {
5639            Some(Token::Ident(name)) => {
5640                let ordering =
5641                    match name.as_str() {
5642                        "Relaxed" => MemoryOrdering::Relaxed,
5643                        "Acquire" => MemoryOrdering::Acquire,
5644                        "Release" => MemoryOrdering::Release,
5645                        "AcqRel" => MemoryOrdering::AcqRel,
5646                        "SeqCst" => MemoryOrdering::SeqCst,
5647                        _ => return Err(ParseError::Custom(
5648                            "expected memory ordering (Relaxed, Acquire, Release, AcqRel, SeqCst)"
5649                                .to_string(),
5650                        )),
5651                    };
5652                self.advance();
5653                Ok(ordering)
5654            }
5655            _ => Err(ParseError::Custom("expected memory ordering".to_string())),
5656        }
5657    }
5658
5659    /// Check if the token after `|` looks like a pipe target (function, closure, morpheme)
5660    /// rather than a bitwise OR operand (literal, parenthesized expression)
5661    fn is_pipe_target_ahead(&mut self) -> bool {
5662        // Peek at the token after the pipe (current token is |)
5663        if let Some(next) = self.peek_next().cloned() {
5664            match &next {
5665                // These indicate a pipe target (function call, closure, morpheme)
5666                Token::Ident(_) => true,
5667                Token::SelfLower | Token::Xi => true,  // this/ξ
5668                Token::SelfUpper => true,  // This
5669                // Morpheme operators (τ, φ, σ, ρ, Π, Σ, etc.)
5670                Token::Tau
5671                | Token::Phi
5672                | Token::Sigma
5673                | Token::Rho
5674                | Token::Lambda
5675                | Token::Delta
5676                | Token::Mu
5677                | Token::Chi
5678                | Token::GradeUp
5679                | Token::GradeDown
5680                | Token::Rotate
5681                | Token::Iota
5682                | Token::ForAll
5683                | Token::Exists
5684                | Token::Pi
5685                | Token::Hourglass => true,
5686                // Closure syntax |x| or || (lookahead for closure parameter list)
5687                Token::Pipe => true,
5688                Token::OrOr => true,    // Empty closure ||
5689                Token::LogicOr => true, // Empty closure ∨
5690                // Move closure
5691                Token::Move => true,
5692                // Block expression used as pipe target
5693                Token::LBrace => true,
5694                // These indicate bitwise OR (literals, grouping, conditionals)
5695                Token::IntLit(_)
5696                | Token::FloatLit(_)
5697                | Token::HexLit(_)
5698                | Token::BinaryLit(_)
5699                | Token::OctalLit(_) => false,
5700                Token::LParen => false, // Parenthesized expression = bitwise OR
5701                Token::True | Token::False => false,
5702                Token::If => false,    // if expression as bitwise OR operand
5703                Token::Match => false, // match expression as bitwise OR operand
5704                // Default to pipe for unknown cases
5705                _ => true,
5706            }
5707        } else {
5708            false // EOF after |, treat as bitwise OR (will error anyway)
5709        }
5710    }
5711
5712    /// Parse postfix operators that can follow a pipe chain (like ?)
5713    fn parse_postfix_after_pipe(&mut self, mut expr: Expr) -> ParseResult<Expr> {
5714        loop {
5715            match self.current_token() {
5716                Some(Token::Question) => {
5717                    self.advance();
5718                    expr = Expr::Try(Box::new(expr));
5719                }
5720                Some(Token::Dot) => {
5721                    self.advance();
5722                    let field = if let Some(Token::IntLit(idx)) = self.current_token() {
5723                        let idx = idx.clone();
5724                        let span = self.current_span();
5725                        self.advance();
5726                        Ident {
5727                            name: idx,
5728                            evidentiality: None,
5729                            affect: None,
5730                            span,
5731                        }
5732                    } else {
5733                        self.parse_ident()?
5734                    };
5735                    if self.check(&Token::ColonColon) {
5736                        self.advance();
5737                        self.expect(Token::Lt)?;
5738                        let type_args = self.parse_type_list()?;
5739                        self.expect_gt()?;
5740                        self.expect(Token::LParen)?;
5741                        let args = self.parse_expr_list()?;
5742                        self.expect(Token::RParen)?;
5743                        expr = Expr::MethodCall {
5744                            receiver: Box::new(expr),
5745                            method: field,
5746                            type_args: Some(type_args),
5747                            args,
5748                        };
5749                    } else if self.check(&Token::LParen) {
5750                        self.advance();
5751                        let args = self.parse_expr_list()?;
5752                        self.expect(Token::RParen)?;
5753                        expr = Expr::MethodCall {
5754                            receiver: Box::new(expr),
5755                            method: field,
5756                            type_args: None,
5757                            args,
5758                        };
5759                    } else {
5760                        expr = Expr::Field {
5761                            expr: Box::new(expr),
5762                            field,
5763                        };
5764                    }
5765                }
5766                _ => break,
5767            }
5768        }
5769        Ok(expr)
5770    }
5771
5772    /// Parse a pipe chain: `expr|op1|op2|op3`
5773    fn parse_pipe_chain(&mut self, initial: Expr) -> ParseResult<Expr> {
5774        let mut operations = Vec::new();
5775
5776        while self.consume_if(&Token::Pipe) {
5777            let op = self.parse_pipe_op()?;
5778            operations.push(op);
5779        }
5780
5781        Ok(Expr::Pipe {
5782            expr: Box::new(initial),
5783            operations,
5784        })
5785    }
5786
5787    fn parse_pipe_op(&mut self) -> ParseResult<PipeOp> {
5788        match self.current_token() {
5789            Some(Token::Tau) => {
5790                self.advance();
5791                self.expect(Token::LBrace)?;
5792                self.skip_comments();
5793                // Check for closure pattern: τ{x => expr} or τ{(a, b) => expr}
5794                let body = if self.looks_like_morpheme_closure() {
5795                    self.parse_morpheme_closure()?
5796                } else {
5797                    self.parse_expr()?
5798                };
5799                self.expect(Token::RBrace)?;
5800                Ok(PipeOp::Transform(Box::new(body)))
5801            }
5802            Some(Token::Phi) => {
5803                self.advance();
5804                self.expect(Token::LBrace)?;
5805                self.skip_comments();
5806                // Check for closure pattern: φ{x => expr} or φ{(a, b) => expr}
5807                let body = if self.looks_like_morpheme_closure() {
5808                    self.parse_morpheme_closure()?
5809                } else {
5810                    self.parse_expr()?
5811                };
5812                self.expect(Token::RBrace)?;
5813                Ok(PipeOp::Filter(Box::new(body)))
5814            }
5815            Some(Token::Sigma) => {
5816                // Σ can be either sort morpheme OR a function call like Σ(dim: -1)
5817                if self.peek_next() == Some(&Token::LParen) {
5818                    // Parse Σ as a function call: Σ(args)
5819                    let name = Ident {
5820                        name: "Σ".to_string(),
5821                        evidentiality: None,
5822                        affect: None,
5823                        span: self.current_span(),
5824                    };
5825                    self.advance(); // consume Σ
5826                    self.advance(); // consume (
5827                    let args = self.parse_expr_list()?;
5828                    self.expect(Token::RParen)?;
5829                    Ok(PipeOp::Call(Box::new(Expr::Call {
5830                        func: Box::new(Expr::Path(TypePath {
5831                            segments: vec![PathSegment {
5832                                ident: name,
5833                                generics: None,
5834                            }],
5835                        })),
5836                        args,
5837                    })))
5838                } else {
5839                    self.advance();
5840                    let field = if self.consume_if(&Token::Dot) {
5841                        Some(self.parse_ident()?)
5842                    } else {
5843                        None
5844                    };
5845                    Ok(PipeOp::Sort(field))
5846                }
5847            }
5848            Some(Token::Rho) => {
5849                self.advance();
5850                // Check for reduction variants: ρ+, ρ*, ρ++, ρ&, ρ|, ρ_sum, ρ_prod, ρ_min, ρ_max, ρ_cat, ρ_all, ρ_any
5851                match self.current_token() {
5852                    Some(Token::Plus) => {
5853                        self.advance();
5854                        Ok(PipeOp::ReduceSum)
5855                    }
5856                    Some(Token::Star) => {
5857                        self.advance();
5858                        Ok(PipeOp::ReduceProd)
5859                    }
5860                    Some(Token::PlusPlus) => {
5861                        self.advance();
5862                        Ok(PipeOp::ReduceConcat)
5863                    }
5864                    Some(Token::Amp) => {
5865                        self.advance();
5866                        Ok(PipeOp::ReduceAll)
5867                    }
5868                    Some(Token::Pipe) => {
5869                        self.advance();
5870                        Ok(PipeOp::ReduceAny)
5871                    }
5872                    Some(Token::Underscore) => {
5873                        self.advance();
5874                        // Parse the variant name: _sum, _prod, _min, _max, _cat, _all, _any
5875                        if let Some(Token::Ident(name)) = self.current_token().cloned() {
5876                            self.advance();
5877                            match name.as_str() {
5878                                "sum" => Ok(PipeOp::ReduceSum),
5879                                "prod" | "product" => Ok(PipeOp::ReduceProd),
5880                                "min" => Ok(PipeOp::ReduceMin),
5881                                "max" => Ok(PipeOp::ReduceMax),
5882                                "cat" | "concat" => Ok(PipeOp::ReduceConcat),
5883                                "all" => Ok(PipeOp::ReduceAll),
5884                                "any" => Ok(PipeOp::ReduceAny),
5885                                _ => Err(ParseError::Custom(format!(
5886                                    "unknown reduction variant: ρ_{}",
5887                                    name
5888                                ))),
5889                            }
5890                        } else {
5891                            Err(ParseError::Custom(
5892                                "expected reduction variant name after ρ_".to_string(),
5893                            ))
5894                        }
5895                    }
5896                    Some(Token::LBrace) => {
5897                        // General reduce with closure: ρ{(acc, x) => ...}
5898                        self.advance();
5899                        self.skip_comments();
5900                        // Check for closure pattern: ρ{x => expr} or ρ{(a, b) => expr}
5901                        let body = if self.looks_like_morpheme_closure() {
5902                            self.parse_morpheme_closure()?
5903                        } else {
5904                            self.parse_expr()?
5905                        };
5906                        self.expect(Token::RBrace)?;
5907                        Ok(PipeOp::Reduce(Box::new(body)))
5908                    }
5909                    _ => Err(ParseError::Custom(
5910                        "expected reduction variant (+, *, ++, &, |, _name) or {body} after ρ"
5911                            .to_string(),
5912                    )),
5913                }
5914            }
5915            // Product reduction: Π - multiply all elements (shorthand for ρ*)
5916            Some(Token::Pi) => {
5917                self.advance();
5918                Ok(PipeOp::ReduceProd)
5919            }
5920            // New access morphemes
5921            Some(Token::Alpha) => {
5922                self.advance();
5923                Ok(PipeOp::First)
5924            }
5925            Some(Token::Omega) => {
5926                self.advance();
5927                Ok(PipeOp::Last)
5928            }
5929            Some(Token::Mu) => {
5930                // μ can be either the "middle" morpheme OR a function call like μ(axis: -1)
5931                // If followed by (, it's a function call - parse as normal expression
5932                if self.peek_next() == Some(&Token::LParen) {
5933                    // Parse μ as a function call: μ(args) - treat as expression piped call
5934                    let name = Ident {
5935                        name: "μ".to_string(),
5936                        evidentiality: None,
5937                        affect: None,
5938                        span: self.current_span(),
5939                    };
5940                    self.advance(); // consume μ
5941                    self.advance(); // consume (
5942                    let args = self.parse_expr_list()?;
5943                    self.expect(Token::RParen)?;
5944                    // Create a call expression and return as PipeOp::Call
5945                    Ok(PipeOp::Call(Box::new(Expr::Call {
5946                        func: Box::new(Expr::Path(TypePath {
5947                            segments: vec![PathSegment {
5948                                ident: name,
5949                                generics: None,
5950                            }],
5951                        })),
5952                        args,
5953                    })))
5954                } else {
5955                    self.advance();
5956                    Ok(PipeOp::Middle)
5957                }
5958            }
5959            Some(Token::Chi) => {
5960                self.advance();
5961                Ok(PipeOp::Choice)
5962            }
5963            Some(Token::Nu) => {
5964                self.advance();
5965                // ν can take an optional index: ν{2}
5966                if self.check(&Token::LBrace) {
5967                    self.advance();
5968                    let index = self.parse_expr()?;
5969                    self.expect(Token::RBrace)?;
5970                    Ok(PipeOp::Nth(Box::new(index)))
5971                } else {
5972                    // Default to first element if no index given
5973                    Ok(PipeOp::Nth(Box::new(Expr::Literal(Literal::Int {
5974                        value: "0".to_string(),
5975                        base: NumBase::Decimal,
5976                        suffix: None,
5977                    }))))
5978                }
5979            }
5980            Some(Token::Xi) => {
5981                self.advance();
5982                Ok(PipeOp::Next)
5983            }
5984            // Parallel morpheme: ∥τ{f} or parallel τ{f} - wraps another operation
5985            Some(Token::Parallel) => {
5986                self.advance();
5987                // Parse the inner operation to parallelize
5988                let inner_op = self.parse_pipe_op()?;
5989                Ok(PipeOp::Parallel(Box::new(inner_op)))
5990            }
5991            // GPU compute morpheme: ⊛τ{f} or gpu τ{f} - execute on GPU
5992            Some(Token::Gpu) => {
5993                self.advance();
5994                // Parse the inner operation to run on GPU
5995                let inner_op = self.parse_pipe_op()?;
5996                Ok(PipeOp::Gpu(Box::new(inner_op)))
5997            }
5998            Some(Token::Await) => {
5999                self.advance();
6000                Ok(PipeOp::Await)
6001            }
6002            Some(Token::Hourglass) => {
6003                self.advance();
6004                Ok(PipeOp::Await)
6005            }
6006            Some(Token::MiddleDot) => {
6007                self.advance();
6008                let mut prefix = Vec::new();
6009                prefix.push(self.parse_ident()?);
6010
6011                while self.consume_if(&Token::MiddleDot) {
6012                    if self.check(&Token::LBrace) {
6013                        break;
6014                    }
6015                    prefix.push(self.parse_ident()?);
6016                }
6017
6018                let body = if self.check(&Token::LBrace) {
6019                    self.advance();
6020                    let expr = self.parse_expr()?;
6021                    self.expect(Token::RBrace)?;
6022                    Some(Box::new(expr))
6023                } else {
6024                    None
6025                };
6026
6027                Ok(PipeOp::Named { prefix, body })
6028            }
6029            // Match morpheme: |match{ Pattern => expr, ... }
6030            Some(Token::Match) => {
6031                self.advance();
6032                self.expect(Token::LBrace)?;
6033                let mut arms = Vec::new();
6034                while !self.check(&Token::RBrace) && !self.is_eof() {
6035                    // Use parse_or_pattern to support "pat1 | pat2 => expr" arms
6036                    let pattern = self.parse_or_pattern()?;
6037                    let guard = if self.consume_if(&Token::If) {
6038                        Some(self.parse_condition()?)
6039                    } else {
6040                        None
6041                    };
6042                    self.expect(Token::FatArrow)?;
6043                    let body = self.parse_expr()?;
6044                    arms.push(MatchArm {
6045                        pattern,
6046                        guard,
6047                        body,
6048                    });
6049                    // Comma is optional after block bodies, just like in regular match
6050                    self.consume_if(&Token::Comma);
6051                }
6052                self.expect(Token::RBrace)?;
6053                Ok(PipeOp::Match(arms))
6054            }
6055            // Trust boundary / unwrap: |‽ or |‽{mapper}
6056            // Uses interrobang (‽) to signal trust boundary crossing
6057            Some(Token::Interrobang) => {
6058                self.advance();
6059                let mapper = if self.check(&Token::LBrace) {
6060                    self.advance();
6061                    let expr = self.parse_expr()?;
6062                    self.expect(Token::RBrace)?;
6063                    Some(Box::new(expr))
6064                } else {
6065                    None
6066                };
6067                Ok(PipeOp::TryMap(mapper))
6068            }
6069            // Handle this.field as a pipe call: |this.layer or |ξ.layer becomes Call(self.layer)
6070            Some(Token::SelfLower) | Some(Token::SelfUpper) | Some(Token::Xi) => {
6071                // Parse self and any field accesses/method calls following it
6072                let expr = self.parse_postfix_expr()?;
6073                Ok(PipeOp::Call(Box::new(expr)))
6074            }
6075            // Gradient/nabla operator: |∇ - backpropagate gradients
6076            Some(Token::Nabla) => {
6077                self.advance();
6078                // ∇ as a simple gradient pipe - creates gradients from tensor
6079                Ok(PipeOp::Method {
6080                    name: Ident {
6081                        name: "∇".to_string(),
6082                        evidentiality: None,
6083                        affect: None,
6084                        span: self.current_span(),
6085                    },
6086                    type_args: None,
6087                    args: vec![],
6088                })
6089            }
6090            Some(Token::Ident(_)) => {
6091                let name = self.parse_ident()?;
6092
6093                // Special handling for evidence promotion operations BEFORE macro check
6094                // |validate!(predicate) - validate and promote to Known (paren-delimited only)
6095                // |validate?{predicate} - validate and promote to Uncertain
6096                // |validate~{predicate} - validate and keep as Reported
6097                // |assume!("reason") - assume evidence level
6098                // NOTE: validate!{...} with braces is treated as a macro invocation, not special validate
6099                if name.name == "validate" || name.name == "assume" {
6100                    // Check for evidentiality marker followed by { or (
6101                    // For !, only treat as special validate if followed by ( not {
6102                    // This allows validate!{struct: fields} to be parsed as a macro
6103                    let (has_marker, target_evidence) = if self.check(&Token::Bang) {
6104                        let peek = self.peek_next();
6105                        if matches!(peek, Some(Token::LParen)) {
6106                            // validate!(predicate) - special handling
6107                            self.advance(); // consume !
6108                            (true, Evidentiality::Known)
6109                        } else {
6110                            // validate!{...} or validate![...] - let macro handling take over
6111                            (false, Evidentiality::Known)
6112                        }
6113                    } else if self.check(&Token::Question) {
6114                        let peek = self.peek_next();
6115                        if matches!(peek, Some(Token::LBrace) | Some(Token::LParen)) {
6116                            self.advance(); // consume ?
6117                            (true, Evidentiality::Uncertain)
6118                        } else {
6119                            (false, Evidentiality::Known)
6120                        }
6121                    } else if self.check(&Token::Tilde) {
6122                        let peek = self.peek_next();
6123                        if matches!(peek, Some(Token::LBrace) | Some(Token::LParen)) {
6124                            self.advance(); // consume ~
6125                            (true, Evidentiality::Reported)
6126                        } else {
6127                            (false, Evidentiality::Known)
6128                        }
6129                    } else {
6130                        (false, name.evidentiality.unwrap_or(Evidentiality::Known))
6131                    };
6132
6133                    // Check for args - either (args) or {closure}
6134                    if has_marker || self.check(&Token::LParen) || self.check(&Token::LBrace) {
6135                        let args = if self.check(&Token::LParen) {
6136                            self.advance();
6137                            let args = self.parse_expr_list()?;
6138                            self.expect(Token::RParen)?;
6139                            args
6140                        } else if self.check(&Token::LBrace) {
6141                            self.advance();
6142                            self.skip_comments();
6143                            let body = if self.looks_like_morpheme_closure() {
6144                                self.parse_morpheme_closure()?
6145                            } else {
6146                                self.parse_expr()?
6147                            };
6148                            self.expect(Token::RBrace)?;
6149                            vec![body]
6150                        } else {
6151                            vec![]
6152                        };
6153
6154                        if name.name == "validate" {
6155                            if args.is_empty() {
6156                                return Err(ParseError::Custom(
6157                                    "validate requires a predicate".to_string(),
6158                                ));
6159                            }
6160                            return Ok(PipeOp::Validate {
6161                                predicate: Box::new(args.into_iter().next().unwrap()),
6162                                target_evidence,
6163                            });
6164                        } else {
6165                            // assume
6166                            let reason = args.into_iter().next().map(Box::new);
6167                            return Ok(PipeOp::Assume {
6168                                reason,
6169                                target_evidence,
6170                            });
6171                        }
6172                    }
6173                }
6174
6175                // Check for macro invocation: |macro_name!{ ... } or |macro_name!(...)
6176                if self.check(&Token::Bang) {
6177                    let peek = self.peek_next();
6178                    if matches!(
6179                        peek,
6180                        Some(Token::LBrace) | Some(Token::LParen) | Some(Token::LBracket)
6181                    ) {
6182                        self.advance(); // consume !
6183                        let tokens = self.parse_macro_tokens()?;
6184                        let path = TypePath {
6185                            segments: vec![PathSegment {
6186                                ident: name,
6187                                generics: None,
6188                            }],
6189                        };
6190                        return Ok(PipeOp::Call(Box::new(Expr::Macro { path, tokens })));
6191                    }
6192                }
6193
6194                // Check for path continuation or turbofish syntax:
6195                // |Tensor::from_slice - path to associated function
6196                // |collect::<String>() or |collect·<String>() - turbofish generics
6197                let mut path_segments = vec![PathSegment {
6198                    ident: name.clone(),
6199                    generics: None,
6200                }];
6201                let type_args = loop {
6202                    if self.check(&Token::ColonColon) || self.check(&Token::MiddleDot) {
6203                        let is_middledot = self.check(&Token::MiddleDot);
6204                        self.advance(); // consume :: or ·
6205                        if self.check(&Token::Lt) {
6206                            // Turbofish: ::<Type> or ·<Type>
6207                            self.advance(); // consume <
6208                            let types = self.parse_type_list()?;
6209                            self.expect_gt()?;
6210                            break Some(types);
6211                        } else if let Some(Token::Ident(_)) = self.current_token() {
6212                            // Path continuation: ::segment or ·segment
6213                            let segment = self.parse_ident()?;
6214                            path_segments.push(PathSegment {
6215                                ident: segment,
6216                                generics: None,
6217                            });
6218                            // Continue to check for more segments or turbofish
6219                        } else {
6220                            let sep = if is_middledot { "·" } else { "::" };
6221                            return Err(ParseError::Custom(format!(
6222                                "expected identifier or '<' after '{}'",
6223                                sep
6224                            )));
6225                        }
6226                    } else {
6227                        break None;
6228                    }
6229                };
6230
6231                // If we have a multi-segment path, convert to a path call
6232                let name = if path_segments.len() > 1 {
6233                    // Build a Call expression with the full path
6234                    let path = TypePath {
6235                        segments: path_segments,
6236                    };
6237                    let args = if self.check(&Token::LParen) {
6238                        self.advance();
6239                        let args = self.parse_expr_list()?;
6240                        self.expect(Token::RParen)?;
6241                        args
6242                    } else {
6243                        vec![]
6244                    };
6245                    return Ok(PipeOp::Call(Box::new(Expr::Call {
6246                        func: Box::new(Expr::Path(path)),
6247                        args,
6248                    })));
6249                } else {
6250                    name
6251                };
6252                let args = if self.check(&Token::LParen) {
6253                    self.advance();
6254                    let args = self.parse_expr_list()?;
6255                    self.expect(Token::RParen)?;
6256                    args
6257                } else if self.check(&Token::LBrace) && !self.in_condition {
6258                    // Handle closure-style argument: |method{closure}
6259                    // But NOT in condition context (for/while/if) where { is the control block
6260                    self.advance();
6261                    self.skip_comments();
6262                    let body = if self.looks_like_morpheme_closure() {
6263                        self.parse_morpheme_closure()?
6264                    } else {
6265                        self.parse_expr()?
6266                    };
6267                    self.expect(Token::RBrace)?;
6268                    vec![body]
6269                } else {
6270                    vec![]
6271                };
6272
6273                // Special handling for evidence promotion operations
6274                if name.name == "validate" {
6275                    let target_evidence = name.evidentiality.unwrap_or(Evidentiality::Known);
6276                    if args.is_empty() {
6277                        return Err(ParseError::Custom(
6278                            "validate requires a predicate: |validate!{predicate}".to_string(),
6279                        ));
6280                    }
6281                    return Ok(PipeOp::Validate {
6282                        predicate: Box::new(args.into_iter().next().unwrap()),
6283                        target_evidence,
6284                    });
6285                }
6286                if name.name == "assume" {
6287                    let target_evidence = name.evidentiality.unwrap_or(Evidentiality::Known);
6288                    let reason = args.into_iter().next().map(Box::new);
6289                    return Ok(PipeOp::Assume {
6290                        reason,
6291                        target_evidence,
6292                    });
6293                }
6294
6295                Ok(PipeOp::Method {
6296                    name,
6297                    type_args,
6298                    args,
6299                })
6300            }
6301
6302            // ==========================================
6303            // Protocol Operations - Sigil-native networking
6304            // ==========================================
6305
6306            // Send: |send{data} or |⇒{data}
6307            Some(Token::Send) | Some(Token::ProtoSend) => {
6308                self.advance();
6309                self.expect(Token::LBrace)?;
6310                let data = self.parse_expr()?;
6311                self.expect(Token::RBrace)?;
6312                Ok(PipeOp::Send(Box::new(data)))
6313            }
6314
6315            // Recv: |recv or |⇐
6316            Some(Token::Recv) | Some(Token::ProtoRecv) => {
6317                self.advance();
6318                Ok(PipeOp::Recv)
6319            }
6320
6321            // Stream: |stream{handler} or |≋{handler}
6322            Some(Token::Stream) | Some(Token::ProtoStream) => {
6323                self.advance();
6324                self.expect(Token::LBrace)?;
6325                let handler = self.parse_expr()?;
6326                self.expect(Token::RBrace)?;
6327                Ok(PipeOp::Stream(Box::new(handler)))
6328            }
6329
6330            // Connect: |connect or |connect{config} or |⊸{config}
6331            Some(Token::Connect) | Some(Token::ProtoConnect) => {
6332                self.advance();
6333                let config = if self.check(&Token::LBrace) {
6334                    self.advance();
6335                    let expr = self.parse_expr()?;
6336                    self.expect(Token::RBrace)?;
6337                    Some(Box::new(expr))
6338                } else {
6339                    None
6340                };
6341                Ok(PipeOp::Connect(config))
6342            }
6343
6344            // Close: |close or |⊗
6345            Some(Token::Close) | Some(Token::Tensor) => {
6346                self.advance();
6347                Ok(PipeOp::Close)
6348            }
6349
6350            // Timeout: |timeout{ms} or |⏱{ms}
6351            Some(Token::Timeout) | Some(Token::ProtoTimeout) => {
6352                self.advance();
6353                self.expect(Token::LBrace)?;
6354                let ms = self.parse_expr()?;
6355                self.expect(Token::RBrace)?;
6356                Ok(PipeOp::Timeout(Box::new(ms)))
6357            }
6358
6359            // Retry: |retry{count} or |retry{count, strategy}
6360            Some(Token::Retry) => {
6361                self.advance();
6362                self.expect(Token::LBrace)?;
6363                let count = self.parse_expr()?;
6364                let strategy = if self.consume_if(&Token::Comma) {
6365                    Some(Box::new(self.parse_expr()?))
6366                } else {
6367                    None
6368                };
6369                self.expect(Token::RBrace)?;
6370                Ok(PipeOp::Retry {
6371                    count: Box::new(count),
6372                    strategy,
6373                })
6374            }
6375
6376            // Header: |header{name, value}
6377            Some(Token::Header) => {
6378                self.advance();
6379                self.expect(Token::LBrace)?;
6380                let name = self.parse_expr()?;
6381                self.expect(Token::Comma)?;
6382                let value = self.parse_expr()?;
6383                self.expect(Token::RBrace)?;
6384                Ok(PipeOp::Header {
6385                    name: Box::new(name),
6386                    value: Box::new(value),
6387                })
6388            }
6389
6390            // Body: |body{data}
6391            Some(Token::Body) => {
6392                self.advance();
6393                self.expect(Token::LBrace)?;
6394                let data = self.parse_expr()?;
6395                self.expect(Token::RBrace)?;
6396                Ok(PipeOp::Body(Box::new(data)))
6397            }
6398
6399            // ==========================================
6400            // Mathematical & APL-Inspired Operations
6401            // ==========================================
6402
6403            // All/ForAll: |∀{p} for predicate check, |∀ for universal reconstruction
6404            Some(Token::ForAll) => {
6405                self.advance();
6406                // Check if followed by brace - if so, it's All(predicate)
6407                // Otherwise, it's Universal (holographic reconstruction)
6408                if self.check(&Token::LBrace) {
6409                    self.advance(); // consume LBrace
6410                    let pred = self.parse_expr()?;
6411                    self.expect(Token::RBrace)?;
6412                    Ok(PipeOp::All(Box::new(pred)))
6413                } else {
6414                    // No brace - universal reconstruction (sum/merge)
6415                    Ok(PipeOp::Universal)
6416                }
6417            }
6418
6419            // Possibility: |◊ or |◊method - extract approximate/speculative answer
6420            Some(Token::Lozenge) => {
6421                self.advance();
6422                // Check if followed by identifier (method call)
6423                if let Some(Token::Ident(_)) = self.current_token() {
6424                    let name = self.parse_ident()?;
6425                    // Check for arguments
6426                    let args = if self.check(&Token::LParen) {
6427                        self.advance();
6428                        let args = self.parse_expr_list()?;
6429                        self.expect(Token::RParen)?;
6430                        args
6431                    } else {
6432                        vec![]
6433                    };
6434                    Ok(PipeOp::PossibilityMethod { name, args })
6435                } else {
6436                    Ok(PipeOp::Possibility)
6437                }
6438            }
6439
6440            // Necessity: |□ or |□method - verify and promote to certain
6441            Some(Token::BoxSymbol) => {
6442                self.advance();
6443                // Check if followed by identifier (method call)
6444                if let Some(Token::Ident(_)) = self.current_token() {
6445                    let name = self.parse_ident()?;
6446                    // Check for arguments
6447                    let args = if self.check(&Token::LParen) {
6448                        self.advance();
6449                        let args = self.parse_expr_list()?;
6450                        self.expect(Token::RParen)?;
6451                        args
6452                    } else {
6453                        vec![]
6454                    };
6455                    Ok(PipeOp::NecessityMethod { name, args })
6456                } else {
6457                    Ok(PipeOp::Necessity)
6458                }
6459            }
6460
6461            // Any/Exists: |∃{p} or |any{p}
6462            Some(Token::Exists) => {
6463                self.advance();
6464                self.expect(Token::LBrace)?;
6465                let pred = self.parse_expr()?;
6466                self.expect(Token::RBrace)?;
6467                Ok(PipeOp::Any(Box::new(pred)))
6468            }
6469
6470            // Compose: |∘{f} or |compose{f}
6471            Some(Token::Compose) => {
6472                self.advance();
6473                self.expect(Token::LBrace)?;
6474                let f = self.parse_expr()?;
6475                self.expect(Token::RBrace)?;
6476                Ok(PipeOp::Compose(Box::new(f)))
6477            }
6478
6479            // Zip/Join: |⋈{other} or |zip{other}
6480            Some(Token::Bowtie) => {
6481                self.advance();
6482                self.expect(Token::LBrace)?;
6483                let other = self.parse_expr()?;
6484                self.expect(Token::RBrace)?;
6485                Ok(PipeOp::Zip(Box::new(other)))
6486            }
6487
6488            // Scan/Integral: |∫{f} or |scan{f}
6489            Some(Token::Integral) => {
6490                self.advance();
6491                self.expect(Token::LBrace)?;
6492                let f = self.parse_expr()?;
6493                self.expect(Token::RBrace)?;
6494                Ok(PipeOp::Scan(Box::new(f)))
6495            }
6496
6497            // Diff/Derivative: |∂ or |diff
6498            Some(Token::Partial) => {
6499                self.advance();
6500                Ok(PipeOp::Diff)
6501            }
6502
6503            // Gradient: |∇{var} or |grad{var}
6504            Some(Token::Nabla) => {
6505                self.advance();
6506                self.expect(Token::LBrace)?;
6507                let var = self.parse_expr()?;
6508                self.expect(Token::RBrace)?;
6509                Ok(PipeOp::Gradient(Box::new(var)))
6510            }
6511
6512            // Sort Ascending: |⍋ or |sort_asc
6513            Some(Token::GradeUp) => {
6514                self.advance();
6515                Ok(PipeOp::SortAsc)
6516            }
6517
6518            // Sort Descending: |⍒ or |sort_desc
6519            Some(Token::GradeDown) => {
6520                self.advance();
6521                Ok(PipeOp::SortDesc)
6522            }
6523
6524            // Reverse: |⌽ or |rev
6525            Some(Token::Rotate) => {
6526                self.advance();
6527                Ok(PipeOp::Reverse)
6528            }
6529
6530            // Cycle: |↻{n} or |cycle{n}
6531            Some(Token::CycleArrow) => {
6532                self.advance();
6533                self.expect(Token::LBrace)?;
6534                let n = self.parse_expr()?;
6535                self.expect(Token::RBrace)?;
6536                Ok(PipeOp::Cycle(Box::new(n)))
6537            }
6538
6539            // Windows: |⌺{n} or |windows{n}
6540            Some(Token::QuadDiamond) => {
6541                self.advance();
6542                self.expect(Token::LBrace)?;
6543                let n = self.parse_expr()?;
6544                self.expect(Token::RBrace)?;
6545                Ok(PipeOp::Windows(Box::new(n)))
6546            }
6547
6548            // Chunks: |⊞{n} or |chunks{n}
6549            Some(Token::SquaredPlus) => {
6550                self.advance();
6551                self.expect(Token::LBrace)?;
6552                let n = self.parse_expr()?;
6553                self.expect(Token::RBrace)?;
6554                Ok(PipeOp::Chunks(Box::new(n)))
6555            }
6556
6557            // Flatten: |⋳ or |flatten
6558            Some(Token::ElementSmallVerticalBar) => {
6559                self.advance();
6560                Ok(PipeOp::Flatten)
6561            }
6562
6563            // Unique: |∪ or |unique
6564            Some(Token::Union) => {
6565                self.advance();
6566                Ok(PipeOp::Unique)
6567            }
6568
6569            // Enumerate: |⍳ or |enumerate
6570            Some(Token::Iota) => {
6571                self.advance();
6572                Ok(PipeOp::Enumerate)
6573            }
6574
6575            // Reference expression: |&self.field or |&expr
6576            Some(Token::Amp) => {
6577                // Parse as expression - the & starts a reference expression
6578                let expr = self.parse_prefix_expr()?;
6579                Ok(PipeOp::Call(Box::new(expr)))
6580            }
6581
6582            // Direct closure: |{x => body} or |{|args| body}
6583            // This is a bare pipe-to-closure without morpheme operator
6584            Some(Token::LBrace) => {
6585                self.advance();
6586                self.skip_comments();
6587                let body = if self.looks_like_morpheme_closure() {
6588                    self.parse_morpheme_closure()?
6589                } else {
6590                    self.parse_expr()?
6591                };
6592                self.expect(Token::RBrace)?;
6593                Ok(PipeOp::Call(Box::new(body)))
6594            }
6595
6596            Some(token) => Err(ParseError::UnexpectedToken {
6597                expected: "pipe operation".to_string(),
6598                found: token.clone(),
6599                span: self.current_span(),
6600            }),
6601            None => Err(ParseError::UnexpectedEof),
6602        }
6603    }
6604
6605    /// Check if current position looks like a morpheme closure: ident => or (pattern) =>
6606    fn looks_like_morpheme_closure(&mut self) -> bool {
6607        // Simple closure: x => or _ => (may have evidentiality: x~ => or x◊ =>)
6608        if matches!(
6609            self.current_token(),
6610            Some(Token::Ident(_)) | Some(Token::Underscore)
6611        ) {
6612            // Check next token - could be => directly or evidentiality marker first
6613            match self.peek_next() {
6614                Some(Token::FatArrow) => return true,
6615                // Evidentiality markers: ident~ =>, ident◊ =>, ident‽ =>
6616                Some(Token::Tilde) | Some(Token::Lozenge) | Some(Token::Interrobang) => {
6617                    // Check if => follows the evidentiality marker
6618                    if matches!(self.peek_n(1), Some(Token::FatArrow)) {
6619                        return true;
6620                    }
6621                }
6622                _ => {}
6623            }
6624        }
6625        // Reference pattern closure: &x => or &mut x =>
6626        if matches!(self.current_token(), Some(Token::Amp)) {
6627            // Look ahead: &x => or &mut x =>
6628            if matches!(self.peek_next(), Some(Token::Ident(_))) {
6629                // Check if token after ident is => (possibly with evidentiality in between)
6630                match self.peek_n(1) {
6631                    Some(Token::FatArrow) => return true,
6632                    Some(Token::Tilde) | Some(Token::Lozenge) | Some(Token::Interrobang) => {
6633                        if matches!(self.peek_n(2), Some(Token::FatArrow)) {
6634                            return true;
6635                        }
6636                    }
6637                    _ => {}
6638                }
6639            } else if matches!(self.peek_next(), Some(Token::Mut) | Some(Token::Delta)) {
6640                // &mut x => or &Δ x =>
6641                return true;
6642            }
6643        }
6644        // Tuple pattern closure: (a, b) =>
6645        // We need to look ahead to find ) followed by =>
6646        if matches!(self.current_token(), Some(Token::LParen)) {
6647            // Look ahead to find closing ) and check for =>
6648            // For simplicity, we'll assume if it starts with ( and contains =>, it's a closure
6649            return true;
6650        }
6651        false
6652    }
6653
6654    /// Parse a morpheme closure: x => expr or (a, b) => expr or &x => expr
6655    /// For morphemes, (a, b) is a SINGLE tuple parameter pattern, not multiple parameters
6656    fn parse_morpheme_closure(&mut self) -> ParseResult<Expr> {
6657        let pattern = if self.check(&Token::LParen) {
6658            // Tuple pattern: (a, b) => expr - treated as single parameter with tuple pattern
6659            self.advance();
6660            let mut patterns = Vec::new();
6661            while !self.check(&Token::RParen) {
6662                let pat = self.parse_pattern()?;
6663                patterns.push(pat);
6664                if !self.consume_if(&Token::Comma) {
6665                    break;
6666                }
6667            }
6668            self.expect(Token::RParen)?;
6669            // Create a single tuple pattern
6670            Pattern::Tuple(patterns)
6671        } else if self.check(&Token::Amp) {
6672            // Reference pattern: &x => expr or &mut x => expr
6673            self.parse_pattern()?
6674        } else if self.check(&Token::Underscore) {
6675            // Wildcard pattern: _ => expr
6676            self.advance();
6677            Pattern::Wildcard
6678        } else {
6679            // Simple pattern: x => expr
6680            let name = self.parse_ident()?;
6681            Pattern::Ident {
6682                mutable: false,
6683                name,
6684                evidentiality: None,
6685            }
6686        };
6687        // Accept either => or | as the arrow (for closure-style syntax)
6688        if !self.consume_if(&Token::FatArrow) {
6689            self.expect(Token::Pipe)?;
6690        }
6691        // Skip comments before body (e.g., // explanation after =>)
6692        self.skip_comments();
6693        // Parse body - can be a single expression or a block of statements
6694        // Multi-line closures have statements + final expression, e.g.:
6695        //   let x = ...;
6696        //   y = some_expr;
6697        //   let z = ...;
6698        //   result_expr
6699        // Or compact form: `expr; final_expr`
6700        let body = {
6701            // Multi-statement body - parse statements until closing brace
6702            let mut stmts = Vec::new();
6703            loop {
6704                self.skip_comments();
6705                if self.check(&Token::RBrace) {
6706                    break;
6707                }
6708                if self.check(&Token::Let) {
6709                    stmts.push(self.parse_let_stmt()?);
6710                } else if self.check(&Token::Return)
6711                    || self.check(&Token::Break) || self.check(&Token::Tensor)
6712                    || self.check(&Token::Continue) || self.check(&Token::CycleArrow)
6713                {
6714                    // Control flow - treat as final expression
6715                    break;
6716                } else {
6717                    // Expression (possibly with assignment) - check if statement or final expr
6718                    let expr = self.parse_expr()?;
6719                    // Skip comments after expression (before deciding if final)
6720                    self.skip_comments();
6721                    if self.consume_if(&Token::Semi) {
6722                        // Expression statement with semicolon
6723                        stmts.push(Stmt::Expr(expr));
6724                    } else if self.check(&Token::RBrace) {
6725                        // Final expression at end of block
6726                        if stmts.is_empty() {
6727                            // Single expression, no block needed
6728                            return Ok(Expr::Closure {
6729                                params: vec![ClosureParam { pattern, ty: None }],
6730                                return_type: None,
6731                                body: Box::new(expr),
6732                                is_move: false,
6733                            });
6734                        }
6735                        return Ok(Expr::Closure {
6736                            params: vec![ClosureParam { pattern, ty: None }],
6737                            return_type: None,
6738                            body: Box::new(Expr::Block(Block {
6739                                stmts,
6740                                expr: Some(Box::new(expr)),
6741                            })),
6742                            is_move: false,
6743                        });
6744                    } else {
6745                        // Continue without semicolon (statement with omitted semi)
6746                        // This handles: `expr\n let x = ...`
6747                        stmts.push(Stmt::Expr(expr));
6748                    }
6749                }
6750            }
6751            // No final expression
6752            Expr::Block(Block { stmts, expr: None })
6753        };
6754        Ok(Expr::Closure {
6755            params: vec![ClosureParam { pattern, ty: None }],
6756            return_type: None,
6757            body: Box::new(body),
6758            is_move: false,
6759        })
6760    }
6761
6762    fn parse_morpheme_kind(&mut self) -> ParseResult<MorphemeKind> {
6763        match self.current_token() {
6764            Some(Token::Tau) => {
6765                self.advance();
6766                Ok(MorphemeKind::Transform)
6767            }
6768            Some(Token::Phi) => {
6769                self.advance();
6770                Ok(MorphemeKind::Filter)
6771            }
6772            Some(Token::Sigma) => {
6773                self.advance();
6774                Ok(MorphemeKind::Sort)
6775            }
6776            Some(Token::Rho) => {
6777                self.advance();
6778                Ok(MorphemeKind::Reduce)
6779            }
6780            Some(Token::Lambda) => {
6781                self.advance();
6782                Ok(MorphemeKind::Lambda)
6783            }
6784            Some(Token::Pi) => {
6785                self.advance();
6786                Ok(MorphemeKind::Product)
6787            }
6788            _ => Err(ParseError::Custom("expected morpheme".to_string())),
6789        }
6790    }
6791
6792    fn parse_block_or_closure(&mut self) -> ParseResult<Expr> {
6793        self.expect(Token::LBrace)?;
6794        self.skip_comments();
6795
6796        // Try to detect closure pattern: `{x => ...}` using lookahead
6797        // We check if current is Ident and next is FatArrow without consuming tokens
6798        let is_simple_closure = matches!(self.current_token(), Some(Token::Ident(_)))
6799            && matches!(self.peek_next(), Some(Token::FatArrow));
6800
6801        if is_simple_closure {
6802            let name = self.parse_ident()?;
6803            self.expect(Token::FatArrow)?;
6804            self.skip_comments();
6805            let body = self.parse_expr()?;
6806            self.skip_comments();
6807            self.expect(Token::RBrace)?;
6808            return Ok(Expr::Closure {
6809                params: vec![ClosureParam {
6810                    pattern: Pattern::Ident {
6811                        mutable: false,
6812                        name,
6813                        evidentiality: None,
6814                    },
6815                    ty: None,
6816                }],
6817                return_type: None,
6818                body: Box::new(body),
6819                is_move: false,
6820            });
6821        }
6822
6823        // Parse as block
6824        let mut stmts = Vec::new();
6825        let mut final_expr = None;
6826
6827        while !self.check(&Token::RBrace) && !self.is_eof() {
6828            self.skip_comments();
6829            if self.check(&Token::RBrace) {
6830                break;
6831            }
6832
6833            // Handle statement-level attributes: #[cfg(...)] { ... } or #[attr] let x = ...
6834            if self.check(&Token::Hash) || self.check(&Token::At) {
6835                // Parse and collect attributes
6836                let mut attrs = Vec::new();
6837                while self.check(&Token::Hash) || self.check(&Token::At) {
6838                    attrs.push(self.parse_outer_attribute()?);
6839                    self.skip_comments();
6840                }
6841
6842                // After attributes, check what follows
6843                if self.is_item_start() {
6844                    // Item with attributes - parse as item
6845                    let item = self.parse_item()?;
6846                    stmts.push(Stmt::Item(Box::new(item.node)));
6847                } else if self.check(&Token::Let) {
6848                    // Let statement with attributes
6849                    stmts.push(self.parse_let_stmt()?);
6850                } else {
6851                    // Expression with attributes (like #[cfg(...)] { block })
6852                    let expr = self.parse_expr()?;
6853                    self.skip_comments();
6854                    if self.consume_if(&Token::Semi) {
6855                        stmts.push(Stmt::Semi(expr));
6856                    } else if self.check(&Token::RBrace) {
6857                        final_expr = Some(Box::new(expr));
6858                    } else {
6859                        stmts.push(Stmt::Expr(expr));
6860                    }
6861                }
6862            } else if self.is_item_start() {
6863                let item = self.parse_item()?;
6864                stmts.push(Stmt::Item(Box::new(item.node)));
6865            } else if self.check(&Token::Let) {
6866                stmts.push(self.parse_let_stmt()?);
6867            } else {
6868                let expr = self.parse_expr()?;
6869                self.skip_comments();
6870                if self.consume_if(&Token::Semi) {
6871                    stmts.push(Stmt::Semi(expr));
6872                } else if self.check(&Token::RBrace) {
6873                    final_expr = Some(Box::new(expr));
6874                } else {
6875                    stmts.push(Stmt::Expr(expr));
6876                }
6877            }
6878        }
6879
6880        self.expect(Token::RBrace)?;
6881
6882        Ok(Expr::Block(Block {
6883            stmts,
6884            expr: final_expr,
6885        }))
6886    }
6887
6888    pub(crate) fn parse_block(&mut self) -> ParseResult<Block> {
6889        match self.parse_block_or_closure()? {
6890            Expr::Block(block) => Ok(block),
6891            _ => Err(ParseError::Custom("expected block".to_string())),
6892        }
6893    }
6894
6895    fn parse_let_stmt(&mut self) -> ParseResult<Stmt> {
6896        self.expect(Token::Let)?;
6897        let pattern = self.parse_pattern()?;
6898        let ty = if self.consume_if(&Token::Colon) {
6899            Some(self.parse_type()?)
6900        } else {
6901            None
6902        };
6903        let init = if self.consume_if(&Token::Eq) {
6904            Some(self.parse_expr()?)
6905        } else {
6906            None
6907        };
6908
6909        // Check for let-else pattern: let PATTERN = EXPR else { ... }
6910        if self.consume_if(&Token::Else) {
6911            let else_branch = Box::new(Expr::Block(self.parse_block()?));
6912            // Optionally consume trailing semicolon (valid in Rust: `let ... else { ... };`)
6913            self.consume_if(&Token::Semi);
6914            Ok(Stmt::LetElse {
6915                pattern,
6916                ty,
6917                init: init.ok_or_else(|| {
6918                    ParseError::Custom("let-else requires initializer".to_string())
6919                })?,
6920                else_branch,
6921            })
6922        } else {
6923            // Semicolon is optional in Sigil's advanced syntax
6924            // Consume if present, or allow if next token can start a new statement
6925            if !self.consume_if(&Token::Semi) {
6926                if !self.can_start_stmt() && !self.check(&Token::RBrace) {
6927                    return Err(ParseError::UnexpectedToken {
6928                        expected: "`;` or new statement".to_string(),
6929                        found: self.current_token().cloned().unwrap_or(Token::Semi),
6930                        span: self.current_span(),
6931                    });
6932                }
6933            }
6934            Ok(Stmt::Let { pattern, ty, init })
6935        }
6936    }
6937
6938    fn parse_if_expr(&mut self) -> ParseResult<Expr> {
6939        self.expect(Token::If)?;
6940
6941        // Check for if let pattern = expr form
6942        let condition = if self.consume_if(&Token::Let) {
6943            let pattern = self.parse_or_pattern()?;
6944            self.expect(Token::Eq)?;
6945            let expr = self.parse_condition()?;
6946            Expr::Let {
6947                pattern,
6948                value: Box::new(expr),
6949            }
6950        } else {
6951            self.parse_condition()?
6952        };
6953
6954        let then_branch = self.parse_block()?;
6955        self.skip_comments(); // Skip comments before else
6956        let else_branch = if self.consume_if(&Token::Else) {
6957            if self.check(&Token::If) {
6958                Some(Box::new(self.parse_if_expr()?))
6959            } else {
6960                Some(Box::new(Expr::Block(self.parse_block()?)))
6961            }
6962        } else {
6963            None
6964        };
6965
6966        Ok(Expr::If {
6967            condition: Box::new(condition),
6968            then_branch,
6969            else_branch,
6970        })
6971    }
6972
6973    fn parse_match_expr(&mut self) -> ParseResult<Expr> {
6974        self.expect(Token::Match)?;
6975        // Use parse_condition to prevent { from being parsed as struct literal
6976        let expr = self.parse_condition()?;
6977        self.expect(Token::LBrace)?;
6978
6979        let mut arms = Vec::new();
6980        while !self.check(&Token::RBrace) && !self.is_eof() {
6981            // Skip comments and attributes before match arms: #[cfg(...)]
6982            loop {
6983                if matches!(
6984                    self.current_token(),
6985                    Some(Token::DocComment(_))
6986                        | Some(
6987                            Token::LineComment(_) | Token::TildeComment(_) | Token::BlockComment(_)
6988                        )
6989                ) {
6990                    self.advance();
6991                } else if self.check(&Token::Hash) {
6992                    // Skip attribute: #[...]
6993                    self.skip_attribute()?;
6994                } else {
6995                    break;
6996                }
6997            }
6998            if self.check(&Token::RBrace) {
6999                break;
7000            }
7001            let pattern = self.parse_or_pattern()?;
7002            let guard = if self.consume_if(&Token::If) {
7003                Some(self.parse_condition()?)
7004            } else {
7005                None
7006            };
7007            self.expect(Token::FatArrow)?;
7008            let body = self.parse_expr()?;
7009            arms.push(MatchArm {
7010                pattern,
7011                guard,
7012                body,
7013            });
7014            // In Rust/Sigil, commas are optional after block-bodied match arms
7015            // So we try to consume a comma, but don't break if absent
7016            self.consume_if(&Token::Comma);
7017            // Skip trailing comments after comma or block
7018            while matches!(
7019                self.current_token(),
7020                Some(Token::DocComment(_))
7021                    | Some(Token::LineComment(_) | Token::TildeComment(_) | Token::BlockComment(_))
7022            ) {
7023                self.advance();
7024            }
7025        }
7026
7027        self.expect(Token::RBrace)?;
7028
7029        Ok(Expr::Match {
7030            expr: Box::new(expr),
7031            arms,
7032        })
7033    }
7034
7035    // === Pattern parsing ===
7036
7037    /// Parse a pattern, handling or-patterns: pat1 | pat2 | pat3
7038    fn parse_or_pattern(&mut self) -> ParseResult<Pattern> {
7039        let first = self.parse_pattern()?;
7040
7041        // Check for | to form or-pattern
7042        if self.check(&Token::Pipe) {
7043            let mut patterns = vec![first];
7044            while self.consume_if(&Token::Pipe) {
7045                patterns.push(self.parse_pattern()?);
7046            }
7047            Ok(Pattern::Or(patterns))
7048        } else {
7049            Ok(first)
7050        }
7051    }
7052
7053    fn parse_pattern(&mut self) -> ParseResult<Pattern> {
7054        // Check for prefix evidentiality markers: ?pattern, !pattern, ~pattern, ◊pattern, ‽pattern
7055        let prefix_ev = match self.current_token() {
7056            Some(Token::Question) => {
7057                self.advance();
7058                Some(Evidentiality::Uncertain)
7059            }
7060            Some(Token::Bang) => {
7061                self.advance();
7062                Some(Evidentiality::Known)
7063            }
7064            Some(Token::Tilde) => {
7065                self.advance();
7066                Some(Evidentiality::Reported)
7067            }
7068            Some(Token::Lozenge) => {
7069                self.advance();
7070                Some(Evidentiality::Predicted)
7071            }
7072            Some(Token::Interrobang) => {
7073                self.advance();
7074                Some(Evidentiality::Paradox)
7075            }
7076            _ => None,
7077        };
7078
7079        // If we had a prefix evidentiality, parse the rest of the pattern
7080        // This handles patterns like `?Some(x)` or `?TypeExpr::Variant { .. }`
7081        if let Some(ev) = prefix_ev {
7082            // Parse the inner pattern and wrap it with evidentiality
7083            let inner_pattern = self.parse_pattern_base()?;
7084            return match inner_pattern {
7085                Pattern::Ident {
7086                    mutable,
7087                    name,
7088                    evidentiality: _,
7089                } => {
7090                    // Simple identifier pattern with evidentiality
7091                    Ok(Pattern::Ident {
7092                        mutable,
7093                        name,
7094                        evidentiality: Some(ev),
7095                    })
7096                }
7097                Pattern::Wildcard => {
7098                    // Convert ?_ to Pattern::Ident with name="_" and evidentiality
7099                    // This ensures the interpreter can distinguish ?_ from plain _
7100                    let span = self.current_span();
7101                    Ok(Pattern::Ident {
7102                        mutable: false,
7103                        name: Ident {
7104                            name: "_".to_string(),
7105                            evidentiality: None,
7106                            affect: None,
7107                            span,
7108                        },
7109                        evidentiality: Some(ev),
7110                    })
7111                }
7112                other => {
7113                    // For complex patterns like enum variants, wrap in an Evidential pattern
7114                    // Note: This might need adjustment based on AST capabilities
7115                    // For now, we'll add evidentiality to identifier-based patterns
7116                    // and pass through complex patterns as-is (the `?` means "if Some")
7117                    Ok(other)
7118                }
7119            };
7120        }
7121
7122        self.parse_pattern_base()
7123    }
7124
7125    /// Parse a pattern without considering prefix evidentiality markers
7126    fn parse_pattern_base(&mut self) -> ParseResult<Pattern> {
7127        match self.current_token().cloned() {
7128            Some(Token::Underscore) => {
7129                self.advance();
7130                Ok(Pattern::Wildcard)
7131            }
7132            Some(Token::DotDot) => {
7133                self.advance();
7134                Ok(Pattern::Rest)
7135            }
7136            Some(Token::Mut) | Some(Token::Delta) => {
7137                self.advance();
7138                // Handle `mut self` / `Δ ⊙` specially
7139                let name = if self.check_self() {
7140                    let span = self.current_span();
7141                    self.advance();
7142                    Ident {
7143                        name: "self".to_string(),
7144                        evidentiality: None,
7145                        affect: None,
7146                        span,
7147                    }
7148                } else {
7149                    self.parse_ident()?
7150                };
7151                let evidentiality = self.parse_evidentiality_opt();
7152                Ok(Pattern::Ident {
7153                    mutable: true,
7154                    name,
7155                    evidentiality,
7156                })
7157            }
7158            // Ref pattern: ref ident or ref mut ident (binds by reference)
7159            Some(Token::Ref) => {
7160                self.advance();
7161                let mutable = self.consume_if_mut();
7162                let name = self.parse_ident()?;
7163                let evidentiality = self.parse_evidentiality_opt();
7164                Ok(Pattern::RefBinding {
7165                    mutable,
7166                    name,
7167                    evidentiality,
7168                })
7169            }
7170            // Reference pattern: &pattern, &mut pattern, &'a pattern, &'a mut pattern
7171            Some(Token::Amp) => {
7172                self.advance();
7173                // Skip optional lifetime annotation in patterns (e.g., &'a self)
7174                if matches!(self.current_token(), Some(Token::Lifetime(_))) {
7175                    self.advance();
7176                }
7177                let mutable = self.consume_if_mut();
7178                let inner = self.parse_pattern()?;
7179                Ok(Pattern::Ref {
7180                    mutable,
7181                    pattern: Box::new(inner),
7182                })
7183            }
7184            // Double reference pattern: &&pattern (lexer tokenizes && as AndAnd)
7185            Some(Token::AndAnd) => {
7186                self.advance();
7187                let inner = self.parse_pattern()?;
7188                // Desugar &&x to &(&x)
7189                let inner_ref = Pattern::Ref {
7190                    mutable: false,
7191                    pattern: Box::new(inner),
7192                };
7193                Ok(Pattern::Ref {
7194                    mutable: false,
7195                    pattern: Box::new(inner_ref),
7196                })
7197            }
7198            Some(Token::LParen) => {
7199                self.advance();
7200                let mut patterns = Vec::new();
7201                while !self.check(&Token::RParen) {
7202                    patterns.push(self.parse_pattern()?);
7203                    if !self.consume_if(&Token::Comma) {
7204                        break;
7205                    }
7206                }
7207                self.expect(Token::RParen)?;
7208                // Check for postfix evidentiality on tuple pattern: (a, b)!
7209                let _ev = self.parse_evidentiality_opt();
7210                // Note: Pattern::Tuple doesn't have evidentiality field, so we just consume it
7211                // This allows the let statement to parse correctly
7212                Ok(Pattern::Tuple(patterns))
7213            }
7214            Some(Token::LBracket) => {
7215                self.advance();
7216                let mut patterns = Vec::new();
7217                while !self.check(&Token::RBracket) {
7218                    patterns.push(self.parse_pattern()?);
7219                    if !self.consume_if(&Token::Comma) {
7220                        break;
7221                    }
7222                }
7223                self.expect(Token::RBracket)?;
7224                Ok(Pattern::Slice(patterns))
7225            }
7226            Some(Token::IntLit(_))
7227            | Some(Token::HexLit(_))
7228            | Some(Token::OctalLit(_))
7229            | Some(Token::BinaryLit(_))
7230            | Some(Token::FloatLit(_))
7231            | Some(Token::StringLit(_))
7232            | Some(Token::CharLit(_))
7233            | Some(Token::True)
7234            | Some(Token::False)
7235            | Some(Token::Null) => {
7236                let lit = self.parse_literal()?;
7237                // Check for range pattern: lit..end or lit..=end
7238                if self.check(&Token::DotDot) || self.check(&Token::DotDotEq) {
7239                    let inclusive = self.consume_if(&Token::DotDotEq);
7240                    if !inclusive {
7241                        self.advance(); // consume ..
7242                    }
7243                    // Parse end of range if present
7244                    let end = if matches!(
7245                        self.current_token(),
7246                        Some(Token::IntLit(_))
7247                            | Some(Token::HexLit(_))
7248                            | Some(Token::OctalLit(_))
7249                            | Some(Token::BinaryLit(_))
7250                            | Some(Token::CharLit(_))
7251                    ) {
7252                        let end_lit = self.parse_literal()?;
7253                        Some(Box::new(Pattern::Literal(end_lit)))
7254                    } else {
7255                        None
7256                    };
7257                    Ok(Pattern::Range {
7258                        start: Some(Box::new(Pattern::Literal(lit))),
7259                        end,
7260                        inclusive,
7261                    })
7262                } else {
7263                    Ok(Pattern::Literal(lit))
7264                }
7265            }
7266            // Handle Self as a pattern (e.g., Self { field1 }, Self::Variant)
7267            Some(Token::SelfUpper) => {
7268                let span = self.current_span();
7269                self.advance();
7270
7271                // Build a path starting with "Self"
7272                let mut segments = vec![PathSegment {
7273                    ident: Ident {
7274                        name: "Self".to_string(),
7275                        evidentiality: None,
7276                        affect: None,
7277                        span,
7278                    },
7279                    generics: None,
7280                }];
7281
7282                // Check for path continuation: Self::Variant or Self::Variant::SubVariant
7283                while self.consume_if(&Token::ColonColon) || self.consume_if(&Token::MiddleDot) {
7284                    let segment_name = self.parse_ident()?;
7285                    segments.push(PathSegment {
7286                        ident: segment_name,
7287                        generics: None,
7288                    });
7289                }
7290
7291                let path = TypePath { segments };
7292
7293                // Check for tuple destructuring: Self(x, y) or Self::Variant(x, y)
7294                if self.check(&Token::LParen) {
7295                    self.advance();
7296                    let mut fields = Vec::new();
7297                    while !self.check(&Token::RParen) {
7298                        fields.push(self.parse_pattern()?);
7299                        if !self.consume_if(&Token::Comma) {
7300                            break;
7301                        }
7302                    }
7303                    self.expect(Token::RParen)?;
7304                    return Ok(Pattern::TupleStruct { path, fields });
7305                }
7306
7307                // Check for struct destructuring: Self { field: x } or Self::Variant { field }
7308                if self.check(&Token::LBrace) {
7309                    self.advance();
7310                    let mut fields = Vec::new();
7311                    let mut rest = false;
7312                    while !self.check(&Token::RBrace) {
7313                        while matches!(
7314                            self.current_token(),
7315                            Some(Token::DocComment(_))
7316                                | Some(
7317                                    Token::LineComment(_)
7318                                        | Token::TildeComment(_)
7319                                        | Token::BlockComment(_)
7320                                )
7321                        ) {
7322                            self.advance();
7323                        }
7324                        if self.check(&Token::RBrace) {
7325                            break;
7326                        }
7327                        if self.consume_if(&Token::DotDot) {
7328                            rest = true;
7329                            if !self.consume_if(&Token::Comma) {
7330                                break;
7331                            }
7332                            continue;
7333                        }
7334                        let field_name = self.parse_ident()?;
7335                        let pattern = if self.consume_if(&Token::Colon) {
7336                            Some(self.parse_pattern()?)
7337                        } else {
7338                            None
7339                        };
7340                        fields.push(FieldPattern {
7341                            name: field_name,
7342                            pattern,
7343                        });
7344                        if !self.consume_if(&Token::Comma) {
7345                            break;
7346                        }
7347                    }
7348                    self.expect(Token::RBrace)?;
7349                    return Ok(Pattern::Struct { path, fields, rest });
7350                }
7351
7352                // Just Self or Self::Variant as a unit pattern
7353                return Ok(Pattern::Path(path));
7354            }
7355            // Handle crate::, self::, super:: path patterns
7356            Some(Token::Crate) | Some(Token::SelfLower) | Some(Token::Xi) | Some(Token::Super) | Some(Token::IntensityUp) => {
7357                let keyword = self.current_token().cloned();
7358                let span = self.current_span();
7359                self.advance();
7360
7361                // These must be followed by :: for a path pattern
7362                if !self.consume_if(&Token::ColonColon) && !self.consume_if(&Token::MiddleDot) {
7363                    // Just `this` or `ξ` as an identifier pattern
7364                    if matches!(keyword, Some(Token::SelfLower) | Some(Token::Xi)) {
7365                        return Ok(Pattern::Ident {
7366                            mutable: false,
7367                            name: Ident {
7368                                name: "self".to_string(),
7369                                evidentiality: None,
7370                                affect: None,
7371                                span,
7372                            },
7373                            evidentiality: self.parse_evidentiality_opt(),
7374                        });
7375                    }
7376                    return Err(ParseError::Custom(
7377                        "expected · after crate/super in path pattern".to_string(),
7378                    ));
7379                }
7380
7381                // Build the path starting with crate/self/super
7382                let keyword_name = match keyword {
7383                    Some(Token::Crate) => "crate",
7384                    Some(Token::SelfLower) | Some(Token::Xi) => "self",  // this or ξ
7385                    Some(Token::Super) | Some(Token::IntensityUp) => "super",  // above or ↑
7386                    _ => unreachable!(),
7387                };
7388                let mut segments = vec![PathSegment {
7389                    ident: Ident {
7390                        name: keyword_name.to_string(),
7391                        evidentiality: None,
7392                        affect: None,
7393                        span,
7394                    },
7395                    generics: None,
7396                }];
7397
7398                // Parse remaining path segments
7399                loop {
7400                    let segment_name = self.parse_ident()?;
7401                    segments.push(PathSegment {
7402                        ident: segment_name,
7403                        generics: None,
7404                    });
7405
7406                    if !self.consume_if(&Token::ColonColon) && !self.consume_if(&Token::MiddleDot) {
7407                        break;
7408                    }
7409                }
7410
7411                let path = TypePath { segments };
7412
7413                // Check for tuple destructuring: crate::module::Variant(x)
7414                if self.check(&Token::LParen) {
7415                    self.advance();
7416                    let mut fields = Vec::new();
7417                    while !self.check(&Token::RParen) {
7418                        fields.push(self.parse_pattern()?);
7419                        if !self.consume_if(&Token::Comma) {
7420                            break;
7421                        }
7422                    }
7423                    self.expect(Token::RParen)?;
7424                    return Ok(Pattern::TupleStruct { path, fields });
7425                }
7426
7427                // Check for struct destructuring: crate::module::Variant { field: x }
7428                if self.check(&Token::LBrace) {
7429                    self.advance();
7430                    let mut fields = Vec::new();
7431                    let mut rest = false;
7432                    while !self.check(&Token::RBrace) {
7433                        while matches!(
7434                            self.current_token(),
7435                            Some(Token::DocComment(_))
7436                                | Some(
7437                                    Token::LineComment(_)
7438                                        | Token::TildeComment(_)
7439                                        | Token::BlockComment(_)
7440                                )
7441                        ) {
7442                            self.advance();
7443                        }
7444                        if self.check(&Token::RBrace) {
7445                            break;
7446                        }
7447                        if self.consume_if(&Token::DotDot) {
7448                            rest = true;
7449                            if !self.consume_if(&Token::Comma) {
7450                                break;
7451                            }
7452                            continue;
7453                        }
7454                        let field_name = self.parse_ident()?;
7455                        let pattern = if self.consume_if(&Token::Colon) {
7456                            Some(self.parse_pattern()?)
7457                        } else {
7458                            None
7459                        };
7460                        fields.push(FieldPattern {
7461                            name: field_name,
7462                            pattern,
7463                        });
7464                        if !self.consume_if(&Token::Comma) {
7465                            break;
7466                        }
7467                    }
7468                    self.expect(Token::RBrace)?;
7469                    return Ok(Pattern::Struct { path, fields, rest });
7470                }
7471
7472                // Just a path pattern (unit variant)
7473                return Ok(Pattern::Path(path));
7474            }
7475            Some(Token::Ident(_)) => {
7476                let name = self.parse_ident()?;
7477
7478                // Check for path continuation :: to form qualified path (e.g., Token::Fn)
7479                if self.consume_if(&Token::ColonColon) || self.consume_if(&Token::MiddleDot) {
7480                    // Build a path pattern
7481                    let mut segments = vec![PathSegment {
7482                        ident: name,
7483                        generics: None,
7484                    }];
7485
7486                    // Parse remaining path segments
7487                    loop {
7488                        let segment_name = self.parse_ident()?;
7489                        segments.push(PathSegment {
7490                            ident: segment_name,
7491                            generics: None,
7492                        });
7493
7494                        if !self.consume_if(&Token::ColonColon)
7495                            && !self.consume_if(&Token::MiddleDot)
7496                        {
7497                            break;
7498                        }
7499                    }
7500
7501                    let path = TypePath { segments };
7502
7503                    // Check for tuple destructuring: Token::IntLit(x)
7504                    if self.check(&Token::LParen) {
7505                        self.advance();
7506                        let mut fields = Vec::new();
7507                        while !self.check(&Token::RParen) {
7508                            fields.push(self.parse_pattern()?);
7509                            if !self.consume_if(&Token::Comma) {
7510                                break;
7511                            }
7512                        }
7513                        self.expect(Token::RParen)?;
7514                        return Ok(Pattern::TupleStruct { path, fields });
7515                    }
7516
7517                    // Check for struct destructuring: Token::SomeVariant { field: x }
7518                    if self.check(&Token::LBrace) {
7519                        self.advance();
7520                        let mut fields = Vec::new();
7521                        let mut rest = false;
7522                        while !self.check(&Token::RBrace) {
7523                            // Skip comments
7524                            while matches!(
7525                                self.current_token(),
7526                                Some(Token::DocComment(_))
7527                                    | Some(
7528                                        Token::LineComment(_)
7529                                            | Token::TildeComment(_)
7530                                            | Token::BlockComment(_)
7531                                    )
7532                            ) {
7533                                self.advance();
7534                            }
7535                            if self.check(&Token::RBrace) {
7536                                break;
7537                            }
7538
7539                            // Check for rest pattern: ..
7540                            if self.consume_if(&Token::DotDot) {
7541                                rest = true;
7542                                if !self.consume_if(&Token::Comma) {
7543                                    break;
7544                                }
7545                                continue;
7546                            }
7547
7548                            let field_name = self.parse_ident()?;
7549                            let pattern = if self.consume_if(&Token::Colon) {
7550                                Some(self.parse_pattern()?)
7551                            } else {
7552                                // Shorthand: field punning
7553                                None
7554                            };
7555                            fields.push(FieldPattern {
7556                                name: field_name,
7557                                pattern,
7558                            });
7559
7560                            if !self.consume_if(&Token::Comma) {
7561                                break;
7562                            }
7563                        }
7564                        self.expect(Token::RBrace)?;
7565                        return Ok(Pattern::Struct { path, fields, rest });
7566                    }
7567
7568                    // Just a path pattern (unit variant)
7569                    return Ok(Pattern::Path(path));
7570                }
7571
7572                // Check for struct pattern with simple identifier: Foo { ... }
7573                if self.check(&Token::LBrace) {
7574                    // Single-segment path for struct pattern
7575                    let path = TypePath {
7576                        segments: vec![PathSegment {
7577                            ident: name,
7578                            generics: None,
7579                        }],
7580                    };
7581                    self.advance();
7582                    let mut fields = Vec::new();
7583                    let mut rest = false;
7584                    while !self.check(&Token::RBrace) {
7585                        while matches!(
7586                            self.current_token(),
7587                            Some(Token::DocComment(_))
7588                                | Some(
7589                                    Token::LineComment(_)
7590                                        | Token::TildeComment(_)
7591                                        | Token::BlockComment(_)
7592                                )
7593                        ) {
7594                            self.advance();
7595                        }
7596                        if self.check(&Token::RBrace) {
7597                            break;
7598                        }
7599                        if self.consume_if(&Token::DotDot) {
7600                            rest = true;
7601                            break;
7602                        }
7603                        let field_name = self.parse_ident()?;
7604                        let pattern = if self.consume_if(&Token::Colon) {
7605                            Some(self.parse_pattern()?)
7606                        } else {
7607                            None
7608                        };
7609                        fields.push(FieldPattern {
7610                            name: field_name,
7611                            pattern,
7612                        });
7613                        if !self.consume_if(&Token::Comma) {
7614                            break;
7615                        }
7616                    }
7617                    self.expect(Token::RBrace)?;
7618                    return Ok(Pattern::Struct { path, fields, rest });
7619                }
7620
7621                // Check for tuple struct pattern with simple identifier: Foo(x, y)
7622                if self.check(&Token::LParen) {
7623                    let path = TypePath {
7624                        segments: vec![PathSegment {
7625                            ident: name,
7626                            generics: None,
7627                        }],
7628                    };
7629                    self.advance();
7630                    let mut fields = Vec::new();
7631                    while !self.check(&Token::RParen) {
7632                        fields.push(self.parse_pattern()?);
7633                        if !self.consume_if(&Token::Comma) {
7634                            break;
7635                        }
7636                    }
7637                    self.expect(Token::RParen)?;
7638                    return Ok(Pattern::TupleStruct { path, fields });
7639                }
7640
7641                // Simple identifier pattern
7642                let evidentiality = self.parse_evidentiality_opt();
7643                Ok(Pattern::Ident {
7644                    mutable: false,
7645                    name,
7646                    evidentiality,
7647                })
7648            }
7649            Some(Token::SelfLower) | Some(Token::Xi) => {
7650                // this or ξ keyword as pattern in method parameters (self)
7651                let span = self.current_span();
7652                self.advance();
7653                Ok(Pattern::Ident {
7654                    mutable: false,
7655                    name: Ident {
7656                        name: "self".to_string(),
7657                        evidentiality: None,
7658                        affect: None,
7659                        span,
7660                    },
7661                    evidentiality: None,
7662                })
7663            }
7664            // Handle contextual keywords as identifiers in patterns
7665            Some(ref token) if Self::keyword_as_ident(token).is_some() => {
7666                let name = self.parse_ident()?;
7667                let evidentiality = self.parse_evidentiality_opt();
7668                Ok(Pattern::Ident {
7669                    mutable: false,
7670                    name,
7671                    evidentiality,
7672                })
7673            }
7674            Some(token) => Err(ParseError::UnexpectedToken {
7675                expected: "pattern".to_string(),
7676                found: token,
7677                span: self.current_span(),
7678            }),
7679            None => Err(ParseError::UnexpectedEof),
7680        }
7681    }
7682
7683    fn parse_literal(&mut self) -> ParseResult<Literal> {
7684        match self.current_token().cloned() {
7685            Some(Token::IntLit(s)) => {
7686                self.advance();
7687                Ok(Literal::Int {
7688                    value: s,
7689                    base: NumBase::Decimal,
7690                    suffix: None,
7691                })
7692            }
7693            Some(Token::HexLit(s)) => {
7694                self.advance();
7695                Ok(Literal::Int {
7696                    value: s,
7697                    base: NumBase::Hex,
7698                    suffix: None,
7699                })
7700            }
7701            Some(Token::OctalLit(s)) => {
7702                self.advance();
7703                Ok(Literal::Int {
7704                    value: s,
7705                    base: NumBase::Octal,
7706                    suffix: None,
7707                })
7708            }
7709            Some(Token::BinaryLit(s)) => {
7710                self.advance();
7711                Ok(Literal::Int {
7712                    value: s,
7713                    base: NumBase::Binary,
7714                    suffix: None,
7715                })
7716            }
7717            Some(Token::FloatLit(s)) => {
7718                self.advance();
7719                Ok(Literal::Float {
7720                    value: s,
7721                    suffix: None,
7722                })
7723            }
7724            Some(Token::StringLit(s)) => {
7725                self.advance();
7726                Ok(Literal::String(s))
7727            }
7728            Some(Token::CharLit(c)) => {
7729                self.advance();
7730                Ok(Literal::Char(c))
7731            }
7732            Some(Token::True) => {
7733                self.advance();
7734                Ok(Literal::Bool(true))
7735            }
7736            Some(Token::False) => {
7737                self.advance();
7738                Ok(Literal::Bool(false))
7739            }
7740            Some(Token::Null) => {
7741                self.advance();
7742                Ok(Literal::Null)
7743            }
7744            _ => Err(ParseError::Custom("expected literal".to_string())),
7745        }
7746    }
7747
7748    // === Helpers ===
7749
7750    /// Convert an expression to an IncorporationSegment for polysynthetic chains
7751    /// E.g., `path` in `path·file·read` becomes IncorporationSegment { name: "path", args: None }
7752    fn expr_to_incorporation_segment(&self, expr: Expr) -> ParseResult<IncorporationSegment> {
7753        match expr {
7754            Expr::Path(path) if path.segments.len() == 1 => Ok(IncorporationSegment {
7755                name: path.segments[0].ident.clone(),
7756                args: None,
7757            }),
7758            Expr::Call { func, args } => {
7759                match *func {
7760                    Expr::Path(path) => {
7761                        // For paths like `use_context[T]()` or `serde_json::from_value(s)`,
7762                        // use the last segment as the incorporation name
7763                        if let Some(last_seg) = path.segments.last() {
7764                            return Ok(IncorporationSegment {
7765                                name: last_seg.ident.clone(),
7766                                args: Some(args),
7767                            });
7768                        }
7769                        Err(ParseError::Custom(
7770                            "incorporation chain: empty path".to_string(),
7771                        ))
7772                    }
7773                    // Handle method calls like obj.method()·chain
7774                    Expr::Field { expr, field } => Ok(IncorporationSegment {
7775                        name: field.clone(),
7776                        args: Some(std::iter::once(*expr).chain(args).collect()),
7777                    }),
7778                    _ => Err(ParseError::Custom(
7779                        "incorporation chain must start with identifier or call".to_string(),
7780                    )),
7781                }
7782            }
7783            // Field access can start an incorporation chain: ctx.navigate·clone()
7784            // We keep the field name and store the object expression as an argument
7785            Expr::Field { expr, field } => {
7786                // Use the field name directly, and store the base object as an argument
7787                // so the interpreter can reconstruct the field access
7788                Ok(IncorporationSegment {
7789                    name: field.clone(),
7790                    args: Some(vec![*expr]), // The object becomes the implicit "self" argument
7791                })
7792            }
7793            // For literals like "string"·to_string(), use a synthetic "__lit__" segment
7794            // The literal itself becomes the argument
7795            Expr::Literal(_) => Ok(IncorporationSegment {
7796                name: Ident {
7797                    name: "__lit__".to_string(),
7798                    evidentiality: None,
7799                    affect: None,
7800                    span: crate::span::Span::default(),
7801                },
7802                args: Some(vec![expr]),
7803            }),
7804            // For unary expressions like *self.field·method(), use a synthetic segment
7805            // The unary expression becomes the argument
7806            Expr::Unary { .. } => Ok(IncorporationSegment {
7807                name: Ident {
7808                    name: "__unary__".to_string(),
7809                    evidentiality: None,
7810                    affect: None,
7811                    span: crate::span::Span::default(),
7812                },
7813                args: Some(vec![expr]),
7814            }),
7815            // For index expressions like arr[i]·method()
7816            Expr::Index { expr: base, index } => Ok(IncorporationSegment {
7817                name: Ident {
7818                    name: "__index__".to_string(),
7819                    evidentiality: None,
7820                    affect: None,
7821                    span: crate::span::Span::default(),
7822                },
7823                args: Some(vec![*base, *index]),
7824            }),
7825            // For any other expression types (if, match, block, closure, etc.)
7826            // Use a synthetic segment to hold the expression as the receiver
7827            other => Ok(IncorporationSegment {
7828                name: Ident {
7829                    name: "__expr__".to_string(),
7830                    evidentiality: None,
7831                    affect: None,
7832                    span: crate::span::Span::default(),
7833                },
7834                args: Some(vec![other]),
7835            }),
7836        }
7837    }
7838
7839    /// Convert a keyword token to its string name for contextual use as identifier
7840    fn keyword_as_ident(token: &Token) -> Option<&'static str> {
7841        match token {
7842            // Common keywords that may be used as field/variable names
7843            Token::Packed => Some("packed"),
7844            Token::As => Some("as"),
7845            Token::Type => Some("type"),
7846            Token::Crate => Some("crate"),
7847            Token::Super => Some("super"),
7848            Token::Mod => Some("mod"),
7849            Token::Use => Some("use"),
7850            Token::Pub => Some("pub"),
7851            Token::Const => Some("const"),
7852            Token::Static => Some("static"),
7853            Token::Extern => Some("extern"),
7854            Token::Unsafe => Some("unsafe"),
7855            Token::Async => Some("async"),
7856            Token::Await => Some("await"),
7857            Token::Move => Some("move"),
7858            Token::Dyn => Some("dyn"),
7859            Token::Atomic => Some("atomic"),
7860            Token::Volatile => Some("volatile"),
7861            Token::Naked => Some("naked"),
7862            Token::Connect => Some("connect"),
7863            Token::Close => Some("close"),
7864            Token::Simd => Some("simd"),
7865            Token::Derive => Some("derive"),
7866            Token::On => Some("on"),
7867            Token::Send => Some("send"),
7868            Token::Recv => Some("recv"),
7869            Token::Stream => Some("stream"),
7870            Token::Timeout => Some("timeout"),
7871            Token::Retry => Some("retry"),
7872            Token::Header => Some("header"),
7873            Token::Body => Some("body"),
7874            Token::Http => Some("http"),
7875            Token::Https => Some("https"),
7876            Token::Ws => Some("ws"),
7877            Token::Wss => Some("wss"),
7878            Token::Grpc => Some("grpc"),
7879            Token::Kafka => Some("kafka"),
7880            Token::Amqp => Some("amqp"),
7881            Token::GraphQL => Some("graphql"),
7882            Token::Actor => Some("actor"),
7883            Token::Saga => Some("saga"),
7884            Token::Scope => Some("scope"),
7885            Token::Rune => Some("rune"),
7886            // Plurality keywords - usable as identifiers in most contexts
7887            Token::Split => Some("split"),
7888            Token::Trigger => Some("trigger"),
7889            Token::Location => Some("location"),
7890            Token::States => Some("states"),
7891            Token::To => Some("to"),
7892            Token::From => Some("from"),
7893            Token::Headspace => Some("headspace"),
7894            Token::CoCon => Some("cocon"),
7895            Token::Reality => Some("reality"),
7896            Token::Layer => Some("layer"),
7897            Token::Anima => Some("anima"),
7898            Token::Struct => Some("sigil"), // Allow 'sigil' as identifier (maps to Struct token)
7899            // Greek morpheme tokens - allow as identifiers in type/variable contexts
7900            Token::Parallel => Some("Parallel"),
7901            Token::Nu => Some("Nu"),
7902            Token::Lambda => Some("Lambda"),
7903            Token::Delta => Some("Delta"),
7904            Token::Tau => Some("Tau"),
7905            Token::Phi => Some("Phi"),
7906            Token::Sigma => Some("Sigma"),
7907            Token::Rho => Some("Rho"),
7908            Token::Pi => Some("Pi"),
7909            Token::Epsilon => Some("Epsilon"),
7910            Token::Omega => Some("Omega"),
7911            Token::Alpha => Some("Alpha"),
7912            Token::Zeta => Some("Zeta"),
7913            Token::Mu => Some("Mu"),
7914            Token::Chi => Some("Chi"),
7915            Token::Xi => Some("Xi"),
7916            Token::Psi => Some("Psi"),
7917            Token::Theta => Some("Theta"),
7918            Token::Kappa => Some("Kappa"),
7919            Token::Nabla => Some("∇"),
7920            Token::Gpu => Some("Gpu"),
7921            // Legion/communication operators - can be used as identifiers
7922            Token::Broadcast => Some("broadcast"),
7923            Token::Gather => Some("gather"),
7924            Token::Distribute => Some("distribute"),
7925            Token::Interfere => Some("interfere"),
7926            Token::Consensus => Some("consensus"),
7927            // Other contextual keywords
7928            Token::Ref => Some("ref"),
7929            Token::Null => Some("null"),
7930            // Neural network keywords - allow as identifiers for struct fields
7931            Token::Linear => Some("linear"),
7932            _ => None,
7933        }
7934    }
7935
7936    pub(crate) fn parse_ident(&mut self) -> ParseResult<Ident> {
7937        match self.current.take() {
7938            Some((Token::Ident(name), span)) => {
7939                self.current = self.lexer.next_token();
7940                // Parse optional UNAMBIGUOUS evidentiality markers after identifier: field◊, value~
7941                // NOTE: Don't consume ! or ? here as they have other meanings (macro!/try?)
7942                let evidentiality = self.parse_unambiguous_evidentiality_opt();
7943                // Parse optional affective markers after identifier
7944                let affect = self.parse_affect_opt();
7945                Ok(Ident {
7946                    name,
7947                    evidentiality,
7948                    affect,
7949                    span,
7950                })
7951            }
7952            Some((ref token, span)) if Self::keyword_as_ident(token).is_some() => {
7953                let mut name = Self::keyword_as_ident(token).unwrap().to_string();
7954                self.current = self.lexer.next_token();
7955                // Check if next token is an identifier starting with underscore
7956                // This handles Greek letter + underscore patterns like λ_Pipeline
7957                if let Some((Token::Ident(suffix), suffix_span)) = &self.current {
7958                    if suffix.starts_with('_') {
7959                        name.push_str(suffix);
7960                        let merged_span = span.merge(*suffix_span);
7961                        self.current = self.lexer.next_token();
7962                        let evidentiality = self.parse_unambiguous_evidentiality_opt();
7963                        let affect = self.parse_affect_opt();
7964                        return Ok(Ident {
7965                            name,
7966                            evidentiality,
7967                            affect,
7968                            span: merged_span,
7969                        });
7970                    }
7971                }
7972                let evidentiality = self.parse_unambiguous_evidentiality_opt();
7973                let affect = self.parse_affect_opt();
7974                Ok(Ident {
7975                    name,
7976                    evidentiality,
7977                    affect,
7978                    span,
7979                })
7980            }
7981            Some((token, span)) => {
7982                self.current = Some((token.clone(), span));
7983                Err(ParseError::UnexpectedToken {
7984                    expected: "identifier".to_string(),
7985                    found: token,
7986                    span,
7987                })
7988            }
7989            None => Err(ParseError::UnexpectedEof),
7990        }
7991    }
7992
7993    fn parse_evidentiality_opt(&mut self) -> Option<Evidentiality> {
7994        // Parse one or more evidentiality markers (e.g., !! or ?!)
7995        // Multiple markers are combined, with the last one taking precedence
7996        let mut ev = None;
7997        loop {
7998            match self.current_token() {
7999                Some(Token::Bang) => {
8000                    self.advance();
8001                    ev = Some(Evidentiality::Known);
8002                }
8003                Some(Token::Question) => {
8004                    self.advance();
8005                    ev = Some(Evidentiality::Uncertain);
8006                }
8007                Some(Token::Tilde) => {
8008                    self.advance();
8009                    ev = Some(Evidentiality::Reported);
8010                }
8011                Some(Token::Lozenge) => {
8012                    self.advance();
8013                    ev = Some(Evidentiality::Predicted);
8014                }
8015                Some(Token::Interrobang) => {
8016                    self.advance();
8017                    ev = Some(Evidentiality::Paradox);
8018                }
8019                _ => break,
8020            }
8021        }
8022        ev
8023    }
8024
8025    /// Parse UNAMBIGUOUS evidentiality markers only: ~, ◊, ‽
8026    /// Does NOT consume ! or ? as they have other meanings (macro!/try?)
8027    fn parse_unambiguous_evidentiality_opt(&mut self) -> Option<Evidentiality> {
8028        let mut ev = None;
8029        loop {
8030            match self.current_token() {
8031                Some(Token::Tilde) => {
8032                    self.advance();
8033                    ev = Some(Evidentiality::Reported);
8034                }
8035                Some(Token::Lozenge) => {
8036                    self.advance();
8037                    ev = Some(Evidentiality::Predicted);
8038                }
8039                Some(Token::Interrobang) => {
8040                    self.advance();
8041                    ev = Some(Evidentiality::Paradox);
8042                }
8043                _ => break,
8044            }
8045        }
8046        ev
8047    }
8048
8049    /// Parse optional affective markers: sentiment, sarcasm, intensity, formality, emotion, confidence
8050    /// Symbols: ⊕ ⊖ ⊜ (sentiment), ⸮ (sarcasm), ↑ ↓ ⇈ (intensity), ♔ ♟ (formality),
8051    ///          ☺ ☹ ⚡ ❄ ✦ ♡ (emotions), ◉ ◎ ○ (confidence)
8052    fn parse_affect_opt(&mut self) -> Option<Affect> {
8053        let mut sentiment = None;
8054        let mut sarcasm = false;
8055        let mut intensity = None;
8056        let mut formality = None;
8057        let mut emotion = None;
8058        let mut confidence = None;
8059        let mut found_any = false;
8060
8061        // Parse all consecutive affective markers
8062        loop {
8063            match self.current_token() {
8064                // Sentiment markers
8065                Some(Token::DirectSum) => {
8066                    self.advance();
8067                    sentiment = Some(Sentiment::Positive);
8068                    found_any = true;
8069                }
8070                Some(Token::AffectNegative) => {
8071                    self.advance();
8072                    sentiment = Some(Sentiment::Negative);
8073                    found_any = true;
8074                }
8075                Some(Token::AffectNeutral) => {
8076                    self.advance();
8077                    sentiment = Some(Sentiment::Neutral);
8078                    found_any = true;
8079                }
8080                // Sarcasm/Irony
8081                Some(Token::IronyMark) => {
8082                    self.advance();
8083                    sarcasm = true;
8084                    found_any = true;
8085                }
8086                // Intensity
8087                Some(Token::IntensityUp) => {
8088                    self.advance();
8089                    intensity = Some(Intensity::Up);
8090                    found_any = true;
8091                }
8092                Some(Token::IntensityDown) => {
8093                    self.advance();
8094                    intensity = Some(Intensity::Down);
8095                    found_any = true;
8096                }
8097                Some(Token::IntensityMax) => {
8098                    self.advance();
8099                    intensity = Some(Intensity::Max);
8100                    found_any = true;
8101                }
8102                // Formality
8103                Some(Token::FormalRegister) => {
8104                    self.advance();
8105                    formality = Some(Formality::Formal);
8106                    found_any = true;
8107                }
8108                Some(Token::InformalRegister) => {
8109                    self.advance();
8110                    formality = Some(Formality::Informal);
8111                    found_any = true;
8112                }
8113                // Emotions (Plutchik's wheel)
8114                Some(Token::EmotionJoy) => {
8115                    self.advance();
8116                    emotion = Some(Emotion::Joy);
8117                    found_any = true;
8118                }
8119                Some(Token::EmotionSadness) => {
8120                    self.advance();
8121                    emotion = Some(Emotion::Sadness);
8122                    found_any = true;
8123                }
8124                Some(Token::EmotionAnger) => {
8125                    self.advance();
8126                    emotion = Some(Emotion::Anger);
8127                    found_any = true;
8128                }
8129                Some(Token::EmotionFear) => {
8130                    self.advance();
8131                    emotion = Some(Emotion::Fear);
8132                    found_any = true;
8133                }
8134                Some(Token::EmotionSurprise) => {
8135                    self.advance();
8136                    emotion = Some(Emotion::Surprise);
8137                    found_any = true;
8138                }
8139                Some(Token::EmotionLove) => {
8140                    self.advance();
8141                    emotion = Some(Emotion::Love);
8142                    found_any = true;
8143                }
8144                // Confidence
8145                Some(Token::ConfidenceHigh) => {
8146                    self.advance();
8147                    confidence = Some(Confidence::High);
8148                    found_any = true;
8149                }
8150                Some(Token::ConfidenceMedium) => {
8151                    self.advance();
8152                    confidence = Some(Confidence::Medium);
8153                    found_any = true;
8154                }
8155                Some(Token::ConfidenceLow) => {
8156                    self.advance();
8157                    confidence = Some(Confidence::Low);
8158                    found_any = true;
8159                }
8160                _ => break,
8161            }
8162        }
8163
8164        if found_any {
8165            Some(Affect {
8166                sentiment,
8167                sarcasm,
8168                intensity,
8169                formality,
8170                emotion,
8171                confidence,
8172            })
8173        } else {
8174            None
8175        }
8176    }
8177
8178    pub(crate) fn parse_generics_opt(&mut self) -> ParseResult<Option<Generics>> {
8179        // Support both <T> and [T] syntax for generics
8180        let use_brackets = if self.consume_if(&Token::Lt) {
8181            false
8182        } else if self.consume_if(&Token::LBracket) {
8183            true
8184        } else {
8185            return Ok(None);
8186        };
8187
8188        let mut params = Vec::new();
8189        // Use check_gt() to handle pending `>` from split `>>` (only for angle brackets)
8190        while !self.is_eof() {
8191            // Skip line comments between generic parameters
8192            self.skip_comments();
8193
8194            if use_brackets {
8195                if self.check(&Token::RBracket) {
8196                    break;
8197                }
8198            } else if self.check_gt() {
8199                break;
8200            }
8201
8202            // Check for lifetime parameter: 'a, 'static, etc.
8203            if let Some(Token::Lifetime(lt)) = self.current_token().cloned() {
8204                self.advance();
8205                params.push(GenericParam::Lifetime(lt));
8206                if !self.consume_if(&Token::Comma) {
8207                    break;
8208                }
8209                continue;
8210            }
8211
8212            // Check for const generic parameter (const N: usize = 10 or just const N)
8213            if self.consume_if(&Token::Const) {
8214                let name = self.parse_ident()?;
8215                // Type annotation is optional: const N: usize or just const N
8216                let ty = if self.consume_if(&Token::Colon) {
8217                    self.parse_type()?
8218                } else {
8219                    TypeExpr::Infer
8220                };
8221                // Parse optional default value: const N: usize = 10
8222                let default = if self.consume_if(&Token::Eq) {
8223                    Some(Box::new(self.parse_expr()?))
8224                } else {
8225                    None
8226                };
8227                params.push(GenericParam::Const { name, ty, default });
8228                if !self.consume_if(&Token::Comma) {
8229                    break;
8230                }
8231                continue;
8232            }
8233
8234            // Type parameter
8235            let name = self.parse_ident()?;
8236            let evidentiality = self.parse_evidentiality_opt();
8237            let bounds = if self.consume_if(&Token::Colon) {
8238                self.parse_type_bounds()?
8239            } else {
8240                vec![]
8241            };
8242            // Parse optional default type: T = DefaultType
8243            let default = if self.consume_if(&Token::Eq) {
8244                Some(self.parse_type()?)
8245            } else {
8246                None
8247            };
8248            params.push(GenericParam::Type {
8249                name,
8250                bounds,
8251                evidentiality,
8252                default,
8253            });
8254
8255            if !self.consume_if(&Token::Comma) {
8256                break;
8257            }
8258        }
8259        // Close the generics
8260        if use_brackets {
8261            self.expect(Token::RBracket)?;
8262        } else {
8263            // Use expect_gt() to handle nested generics with `>>`
8264            self.expect_gt()?;
8265        }
8266
8267        Ok(Some(Generics { params }))
8268    }
8269
8270    pub(crate) fn parse_where_clause_opt(&mut self) -> ParseResult<Option<WhereClause>> {
8271        if !self.consume_if(&Token::Where) {
8272            return Ok(None);
8273        }
8274
8275        let mut predicates = Vec::new();
8276        loop {
8277            self.skip_comments(); // Skip comments between predicates
8278
8279            // Check for expression predicates: EXPR == EXPR (e.g., QH % KVH == 0)
8280            // These start with an identifier followed by an operator other than :
8281            // Try to detect expression predicate by peeking ahead
8282            // Expression predicates have operators like %, ==, !=, <, >, etc.
8283            let is_expr_predicate = if let Some(Token::Ident(_)) = self.current_token() {
8284                // Peek ahead to see if we have an expression operator instead of :
8285                let next = self.peek_next();
8286                matches!(
8287                    next,
8288                    Some(Token::Percent)
8289                        | Some(Token::EqEq)
8290                        | Some(Token::NotEq)
8291                        | Some(Token::Plus)
8292                        | Some(Token::Minus)
8293                        | Some(Token::Star)
8294                        | Some(Token::Slash)
8295                )
8296            } else {
8297                false
8298            };
8299
8300            if is_expr_predicate {
8301                // Parse as expression predicate: EXPR == EXPR or EXPR != EXPR
8302                let _expr = self.parse_expr()?;
8303                // For now, just skip the constraint - we'll store it properly later
8304                self.skip_comments();
8305                if !self.consume_if(&Token::Comma) {
8306                    break;
8307                }
8308                self.skip_comments();
8309                if self.check(&Token::LBrace) {
8310                    break;
8311                }
8312                continue;
8313            }
8314
8315            let ty = self.parse_type()?;
8316
8317            // Check if this is a type bound (T: Trait) or if we should skip
8318            if self.check(&Token::Colon) {
8319                self.advance(); // consume :
8320                let bounds = self.parse_type_bounds()?;
8321                self.skip_comments(); // Skip comments after bounds
8322                predicates.push(WherePredicate { ty, bounds });
8323            } else {
8324                // Not a type bound, might be an expression we couldn't detect earlier
8325                // Just skip this predicate
8326            }
8327
8328            if !self.consume_if(&Token::Comma) {
8329                break;
8330            }
8331            // Stop if we hit a brace
8332            self.skip_comments();
8333            if self.check(&Token::LBrace) {
8334                break;
8335            }
8336        }
8337
8338        Ok(Some(WhereClause { predicates }))
8339    }
8340
8341    pub(crate) fn parse_params(&mut self) -> ParseResult<Vec<Param>> {
8342        let mut params = Vec::new();
8343        while !self.check(&Token::RParen) && !self.is_eof() {
8344            // Skip comments and parameter attributes: @[...] or #[...]
8345            self.skip_comments();
8346            while self.check(&Token::At) || self.check(&Token::Hash) {
8347                self.skip_attribute()?;
8348                self.skip_comments();
8349            }
8350            if self.check(&Token::RParen) {
8351                break;
8352            }
8353            let pattern = self.parse_pattern()?;
8354            // Type annotation is optional - use Infer if not provided
8355            let ty = if self.consume_if(&Token::Colon) {
8356                self.parse_type()?
8357            } else {
8358                TypeExpr::Infer
8359            };
8360            params.push(Param { pattern, ty });
8361            if !self.consume_if(&Token::Comma) {
8362                break;
8363            }
8364        }
8365        Ok(params)
8366    }
8367
8368    /// Skip an attribute (@[...] or #[...]) without parsing its contents
8369    fn skip_attribute(&mut self) -> ParseResult<()> {
8370        // Consume @ or #
8371        if self.check(&Token::At) || self.check(&Token::Hash) {
8372            self.advance();
8373        }
8374        // Consume [...] if present
8375        if self.consume_if(&Token::LBracket) {
8376            let mut depth = 1;
8377            while depth > 0 && !self.is_eof() {
8378                match self.current_token() {
8379                    Some(Token::LBracket) => depth += 1,
8380                    Some(Token::RBracket) => depth -= 1,
8381                    _ => {}
8382                }
8383                self.advance();
8384            }
8385        }
8386        Ok(())
8387    }
8388
8389    fn parse_field_defs(&mut self) -> ParseResult<Vec<FieldDef>> {
8390        let mut fields = Vec::new();
8391        while !self.check(&Token::RBrace) && !self.is_eof() {
8392            // Skip doc comments, line comments, and attributes before fields
8393            while matches!(
8394                self.current_token(),
8395                Some(Token::DocComment(_))
8396                    | Some(Token::LineComment(_) | Token::TildeComment(_) | Token::BlockComment(_))
8397            ) || self.check(&Token::Hash)
8398                || self.check(&Token::At)
8399            {
8400                if self.check(&Token::Hash) || self.check(&Token::At) {
8401                    self.skip_attribute()?;
8402                } else {
8403                    self.advance();
8404                }
8405            }
8406            if self.check(&Token::RBrace) {
8407                break;
8408            }
8409            let visibility = self.parse_visibility()?;
8410            let name = self.parse_ident()?;
8411            // Optional evidentiality marker after field name: `field~: Type`, `field◊: Type`
8412            let _evidentiality = self.parse_evidentiality_opt();
8413            self.expect(Token::Colon)?;
8414            let ty = self.parse_type()?;
8415            // Parse optional default value: `field: Type = default_expr`
8416            let default = if self.consume_if(&Token::Eq) {
8417                Some(self.parse_expr()?)
8418            } else {
8419                None
8420            };
8421            fields.push(FieldDef {
8422                visibility,
8423                name,
8424                ty,
8425                default,
8426            });
8427            if !self.consume_if(&Token::Comma) {
8428                break;
8429            }
8430        }
8431        Ok(fields)
8432    }
8433
8434    fn parse_expr_list(&mut self) -> ParseResult<Vec<Expr>> {
8435        let mut exprs = Vec::new();
8436        // Skip leading comments
8437        self.skip_comments();
8438        while !self.check(&Token::RParen) && !self.check(&Token::RBracket) && !self.is_eof() {
8439            // Check for named argument syntax: name: expr
8440            // This handles calls like `stack(axis: 0)` or `func(x: 1, y: 2)`
8441            // We detect `ident :` but not `ident ::` (path separator)
8442            let expr = if let Some(Token::Ident(name)) = self.current_token().cloned() {
8443                // Look ahead: is next token `:` (single colon) not `::` (double colon)?
8444                let is_named_arg = self.peek_next() == Some(&Token::Colon);
8445                if is_named_arg {
8446                    let span = self.current_span();
8447                    self.advance(); // consume name
8448                    self.advance(); // consume :
8449                    let value = self.parse_expr()?;
8450                    // Represent as a named argument via NamedArg expression
8451                    Expr::NamedArg {
8452                        name: Ident {
8453                            name,
8454                            evidentiality: None,
8455                            affect: None,
8456                            span,
8457                        },
8458                        value: Box::new(value),
8459                    }
8460                } else {
8461                    self.parse_expr()?
8462                }
8463            } else {
8464                self.parse_expr()?
8465            };
8466            exprs.push(expr);
8467            if !self.consume_if(&Token::Comma) {
8468                break;
8469            }
8470            // Skip comments after comma (e.g., trailing comments on argument lines)
8471            self.skip_comments();
8472        }
8473        Ok(exprs)
8474    }
8475
8476    fn parse_struct_fields(&mut self) -> ParseResult<(Vec<FieldInit>, Option<Box<Expr>>)> {
8477        let mut fields = Vec::new();
8478        let mut rest = None;
8479
8480        while !self.check(&Token::RBrace) && !self.is_eof() {
8481            // Skip comments and attributes before field
8482            while matches!(
8483                self.current_token(),
8484                Some(Token::DocComment(_))
8485                    | Some(Token::LineComment(_) | Token::TildeComment(_) | Token::BlockComment(_))
8486                    | Some(Token::Hash)
8487            ) {
8488                if self.check(&Token::Hash) {
8489                    // Skip attribute: #[...] or #![...]
8490                    self.advance();
8491                    self.consume_if(&Token::Bang); // optional ! for inner attributes
8492                    if self.consume_if(&Token::LBracket) {
8493                        let mut depth = 1;
8494                        while depth > 0 && !self.is_eof() {
8495                            match self.current_token() {
8496                                Some(Token::LBracket) => depth += 1,
8497                                Some(Token::RBracket) => depth -= 1,
8498                                _ => {}
8499                            }
8500                            self.advance();
8501                        }
8502                    }
8503                } else {
8504                    self.advance();
8505                }
8506            }
8507            if self.check(&Token::RBrace) {
8508                break;
8509            }
8510            if self.consume_if(&Token::DotDot) {
8511                rest = Some(Box::new(self.parse_expr()?));
8512                break;
8513            }
8514
8515            let name = self.parse_ident()?;
8516            let value = if self.consume_if(&Token::Colon) {
8517                Some(self.parse_expr()?)
8518            } else {
8519                None
8520            };
8521            fields.push(FieldInit { name, value });
8522
8523            if !self.consume_if(&Token::Comma) {
8524                break;
8525            }
8526        }
8527
8528        Ok((fields, rest))
8529    }
8530
8531    fn is_item_start(&mut self) -> bool {
8532        match self.current_token() {
8533            Some(Token::Fn) | Some(Token::Lambda) // λ = fn
8534            | Some(Token::Struct) | Some(Token::Sigma) // Σ = struct
8535            | Some(Token::Enum) // ᛈ handled in lexer
8536            | Some(Token::Trait) | Some(Token::Theta) // Θ = trait
8537            | Some(Token::Impl) // ⊢ handled in lexer
8538            | Some(Token::Type) | Some(Token::Mod) | Some(Token::Use)
8539            | Some(Token::Const) | Some(Token::Static) | Some(Token::Actor) | Some(Token::Pub)
8540            | Some(Token::Extern) => true,
8541            // async/⌛ is only item start if followed by fn/λ
8542            Some(Token::Async) | Some(Token::Hourglass) => {
8543                matches!(self.peek_next(), Some(Token::Fn) | Some(Token::Lambda))
8544            }
8545            _ => false,
8546        }
8547    }
8548
8549    fn is_in_condition(&self) -> bool {
8550        self.in_condition
8551    }
8552
8553    /// Parse an expression in condition context (< is comparison, not generics)
8554    fn parse_condition(&mut self) -> ParseResult<Expr> {
8555        let was_in_condition = self.in_condition;
8556        self.in_condition = true;
8557        let result = self.parse_expr();
8558        self.in_condition = was_in_condition;
8559        result
8560    }
8561
8562    // ==========================================
8563    // Legion Morpheme Parsing
8564    // ==========================================
8565
8566    /// Parse Legion operators that follow an expression.
8567    /// Handles: ⫰ (interference), ⟁ (distribute), ↠ (broadcast),
8568    ///          ⟀ (gather), ⇢ (consensus), ◉ (resonance)
8569    fn parse_legion_operator(&mut self, lhs: Expr) -> ParseResult<Expr> {
8570        match self.current_token() {
8571            Some(Token::Interfere) => {
8572                // Interference: query ⫰ field
8573                self.advance();
8574                let field = self.parse_expr_bp(15)?; // Higher precedence
8575                Ok(Expr::LegionInterference {
8576                    query: Box::new(lhs),
8577                    field: Box::new(field),
8578                })
8579            }
8580            Some(Token::Distribute) => {
8581                // Distribute: task ⟁ count
8582                self.advance();
8583                let count = self.parse_expr_bp(15)?;
8584                Ok(Expr::LegionDistribute {
8585                    task: Box::new(lhs),
8586                    count: Box::new(count),
8587                })
8588            }
8589            Some(Token::Broadcast) => {
8590                // Broadcast: signal ↠ target
8591                self.advance();
8592                let target = self.parse_expr_bp(15)?;
8593                Ok(Expr::LegionBroadcast {
8594                    signal: Box::new(lhs),
8595                    target: Box::new(target),
8596                })
8597            }
8598            Some(Token::Gather) => {
8599                // Gather: fragments ⟀ (postfix unary)
8600                self.advance();
8601                Ok(Expr::LegionGather {
8602                    fragments: Box::new(lhs),
8603                })
8604            }
8605            Some(Token::Consensus) => {
8606                // Consensus: contributions ⇢ (postfix unary)
8607                self.advance();
8608                Ok(Expr::LegionConsensus {
8609                    contributions: Box::new(lhs),
8610                })
8611            }
8612            Some(Token::ConfidenceHigh) => {
8613                // Resonance: resonance |◉ (postfix unary, dual-purpose token)
8614                self.advance();
8615                Ok(Expr::LegionResonance {
8616                    expr: Box::new(lhs),
8617                })
8618            }
8619            _ => Ok(lhs),
8620        }
8621    }
8622
8623    /// Check if an identifier ends with the Legion field marker ∿
8624    /// Used to parse variable names like `memory∿`
8625    fn is_legion_field_ident(&self, name: &str) -> bool {
8626        name.ends_with('∿')
8627    }
8628}
8629
8630/// Binding power for infix operators.
8631fn infix_binding_power(op: BinOp) -> (u8, u8) {
8632    match op {
8633        BinOp::Or => (1, 2),
8634        BinOp::And => (3, 4),
8635        BinOp::Eq | BinOp::Ne | BinOp::Lt | BinOp::Le | BinOp::Gt | BinOp::Ge => (5, 6),
8636        BinOp::BitOr => (7, 8),
8637        BinOp::BitXor => (9, 10),
8638        BinOp::BitAnd => (11, 12),
8639        BinOp::Shl | BinOp::Shr => (13, 14),
8640        BinOp::Add | BinOp::Sub | BinOp::Concat => (15, 16),
8641        BinOp::Mul
8642        | BinOp::Div
8643        | BinOp::Rem
8644        | BinOp::MatMul
8645        | BinOp::Hadamard
8646        | BinOp::TensorProd
8647        | BinOp::Convolve => (17, 18),
8648        BinOp::Pow => (20, 19), // Right associative
8649    }
8650}
8651
8652#[cfg(test)]
8653mod tests {
8654    use super::*;
8655
8656    #[test]
8657    fn test_parse_function() {
8658        // Simple function with semicolon-terminated statement
8659        let source = "fn hello(name: str) -> str { return name; }";
8660        let mut parser = Parser::new(source);
8661        let file = parser.parse_file().unwrap();
8662        assert_eq!(file.items.len(), 1);
8663    }
8664
8665    #[test]
8666    fn test_parse_pipe_chain() {
8667        let source = "fn main() { let result = data|τ{_ * 2}|φ{_ > 0}|σ; }";
8668        let mut parser = Parser::new(source);
8669        let file = parser.parse_file().unwrap();
8670        assert_eq!(file.items.len(), 1);
8671    }
8672
8673    #[test]
8674    fn test_parse_async_function() {
8675        let source = "async fn fetch(url: str) -> Response~ { return client·get(url)|await; }";
8676        let mut parser = Parser::new(source);
8677        let file = parser.parse_file().unwrap();
8678        assert_eq!(file.items.len(), 1);
8679    }
8680
8681    #[test]
8682    fn test_parse_struct() {
8683        let source = "struct Point { x: f64, y: f64 }";
8684        let mut parser = Parser::new(source);
8685        let file = parser.parse_file().unwrap();
8686        assert_eq!(file.items.len(), 1);
8687    }
8688
8689    #[test]
8690    fn test_parse_actor() {
8691        // Simplified actor without compound assignment
8692        let source = r#"
8693            actor Counter {
8694                state: i64 = 0
8695                on Increment(n: i64) { return self.state + n; }
8696            }
8697        "#;
8698        let mut parser = Parser::new(source);
8699        let file = parser.parse_file().unwrap();
8700        assert_eq!(file.items.len(), 1);
8701    }
8702
8703    #[test]
8704    fn test_parse_number_bases() {
8705        let source = "fn bases() { let a = 42; let b = 0b101010; let c = 0x2A; let d = 0v22; }";
8706        let mut parser = Parser::new(source);
8707        let file = parser.parse_file().unwrap();
8708        assert_eq!(file.items.len(), 1);
8709    }
8710
8711    #[test]
8712    fn test_parse_labeled_loops() {
8713        // Test labeled loop with break
8714        let source = r#"
8715            fn test() {
8716                'outer: loop {
8717                    'inner: while true {
8718                        break 'outer;
8719                    }
8720                }
8721            }
8722        "#;
8723        let mut parser = Parser::new(source);
8724        let file = parser.parse_file().unwrap();
8725        assert_eq!(file.items.len(), 1);
8726
8727        // Test labeled for with continue
8728        let source2 = r#"
8729            fn test2() {
8730                'rows: for i in 0..10 {
8731                    'cols: for j in 0..10 {
8732                        if j == 5 { continue 'rows; }
8733                    }
8734                }
8735            }
8736        "#;
8737        let mut parser2 = Parser::new(source2);
8738        let file2 = parser2.parse_file().unwrap();
8739        assert_eq!(file2.items.len(), 1);
8740    }
8741
8742    #[test]
8743    fn test_parse_inline_asm() {
8744        let source = r#"
8745            fn outb(port: u16, value: u8) {
8746                asm!("out dx, al",
8747                    in("dx") port,
8748                    in("al") value,
8749                    options(nostack));
8750            }
8751        "#;
8752        let mut parser = Parser::new(source);
8753        let file = parser.parse_file().unwrap();
8754        assert_eq!(file.items.len(), 1);
8755
8756        if let Item::Function(func) = &file.items[0].node {
8757            assert_eq!(func.name.name, "outb");
8758        } else {
8759            panic!("Expected function");
8760        }
8761    }
8762
8763    #[test]
8764    fn test_parse_inline_asm_with_outputs() {
8765        let source = r#"
8766            fn inb(port: u16) -> u8 {
8767                let result: u8 = 0;
8768                asm!("in al, dx",
8769                    out("al") result,
8770                    in("dx") port,
8771                    options(nostack, nomem));
8772                return result;
8773            }
8774        "#;
8775        let mut parser = Parser::new(source);
8776        let file = parser.parse_file().unwrap();
8777        assert_eq!(file.items.len(), 1);
8778    }
8779
8780    #[test]
8781    fn test_parse_volatile_read() {
8782        let source = r#"
8783            fn read_mmio(addr: *mut u32) -> u32 {
8784                return volatile read<u32>(addr);
8785            }
8786        "#;
8787        let mut parser = Parser::new(source);
8788        let file = parser.parse_file().unwrap();
8789        assert_eq!(file.items.len(), 1);
8790    }
8791
8792    #[test]
8793    fn test_parse_volatile_write() {
8794        let source = r#"
8795            fn write_mmio(addr: *mut u32, value: u32) {
8796                volatile write<u32>(addr, value);
8797            }
8798        "#;
8799        let mut parser = Parser::new(source);
8800        let file = parser.parse_file().unwrap();
8801        assert_eq!(file.items.len(), 1);
8802    }
8803
8804    #[test]
8805    fn test_parse_naked_function() {
8806        let source = r#"
8807            naked fn interrupt_handler() {
8808                asm!("push rax; push rbx; call handler_impl; pop rbx; pop rax; iretq",
8809                    options(nostack));
8810            }
8811        "#;
8812        let mut parser = Parser::new(source);
8813        let file = parser.parse_file().unwrap();
8814        assert_eq!(file.items.len(), 1);
8815
8816        if let Item::Function(func) = &file.items[0].node {
8817            assert!(func.attrs.naked, "Function should be naked");
8818        } else {
8819            panic!("Expected function");
8820        }
8821    }
8822
8823    #[test]
8824    fn test_parse_packed_struct() {
8825        let source = r#"
8826            packed struct GDTEntry {
8827                limit_low: u16,
8828                base_low: u16,
8829                base_middle: u8,
8830                access: u8,
8831                granularity: u8,
8832                base_high: u8,
8833            }
8834        "#;
8835        let mut parser = Parser::new(source);
8836        let file = parser.parse_file().unwrap();
8837        assert_eq!(file.items.len(), 1);
8838
8839        if let Item::Struct(s) = &file.items[0].node {
8840            assert!(s.attrs.packed, "Struct should be packed");
8841            assert_eq!(s.name.name, "GDTEntry");
8842            if let StructFields::Named(fields) = &s.fields {
8843                assert_eq!(fields.len(), 6);
8844            } else {
8845                panic!("Expected named fields");
8846            }
8847        } else {
8848            panic!("Expected struct");
8849        }
8850    }
8851
8852    #[test]
8853    fn test_parse_no_std_attribute() {
8854        let source = r#"
8855            #![no_std]
8856            #![no_main]
8857
8858            fn kernel_main() -> ! {
8859                loop {}
8860            }
8861        "#;
8862        let mut parser = Parser::new(source);
8863        let file = parser.parse_file().unwrap();
8864
8865        assert!(file.config.no_std, "Should have no_std");
8866        assert!(file.config.no_main, "Should have no_main");
8867        assert_eq!(file.attrs.len(), 2);
8868    }
8869
8870    #[test]
8871    fn test_parse_feature_attribute() {
8872        let source = r#"
8873            #![feature(asm, naked_functions)]
8874
8875            fn main() -> i64 { 0 }
8876        "#;
8877        let mut parser = Parser::new(source);
8878        let file = parser.parse_file().unwrap();
8879
8880        assert_eq!(file.config.features.len(), 2);
8881        assert!(file.config.features.contains(&"asm".to_string()));
8882        assert!(file
8883            .config
8884            .features
8885            .contains(&"naked_functions".to_string()));
8886    }
8887
8888    #[test]
8889    fn test_parse_target_attribute() {
8890        let source = r#"
8891            #![no_std]
8892            #![target(arch = "x86_64", os = "none")]
8893
8894            fn kernel_main() { }
8895        "#;
8896        let mut parser = Parser::new(source);
8897        let file = parser.parse_file().unwrap();
8898
8899        assert!(file.config.no_std);
8900        let target = file
8901            .config
8902            .target
8903            .as_ref()
8904            .expect("Should have target config");
8905        assert_eq!(target.arch, Some("x86_64".to_string()));
8906        assert_eq!(target.os, Some("none".to_string()));
8907    }
8908
8909    #[test]
8910    fn test_parse_panic_handler() {
8911        let source = r#"
8912            #![no_std]
8913
8914            #[panic_handler]
8915            fn panic(info: *const PanicInfo) -> ! {
8916                loop {}
8917            }
8918        "#;
8919        let mut parser = Parser::new(source);
8920        let file = parser.parse_file().unwrap();
8921
8922        assert_eq!(file.items.len(), 1);
8923        if let Item::Function(func) = &file.items[0].node {
8924            assert!(
8925                func.attrs.panic_handler,
8926                "Should have panic_handler attribute"
8927            );
8928        } else {
8929            panic!("Expected function");
8930        }
8931    }
8932
8933    #[test]
8934    fn test_parse_entry_point() {
8935        let source = r#"
8936            #![no_std]
8937            #![no_main]
8938
8939            #[entry]
8940            #[no_mangle]
8941            fn _start() -> ! {
8942                loop {}
8943            }
8944        "#;
8945        let mut parser = Parser::new(source);
8946        let file = parser.parse_file().unwrap();
8947
8948        assert_eq!(file.items.len(), 1);
8949        if let Item::Function(func) = &file.items[0].node {
8950            assert!(func.attrs.entry, "Should have entry attribute");
8951            assert!(func.attrs.no_mangle, "Should have no_mangle attribute");
8952        } else {
8953            panic!("Expected function");
8954        }
8955    }
8956
8957    #[test]
8958    fn test_parse_link_section() {
8959        let source = r#"
8960            #[link_section = ".text.boot"]
8961            fn boot_code() { }
8962        "#;
8963        let mut parser = Parser::new(source);
8964        let file = parser.parse_file().unwrap();
8965
8966        assert_eq!(file.items.len(), 1);
8967        if let Item::Function(func) = &file.items[0].node {
8968            assert_eq!(func.attrs.link_section, Some(".text.boot".to_string()));
8969        } else {
8970            panic!("Expected function");
8971        }
8972    }
8973
8974    #[test]
8975    fn test_parse_linker_config() {
8976        let source = r#"
8977            #![no_std]
8978            #![linker_script = "kernel.ld"]
8979            #![entry_point = "_start"]
8980            #![base_address = 0x100000]
8981            #![stack_size = 0x4000]
8982
8983            fn kernel_main() { }
8984        "#;
8985        let mut parser = Parser::new(source);
8986        let file = parser.parse_file().unwrap();
8987
8988        let linker = file
8989            .config
8990            .linker
8991            .as_ref()
8992            .expect("Should have linker config");
8993        assert_eq!(linker.script, Some("kernel.ld".to_string()));
8994        assert_eq!(linker.entry_point, Some("_start".to_string()));
8995        assert_eq!(linker.base_address, Some(0x100000));
8996        assert_eq!(linker.stack_size, Some(0x4000));
8997    }
8998
8999    #[test]
9000    fn test_parse_interrupt_handler() {
9001        let source = r#"
9002            #[interrupt(32)]
9003            #[naked]
9004            fn timer_handler() {
9005                asm!("iretq", options(nostack));
9006            }
9007        "#;
9008        let mut parser = Parser::new(source);
9009        let file = parser.parse_file().unwrap();
9010
9011        if let Item::Function(func) = &file.items[0].node {
9012            assert_eq!(func.attrs.interrupt, Some(32));
9013            assert!(func.attrs.naked);
9014        } else {
9015            panic!("Expected function");
9016        }
9017    }
9018
9019    #[test]
9020    fn test_parse_inline_attributes() {
9021        let source = r#"
9022            #[inline]
9023            fn fast() -> i64 { 0 }
9024
9025            #[inline(always)]
9026            fn very_fast() -> i64 { 0 }
9027
9028            #[inline(never)]
9029            fn never_inline() -> i64 { 0 }
9030        "#;
9031        let mut parser = Parser::new(source);
9032        let file = parser.parse_file().unwrap();
9033
9034        assert_eq!(file.items.len(), 3);
9035
9036        if let Item::Function(func) = &file.items[0].node {
9037            assert_eq!(func.attrs.inline, Some(InlineHint::Hint));
9038        }
9039        if let Item::Function(func) = &file.items[1].node {
9040            assert_eq!(func.attrs.inline, Some(InlineHint::Always));
9041        }
9042        if let Item::Function(func) = &file.items[2].node {
9043            assert_eq!(func.attrs.inline, Some(InlineHint::Never));
9044        }
9045    }
9046
9047    #[test]
9048    fn test_parse_simd_type() {
9049        let source = r#"
9050            fn vec_add(a: simd<f32, 4>, b: simd<f32, 4>) -> simd<f32, 4> {
9051                return simd.add(a, b);
9052            }
9053        "#;
9054        let mut parser = Parser::new(source);
9055        let file = parser.parse_file().unwrap();
9056        assert_eq!(file.items.len(), 1);
9057
9058        if let Item::Function(func) = &file.items[0].node {
9059            assert_eq!(func.name.name, "vec_add");
9060            // Check first parameter type
9061            if let TypeExpr::Simd { element, lanes } = &func.params[0].ty {
9062                assert_eq!(*lanes, 4);
9063                if let TypeExpr::Path(path) = element.as_ref() {
9064                    assert_eq!(path.segments[0].ident.name, "f32");
9065                }
9066            } else {
9067                panic!("Expected SIMD type");
9068            }
9069        } else {
9070            panic!("Expected function");
9071        }
9072    }
9073
9074    #[test]
9075    fn test_parse_simd_literal() {
9076        let source = r#"
9077            fn make_vec() -> simd<f32, 4> {
9078                return simd[1.0, 2.0, 3.0, 4.0];
9079            }
9080        "#;
9081        let mut parser = Parser::new(source);
9082        let file = parser.parse_file().unwrap();
9083        assert_eq!(file.items.len(), 1);
9084    }
9085
9086    #[test]
9087    fn test_parse_simd_intrinsics() {
9088        let source = r#"
9089            fn dot_product(a: simd<f32, 4>, b: simd<f32, 4>) -> f32 {
9090                let prod = simd.mul(a, b);
9091                return simd.hadd(prod);
9092            }
9093        "#;
9094        let mut parser = Parser::new(source);
9095        let file = parser.parse_file().unwrap();
9096        assert_eq!(file.items.len(), 1);
9097    }
9098
9099    #[test]
9100    fn test_parse_simd_shuffle() {
9101        let source = r#"
9102            fn interleave(a: simd<f32, 4>, b: simd<f32, 4>) -> simd<f32, 4> {
9103                return simd.shuffle(a, b, [0, 4, 1, 5]);
9104            }
9105        "#;
9106        let mut parser = Parser::new(source);
9107        let file = parser.parse_file().unwrap();
9108        assert_eq!(file.items.len(), 1);
9109    }
9110
9111    #[test]
9112    fn test_parse_atomic_type() {
9113        let source = r#"
9114            struct Counter {
9115                value: atomic<i64>,
9116            }
9117        "#;
9118        let mut parser = Parser::new(source);
9119        let file = parser.parse_file().unwrap();
9120        assert_eq!(file.items.len(), 1);
9121
9122        if let Item::Struct(s) = &file.items[0].node {
9123            if let StructFields::Named(fields) = &s.fields {
9124                if let TypeExpr::Atomic(inner) = &fields[0].ty {
9125                    if let TypeExpr::Path(path) = inner.as_ref() {
9126                        assert_eq!(path.segments[0].ident.name, "i64");
9127                    }
9128                } else {
9129                    panic!("Expected atomic type");
9130                }
9131            }
9132        } else {
9133            panic!("Expected struct");
9134        }
9135    }
9136
9137    #[test]
9138    fn test_parse_atomic_operations() {
9139        let source = r#"
9140            fn increment(ptr: *mut i64) -> i64 {
9141                return atomic.fetch_add(ptr, 1, SeqCst);
9142            }
9143        "#;
9144        let mut parser = Parser::new(source);
9145        let file = parser.parse_file().unwrap();
9146        assert_eq!(file.items.len(), 1);
9147    }
9148
9149    #[test]
9150    fn test_parse_atomic_compare_exchange() {
9151        let source = r#"
9152            fn cas(ptr: *mut i64, expected: i64, new: i64) -> bool {
9153                let result = atomic.compare_exchange(ptr, expected, new, AcqRel, Relaxed);
9154                return result;
9155            }
9156        "#;
9157        let mut parser = Parser::new(source);
9158        let file = parser.parse_file().unwrap();
9159        assert_eq!(file.items.len(), 1);
9160    }
9161
9162    #[test]
9163    fn test_parse_atomic_fence() {
9164        let source = r#"
9165            fn memory_barrier() {
9166                atomic.fence(SeqCst);
9167            }
9168        "#;
9169        let mut parser = Parser::new(source);
9170        let file = parser.parse_file().unwrap();
9171        assert_eq!(file.items.len(), 1);
9172    }
9173
9174    #[test]
9175    fn test_parse_derive_macro() {
9176        let source = r#"
9177            #[derive(Debug, Clone, Component)]
9178            struct Position {
9179                x: f32,
9180                y: f32,
9181                z: f32,
9182            }
9183        "#;
9184        let mut parser = Parser::new(source);
9185        let file = parser.parse_file().unwrap();
9186        assert_eq!(file.items.len(), 1);
9187
9188        if let Item::Struct(s) = &file.items[0].node {
9189            assert_eq!(s.attrs.derives.len(), 3);
9190            assert!(matches!(s.attrs.derives[0], DeriveTrait::Debug));
9191            assert!(matches!(s.attrs.derives[1], DeriveTrait::Clone));
9192            assert!(matches!(s.attrs.derives[2], DeriveTrait::Component));
9193        } else {
9194            panic!("Expected struct");
9195        }
9196    }
9197
9198    #[test]
9199    fn test_parse_repr_c_struct() {
9200        let source = r#"
9201            #[repr(C)]
9202            struct FFIStruct {
9203                field: i32,
9204            }
9205        "#;
9206        let mut parser = Parser::new(source);
9207        let file = parser.parse_file().unwrap();
9208        assert_eq!(file.items.len(), 1);
9209
9210        if let Item::Struct(s) = &file.items[0].node {
9211            assert_eq!(s.attrs.repr, Some(StructRepr::C));
9212        } else {
9213            panic!("Expected struct");
9214        }
9215    }
9216
9217    #[test]
9218    fn test_parse_allocator_trait() {
9219        let source = r#"
9220            trait Allocator {
9221                type Error;
9222
9223                fn allocate(size: usize, align: usize) -> *mut u8;
9224                fn deallocate(ptr: *mut u8, size: usize, align: usize);
9225            }
9226        "#;
9227        let mut parser = Parser::new(source);
9228        let file = parser.parse_file().unwrap();
9229        assert_eq!(file.items.len(), 1);
9230
9231        if let Item::Trait(t) = &file.items[0].node {
9232            assert_eq!(t.name.name, "Allocator");
9233            assert_eq!(t.items.len(), 3); // associated type + 2 methods
9234            assert!(matches!(t.items[0], TraitItem::Type { .. }));
9235        } else {
9236            panic!("Expected trait");
9237        }
9238    }
9239
9240    #[test]
9241    fn test_parse_where_clause() {
9242        let source = r#"
9243            fn alloc_array<T, A>(allocator: &mut A, count: usize) -> *mut T
9244            where
9245                A: Allocator,
9246            {
9247                return allocator.allocate(count, 8);
9248            }
9249        "#;
9250        let mut parser = Parser::new(source);
9251        let file = parser.parse_file().unwrap();
9252        assert_eq!(file.items.len(), 1);
9253
9254        if let Item::Function(func) = &file.items[0].node {
9255            assert!(func.where_clause.is_some());
9256            let wc = func.where_clause.as_ref().unwrap();
9257            assert_eq!(wc.predicates.len(), 1);
9258        } else {
9259            panic!("Expected function");
9260        }
9261    }
9262}