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