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