Skip to main content

logicaffeine_language/parser/
mod.rs

1//! Recursive descent parser for natural language to first-order logic.
2//!
3//! This module implements a hand-written recursive descent parser that transforms
4//! natural language sentences into logical expressions. The parser operates in two
5//! modes: **Declarative** for natural language propositions (Logicaffeine mode) and
6//! **Imperative** for strict, deterministic scoping (LOGOS mode).
7//!
8//! # Architecture
9//!
10//! The parser is split into specialized submodules:
11//!
12//! | Module | Responsibility |
13//! |--------|----------------|
14//! | `clause` | Sentence-level parsing: conditionals, conjunctions, relative clauses |
15//! | `noun` | Noun phrase parsing with determiners, adjectives, possessives |
16//! | `verb` | Verb phrase parsing, event semantics, thematic roles |
17//! | `modal` | Modal verbs (can, must, might) with Kripke semantics |
18//! | `quantifier` | Quantifier scope: every, some, no, most |
19//! | `question` | Wh-movement and question formation |
20//! | `pragmatics` | Pragmatic inference during parsing |
21//! | `common` | Shared utilities (copula lists, etc.) |
22//!
23//! # Key Types
24//!
25//! - [`Parser`]: The main parser struct holding tokens, state, and arenas
26//! - [`ParserMode`]: Declarative (NL) vs Imperative (LOGOS) mode
27//! - [`ParserGuard`]: RAII guard for speculative parsing with automatic rollback
28//! - [`NegativeScopeMode`]: Wide vs narrow scope for lexically negative verbs
29//! - [`ModalPreference`]: Default, epistemic, or deontic readings for modals
30//!
31//! # Example
32//!
33//! ```no_run
34//! use logicaffeine_language::parser::{Parser, ParserMode, ClauseParsing};
35//! # use logicaffeine_base::{Arena, Interner};
36//! # use logicaffeine_language::{lexer::Lexer, drs::WorldState, arena_ctx::AstContext, analysis::DiscoveryPass, ParseError};
37//! # fn main() -> Result<(), ParseError> {
38//! # let mut interner = Interner::new();
39//! # let mut lexer = Lexer::new("Every cat runs.", &mut interner);
40//! # let tokens = lexer.tokenize();
41//! # let type_registry = { let mut d = DiscoveryPass::new(&tokens, &mut interner); d.run() };
42//! # let ea = Arena::new(); let ta = Arena::new(); let na = Arena::new();
43//! # let sa = Arena::new(); let ra = Arena::new(); let pa = Arena::new();
44//! # let ctx = AstContext::new(&ea, &ta, &na, &sa, &ra, &pa);
45//! # let mut ws = WorldState::new();
46//! # let mut parser = Parser::new(tokens, &mut ws, &mut interner, ctx, type_registry);
47//!
48//! // Lexer produces tokens, then parser produces LogicExpr
49//! let expr = parser.parse_sentence()?;
50//! # Ok(())
51//! # }
52//! ```
53
54mod clause;
55mod common;
56mod modal;
57mod noun;
58mod pragmatics;
59mod quantifier;
60mod question;
61mod verb;
62
63#[cfg(test)]
64mod tests;
65
66pub use clause::ClauseParsing;
67pub use modal::ModalParsing;
68pub use noun::NounParsing;
69pub use pragmatics::PragmaticsParsing;
70pub use quantifier::QuantifierParsing;
71pub use question::QuestionParsing;
72pub use verb::{LogicVerbParsing, ImperativeVerbParsing};
73
74use crate::analysis::TypeRegistry;
75use crate::arena_ctx::AstContext;
76use crate::ast::{AspectOperator, LogicExpr, NeoEventData, NumberKind, QuantifierKind, TemporalOperator, Term, ThematicRole, Stmt, Expr, Literal, TypeExpr, BinaryOpKind, MatchArm};
77use crate::ast::stmt::{ReadSource, Pattern};
78use crate::drs::{Case, Gender, Number, ReferentSource};
79use crate::drs::{Drs, BoxType, WorldState};
80use crate::error::{ParseError, ParseErrorKind};
81use logicaffeine_base::{Interner, Symbol, SymbolEq};
82use crate::lexer::Lexer;
83use crate::lexicon::{self, Aspect, Definiteness, Time, VerbClass};
84use crate::token::{BlockType, FocusKind, Token, TokenType};
85
86pub(super) type ParseResult<T> = Result<T, ParseError>;
87
88use std::ops::{Deref, DerefMut};
89
90/// Determines how the parser interprets sentences.
91#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
92pub enum ParserMode {
93    /// Logicaffeine mode: propositions, NeoEvents, ambiguity allowed.
94    #[default]
95    Declarative,
96    /// LOGOS mode: statements, strict scoping, deterministic.
97    Imperative,
98}
99
100/// Controls scope of negation for lexically negative verbs (lacks, miss).
101/// "user who lacks a key" can mean:
102///   - Wide:   ¬∃y(Key(y) ∧ Have(x,y)) - "has NO keys" (natural reading)
103///   - Narrow: ∃y(Key(y) ∧ ¬Have(x,y)) - "missing SOME key" (literal reading)
104#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
105pub enum NegativeScopeMode {
106    /// Narrow scope negation (literal reading): ∃y(Key(y) ∧ ¬Have(x,y))
107    /// "User is missing some key" - need all keys (default/traditional reading)
108    #[default]
109    Narrow,
110    /// Wide scope negation (natural reading): ¬∃y(Key(y) ∧ Have(x,y))
111    /// "User has no keys" - need at least one key
112    Wide,
113}
114
115/// Controls interpretation of polysemous modals (may, can, could).
116/// Used by compile_forest to generate multiple semantic readings.
117///
118/// Semantic Matrix:
119///   may:   Default=Permission (Deontic, Root)    Epistemic=Possibility (Alethic, Epistemic)
120///   can:   Default=Ability (Alethic, Root)       Deontic=Permission (Deontic, Root)
121///   could: Default=PastAbility (Alethic, Root)   Epistemic=Possibility (Alethic, Epistemic)
122#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
123pub enum ModalPreference {
124    /// Default readings: may=Permission, can=Ability, could=PastAbility
125    #[default]
126    Default,
127    /// Epistemic readings: may=Possibility (wide scope), could=Possibility (wide scope)
128    Epistemic,
129    /// Deontic readings: can=Permission (narrow scope, deontic domain)
130    Deontic,
131}
132
133/// Result of pronoun resolution during parsing.
134///
135/// Determines whether a pronoun refers to a bound variable (anaphoric) or
136/// a deictic constant (referring to an entity outside the discourse).
137#[derive(Debug, Clone, Copy)]
138pub enum ResolvedPronoun {
139    /// Bound variable from DRS or telescope (use [`Term::Variable`]).
140    Variable(Symbol),
141    /// Constant (deictic or proper name) (use [`Term::Constant`]).
142    Constant(Symbol),
143}
144
145#[derive(Clone)]
146struct ParserCheckpoint {
147    pos: usize,
148    var_counter: usize,
149    bindings_len: usize,
150    island: u32,
151    time: Option<Time>,
152    negative_depth: u32,
153}
154
155/// RAII guard for speculative parsing with automatic rollback.
156///
157/// Created by [`Parser::guard()`], this guard saves the parser state
158/// on creation and automatically restores it if the guard is dropped
159/// without being committed.
160///
161/// # Usage
162///
163/// ```no_run
164/// # use logicaffeine_base::{Arena, Interner};
165/// # use logicaffeine_language::{lexer::Lexer, drs::WorldState, arena_ctx::AstContext, analysis::DiscoveryPass, ParseError};
166/// # use logicaffeine_language::parser::Parser;
167/// # fn try_parse<T>(_: &mut T) -> Result<(), ParseError> { todo!() }
168/// # fn main() -> Result<(), ParseError> {
169/// # let mut interner = Interner::new();
170/// # let mut lexer = Lexer::new("test.", &mut interner);
171/// # let tokens = lexer.tokenize();
172/// # let tr = { let mut d = DiscoveryPass::new(&tokens, &mut interner); d.run() };
173/// # let ea = Arena::new(); let ta = Arena::new(); let na = Arena::new();
174/// # let sa = Arena::new(); let ra = Arena::new(); let pa = Arena::new();
175/// # let ctx = AstContext::new(&ea, &ta, &na, &sa, &ra, &pa);
176/// # let mut ws = WorldState::new();
177/// # let mut parser = Parser::new(tokens, &mut ws, &mut interner, ctx, tr);
178/// let mut guard = parser.guard();
179/// if let Ok(result) = try_parse(&mut *guard) {
180///     guard.commit(); // Success - keep changes
181///     return Ok(result);
182/// }
183/// // guard dropped here - parser state restored
184/// # Ok(())
185/// # }
186/// ```
187pub struct ParserGuard<'p, 'a, 'ctx, 'int> {
188    parser: &'p mut Parser<'a, 'ctx, 'int>,
189    checkpoint: ParserCheckpoint,
190    committed: bool,
191}
192
193impl<'p, 'a, 'ctx, 'int> ParserGuard<'p, 'a, 'ctx, 'int> {
194    /// Commits the parse, preventing rollback when the guard is dropped.
195    pub fn commit(mut self) {
196        self.committed = true;
197    }
198}
199
200impl<'p, 'a, 'ctx, 'int> Drop for ParserGuard<'p, 'a, 'ctx, 'int> {
201    fn drop(&mut self) {
202        if !self.committed {
203            self.parser.restore(self.checkpoint.clone());
204        }
205    }
206}
207
208impl<'p, 'a, 'ctx, 'int> Deref for ParserGuard<'p, 'a, 'ctx, 'int> {
209    type Target = Parser<'a, 'ctx, 'int>;
210    fn deref(&self) -> &Self::Target {
211        self.parser
212    }
213}
214
215impl<'p, 'a, 'ctx, 'int> DerefMut for ParserGuard<'p, 'a, 'ctx, 'int> {
216    fn deref_mut(&mut self) -> &mut Self::Target {
217        self.parser
218    }
219}
220
221/// Template for constructing Neo-Davidsonian events.
222///
223/// Used during parsing to accumulate thematic roles and modifiers
224/// before the agent is known (e.g., in VP ellipsis resolution).
225#[derive(Clone, Debug)]
226pub struct EventTemplate<'a> {
227    /// The verb predicate.
228    pub verb: Symbol,
229    /// Thematic roles excluding the agent (filled later).
230    pub non_agent_roles: Vec<(ThematicRole, Term<'a>)>,
231    /// Adverbial modifiers.
232    pub modifiers: Vec<Symbol>,
233}
234
235/// Recursive descent parser for natural language to first-order logic.
236///
237/// The parser transforms a token stream (from [`Lexer`]) into logical expressions
238/// ([`LogicExpr`]). It handles complex linguistic phenomena including:
239///
240/// - Quantifier scope ambiguity
241/// - Pronoun resolution via DRS
242/// - Modal verb interpretation
243/// - Temporal and aspectual marking
244/// - VP ellipsis resolution
245///
246/// # Lifetimes
247///
248/// - `'a`: Arena lifetime for allocated AST nodes
249/// - `'ctx`: WorldState lifetime for discourse tracking
250/// - `'int`: Interner lifetime for symbol management
251pub struct Parser<'a, 'ctx, 'int> {
252    /// Token stream from lexer.
253    pub(super) tokens: Vec<Token>,
254    /// Current position in token stream.
255    pub(super) current: usize,
256    /// Counter for generating fresh variables.
257    pub(super) var_counter: usize,
258    /// Pending tense from temporal adverbs.
259    pub(super) pending_time: Option<Time>,
260    /// Donkey bindings: (noun, var, is_donkey_used, wide_scope_negation).
261    pub(super) donkey_bindings: Vec<(Symbol, Symbol, bool, bool)>,
262    /// String interner for symbol management.
263    pub(super) interner: &'int mut Interner,
264    /// Arena context for AST allocation.
265    pub(super) ctx: AstContext<'a>,
266    /// Current scope island ID.
267    pub(super) current_island: u32,
268    /// Whether PP attaches to noun (vs verb).
269    pub(super) pp_attach_to_noun: bool,
270    /// Filler for wh-movement gap.
271    pub(super) filler_gap: Option<Symbol>,
272    /// Depth of negation scope.
273    pub(super) negative_depth: u32,
274    /// Event variable for discourse coherence.
275    pub(super) discourse_event_var: Option<Symbol>,
276    /// Last event template for VP ellipsis.
277    pub(super) last_event_template: Option<EventTemplate<'a>>,
278    /// Whether to prefer noun readings.
279    pub(super) noun_priority_mode: bool,
280    /// Whether plural NPs get collective readings.
281    pub(super) collective_mode: bool,
282    /// Pending cardinal for delayed quantification.
283    pub(super) pending_cardinal: Option<u32>,
284    /// Parser mode: Declarative or Imperative.
285    pub(super) mode: ParserMode,
286    /// Type registry for LOGOS mode.
287    pub(super) type_registry: Option<TypeRegistry>,
288    /// Whether to produce event readings.
289    pub(super) event_reading_mode: bool,
290    /// Internal DRS for sentence-level scope tracking.
291    pub(super) drs: Drs,
292    /// Negation scope mode for lexically negative verbs.
293    pub(super) negative_scope_mode: NegativeScopeMode,
294    /// Modal interpretation preference.
295    pub(super) modal_preference: ModalPreference,
296    /// WorldState for discourse-level parsing.
297    pub(super) world_state: &'ctx mut WorldState,
298    /// Whether inside "No X" quantifier scope.
299    pub(super) in_negative_quantifier: bool,
300}
301
302impl<'a, 'ctx, 'int> Parser<'a, 'ctx, 'int> {
303    /// Create a parser with WorldState for discourse-level parsing.
304    /// WorldState is REQUIRED - there is no "single sentence mode".
305    /// A single sentence is just a discourse of length 1.
306    pub fn new(
307        tokens: Vec<Token>,
308        world_state: &'ctx mut WorldState,
309        interner: &'int mut Interner,
310        ctx: AstContext<'a>,
311        types: TypeRegistry,
312    ) -> Self {
313        Parser {
314            tokens,
315            current: 0,
316            var_counter: 0,
317            pending_time: None,
318            donkey_bindings: Vec::new(),
319            interner,
320            ctx,
321            current_island: 0,
322            pp_attach_to_noun: false,
323            filler_gap: None,
324            negative_depth: 0,
325            discourse_event_var: None,
326            last_event_template: None,
327            noun_priority_mode: false,
328            collective_mode: false,
329            pending_cardinal: None,
330            mode: ParserMode::Declarative,
331            type_registry: Some(types),
332            event_reading_mode: false,
333            drs: Drs::new(), // Internal DRS for sentence-level scope tracking
334            negative_scope_mode: NegativeScopeMode::default(),
335            modal_preference: ModalPreference::default(),
336            world_state,
337            in_negative_quantifier: false,
338        }
339    }
340
341    pub fn set_discourse_event_var(&mut self, var: Symbol) {
342        self.discourse_event_var = Some(var);
343    }
344
345    /// Get mutable reference to the active DRS (from WorldState).
346    pub fn drs_mut(&mut self) -> &mut Drs {
347        &mut self.world_state.drs
348    }
349
350    /// Get immutable reference to the active DRS (from WorldState).
351    pub fn drs_ref(&self) -> &Drs {
352        &self.world_state.drs
353    }
354
355    /// Swap DRS between Parser and WorldState.
356    /// Call at start of parsing to get the accumulated DRS from WorldState.
357    /// Call at end of parsing to save the updated DRS back to WorldState.
358    pub fn swap_drs_with_world_state(&mut self) {
359        std::mem::swap(&mut self.drs, &mut self.world_state.drs);
360    }
361
362    /// WorldState is always present (no "single sentence mode")
363    pub fn has_world_state(&self) -> bool {
364        true
365    }
366
367    pub fn mode(&self) -> ParserMode {
368        self.mode
369    }
370
371    /// Check if a symbol is a known type in the registry.
372    /// Used to disambiguate "Stack of Integers" (generic type) vs "Owner of House" (possessive).
373    pub fn is_known_type(&self, sym: Symbol) -> bool {
374        self.type_registry
375            .as_ref()
376            .map(|r| r.is_type(sym))
377            .unwrap_or(false)
378    }
379
380    /// Check if a symbol is a known generic type (takes type parameters).
381    /// Used to parse "Stack of Integers" as generic instantiation.
382    pub fn is_generic_type(&self, sym: Symbol) -> bool {
383        self.type_registry
384            .as_ref()
385            .map(|r| r.is_generic(sym))
386            .unwrap_or(false)
387    }
388
389    /// Get the parameter count for a generic type.
390    fn get_generic_param_count(&self, sym: Symbol) -> Option<usize> {
391        use crate::analysis::TypeDef;
392        self.type_registry.as_ref().and_then(|r| {
393            match r.get(sym) {
394                Some(TypeDef::Generic { param_count }) => Some(*param_count),
395                _ => None,
396            }
397        })
398    }
399
400    /// Phase 33: Check if a symbol is a known enum variant and return the enum name.
401    fn find_variant(&self, sym: Symbol) -> Option<Symbol> {
402        self.type_registry
403            .as_ref()
404            .and_then(|r| r.find_variant(sym).map(|(enum_name, _)| enum_name))
405    }
406
407    /// Consume a type name token (doesn't check entity registration).
408    fn consume_type_name(&mut self) -> ParseResult<Symbol> {
409        let t = self.advance().clone();
410        match t.kind {
411            TokenType::Noun(s) | TokenType::Adjective(s) => Ok(s),
412            TokenType::ProperName(s) => Ok(s),
413            // Verbs can be type names when lexed ambiguously (e.g., "Set" as type vs verb)
414            TokenType::Verb { .. } => Ok(t.lexeme),
415            // Phase 49b: CRDT type keywords are valid type names
416            TokenType::Tally => Ok(self.interner.intern("Tally")),
417            TokenType::SharedSet => Ok(self.interner.intern("SharedSet")),
418            TokenType::SharedSequence => Ok(self.interner.intern("SharedSequence")),
419            TokenType::CollaborativeSequence => Ok(self.interner.intern("CollaborativeSequence")),
420            TokenType::SharedMap => Ok(self.interner.intern("SharedMap")),
421            TokenType::Divergent => Ok(self.interner.intern("Divergent")),
422            other => Err(ParseError {
423                kind: ParseErrorKind::ExpectedContentWord { found: other },
424                span: self.current_span(),
425            }),
426        }
427    }
428
429    /// Parse a type expression: Int, Text, List of Int, Result of Int and Text.
430    /// Phase 36: Also supports "Type from Module" for qualified imports.
431    /// Uses TypeRegistry to distinguish primitives from generics.
432    /// Also handles `fn(A, B) -> C` function types.
433    fn parse_type_expression(&mut self) -> ParseResult<TypeExpr<'a>> {
434        use noun::NounParsing;
435
436        // Handle `fn(A, B) -> C` function type syntax
437        if self.check_word("fn") {
438            if let Some(next) = self.tokens.get(self.current + 1) {
439                if matches!(next.kind, TokenType::LParen) {
440                    self.advance(); // consume "fn"
441                    self.advance(); // consume "("
442
443                    // Parse input types
444                    let mut inputs = Vec::new();
445                    if !self.check(&TokenType::RParen) {
446                        inputs.push(self.parse_type_expression()?);
447                        while self.check(&TokenType::Comma) {
448                            self.advance(); // consume ","
449                            inputs.push(self.parse_type_expression()?);
450                        }
451                    }
452
453                    if !self.check(&TokenType::RParen) {
454                        return Err(ParseError {
455                            kind: ParseErrorKind::ExpectedKeyword { keyword: ")".to_string() },
456                            span: self.current_span(),
457                        });
458                    }
459                    self.advance(); // consume ")"
460
461                    // Expect ->
462                    if !self.check(&TokenType::Arrow) {
463                        return Err(ParseError {
464                            kind: ParseErrorKind::ExpectedKeyword { keyword: "->".to_string() },
465                            span: self.current_span(),
466                        });
467                    }
468                    self.advance(); // consume "->"
469
470                    let output = self.parse_type_expression()?;
471                    let output_ref = self.ctx.alloc_type_expr(output);
472                    let inputs_ref = self.ctx.alloc_type_exprs(inputs);
473                    return Ok(TypeExpr::Function { inputs: inputs_ref, output: output_ref });
474                }
475            }
476        }
477
478        // Bug fix: Handle parenthesized type expressions: "Seq of (Seq of Int)"
479        if self.check(&TokenType::LParen) {
480            self.advance(); // consume "("
481            let inner = self.parse_type_expression()?;
482            if !self.check(&TokenType::RParen) {
483                return Err(ParseError {
484                    kind: ParseErrorKind::ExpectedKeyword { keyword: ")".to_string() },
485                    span: self.current_span(),
486                });
487            }
488            self.advance(); // consume ")"
489            return Ok(inner);
490        }
491
492        // Phase 53: Handle "Persistent T" type modifier
493        if self.check(&TokenType::Persistent) {
494            self.advance(); // consume "Persistent"
495            let inner = self.parse_type_expression()?;
496            let inner_ref = self.ctx.alloc_type_expr(inner);
497            return Ok(TypeExpr::Persistent { inner: inner_ref });
498        }
499
500        // Get the base type name (must be a noun or proper name - type names bypass entity check)
501        let mut base = self.consume_type_name()?;
502
503        // Phase 49c: Check for bias modifier on SharedSet: "SharedSet (RemoveWins) of T"
504        let base_name = self.interner.resolve(base);
505        if base_name == "SharedSet" || base_name == "ORSet" {
506            if self.check(&TokenType::LParen) {
507                self.advance(); // consume "("
508                if self.check(&TokenType::RemoveWins) {
509                    self.advance(); // consume "RemoveWins"
510                    base = self.interner.intern("SharedSet_RemoveWins");
511                } else if self.check(&TokenType::AddWins) {
512                    self.advance(); // consume "AddWins"
513                    // AddWins is default, but we can be explicit
514                    base = self.interner.intern("SharedSet_AddWins");
515                }
516                if !self.check(&TokenType::RParen) {
517                    return Err(ParseError {
518                        kind: ParseErrorKind::ExpectedKeyword { keyword: ")".to_string() },
519                        span: self.current_span(),
520                    });
521                }
522                self.advance(); // consume ")"
523            }
524        }
525
526        // Phase 49c: Check for algorithm modifier on SharedSequence: "SharedSequence (YATA) of T"
527        let base_name = self.interner.resolve(base);
528        if base_name == "SharedSequence" || base_name == "RGA" {
529            if self.check(&TokenType::LParen) {
530                self.advance(); // consume "("
531                if self.check(&TokenType::YATA) {
532                    self.advance(); // consume "YATA"
533                    base = self.interner.intern("SharedSequence_YATA");
534                }
535                if !self.check(&TokenType::RParen) {
536                    return Err(ParseError {
537                        kind: ParseErrorKind::ExpectedKeyword { keyword: ")".to_string() },
538                        span: self.current_span(),
539                    });
540                }
541                self.advance(); // consume ")"
542            }
543        }
544
545        // Phase 36: Check for "from Module" qualification
546        let base_type = if self.check(&TokenType::From) {
547            self.advance(); // consume "from"
548            let module_name = self.consume_type_name()?;
549            let module_str = self.interner.resolve(module_name);
550            let base_str = self.interner.resolve(base);
551            let qualified = format!("{}::{}", module_str, base_str);
552            let qualified_sym = self.interner.intern(&qualified);
553            TypeExpr::Named(qualified_sym)
554        } else {
555            // Phase 38: Get param count from registry OR from built-in std types
556            let base_name = self.interner.resolve(base);
557            let param_count = self.get_generic_param_count(base)
558                .or_else(|| match base_name {
559                    // Built-in generic types for Phase 38 std library
560                    "Result" => Some(2),    // Result of T and E
561                    "Option" => Some(1),    // Option of T
562                    "Seq" | "List" | "Vec" => Some(1),  // Seq of T
563                    "Set" | "HashSet" => Some(1), // Set of T
564                    "Map" | "HashMap" => Some(2), // Map of K and V
565                    "Pair" => Some(2),      // Pair of A and B
566                    "Triple" => Some(3),    // Triple of A and B and C
567                    // Phase 49b: CRDT generic types
568                    "SharedSet" | "ORSet" | "SharedSet_AddWins" | "SharedSet_RemoveWins" => Some(1),
569                    "SharedSequence" | "RGA" | "SharedSequence_YATA" | "CollaborativeSequence" => Some(1),
570                    "SharedMap" | "ORMap" => Some(2),      // SharedMap from K to V
571                    "Divergent" | "MVRegister" => Some(1), // Divergent T
572                    _ => None,
573                });
574
575            // Check if it's a known generic type with parameters
576            if let Some(count) = param_count {
577                if self.check_of_preposition() || self.check_preposition_is("from") {
578                    self.advance(); // consume "of" or "from"
579
580                    let mut params = Vec::new();
581                    for i in 0..count {
582                        if i > 0 {
583                            // Expect separator for params > 1: "and", "to", or ","
584                            if self.check(&TokenType::And) || self.check_to_preposition() || self.check(&TokenType::Comma) {
585                                self.advance();
586                            }
587                        }
588                        let param = self.parse_type_expression()?;
589                        params.push(param);
590                    }
591
592                    let params_slice = self.ctx.alloc_type_exprs(params);
593                    TypeExpr::Generic { base, params: params_slice }
594                } else {
595                    // Generic type without parameters - treat as primitive or named
596                    let is_primitive = self.type_registry.as_ref().map(|r| r.is_type(base)).unwrap_or(false)
597                        || matches!(base_name, "Int" | "Nat" | "Text" | "Bool" | "Boolean" | "Real" | "Unit");
598                    if is_primitive {
599                        TypeExpr::Primitive(base)
600                    } else {
601                        TypeExpr::Named(base)
602                    }
603                }
604            } else {
605                // Check if it's a known primitive type (Int, Nat, Text, Bool, Real, Unit)
606                let is_primitive = self.type_registry.as_ref().map(|r| r.is_type(base)).unwrap_or(false)
607                    || matches!(base_name, "Int" | "Nat" | "Text" | "Bool" | "Boolean" | "Real" | "Unit");
608                if is_primitive {
609                    TypeExpr::Primitive(base)
610                } else {
611                    // User-defined or unknown type
612                    TypeExpr::Named(base)
613                }
614            }
615        };
616
617        // Phase 43C: Check for refinement "where" clause
618        if self.check(&TokenType::Where) {
619            self.advance(); // consume "where"
620
621            // Parse the predicate expression (supports compound: `x > 0 and x < 100`)
622            let predicate_expr = self.parse_condition()?;
623
624            // Extract bound variable from the left side of the expression
625            let bound_var = self.extract_bound_var(&predicate_expr)
626                .unwrap_or_else(|| self.interner.intern("it"));
627
628            // Convert imperative Expr to logic LogicExpr
629            let predicate = self.expr_to_logic_predicate(&predicate_expr, bound_var)
630                .ok_or_else(|| ParseError {
631                    kind: ParseErrorKind::InvalidRefinementPredicate,
632                    span: self.peek().span,
633                })?;
634
635            // Allocate the base type
636            let base_alloc = self.ctx.alloc_type_expr(base_type);
637
638            return Ok(TypeExpr::Refinement { base: base_alloc, var: bound_var, predicate });
639        }
640
641        Ok(base_type)
642    }
643
644    /// Extracts the leftmost identifier from an expression as the bound variable.
645    fn extract_bound_var(&self, expr: &Expr<'a>) -> Option<Symbol> {
646        match expr {
647            Expr::Identifier(sym) => Some(*sym),
648            Expr::BinaryOp { left, .. } => self.extract_bound_var(left),
649            _ => None,
650        }
651    }
652
653    /// Converts an imperative comparison Expr to a Logic Kernel LogicExpr.
654    /// Used for refinement type predicates: `Int where x > 0`
655    fn expr_to_logic_predicate(&mut self, expr: &Expr<'a>, bound_var: Symbol) -> Option<&'a LogicExpr<'a>> {
656        match expr {
657            Expr::BinaryOp { op, left, right } => {
658                // Map BinaryOpKind to predicate name
659                let pred_name = match op {
660                    BinaryOpKind::Gt => "Greater",
661                    BinaryOpKind::Lt => "Less",
662                    BinaryOpKind::GtEq => "GreaterEqual",
663                    BinaryOpKind::LtEq => "LessEqual",
664                    BinaryOpKind::Eq => "Equal",
665                    BinaryOpKind::NotEq => "NotEqual",
666                    BinaryOpKind::And => {
667                        // Handle compound `x > 0 and x < 100`
668                        let left_logic = self.expr_to_logic_predicate(left, bound_var)?;
669                        let right_logic = self.expr_to_logic_predicate(right, bound_var)?;
670                        return Some(self.ctx.exprs.alloc(LogicExpr::BinaryOp {
671                            left: left_logic,
672                            op: TokenType::And,
673                            right: right_logic,
674                        }));
675                    }
676                    BinaryOpKind::Or => {
677                        let left_logic = self.expr_to_logic_predicate(left, bound_var)?;
678                        let right_logic = self.expr_to_logic_predicate(right, bound_var)?;
679                        return Some(self.ctx.exprs.alloc(LogicExpr::BinaryOp {
680                            left: left_logic,
681                            op: TokenType::Or,
682                            right: right_logic,
683                        }));
684                    }
685                    _ => return None, // Arithmetic ops not valid as predicates
686                };
687                let pred_sym = self.interner.intern(pred_name);
688
689                // Convert operands to Terms
690                let left_term = self.expr_to_term(left)?;
691                let right_term = self.expr_to_term(right)?;
692
693                let args = self.ctx.terms.alloc_slice([left_term, right_term]);
694                Some(self.ctx.exprs.alloc(LogicExpr::Predicate { name: pred_sym, args, world: None }))
695            }
696            _ => None,
697        }
698    }
699
700    /// Converts an imperative Expr to a logic Term.
701    fn expr_to_term(&mut self, expr: &Expr<'a>) -> Option<Term<'a>> {
702        match expr {
703            Expr::Identifier(sym) => Some(Term::Variable(*sym)),
704            Expr::Literal(lit) => {
705                match lit {
706                    Literal::Number(n) => Some(Term::Value {
707                        kind: NumberKind::Integer(*n),
708                        unit: None,
709                        dimension: None,
710                    }),
711                    Literal::Boolean(b) => {
712                        let sym = self.interner.intern(if *b { "true" } else { "false" });
713                        Some(Term::Constant(sym))
714                    }
715                    _ => None, // Text, Nothing not supported in predicates
716                }
717            }
718            _ => None,
719        }
720    }
721
722    pub fn process_block_headers(&mut self) {
723        use crate::token::BlockType;
724
725        while self.current < self.tokens.len() {
726            if let TokenType::BlockHeader { block_type } = &self.tokens[self.current].kind {
727                self.mode = match block_type {
728                    BlockType::Main | BlockType::Function => ParserMode::Imperative,
729                    BlockType::Theorem | BlockType::Definition | BlockType::Proof |
730                    BlockType::Example | BlockType::Logic | BlockType::Note | BlockType::TypeDef |
731                    BlockType::Policy | BlockType::Requires => ParserMode::Declarative,
732                };
733                self.current += 1;
734            } else {
735                break;
736            }
737        }
738    }
739
740    pub fn get_event_var(&mut self) -> Symbol {
741        self.discourse_event_var.unwrap_or_else(|| self.interner.intern("e"))
742    }
743
744    pub fn capture_event_template(&mut self, verb: Symbol, roles: &[(ThematicRole, Term<'a>)], modifiers: &[Symbol]) {
745        let non_agent_roles: Vec<_> = roles.iter()
746            .filter(|(role, _)| *role != ThematicRole::Agent)
747            .cloned()
748            .collect();
749        self.last_event_template = Some(EventTemplate {
750            verb,
751            non_agent_roles,
752            modifiers: modifiers.to_vec(),
753        });
754    }
755
756    fn parse_embedded_wh_clause(&mut self) -> ParseResult<&'a LogicExpr<'a>> {
757        // Parse embedded question body: "who runs", "what John ate"
758        let var_name = self.interner.intern("x");
759        let var_term = Term::Variable(var_name);
760
761        if self.check_verb() {
762            // "who runs" pattern
763            let verb = self.consume_verb();
764            let body = self.ctx.exprs.alloc(LogicExpr::Predicate {
765                name: verb,
766                args: self.ctx.terms.alloc_slice([var_term]),
767                world: None,
768            });
769            return Ok(body);
770        }
771
772        if self.check_content_word() || self.check_article() {
773            // "what John ate" pattern
774            let subject = self.parse_noun_phrase(true)?;
775            if self.check_verb() {
776                let verb = self.consume_verb();
777                let body = self.ctx.exprs.alloc(LogicExpr::Predicate {
778                    name: verb,
779                    args: self.ctx.terms.alloc_slice([
780                        Term::Constant(subject.noun),
781                        var_term,
782                    ]),
783                    world: None,
784                });
785                return Ok(body);
786            }
787        }
788
789        // Fallback: just the wh-variable
790        Ok(self.ctx.exprs.alloc(LogicExpr::Atom(var_name)))
791    }
792
793    pub fn set_pp_attachment_mode(&mut self, attach_to_noun: bool) {
794        self.pp_attach_to_noun = attach_to_noun;
795    }
796
797    pub fn set_noun_priority_mode(&mut self, mode: bool) {
798        self.noun_priority_mode = mode;
799    }
800
801    pub fn set_collective_mode(&mut self, mode: bool) {
802        self.collective_mode = mode;
803    }
804
805    pub fn set_event_reading_mode(&mut self, mode: bool) {
806        self.event_reading_mode = mode;
807    }
808
809    pub fn set_negative_scope_mode(&mut self, mode: NegativeScopeMode) {
810        self.negative_scope_mode = mode;
811    }
812
813    pub fn set_modal_preference(&mut self, pref: ModalPreference) {
814        self.modal_preference = pref;
815    }
816
817    fn checkpoint(&self) -> ParserCheckpoint {
818        ParserCheckpoint {
819            pos: self.current,
820            var_counter: self.var_counter,
821            bindings_len: self.donkey_bindings.len(),
822            island: self.current_island,
823            time: self.pending_time,
824            negative_depth: self.negative_depth,
825        }
826    }
827
828    fn restore(&mut self, cp: ParserCheckpoint) {
829        self.current = cp.pos;
830        self.var_counter = cp.var_counter;
831        self.donkey_bindings.truncate(cp.bindings_len);
832        self.current_island = cp.island;
833        self.pending_time = cp.time;
834        self.negative_depth = cp.negative_depth;
835    }
836
837    fn is_negative_context(&self) -> bool {
838        self.negative_depth % 2 == 1
839    }
840
841    pub fn guard(&mut self) -> ParserGuard<'_, 'a, 'ctx, 'int> {
842        ParserGuard {
843            checkpoint: self.checkpoint(),
844            parser: self,
845            committed: false,
846        }
847    }
848
849    pub(super) fn try_parse<F, T>(&mut self, op: F) -> Option<T>
850    where
851        F: FnOnce(&mut Self) -> ParseResult<T>,
852    {
853        let cp = self.checkpoint();
854        match op(self) {
855            Ok(res) => Some(res),
856            Err(_) => {
857                self.restore(cp);
858                None
859            }
860        }
861    }
862
863    fn resolve_pronoun(&mut self, gender: Gender, number: Number) -> ParseResult<ResolvedPronoun> {
864        // MODAL BARRIER: In discourse mode, try telescope FIRST if prior sentence was modal.
865        // This ensures the modal barrier check runs before we search the swapped DRS.
866        // The DRS contains referents from all prior sentences (merged via swap), but
867        // telescope has modal filtering to block hypothetical entities from reality.
868        if self.world_state.in_discourse_mode() && self.world_state.has_prior_modal_context() {
869            // Only use telescope for cross-sentence reference when prior was modal
870            // Telescope has modal barrier: won't return modal candidates unless we're in modal context
871            if let Some(candidate) = self.world_state.resolve_via_telescope(gender) {
872                return Ok(ResolvedPronoun::Variable(candidate.variable));
873            }
874            // Modal barrier blocked telescope resolution - pronoun can't access hypothetical entities
875            // from the prior modal sentence. Check if there are ANY telescope candidates that
876            // were blocked due to modal scope. If so, this is a modal barrier error.
877            let blocked_candidates: Vec<_> = self.world_state.telescope_candidates()
878                .iter()
879                .filter(|c| c.in_modal_scope)
880                .collect();
881            if !blocked_candidates.is_empty() {
882                // Before returning error, look ahead for modal subordinating verbs (would, could, etc.)
883                // If we see one, this sentence is also modal and can access the hypothetical entity.
884                let has_upcoming_modal = self.has_modal_subordination_ahead();
885                if has_upcoming_modal {
886                    // Modal subordination detected - allow access to the first matching candidate
887                    if let Some(candidate) = blocked_candidates.into_iter().find(|c| {
888                        c.gender == gender || gender == Gender::Unknown || c.gender == Gender::Unknown
889                    }) {
890                        return Ok(ResolvedPronoun::Variable(candidate.variable));
891                    }
892                }
893                // There were candidates but they're all in modal scope - modal barrier blocks access
894                return Err(ParseError {
895                    kind: ParseErrorKind::ScopeViolation(
896                        "Cannot access hypothetical entity from reality. Use modal subordination (e.g., 'would') to continue a hypothetical context.".to_string()
897                    ),
898                    span: self.current_span(),
899                });
900            }
901            // No modal candidates were blocked, continue to check for same-sentence referents
902        }
903
904        // Try DRS resolution (scope-aware) for same-sentence referents
905        let current_box = self.drs.current_box_index();
906        match self.drs.resolve_pronoun(current_box, gender, number) {
907            Ok(sym) => return Ok(ResolvedPronoun::Variable(sym)),
908            Err(crate::drs::ScopeError::InaccessibleReferent { gender: g, reason, .. }) => {
909                // Referent exists but is trapped in inaccessible scope.
910                // In multi-sentence discourse, try telescoping first - the referent
911                // from a previous sentence's conditional may be in telescope candidates.
912                if self.world_state.in_discourse_mode() {
913                    if let Some(candidate) = self.world_state.resolve_via_telescope(g) {
914                        return Ok(ResolvedPronoun::Variable(candidate.variable));
915                    }
916                }
917                // No telescope candidate found - this is a hard scope error
918                return Err(ParseError {
919                    kind: ParseErrorKind::ScopeViolation(reason),
920                    span: self.current_span(),
921                });
922            }
923            Err(crate::drs::ScopeError::NoMatchingReferent { gender: g, number: n }) => {
924                // Try telescoping across sentence boundaries (if not already tried above)
925                if !self.world_state.has_prior_modal_context() {
926                    if let Some(candidate) = self.world_state.resolve_via_telescope(g) {
927                        return Ok(ResolvedPronoun::Variable(candidate.variable));
928                    }
929                }
930
931                // In discourse mode (multi-sentence context), unresolved pronouns are an error
932                if self.world_state.in_discourse_mode() {
933                    return Err(ParseError {
934                        kind: ParseErrorKind::UnresolvedPronoun {
935                            gender: g,
936                            number: n,
937                        },
938                        span: self.current_span(),
939                    });
940                }
941
942                // No prior referent - introduce deictic referent (pointing to someone in the world)
943                // This handles sentences like "She told him a story" without prior discourse
944                let deictic_name = match (g, n) {
945                    (Gender::Male, Number::Singular) => "Him",
946                    (Gender::Female, Number::Singular) => "Her",
947                    (Gender::Neuter, Number::Singular) => "It",
948                    (Gender::Male, Number::Plural) | (Gender::Female, Number::Plural) => "Them",
949                    (Gender::Neuter, Number::Plural) => "Them",
950                    (Gender::Unknown, _) => "Someone",
951                };
952                let sym = self.interner.intern(deictic_name);
953                // Introduce the deictic referent to DRS for potential later reference
954                self.drs.introduce_referent(sym, sym, g, n);
955                return Ok(ResolvedPronoun::Constant(sym));
956            }
957        }
958    }
959
960    fn resolve_donkey_pronoun(&mut self, gender: Gender) -> Option<Symbol> {
961        for (noun_class, var_name, used, _wide_neg) in self.donkey_bindings.iter_mut().rev() {
962            let noun_str = self.interner.resolve(*noun_class);
963            let noun_gender = Self::infer_noun_gender(noun_str);
964            if noun_gender == gender || gender == Gender::Neuter || noun_gender == Gender::Unknown {
965                *used = true; // Mark as used by a pronoun (donkey anaphor)
966                return Some(*var_name);
967            }
968        }
969        None
970    }
971
972    fn infer_noun_gender(noun: &str) -> Gender {
973        let lower = noun.to_lowercase();
974        if lexicon::is_female_noun(&lower) {
975            Gender::Female
976        } else if lexicon::is_male_noun(&lower) {
977            Gender::Male
978        } else if lexicon::is_neuter_noun(&lower) {
979            Gender::Neuter
980        } else {
981            Gender::Unknown
982        }
983    }
984
985    fn is_plural_noun(noun: &str) -> bool {
986        let lower = noun.to_lowercase();
987        // Proper names like "Socrates", "James", "Chris" end in 's' but aren't plurals
988        if lexicon::is_proper_name(&lower) {
989            return false;
990        }
991        if lexicon::is_irregular_plural(&lower) {
992            return true;
993        }
994        lower.ends_with('s') && !lower.ends_with("ss") && lower.len() > 2
995    }
996
997    fn singularize_noun(noun: &str) -> String {
998        let lower = noun.to_lowercase();
999        if let Some(singular) = lexicon::singularize(&lower) {
1000            return singular.to_string();
1001        }
1002        if lower.ends_with('s') && !lower.ends_with("ss") && lower.len() > 2 {
1003            let base = &lower[..lower.len() - 1];
1004            let mut chars: Vec<char> = base.chars().collect();
1005            if !chars.is_empty() {
1006                chars[0] = chars[0].to_uppercase().next().unwrap();
1007            }
1008            return chars.into_iter().collect();
1009        }
1010        let mut chars: Vec<char> = lower.chars().collect();
1011        if !chars.is_empty() {
1012            chars[0] = chars[0].to_uppercase().next().unwrap();
1013        }
1014        chars.into_iter().collect()
1015    }
1016
1017    fn infer_gender(name: &str) -> Gender {
1018        let lower = name.to_lowercase();
1019        if lexicon::is_male_name(&lower) {
1020            Gender::Male
1021        } else if lexicon::is_female_name(&lower) {
1022            Gender::Female
1023        } else {
1024            Gender::Unknown
1025        }
1026    }
1027
1028
1029    fn next_var_name(&mut self) -> Symbol {
1030        const VARS: &[&str] = &["x", "y", "z", "w", "v", "u"];
1031        let idx = self.var_counter;
1032        self.var_counter += 1;
1033        if idx < VARS.len() {
1034            self.interner.intern(VARS[idx])
1035        } else {
1036            let name = format!("x{}", idx - VARS.len() + 1);
1037            self.interner.intern(&name)
1038        }
1039    }
1040
1041    /// Parses the token stream into a logical expression.
1042    ///
1043    /// This is the main entry point for declarative/FOL parsing. It handles
1044    /// multi-sentence inputs by conjoining them with logical AND, and processes
1045    /// various sentence types including declaratives, questions, and imperatives.
1046    ///
1047    /// # Returns
1048    ///
1049    /// An arena-allocated [`LogicExpr`] representing the parsed input, or
1050    /// a [`ParseError`] with source location and Socratic explanation.
1051    ///
1052    /// # Discourse State
1053    ///
1054    /// The parser maintains discourse state across sentences, enabling
1055    /// anaphora resolution ("he", "she", "they" refer to prior entities)
1056    /// and temporal coherence (tense interpretation relative to reference time).
1057    pub fn parse(&mut self) -> ParseResult<&'a LogicExpr<'a>> {
1058        let mut result = self.parse_sentence()?;
1059
1060        // Loop: handle ANY number of additional sentences (unlimited)
1061        // Handle all sentence terminators: . ? !
1062        while self.check(&TokenType::Period) || self.check(&TokenType::Exclamation) {
1063            self.advance(); // consume terminator
1064            if !self.is_at_end() {
1065                let next = self.parse_sentence()?;
1066                result = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
1067                    left: result,
1068                    op: TokenType::And,
1069                    right: next,
1070                });
1071            }
1072        }
1073
1074        Ok(result)
1075    }
1076
1077    /// Parses a LOGOS program into a list of statements.
1078    ///
1079    /// This is the main entry point for imperative/executable LOGOS code.
1080    /// It handles block structures (Definition, Policy, Procedure, Theorem),
1081    /// function definitions, type definitions, and executable statements.
1082    ///
1083    /// # Returns
1084    ///
1085    /// A vector of arena-allocated [`Stmt`] representing the program, or
1086    /// a [`ParseError`] with source location and Socratic explanation.
1087    ///
1088    /// # Block Types
1089    ///
1090    /// - **Definition**: Type definitions (structs, enums, generics)
1091    /// - **Policy**: Security predicates and capability rules
1092    /// - **Procedure**: Executable code blocks
1093    /// - **Theorem**: Logical propositions with proof strategies
1094    pub fn parse_program(&mut self) -> ParseResult<Vec<Stmt<'a>>> {
1095        let mut statements = Vec::new();
1096        let mut in_definition_block = false;
1097
1098        // Check if we started in a Definition block (from process_block_headers)
1099        if self.mode == ParserMode::Declarative {
1100            // Check if the previous token was a Definition header
1101            // For now, assume Definition blocks should be skipped
1102            // We'll detect them by checking the content pattern
1103        }
1104
1105        while !self.is_at_end() {
1106            // Handle block headers
1107            if let Some(Token { kind: TokenType::BlockHeader { block_type }, .. }) = self.tokens.get(self.current) {
1108                match block_type {
1109                    BlockType::Definition => {
1110                        in_definition_block = true;
1111                        self.mode = ParserMode::Declarative;
1112                        self.advance();
1113                        continue;
1114                    }
1115                    BlockType::Main => {
1116                        in_definition_block = false;
1117                        self.mode = ParserMode::Imperative;
1118                        self.advance();
1119                        continue;
1120                    }
1121                    BlockType::Function => {
1122                        in_definition_block = false;
1123                        self.mode = ParserMode::Imperative;
1124                        self.advance();
1125                        // Parse function definition
1126                        let func_def = self.parse_function_def()?;
1127                        statements.push(func_def);
1128                        continue;
1129                    }
1130                    BlockType::TypeDef => {
1131                        // Type definitions are handled by DiscoveryPass
1132                        // Skip content until next block header
1133                        self.advance();
1134                        self.skip_type_def_content();
1135                        continue;
1136                    }
1137                    BlockType::Policy => {
1138                        // Phase 50: Policy definitions are handled by DiscoveryPass
1139                        // Skip content until next block header
1140                        in_definition_block = true;  // Reuse flag to skip content
1141                        self.mode = ParserMode::Declarative;
1142                        self.advance();
1143                        continue;
1144                    }
1145                    BlockType::Theorem => {
1146                        // Phase 63: Parse theorem block
1147                        in_definition_block = false;
1148                        self.mode = ParserMode::Declarative;
1149                        self.advance();
1150                        let theorem = self.parse_theorem_block()?;
1151                        statements.push(theorem);
1152                        continue;
1153                    }
1154                    BlockType::Requires => {
1155                        in_definition_block = false;
1156                        self.mode = ParserMode::Declarative;
1157                        self.advance();
1158                        let deps = self.parse_requires_block()?;
1159                        statements.extend(deps);
1160                        continue;
1161                    }
1162                    _ => {
1163                        // Skip other declarative blocks (Proof, Example, Logic, Note)
1164                        in_definition_block = false;
1165                        self.mode = ParserMode::Declarative;
1166                        self.advance();
1167                        continue;
1168                    }
1169                }
1170            }
1171
1172            // Skip Definition block content - handled by DiscoveryPass
1173            if in_definition_block {
1174                self.advance();
1175                continue;
1176            }
1177
1178            // Skip indent/dedent/newline tokens at program level
1179            if self.check(&TokenType::Indent) || self.check(&TokenType::Dedent) || self.check(&TokenType::Newline) {
1180                self.advance();
1181                continue;
1182            }
1183
1184            // In imperative mode, parse statements
1185            if self.mode == ParserMode::Imperative {
1186                let stmt = self.parse_statement()?;
1187                statements.push(stmt);
1188
1189                if self.check(&TokenType::Period) {
1190                    self.advance();
1191                }
1192            } else {
1193                // In declarative mode (Theorem, etc.), skip for now
1194                self.advance();
1195            }
1196        }
1197
1198        Ok(statements)
1199    }
1200
1201    fn parse_statement(&mut self) -> ParseResult<Stmt<'a>> {
1202        // Phase 32: Function definitions can appear inside Main block
1203        // Handle both TokenType::To and Preposition("to")
1204        if self.check(&TokenType::To) || self.check_preposition_is("to") {
1205            return self.parse_function_def();
1206        }
1207        if self.check(&TokenType::Let) {
1208            return self.parse_let_statement();
1209        }
1210        // Phase 23b: Equals-style assignment with explicit `mut` keyword
1211        // Syntax: `mut x = 5` or `mut x: Int = 5`
1212        if self.check(&TokenType::Mut) {
1213            return self.parse_equals_assignment(true);
1214        }
1215        // Phase 23b: Equals-style assignment (identifier = value)
1216        // Syntax: `x = 5` or `x: Int = 5`
1217        if self.peek_equals_assignment() {
1218            return self.parse_equals_assignment(false);
1219        }
1220        if self.check(&TokenType::Set) {
1221            return self.parse_set_statement();
1222        }
1223        if self.check(&TokenType::Return) {
1224            return self.parse_return_statement();
1225        }
1226        if self.check(&TokenType::If) {
1227            return self.parse_if_statement();
1228        }
1229        if self.check(&TokenType::Assert) {
1230            return self.parse_assert_statement();
1231        }
1232        // Phase 35: Trust statement
1233        if self.check(&TokenType::Trust) {
1234            return self.parse_trust_statement();
1235        }
1236        // Phase 50: Security Check statement
1237        if self.check(&TokenType::Check) {
1238            return self.parse_check_statement();
1239        }
1240        // Phase 51: P2P Networking statements
1241        if self.check(&TokenType::Listen) {
1242            return self.parse_listen_statement();
1243        }
1244        if self.check(&TokenType::NetConnect) {
1245            return self.parse_connect_statement();
1246        }
1247        if self.check(&TokenType::Sleep) {
1248            return self.parse_sleep_statement();
1249        }
1250        // Phase 52: GossipSub sync statement
1251        if self.check(&TokenType::Sync) {
1252            return self.parse_sync_statement();
1253        }
1254        // Phase 53: Persistent storage mount statement
1255        if self.check(&TokenType::Mount) {
1256            return self.parse_mount_statement();
1257        }
1258        if self.check(&TokenType::While) {
1259            return self.parse_while_statement();
1260        }
1261        if self.check(&TokenType::Repeat) {
1262            return self.parse_repeat_statement();
1263        }
1264        // Phase 30b: Allow "for" without "Repeat" keyword
1265        if self.check(&TokenType::For) {
1266            return self.parse_for_statement();
1267        }
1268        if self.check(&TokenType::Call) {
1269            return self.parse_call_statement();
1270        }
1271        if self.check(&TokenType::Give) {
1272            return self.parse_give_statement();
1273        }
1274        if self.check(&TokenType::Show) {
1275            return self.parse_show_statement();
1276        }
1277        // Phase 33: Pattern matching on sum types
1278        if self.check(&TokenType::Inspect) {
1279            return self.parse_inspect_statement();
1280        }
1281
1282        // Phase 43D: Collection operations
1283        if self.check(&TokenType::Push) {
1284            return self.parse_push_statement();
1285        }
1286        if self.check(&TokenType::Pop) {
1287            return self.parse_pop_statement();
1288        }
1289        // Set operations
1290        if self.check(&TokenType::Add) {
1291            return self.parse_add_statement();
1292        }
1293        if self.check(&TokenType::Remove) {
1294            return self.parse_remove_statement();
1295        }
1296
1297        // Phase 8.5: Memory zone block
1298        if self.check(&TokenType::Inside) {
1299            return self.parse_zone_statement();
1300        }
1301
1302        // Phase 9: Structured Concurrency blocks
1303        if self.check(&TokenType::Attempt) {
1304            return self.parse_concurrent_block();
1305        }
1306        if self.check(&TokenType::Simultaneously) {
1307            return self.parse_parallel_block();
1308        }
1309
1310        // Phase 10: IO statements
1311        if self.check(&TokenType::Read) {
1312            return self.parse_read_statement();
1313        }
1314        if self.check(&TokenType::Write) {
1315            return self.parse_write_statement();
1316        }
1317
1318        // Phase 46: Agent System statements
1319        if self.check(&TokenType::Spawn) {
1320            return self.parse_spawn_statement();
1321        }
1322        if self.check(&TokenType::Send) {
1323            // Phase 54: Disambiguate "Send x into pipe" vs "Send x to agent"
1324            if self.lookahead_contains_into() {
1325                return self.parse_send_pipe_statement();
1326            }
1327            return self.parse_send_statement();
1328        }
1329        if self.check(&TokenType::Await) {
1330            // Phase 54: Disambiguate "Await the first of:" vs "Await response from agent"
1331            if self.lookahead_is_first_of() {
1332                return self.parse_select_statement();
1333            }
1334            return self.parse_await_statement();
1335        }
1336
1337        // Phase 49: CRDT statements
1338        if self.check(&TokenType::Merge) {
1339            return self.parse_merge_statement();
1340        }
1341        if self.check(&TokenType::Increase) {
1342            return self.parse_increase_statement();
1343        }
1344        // Phase 49b: Extended CRDT statements
1345        if self.check(&TokenType::Decrease) {
1346            return self.parse_decrease_statement();
1347        }
1348        if self.check(&TokenType::Append) {
1349            return self.parse_append_statement();
1350        }
1351        if self.check(&TokenType::Resolve) {
1352            return self.parse_resolve_statement();
1353        }
1354
1355        // Phase 54: Go-like Concurrency statements
1356        if self.check(&TokenType::Launch) {
1357            return self.parse_launch_statement();
1358        }
1359        if self.check(&TokenType::Stop) {
1360            return self.parse_stop_statement();
1361        }
1362        if self.check(&TokenType::Try) {
1363            return self.parse_try_statement();
1364        }
1365        if self.check(&TokenType::Receive) {
1366            return self.parse_receive_pipe_statement();
1367        }
1368
1369        // Escape hatch: raw foreign code blocks
1370        if self.check(&TokenType::Escape) {
1371            return self.parse_escape_statement();
1372        }
1373
1374        // Expression-statement: function call without "Call" keyword
1375        // e.g., `greet("Alice").` instead of `Call greet with "Alice".`
1376        // Check if next token is LParen (indicating a function call)
1377        if self.tokens.get(self.current + 1)
1378            .map(|t| matches!(t.kind, TokenType::LParen))
1379            .unwrap_or(false)
1380        {
1381            // Get the function name from current token
1382            let function = self.peek().lexeme;
1383            self.advance(); // consume function name
1384
1385            // Parse the call expression (starts from LParen)
1386            let expr = self.parse_call_expr(function)?;
1387            if let Expr::Call { function, args } = expr {
1388                return Ok(Stmt::Call { function: *function, args: args.clone() });
1389            }
1390        }
1391
1392        Err(ParseError {
1393            kind: ParseErrorKind::ExpectedStatement,
1394            span: self.current_span(),
1395        })
1396    }
1397
1398    fn parse_if_statement(&mut self) -> ParseResult<Stmt<'a>> {
1399        self.advance(); // consume "If"
1400
1401        // Parse condition expression (simple: identifier equals value)
1402        let cond = self.parse_condition()?;
1403
1404        // Optionally consume "then" before the colon (supports "If x = 5 then:" syntax)
1405        if self.check(&TokenType::Then) {
1406            self.advance();
1407        }
1408
1409        // Expect colon
1410        if !self.check(&TokenType::Colon) {
1411            return Err(ParseError {
1412                kind: ParseErrorKind::ExpectedKeyword { keyword: ":".to_string() },
1413                span: self.current_span(),
1414            });
1415        }
1416        self.advance(); // consume ":"
1417
1418        // Expect indent
1419        if !self.check(&TokenType::Indent) {
1420            return Err(ParseError {
1421                kind: ParseErrorKind::ExpectedStatement,
1422                span: self.current_span(),
1423            });
1424        }
1425        self.advance(); // consume Indent
1426
1427        // Parse then block
1428        let mut then_stmts = Vec::new();
1429        while !self.check(&TokenType::Dedent) && !self.is_at_end() {
1430            let stmt = self.parse_statement()?;
1431            then_stmts.push(stmt);
1432            if self.check(&TokenType::Period) {
1433                self.advance();
1434            }
1435        }
1436
1437        // Consume dedent
1438        if self.check(&TokenType::Dedent) {
1439            self.advance();
1440        }
1441
1442        // Allocate then_block in arena
1443        let then_block = self.ctx.stmts.expect("imperative arenas not initialized")
1444            .alloc_slice(then_stmts.into_iter());
1445
1446        // Check for else clause: Otherwise/Else/Otherwise If/Else If/elif
1447        let else_block = if self.check(&TokenType::Otherwise) || self.check(&TokenType::Else) {
1448            self.advance(); // consume "Otherwise" or "Else"
1449
1450            // Check for "Otherwise If" / "Else If" chain
1451            if self.check(&TokenType::If) {
1452                // Parse as else-if: create single-statement else block containing nested If
1453                let nested_if = self.parse_if_statement()?;
1454                let nested_slice = self.ctx.stmts.expect("imperative arenas not initialized")
1455                    .alloc_slice(std::iter::once(nested_if));
1456                Some(nested_slice)
1457            } else {
1458                // Regular else block - expect colon and indent
1459                if !self.check(&TokenType::Colon) {
1460                    return Err(ParseError {
1461                        kind: ParseErrorKind::ExpectedKeyword { keyword: ":".to_string() },
1462                        span: self.current_span(),
1463                    });
1464                }
1465                self.advance(); // consume ":"
1466
1467                if !self.check(&TokenType::Indent) {
1468                    return Err(ParseError {
1469                        kind: ParseErrorKind::ExpectedStatement,
1470                        span: self.current_span(),
1471                    });
1472                }
1473                self.advance(); // consume Indent
1474
1475                let mut else_stmts = Vec::new();
1476                while !self.check(&TokenType::Dedent) && !self.is_at_end() {
1477                    let stmt = self.parse_statement()?;
1478                    else_stmts.push(stmt);
1479                    if self.check(&TokenType::Period) {
1480                        self.advance();
1481                    }
1482                }
1483
1484                if self.check(&TokenType::Dedent) {
1485                    self.advance();
1486                }
1487
1488                Some(self.ctx.stmts.expect("imperative arenas not initialized")
1489                    .alloc_slice(else_stmts.into_iter()))
1490            }
1491        } else if self.check(&TokenType::Elif) {
1492            // Python-style elif: equivalent to "Else If"
1493            self.advance(); // consume "elif"
1494            // Parse the condition and body directly (elif acts like "Else If" without the separate If token)
1495            let nested_if = self.parse_elif_as_if()?;
1496            let nested_slice = self.ctx.stmts.expect("imperative arenas not initialized")
1497                .alloc_slice(std::iter::once(nested_if));
1498            Some(nested_slice)
1499        } else {
1500            None
1501        };
1502
1503        Ok(Stmt::If {
1504            cond,
1505            then_block,
1506            else_block,
1507        })
1508    }
1509
1510    /// Parse an elif clause as an if statement.
1511    /// Called after "elif" has been consumed - parses condition and body directly.
1512    fn parse_elif_as_if(&mut self) -> ParseResult<Stmt<'a>> {
1513        // Parse condition expression (elif is already consumed)
1514        let cond = self.parse_condition()?;
1515
1516        // Expect colon
1517        if !self.check(&TokenType::Colon) {
1518            return Err(ParseError {
1519                kind: ParseErrorKind::ExpectedKeyword { keyword: ":".to_string() },
1520                span: self.current_span(),
1521            });
1522        }
1523        self.advance(); // consume ":"
1524
1525        // Expect indent
1526        if !self.check(&TokenType::Indent) {
1527            return Err(ParseError {
1528                kind: ParseErrorKind::ExpectedStatement,
1529                span: self.current_span(),
1530            });
1531        }
1532        self.advance(); // consume Indent
1533
1534        // Parse then block
1535        let mut then_stmts = Vec::new();
1536        while !self.check(&TokenType::Dedent) && !self.is_at_end() {
1537            let stmt = self.parse_statement()?;
1538            then_stmts.push(stmt);
1539            if self.check(&TokenType::Period) {
1540                self.advance();
1541            }
1542        }
1543
1544        // Consume dedent
1545        if self.check(&TokenType::Dedent) {
1546            self.advance();
1547        }
1548
1549        // Allocate then_block in arena
1550        let then_block = self.ctx.stmts.expect("imperative arenas not initialized")
1551            .alloc_slice(then_stmts.into_iter());
1552
1553        // Check for else clause: Otherwise/Else/Otherwise If/Else If/elif
1554        let else_block = if self.check(&TokenType::Otherwise) || self.check(&TokenType::Else) {
1555            self.advance(); // consume "Otherwise" or "Else"
1556
1557            // Check for "Otherwise If" / "Else If" chain
1558            if self.check(&TokenType::If) {
1559                let nested_if = self.parse_if_statement()?;
1560                let nested_slice = self.ctx.stmts.expect("imperative arenas not initialized")
1561                    .alloc_slice(std::iter::once(nested_if));
1562                Some(nested_slice)
1563            } else {
1564                // Regular else block
1565                if !self.check(&TokenType::Colon) {
1566                    return Err(ParseError {
1567                        kind: ParseErrorKind::ExpectedKeyword { keyword: ":".to_string() },
1568                        span: self.current_span(),
1569                    });
1570                }
1571                self.advance(); // consume ":"
1572
1573                if !self.check(&TokenType::Indent) {
1574                    return Err(ParseError {
1575                        kind: ParseErrorKind::ExpectedStatement,
1576                        span: self.current_span(),
1577                    });
1578                }
1579                self.advance(); // consume Indent
1580
1581                let mut else_stmts = Vec::new();
1582                while !self.check(&TokenType::Dedent) && !self.is_at_end() {
1583                    let stmt = self.parse_statement()?;
1584                    else_stmts.push(stmt);
1585                    if self.check(&TokenType::Period) {
1586                        self.advance();
1587                    }
1588                }
1589
1590                if self.check(&TokenType::Dedent) {
1591                    self.advance();
1592                }
1593
1594                Some(self.ctx.stmts.expect("imperative arenas not initialized")
1595                    .alloc_slice(else_stmts.into_iter()))
1596            }
1597        } else if self.check(&TokenType::Elif) {
1598            self.advance(); // consume "elif"
1599            let nested_if = self.parse_elif_as_if()?;
1600            let nested_slice = self.ctx.stmts.expect("imperative arenas not initialized")
1601                .alloc_slice(std::iter::once(nested_if));
1602            Some(nested_slice)
1603        } else {
1604            None
1605        };
1606
1607        Ok(Stmt::If {
1608            cond,
1609            then_block,
1610            else_block,
1611        })
1612    }
1613
1614    fn parse_while_statement(&mut self) -> ParseResult<Stmt<'a>> {
1615        self.advance(); // consume "While"
1616
1617        let cond = self.parse_condition()?;
1618
1619        // Phase 44: Parse optional (decreasing expr)
1620        let decreasing = if self.check(&TokenType::LParen) {
1621            self.advance(); // consume '('
1622
1623            // Expect "decreasing" keyword
1624            if !self.check_word("decreasing") {
1625                return Err(ParseError {
1626                    kind: ParseErrorKind::ExpectedKeyword { keyword: "decreasing".to_string() },
1627                    span: self.current_span(),
1628                });
1629            }
1630            self.advance(); // consume "decreasing"
1631
1632            let variant = self.parse_imperative_expr()?;
1633
1634            if !self.check(&TokenType::RParen) {
1635                return Err(ParseError {
1636                    kind: ParseErrorKind::ExpectedKeyword { keyword: ")".to_string() },
1637                    span: self.current_span(),
1638                });
1639            }
1640            self.advance(); // consume ')'
1641
1642            Some(variant)
1643        } else {
1644            None
1645        };
1646
1647        if !self.check(&TokenType::Colon) {
1648            return Err(ParseError {
1649                kind: ParseErrorKind::ExpectedKeyword { keyword: ":".to_string() },
1650                span: self.current_span(),
1651            });
1652        }
1653        self.advance(); // consume ":"
1654
1655        if !self.check(&TokenType::Indent) {
1656            return Err(ParseError {
1657                kind: ParseErrorKind::ExpectedStatement,
1658                span: self.current_span(),
1659            });
1660        }
1661        self.advance(); // consume Indent
1662
1663        let mut body_stmts = Vec::new();
1664        while !self.check(&TokenType::Dedent) && !self.is_at_end() {
1665            let stmt = self.parse_statement()?;
1666            body_stmts.push(stmt);
1667            if self.check(&TokenType::Period) {
1668                self.advance();
1669            }
1670        }
1671
1672        if self.check(&TokenType::Dedent) {
1673            self.advance();
1674        }
1675
1676        let body = self.ctx.stmts.expect("imperative arenas not initialized")
1677            .alloc_slice(body_stmts.into_iter());
1678
1679        Ok(Stmt::While { cond, body, decreasing })
1680    }
1681
1682    /// Parse a loop pattern: single identifier or tuple destructuring.
1683    /// Examples: `x` or `(k, v)` or `(a, b, c)`
1684    fn parse_loop_pattern(&mut self) -> ParseResult<Pattern> {
1685        use crate::ast::stmt::Pattern;
1686
1687        // Check for tuple pattern: (x, y, ...)
1688        if self.check(&TokenType::LParen) {
1689            self.advance(); // consume "("
1690
1691            let mut identifiers = Vec::new();
1692            loop {
1693                let id = self.expect_identifier()?;
1694                identifiers.push(id);
1695
1696                // Check for comma to continue
1697                if self.check(&TokenType::Comma) {
1698                    self.advance(); // consume ","
1699                    continue;
1700                }
1701                break;
1702            }
1703
1704            // Expect closing paren
1705            if !self.check(&TokenType::RParen) {
1706                return Err(ParseError {
1707                    kind: ParseErrorKind::ExpectedKeyword { keyword: ")".to_string() },
1708                    span: self.current_span(),
1709                });
1710            }
1711            self.advance(); // consume ")"
1712
1713            Ok(Pattern::Tuple(identifiers))
1714        } else {
1715            // Single identifier pattern
1716            let id = self.expect_identifier()?;
1717            Ok(Pattern::Identifier(id))
1718        }
1719    }
1720
1721    fn parse_repeat_statement(&mut self) -> ParseResult<Stmt<'a>> {
1722        self.advance(); // consume "Repeat"
1723
1724        // Optional "for"
1725        if self.check(&TokenType::For) {
1726            self.advance();
1727        }
1728
1729        // Parse loop pattern: single identifier or tuple destructuring
1730        let pattern = self.parse_loop_pattern()?;
1731
1732        // Determine iteration type: "in" for collection, "from" for range
1733        let iterable = if self.check(&TokenType::From) || self.check_preposition_is("from") {
1734            self.advance(); // consume "from"
1735            let start = self.parse_imperative_expr()?;
1736
1737            // Expect "to" (can be keyword or preposition)
1738            if !self.check(&TokenType::To) && !self.check_preposition_is("to") {
1739                return Err(ParseError {
1740                    kind: ParseErrorKind::ExpectedKeyword { keyword: "to".to_string() },
1741                    span: self.current_span(),
1742                });
1743            }
1744            self.advance();
1745
1746            let end = self.parse_imperative_expr()?;
1747            self.ctx.alloc_imperative_expr(Expr::Range { start, end })
1748        } else if self.check(&TokenType::In) || self.check_preposition_is("in") {
1749            self.advance(); // consume "in"
1750            self.parse_imperative_expr()?
1751        } else {
1752            return Err(ParseError {
1753                kind: ParseErrorKind::ExpectedKeyword { keyword: "in or from".to_string() },
1754                span: self.current_span(),
1755            });
1756        };
1757
1758        // Expect colon
1759        if !self.check(&TokenType::Colon) {
1760            return Err(ParseError {
1761                kind: ParseErrorKind::ExpectedKeyword { keyword: ":".to_string() },
1762                span: self.current_span(),
1763            });
1764        }
1765        self.advance();
1766
1767        // Expect indent
1768        if !self.check(&TokenType::Indent) {
1769            return Err(ParseError {
1770                kind: ParseErrorKind::ExpectedStatement,
1771                span: self.current_span(),
1772            });
1773        }
1774        self.advance();
1775
1776        // Parse body statements
1777        let mut body_stmts = Vec::new();
1778        while !self.check(&TokenType::Dedent) && !self.is_at_end() {
1779            let stmt = self.parse_statement()?;
1780            body_stmts.push(stmt);
1781            if self.check(&TokenType::Period) {
1782                self.advance();
1783            }
1784        }
1785
1786        if self.check(&TokenType::Dedent) {
1787            self.advance();
1788        }
1789
1790        let body = self.ctx.stmts.expect("imperative arenas not initialized")
1791            .alloc_slice(body_stmts.into_iter());
1792
1793        Ok(Stmt::Repeat { pattern, iterable, body })
1794    }
1795
1796    /// Parse a for-loop without the "Repeat" keyword prefix.
1797    /// Syntax: `for <var> from <start> to <end>:` or `for <var> in <collection>:`
1798    fn parse_for_statement(&mut self) -> ParseResult<Stmt<'a>> {
1799        self.advance(); // consume "for"
1800
1801        // Parse loop pattern: single identifier or tuple destructuring
1802        let pattern = self.parse_loop_pattern()?;
1803
1804        // Determine iteration type: "in" for collection, "from" for range
1805        let iterable = if self.check(&TokenType::From) || self.check_preposition_is("from") {
1806            self.advance(); // consume "from"
1807            let start = self.parse_imperative_expr()?;
1808
1809            // Expect "to" (can be keyword or preposition)
1810            if !self.check(&TokenType::To) && !self.check_preposition_is("to") {
1811                return Err(ParseError {
1812                    kind: ParseErrorKind::ExpectedKeyword { keyword: "to".to_string() },
1813                    span: self.current_span(),
1814                });
1815            }
1816            self.advance();
1817
1818            let end = self.parse_imperative_expr()?;
1819            self.ctx.alloc_imperative_expr(Expr::Range { start, end })
1820        } else if self.check(&TokenType::In) || self.check_preposition_is("in") {
1821            self.advance(); // consume "in"
1822            self.parse_imperative_expr()?
1823        } else {
1824            return Err(ParseError {
1825                kind: ParseErrorKind::ExpectedKeyword { keyword: "in or from".to_string() },
1826                span: self.current_span(),
1827            });
1828        };
1829
1830        // Expect colon
1831        if !self.check(&TokenType::Colon) {
1832            return Err(ParseError {
1833                kind: ParseErrorKind::ExpectedKeyword { keyword: ":".to_string() },
1834                span: self.current_span(),
1835            });
1836        }
1837        self.advance();
1838
1839        // Expect indent
1840        if !self.check(&TokenType::Indent) {
1841            return Err(ParseError {
1842                kind: ParseErrorKind::ExpectedStatement,
1843                span: self.current_span(),
1844            });
1845        }
1846        self.advance();
1847
1848        // Parse body statements
1849        let mut body_stmts = Vec::new();
1850        while !self.check(&TokenType::Dedent) && !self.is_at_end() {
1851            let stmt = self.parse_statement()?;
1852            body_stmts.push(stmt);
1853            if self.check(&TokenType::Period) {
1854                self.advance();
1855            }
1856        }
1857
1858        if self.check(&TokenType::Dedent) {
1859            self.advance();
1860        }
1861
1862        let body = self.ctx.stmts.expect("imperative arenas not initialized")
1863            .alloc_slice(body_stmts.into_iter());
1864
1865        Ok(Stmt::Repeat { pattern, iterable, body })
1866    }
1867
1868    fn parse_call_statement(&mut self) -> ParseResult<Stmt<'a>> {
1869        self.advance(); // consume "Call"
1870
1871        // Parse function name (identifier)
1872        // Function names can be nouns, adjectives, or verbs (e.g., "work", "process")
1873        // Use the token's lexeme to match function definition casing
1874        let function = match &self.peek().kind {
1875            TokenType::Noun(sym) | TokenType::Adjective(sym) => {
1876                let s = *sym;
1877                self.advance();
1878                s
1879            }
1880            TokenType::Verb { .. } | TokenType::Ambiguous { .. } => {
1881                // Use lexeme (actual text) not lemma to preserve casing
1882                let s = self.peek().lexeme;
1883                self.advance();
1884                s
1885            }
1886            _ => {
1887                return Err(ParseError {
1888                    kind: ParseErrorKind::ExpectedIdentifier,
1889                    span: self.current_span(),
1890                });
1891            }
1892        };
1893
1894        // Expect "with" followed by arguments
1895        let args = if self.check_preposition_is("with") {
1896            self.advance(); // consume "with"
1897            self.parse_call_arguments()?
1898        } else {
1899            Vec::new()
1900        };
1901
1902        Ok(Stmt::Call { function, args })
1903    }
1904
1905    fn parse_call_arguments(&mut self) -> ParseResult<Vec<&'a Expr<'a>>> {
1906        let mut args = Vec::new();
1907
1908        // Parse first argument (may have Give keyword)
1909        let arg = self.parse_call_arg()?;
1910        args.push(arg);
1911
1912        // Parse additional arguments separated by "and" or ","
1913        while self.check(&TokenType::And) || self.check(&TokenType::Comma) {
1914            self.advance(); // consume "and" or ","
1915            let arg = self.parse_call_arg()?;
1916            args.push(arg);
1917        }
1918
1919        Ok(args)
1920    }
1921
1922    fn parse_call_arg(&mut self) -> ParseResult<&'a Expr<'a>> {
1923        // Check for Give keyword to mark ownership transfer
1924        if self.check(&TokenType::Give) {
1925            self.advance(); // consume "Give"
1926            let value = self.parse_imperative_expr()?;
1927            return Ok(self.ctx.alloc_imperative_expr(Expr::Give { value }));
1928        }
1929
1930        // Otherwise parse normal expression
1931        self.parse_imperative_expr()
1932    }
1933
1934    fn parse_condition(&mut self) -> ParseResult<&'a Expr<'a>> {
1935        // Grand Challenge: Parse compound conditions with "and" and "or"
1936        // "or" has lower precedence than "and"
1937        self.parse_or_condition()
1938    }
1939
1940    /// Parse "or" conditions (lower precedence than "and")
1941    fn parse_or_condition(&mut self) -> ParseResult<&'a Expr<'a>> {
1942        let mut left = self.parse_and_condition()?;
1943
1944        while self.check(&TokenType::Or) || self.check_word("or") {
1945            self.advance();
1946            let right = self.parse_and_condition()?;
1947            left = self.ctx.alloc_imperative_expr(Expr::BinaryOp {
1948                op: BinaryOpKind::Or,
1949                left,
1950                right,
1951            });
1952        }
1953
1954        Ok(left)
1955    }
1956
1957    /// Parse "and" conditions (higher precedence than "or")
1958    fn parse_and_condition(&mut self) -> ParseResult<&'a Expr<'a>> {
1959        let mut left = self.parse_comparison()?;
1960
1961        while self.check(&TokenType::And) || self.check_word("and") {
1962            self.advance();
1963            let right = self.parse_comparison()?;
1964            left = self.ctx.alloc_imperative_expr(Expr::BinaryOp {
1965                op: BinaryOpKind::And,
1966                left,
1967                right,
1968            });
1969        }
1970
1971        Ok(left)
1972    }
1973
1974    /// Grand Challenge: Parse a single comparison expression
1975    fn parse_comparison(&mut self) -> ParseResult<&'a Expr<'a>> {
1976        // Handle unary "not" operator: "not a" or "not (x > 5)"
1977        if self.check(&TokenType::Not) || self.check_word("not") {
1978            self.advance(); // consume "not"
1979            let operand = self.parse_comparison()?; // recursive to handle "not not x"
1980            // Implement as: operand == false (since we don't have UnaryNot)
1981            return Ok(self.ctx.alloc_imperative_expr(Expr::BinaryOp {
1982                op: BinaryOpKind::Eq,
1983                left: operand,
1984                right: self.ctx.alloc_imperative_expr(Expr::Literal(Literal::Boolean(false))),
1985            }));
1986        }
1987
1988        let left = self.parse_imperative_expr()?;
1989
1990        // Check for comparison operators
1991        let op = if self.check(&TokenType::Equals) {
1992            self.advance();
1993            Some(BinaryOpKind::Eq)
1994        } else if self.check(&TokenType::Identity) {
1995            // "is equal to" was tokenized as TokenType::Identity
1996            self.advance();
1997            Some(BinaryOpKind::Eq)
1998        } else if self.check_word("is") {
1999            // Peek ahead to determine which comparison
2000            let saved_pos = self.current;
2001            self.advance(); // consume "is"
2002
2003            if self.check_word("greater") {
2004                self.advance(); // consume "greater"
2005                if self.check_word("than") || self.check_preposition_is("than") {
2006                    self.advance(); // consume "than"
2007                    Some(BinaryOpKind::Gt)
2008                } else {
2009                    self.current = saved_pos;
2010                    None
2011                }
2012            } else if self.check_word("less") {
2013                self.advance(); // consume "less"
2014                if self.check_word("than") || self.check_preposition_is("than") {
2015                    self.advance(); // consume "than"
2016                    Some(BinaryOpKind::Lt)
2017                } else {
2018                    self.current = saved_pos;
2019                    None
2020                }
2021            } else if self.check_word("at") {
2022                self.advance(); // consume "at"
2023                if self.check_word("least") {
2024                    self.advance(); // consume "least"
2025                    Some(BinaryOpKind::GtEq)
2026                } else if self.check_word("most") {
2027                    self.advance(); // consume "most"
2028                    Some(BinaryOpKind::LtEq)
2029                } else {
2030                    self.current = saved_pos;
2031                    None
2032                }
2033            } else if self.check_word("not") || self.check(&TokenType::Not) {
2034                // "is not X" → NotEq
2035                self.advance(); // consume "not"
2036                Some(BinaryOpKind::NotEq)
2037            } else if self.check_word("equal") {
2038                // "is equal to X" → Eq
2039                self.advance(); // consume "equal"
2040                if self.check_preposition_is("to") {
2041                    self.advance(); // consume "to"
2042                    Some(BinaryOpKind::Eq)
2043                } else {
2044                    self.current = saved_pos;
2045                    None
2046                }
2047            } else {
2048                self.current = saved_pos;
2049                None
2050            }
2051        } else if self.check(&TokenType::Lt) {
2052            self.advance();
2053            Some(BinaryOpKind::Lt)
2054        } else if self.check(&TokenType::Gt) {
2055            self.advance();
2056            Some(BinaryOpKind::Gt)
2057        } else if self.check(&TokenType::LtEq) {
2058            self.advance();
2059            Some(BinaryOpKind::LtEq)
2060        } else if self.check(&TokenType::GtEq) {
2061            self.advance();
2062            Some(BinaryOpKind::GtEq)
2063        } else if self.check(&TokenType::EqEq) || self.check(&TokenType::Assign) {
2064            self.advance();
2065            Some(BinaryOpKind::Eq)
2066        } else if self.check(&TokenType::NotEq) {
2067            self.advance();
2068            Some(BinaryOpKind::NotEq)
2069        } else {
2070            None
2071        };
2072
2073        if let Some(op) = op {
2074            let right = self.parse_imperative_expr()?;
2075            Ok(self.ctx.alloc_imperative_expr(Expr::BinaryOp { op, left, right }))
2076        } else {
2077            Ok(left)
2078        }
2079    }
2080
2081    fn parse_let_statement(&mut self) -> ParseResult<Stmt<'a>> {
2082        self.advance(); // consume "Let"
2083
2084        // Check for "mutable" keyword
2085        let mutable = if self.check_mutable_keyword() {
2086            self.advance();
2087            true
2088        } else {
2089            false
2090        };
2091
2092        // Get identifier
2093        let var = self.expect_identifier()?;
2094
2095        // Check for optional type annotation: `: Type`
2096        let ty = if self.check(&TokenType::Colon) {
2097            self.advance(); // consume ":"
2098            let type_expr = self.parse_type_expression()?;
2099            Some(self.ctx.alloc_type_expr(type_expr))
2100        } else {
2101            None
2102        };
2103
2104        // Expect "be" or "="
2105        if !self.check(&TokenType::Be) && !self.check(&TokenType::Assign) {
2106            return Err(ParseError {
2107                kind: ParseErrorKind::ExpectedKeyword { keyword: "be or =".to_string() },
2108                span: self.current_span(),
2109            });
2110        }
2111        self.advance(); // consume "be" or "="
2112
2113        // Phase 53: Check for "mounted at [path]" pattern (for Persistent types)
2114        if self.check_word("mounted") {
2115            self.advance(); // consume "mounted"
2116            if !self.check(&TokenType::At) && !self.check_preposition_is("at") {
2117                return Err(ParseError {
2118                    kind: ParseErrorKind::ExpectedKeyword { keyword: "at".to_string() },
2119                    span: self.current_span(),
2120                });
2121            }
2122            self.advance(); // consume "at"
2123            let path = self.parse_imperative_expr()?;
2124            return Ok(Stmt::Mount { var, path });
2125        }
2126
2127        // Phase 51: Check for "a PeerAgent at [addr]" pattern
2128        if self.check_article() {
2129            let saved_pos = self.current;
2130            self.advance(); // consume article
2131
2132            // Check if next word is "PeerAgent" (case insensitive)
2133            if let TokenType::Noun(sym) | TokenType::ProperName(sym) = self.peek().kind {
2134                let word = self.interner.resolve(sym).to_lowercase();
2135                if word == "peeragent" {
2136                    self.advance(); // consume "PeerAgent"
2137
2138                    // Check for "at" keyword
2139                    if self.check(&TokenType::At) || self.check_preposition_is("at") {
2140                        self.advance(); // consume "at"
2141
2142                        // Parse address expression
2143                        let address = self.parse_imperative_expr()?;
2144
2145                        return Ok(Stmt::LetPeerAgent { var, address });
2146                    }
2147                }
2148            }
2149            // Not a PeerAgent, backtrack
2150            self.current = saved_pos;
2151        }
2152
2153        // Phase 54: Check for "a Pipe of Type" pattern
2154        if self.check_article() {
2155            let saved_pos = self.current;
2156            self.advance(); // consume article
2157
2158            if self.check(&TokenType::Pipe) {
2159                self.advance(); // consume "Pipe"
2160
2161                // Expect "of"
2162                if !self.check_word("of") {
2163                    return Err(ParseError {
2164                        kind: ParseErrorKind::ExpectedKeyword { keyword: "of".to_string() },
2165                        span: self.current_span(),
2166                    });
2167                }
2168                self.advance(); // consume "of"
2169
2170                // Parse element type
2171                let element_type = self.expect_identifier()?;
2172
2173                // Variable registration now handled by DRS
2174
2175                return Ok(Stmt::CreatePipe { var, element_type, capacity: None });
2176            }
2177            // Not a Pipe, backtrack
2178            self.current = saved_pos;
2179        }
2180
2181        // Phase 54: Check for "Launch a task to..." pattern (for task handles)
2182        if self.check(&TokenType::Launch) {
2183            self.advance(); // consume "Launch"
2184
2185            // Expect "a"
2186            if !self.check_article() {
2187                return Err(ParseError {
2188                    kind: ParseErrorKind::ExpectedKeyword { keyword: "a".to_string() },
2189                    span: self.current_span(),
2190                });
2191            }
2192            self.advance();
2193
2194            // Expect "task"
2195            if !self.check(&TokenType::Task) {
2196                return Err(ParseError {
2197                    kind: ParseErrorKind::ExpectedKeyword { keyword: "task".to_string() },
2198                    span: self.current_span(),
2199                });
2200            }
2201            self.advance();
2202
2203            // Expect "to"
2204            if !self.check(&TokenType::To) && !self.check_word("to") {
2205                return Err(ParseError {
2206                    kind: ParseErrorKind::ExpectedKeyword { keyword: "to".to_string() },
2207                    span: self.current_span(),
2208                });
2209            }
2210            self.advance();
2211
2212            // Parse function name
2213            let function = self.expect_identifier()?;
2214
2215            // Parse optional arguments: "with arg1, arg2"
2216            let args = if self.check_word("with") {
2217                self.advance();
2218                self.parse_call_arguments()?
2219            } else {
2220                vec![]
2221            };
2222
2223            return Ok(Stmt::LaunchTaskWithHandle { handle: var, function, args });
2224        }
2225
2226        // Parse expression value (simple: just a number for now)
2227        let value = self.parse_imperative_expr()?;
2228
2229        // Phase 43B: Type check - verify declared type matches value type
2230        if let Some(declared_ty) = &ty {
2231            if let Some(inferred) = self.infer_literal_type(value) {
2232                if !self.check_type_compatibility(declared_ty, inferred) {
2233                    let expected = match declared_ty {
2234                        TypeExpr::Primitive(sym) | TypeExpr::Named(sym) => {
2235                            self.interner.resolve(*sym).to_string()
2236                        }
2237                        _ => "unknown".to_string(),
2238                    };
2239                    return Err(ParseError {
2240                        kind: ParseErrorKind::TypeMismatch {
2241                            expected,
2242                            found: inferred.to_string(),
2243                        },
2244                        span: self.current_span(),
2245                    });
2246                }
2247            }
2248        }
2249
2250        // Check for optional "with capacity <expr>" — wraps value in Expr::WithCapacity
2251        let value = if self.check_word("with") {
2252            let saved = self.current;
2253            self.advance(); // consume "with"
2254            if self.check_word("capacity") {
2255                self.advance(); // consume "capacity"
2256                let cap_expr = self.parse_imperative_expr()?;
2257                self.ctx.alloc_imperative_expr(Expr::WithCapacity { value, capacity: cap_expr })
2258            } else {
2259                self.current = saved; // backtrack — "with" belongs to something else
2260                value
2261            }
2262        } else {
2263            value
2264        };
2265
2266        // Register variable in WorldState's DRS with Owned state for ownership tracking
2267        self.world_state.drs.introduce_referent(var, var, crate::drs::Gender::Unknown, crate::drs::Number::Singular);
2268
2269        Ok(Stmt::Let { var, ty, value, mutable })
2270    }
2271
2272    fn check_mutable_keyword(&self) -> bool {
2273        // Check for TokenType::Mut (Phase 23b keyword)
2274        if matches!(self.peek().kind, TokenType::Mut) {
2275            return true;
2276        }
2277        // Check for "mutable" or "mut" as Noun/Adjective (backward compatibility)
2278        if let TokenType::Noun(sym) | TokenType::Adjective(sym) = self.peek().kind {
2279            let word = self.interner.resolve(sym).to_lowercase();
2280            word == "mutable" || word == "mut"
2281        } else {
2282            false
2283        }
2284    }
2285
2286    /// Phase 43B: Infer the type of a literal expression
2287    fn infer_literal_type(&self, expr: &Expr<'_>) -> Option<&'static str> {
2288        match expr {
2289            Expr::Literal(lit) => match lit {
2290                crate::ast::Literal::Number(_) => Some("Int"),
2291                crate::ast::Literal::Float(_) => Some("Real"),
2292                crate::ast::Literal::Text(_) => Some("Text"),
2293                crate::ast::Literal::Boolean(_) => Some("Bool"),
2294                crate::ast::Literal::Nothing => Some("Unit"),
2295                crate::ast::Literal::Char(_) => Some("Char"),
2296                crate::ast::Literal::Duration(_) => Some("Duration"),
2297                crate::ast::Literal::Date(_) => Some("Date"),
2298                crate::ast::Literal::Moment(_) => Some("Moment"),
2299                crate::ast::Literal::Span { .. } => Some("Span"),
2300                crate::ast::Literal::Time(_) => Some("Time"),
2301            },
2302            _ => None, // Can't infer type for non-literals yet
2303        }
2304    }
2305
2306    /// Phase 43B: Check if declared type matches inferred type
2307    fn check_type_compatibility(&self, declared: &TypeExpr<'_>, inferred: &str) -> bool {
2308        match declared {
2309            TypeExpr::Primitive(sym) | TypeExpr::Named(sym) => {
2310                let declared_name = self.interner.resolve(*sym);
2311                // Nat and Byte are compatible with Int literals
2312                declared_name.eq_ignore_ascii_case(inferred)
2313                    || (declared_name.eq_ignore_ascii_case("Nat") && inferred == "Int")
2314                    || (declared_name.eq_ignore_ascii_case("Byte") && inferred == "Int")
2315            }
2316            _ => true, // For generics/functions, skip check for now
2317        }
2318    }
2319
2320    // =========================================================================
2321    // Phase 23b: Equals-style Assignment (x = 5)
2322    // =========================================================================
2323
2324    /// Check if current token starts an equals-style assignment.
2325    /// Patterns: `identifier = value` or `identifier: Type = value`
2326    fn peek_equals_assignment(&self) -> bool {
2327        // Must start with an identifier-like token
2328        // Note: Unknown words default to Adjective in the lexer
2329        // Verbs, Particles, and Ambiguous can also be variable names
2330        let is_identifier = matches!(
2331            self.peek().kind,
2332            TokenType::Noun(_) | TokenType::ProperName(_) | TokenType::Identifier
2333            | TokenType::Adjective(_) | TokenType::Verb { .. }
2334            | TokenType::Particle(_) | TokenType::Ambiguous { .. }
2335            | TokenType::Pronoun { .. }
2336        );
2337        if !is_identifier {
2338            return false;
2339        }
2340
2341        // Check what follows the identifier
2342        if self.current + 1 >= self.tokens.len() {
2343            return false;
2344        }
2345
2346        let next = &self.tokens[self.current + 1].kind;
2347
2348        // Direct assignment: identifier = value
2349        if matches!(next, TokenType::Assign) {
2350            return true;
2351        }
2352
2353        // Type-annotated assignment: identifier: Type = value
2354        // Check for colon, then scan for = before Period/Newline
2355        if matches!(next, TokenType::Colon) {
2356            let mut offset = 2;
2357            while self.current + offset < self.tokens.len() {
2358                let tok = &self.tokens[self.current + offset].kind;
2359                if matches!(tok, TokenType::Assign) {
2360                    return true;
2361                }
2362                if matches!(tok, TokenType::Period | TokenType::Newline | TokenType::EOF) {
2363                    return false;
2364                }
2365                offset += 1;
2366            }
2367        }
2368
2369        false
2370    }
2371
2372    /// Parse equals-style assignment: `x = 5` or `x: Int = 5` or `mut x = 5`
2373    fn parse_equals_assignment(&mut self, explicit_mutable: bool) -> ParseResult<Stmt<'a>> {
2374        // If explicit_mutable is true, we've already checked for Mut token
2375        if explicit_mutable {
2376            self.advance(); // consume "mut"
2377        }
2378
2379        // Get variable name
2380        let var = self.expect_identifier()?;
2381
2382        // Check for optional type annotation: `: Type`
2383        let ty = if self.check(&TokenType::Colon) {
2384            self.advance(); // consume ":"
2385            let type_expr = self.parse_type_expression()?;
2386            Some(self.ctx.alloc_type_expr(type_expr))
2387        } else {
2388            None
2389        };
2390
2391        // Expect '='
2392        if !self.check(&TokenType::Assign) {
2393            return Err(ParseError {
2394                kind: ParseErrorKind::ExpectedKeyword { keyword: "=".to_string() },
2395                span: self.current_span(),
2396            });
2397        }
2398        self.advance(); // consume '='
2399
2400        // Parse value expression
2401        let value = self.parse_imperative_expr()?;
2402
2403        // Check for optional "with capacity <expr>" — wraps value in Expr::WithCapacity
2404        let value = if self.check_word("with") {
2405            let saved = self.current;
2406            self.advance(); // consume "with"
2407            if self.check_word("capacity") {
2408                self.advance(); // consume "capacity"
2409                let cap_expr = self.parse_imperative_expr()?;
2410                self.ctx.alloc_imperative_expr(Expr::WithCapacity { value, capacity: cap_expr })
2411            } else {
2412                self.current = saved; // backtrack
2413                value
2414            }
2415        } else {
2416            value
2417        };
2418
2419        // Register variable in WorldState's DRS
2420        self.world_state.drs.introduce_referent(var, var, crate::drs::Gender::Unknown, crate::drs::Number::Singular);
2421
2422        Ok(Stmt::Let { var, ty, value, mutable: explicit_mutable })
2423    }
2424
2425    fn parse_set_statement(&mut self) -> ParseResult<Stmt<'a>> {
2426        use crate::ast::Expr;
2427        self.advance(); // consume "Set"
2428
2429        // Parse target - can be identifier or field access expression
2430        let target_expr = self.parse_imperative_expr()?;
2431
2432        // Support "Set X at KEY to VALUE" syntax for map insertion
2433        let target_expr = if self.check(&TokenType::At) {
2434            self.advance(); // consume "at"
2435            let key = self.parse_imperative_expr()?;
2436            self.ctx.alloc_imperative_expr(Expr::Index { collection: target_expr, index: key })
2437        } else {
2438            target_expr
2439        };
2440
2441        // Expect "to" - can be TokenType::To or Preposition("to")
2442        let is_to = self.check(&TokenType::To) || matches!(
2443            &self.peek().kind,
2444            TokenType::Preposition(sym) if self.interner.resolve(*sym) == "to"
2445        );
2446        if !is_to {
2447            return Err(ParseError {
2448                kind: ParseErrorKind::ExpectedKeyword { keyword: "to".to_string() },
2449                span: self.current_span(),
2450            });
2451        }
2452        self.advance(); // consume "to"
2453
2454        // Parse expression value
2455        let value = self.parse_imperative_expr()?;
2456
2457        // Phase 31: Handle field access targets
2458        // Also handle index targets: Set item N of X to Y
2459        match target_expr {
2460            Expr::FieldAccess { object, field } => {
2461                Ok(Stmt::SetField { object: *object, field: *field, value })
2462            }
2463            Expr::Identifier(target) => {
2464                Ok(Stmt::Set { target: *target, value })
2465            }
2466            Expr::Index { collection, index } => {
2467                Ok(Stmt::SetIndex { collection: *collection, index: *index, value })
2468            }
2469            _ => Err(ParseError {
2470                kind: ParseErrorKind::ExpectedIdentifier,
2471                span: self.current_span(),
2472            })
2473        }
2474    }
2475
2476    fn parse_return_statement(&mut self) -> ParseResult<Stmt<'a>> {
2477        self.advance(); // consume "Return"
2478
2479        // Check if there's a value or just "Return."
2480        if self.check(&TokenType::Period) || self.is_at_end() {
2481            return Ok(Stmt::Return { value: None });
2482        }
2483
2484        // Use parse_comparison to support returning comparison results like "n equals 5"
2485        let value = self.parse_comparison()?;
2486        Ok(Stmt::Return { value: Some(value) })
2487    }
2488
2489    fn parse_assert_statement(&mut self) -> ParseResult<Stmt<'a>> {
2490        self.advance(); // consume "Assert"
2491
2492        // Optionally consume "that" (may be tokenized as That or Article(Distal))
2493        if self.check(&TokenType::That) || matches!(self.peek().kind, TokenType::Article(Definiteness::Distal)) {
2494            self.advance();
2495        }
2496
2497        // Parse condition using imperative expression parser
2498        // This allows syntax like "Assert that b is not 0."
2499        let condition = self.parse_condition()?;
2500
2501        Ok(Stmt::RuntimeAssert { condition })
2502    }
2503
2504    /// Phase 35: Parse Trust statement
2505    /// Syntax: Trust [that] [proposition] because [justification].
2506    fn parse_trust_statement(&mut self) -> ParseResult<Stmt<'a>> {
2507        self.advance(); // consume "Trust"
2508
2509        // Optionally consume "that" (may be tokenized as That or Article(Distal))
2510        if self.check(&TokenType::That) || matches!(self.peek().kind, TokenType::Article(Definiteness::Distal)) {
2511            self.advance();
2512        }
2513
2514        // Save current mode and switch to declarative for proposition parsing
2515        let saved_mode = self.mode;
2516        self.mode = ParserMode::Declarative;
2517
2518        // Parse the proposition using the Logic Kernel
2519        let proposition = self.parse()?;
2520
2521        // Restore mode
2522        self.mode = saved_mode;
2523
2524        // Expect "because"
2525        if !self.check(&TokenType::Because) {
2526            return Err(ParseError {
2527                kind: ParseErrorKind::UnexpectedToken {
2528                    expected: TokenType::Because,
2529                    found: self.peek().kind.clone(),
2530                },
2531                span: self.current_span(),
2532            });
2533        }
2534        self.advance(); // consume "because"
2535
2536        // Parse justification (string literal)
2537        let justification = match &self.peek().kind {
2538            TokenType::StringLiteral(sym) => {
2539                let s = *sym;
2540                self.advance();
2541                s
2542            }
2543            _ => {
2544                return Err(ParseError {
2545                    kind: ParseErrorKind::UnexpectedToken {
2546                        expected: TokenType::StringLiteral(self.interner.intern("")),
2547                        found: self.peek().kind.clone(),
2548                    },
2549                    span: self.current_span(),
2550                });
2551            }
2552        };
2553
2554        Ok(Stmt::Trust { proposition, justification })
2555    }
2556
2557    /// Phase 50: Parse Check statement - mandatory security guard
2558    /// Syntax: Check that [subject] is [predicate].
2559    /// Syntax: Check that [subject] can [action] the [object].
2560    fn parse_check_statement(&mut self) -> ParseResult<Stmt<'a>> {
2561        let start_span = self.current_span();
2562        self.advance(); // consume "Check"
2563
2564        // Optionally consume "that"
2565        if self.check(&TokenType::That) {
2566            self.advance();
2567        }
2568
2569        // Consume optional "the"
2570        if matches!(self.peek().kind, TokenType::Article(_)) {
2571            self.advance();
2572        }
2573
2574        // Parse subject identifier (e.g., "user")
2575        let subject = match &self.peek().kind {
2576            TokenType::Noun(sym) | TokenType::Adjective(sym) | TokenType::ProperName(sym) => {
2577                let s = *sym;
2578                self.advance();
2579                s
2580            }
2581            _ => {
2582                // Try to get an identifier
2583                let tok = self.peek();
2584                let s = tok.lexeme;
2585                self.advance();
2586                s
2587            }
2588        };
2589
2590        // Determine if this is a predicate check ("is admin") or capability check ("can publish")
2591        let is_capability;
2592        let predicate;
2593        let object;
2594
2595        if self.check(&TokenType::Is) || self.check(&TokenType::Are) {
2596            // Predicate check: "user is admin"
2597            is_capability = false;
2598            self.advance(); // consume "is" / "are"
2599
2600            // Parse predicate name (e.g., "admin")
2601            predicate = match &self.peek().kind {
2602                TokenType::Noun(sym) | TokenType::Adjective(sym) | TokenType::ProperName(sym) => {
2603                    let s = *sym;
2604                    self.advance();
2605                    s
2606                }
2607                _ => {
2608                    let tok = self.peek();
2609                    let s = tok.lexeme;
2610                    self.advance();
2611                    s
2612                }
2613            };
2614            object = None;
2615        } else if self.check(&TokenType::Can) {
2616            // Capability check: "user can publish the document"
2617            is_capability = true;
2618            self.advance(); // consume "can"
2619
2620            // Parse action (e.g., "publish", "edit", "delete")
2621            predicate = match &self.peek().kind {
2622                TokenType::Verb { lemma, .. } => {
2623                    let s = *lemma;
2624                    self.advance();
2625                    s
2626                }
2627                TokenType::Noun(sym) | TokenType::Adjective(sym) | TokenType::ProperName(sym) => {
2628                    let s = *sym;
2629                    self.advance();
2630                    s
2631                }
2632                _ => {
2633                    let tok = self.peek();
2634                    let s = tok.lexeme;
2635                    self.advance();
2636                    s
2637                }
2638            };
2639
2640            // Consume optional "the"
2641            if matches!(self.peek().kind, TokenType::Article(_)) {
2642                self.advance();
2643            }
2644
2645            // Parse object (e.g., "document")
2646            let obj = match &self.peek().kind {
2647                TokenType::Noun(sym) | TokenType::Adjective(sym) | TokenType::ProperName(sym) => {
2648                    let s = *sym;
2649                    self.advance();
2650                    s
2651                }
2652                _ => {
2653                    let tok = self.peek();
2654                    let s = tok.lexeme;
2655                    self.advance();
2656                    s
2657                }
2658            };
2659            object = Some(obj);
2660        } else {
2661            return Err(ParseError {
2662                kind: ParseErrorKind::ExpectedKeyword { keyword: "is/can".to_string() },
2663                span: self.current_span(),
2664            });
2665        }
2666
2667        // Build source text for error message
2668        let source_text = if is_capability {
2669            let obj_name = self.interner.resolve(object.unwrap());
2670            let pred_name = self.interner.resolve(predicate);
2671            let subj_name = self.interner.resolve(subject);
2672            format!("{} can {} the {}", subj_name, pred_name, obj_name)
2673        } else {
2674            let pred_name = self.interner.resolve(predicate);
2675            let subj_name = self.interner.resolve(subject);
2676            format!("{} is {}", subj_name, pred_name)
2677        };
2678
2679        Ok(Stmt::Check {
2680            subject,
2681            predicate,
2682            is_capability,
2683            object,
2684            source_text,
2685            span: start_span,
2686        })
2687    }
2688
2689    /// Phase 51: Parse Listen statement - bind to network address
2690    /// Syntax: Listen on [address].
2691    fn parse_listen_statement(&mut self) -> ParseResult<Stmt<'a>> {
2692        self.advance(); // consume "Listen"
2693
2694        // Expect "on" preposition
2695        if !self.check_preposition_is("on") {
2696            return Err(ParseError {
2697                kind: ParseErrorKind::ExpectedKeyword { keyword: "on".to_string() },
2698                span: self.current_span(),
2699            });
2700        }
2701        self.advance(); // consume "on"
2702
2703        // Parse address expression (string literal or variable)
2704        let address = self.parse_imperative_expr()?;
2705
2706        Ok(Stmt::Listen { address })
2707    }
2708
2709    /// Phase 51: Parse Connect statement - dial remote peer
2710    /// Syntax: Connect to [address].
2711    fn parse_connect_statement(&mut self) -> ParseResult<Stmt<'a>> {
2712        self.advance(); // consume "Connect"
2713
2714        // Expect "to" (can be TokenType::To or preposition)
2715        if !self.check(&TokenType::To) && !self.check_preposition_is("to") {
2716            return Err(ParseError {
2717                kind: ParseErrorKind::ExpectedKeyword { keyword: "to".to_string() },
2718                span: self.current_span(),
2719            });
2720        }
2721        self.advance(); // consume "to"
2722
2723        // Parse address expression
2724        let address = self.parse_imperative_expr()?;
2725
2726        Ok(Stmt::ConnectTo { address })
2727    }
2728
2729    /// Phase 51: Parse Sleep statement - pause execution
2730    /// Syntax: Sleep [milliseconds].
2731    fn parse_sleep_statement(&mut self) -> ParseResult<Stmt<'a>> {
2732        self.advance(); // consume "Sleep"
2733
2734        // Parse milliseconds expression (number or variable)
2735        let milliseconds = self.parse_imperative_expr()?;
2736
2737        Ok(Stmt::Sleep { milliseconds })
2738    }
2739
2740    /// Phase 52: Parse Sync statement - automatic CRDT replication
2741    /// Syntax: Sync [var] on [topic].
2742    fn parse_sync_statement(&mut self) -> ParseResult<Stmt<'a>> {
2743        self.advance(); // consume "Sync"
2744
2745        // Parse variable name (must be an identifier)
2746        // Phase 49: Also handle Verb and Ambiguous tokens (e.g., "state" can be verb or noun)
2747        let var = match &self.tokens[self.current].kind {
2748            TokenType::ProperName(sym) | TokenType::Noun(sym) | TokenType::Adjective(sym) => {
2749                let s = *sym;
2750                self.advance();
2751                s
2752            }
2753            TokenType::Verb { .. } | TokenType::Ambiguous { .. } => {
2754                let s = self.tokens[self.current].lexeme;
2755                self.advance();
2756                s
2757            }
2758            _ => {
2759                return Err(ParseError {
2760                    kind: ParseErrorKind::ExpectedKeyword { keyword: "variable name".to_string() },
2761                    span: self.current_span(),
2762                });
2763            }
2764        };
2765
2766        // Expect "on" preposition
2767        if !self.check_preposition_is("on") {
2768            return Err(ParseError {
2769                kind: ParseErrorKind::ExpectedKeyword { keyword: "on".to_string() },
2770                span: self.current_span(),
2771            });
2772        }
2773        self.advance(); // consume "on"
2774
2775        // Parse topic expression (string literal or variable)
2776        let topic = self.parse_imperative_expr()?;
2777
2778        Ok(Stmt::Sync { var, topic })
2779    }
2780
2781    /// Phase 53: Parse Mount statement
2782    /// Syntax: Mount [var] at [path].
2783    /// Example: Mount counter at "data/counter.journal".
2784    fn parse_mount_statement(&mut self) -> ParseResult<Stmt<'a>> {
2785        self.advance(); // consume "Mount"
2786
2787        // Parse variable name (must be an identifier)
2788        // Phase 49: Also handle Verb and Ambiguous tokens
2789        let var = match &self.tokens[self.current].kind {
2790            TokenType::ProperName(sym) | TokenType::Noun(sym) | TokenType::Adjective(sym) => {
2791                let s = *sym;
2792                self.advance();
2793                s
2794            }
2795            TokenType::Verb { .. } | TokenType::Ambiguous { .. } => {
2796                let s = self.tokens[self.current].lexeme;
2797                self.advance();
2798                s
2799            }
2800            _ => {
2801                return Err(ParseError {
2802                    kind: ParseErrorKind::ExpectedKeyword { keyword: "variable name".to_string() },
2803                    span: self.current_span(),
2804                });
2805            }
2806        };
2807
2808        // Expect "at" keyword (TokenType::At in imperative mode)
2809        if !self.check(&TokenType::At) {
2810            return Err(ParseError {
2811                kind: ParseErrorKind::ExpectedKeyword { keyword: "at".to_string() },
2812                span: self.current_span(),
2813            });
2814        }
2815        self.advance(); // consume "at"
2816
2817        // Parse path expression (string literal or variable)
2818        let path = self.parse_imperative_expr()?;
2819
2820        Ok(Stmt::Mount { var, path })
2821    }
2822
2823    // =========================================================================
2824    // Phase 54: Go-like Concurrency Parser Methods
2825    // =========================================================================
2826
2827    /// Helper: Check if lookahead contains "into" (for Send...into pipe disambiguation)
2828    fn lookahead_contains_into(&self) -> bool {
2829        for i in self.current..std::cmp::min(self.current + 5, self.tokens.len()) {
2830            if matches!(self.tokens[i].kind, TokenType::Into) {
2831                return true;
2832            }
2833        }
2834        false
2835    }
2836
2837    /// Helper: Check if lookahead is "the first of" (for Await select disambiguation)
2838    fn lookahead_is_first_of(&self) -> bool {
2839        // Check for "Await the first of:"
2840        self.current + 3 < self.tokens.len()
2841            && matches!(self.tokens.get(self.current + 1), Some(t) if matches!(t.kind, TokenType::Article(_)))
2842            && self.tokens.get(self.current + 2)
2843                .map(|t| self.interner.resolve(t.lexeme).to_lowercase() == "first")
2844                .unwrap_or(false)
2845    }
2846
2847    /// Phase 54: Parse Launch statement - spawn a task
2848    /// Syntax: Launch a task to verb(args).
2849    fn parse_launch_statement(&mut self) -> ParseResult<Stmt<'a>> {
2850        self.advance(); // consume "Launch"
2851
2852        // Expect "a"
2853        if !self.check_article() {
2854            return Err(ParseError {
2855                kind: ParseErrorKind::ExpectedKeyword { keyword: "a".to_string() },
2856                span: self.current_span(),
2857            });
2858        }
2859        self.advance();
2860
2861        // Expect "task"
2862        if !self.check(&TokenType::Task) {
2863            return Err(ParseError {
2864                kind: ParseErrorKind::ExpectedKeyword { keyword: "task".to_string() },
2865                span: self.current_span(),
2866            });
2867        }
2868        self.advance();
2869
2870        // Expect "to"
2871        if !self.check(&TokenType::To) && !self.check_preposition_is("to") {
2872            return Err(ParseError {
2873                kind: ParseErrorKind::ExpectedKeyword { keyword: "to".to_string() },
2874                span: self.current_span(),
2875            });
2876        }
2877        self.advance();
2878
2879        // Parse function name
2880        // Phase 49: Also handle Verb and Ambiguous tokens (e.g., "greet" can be a verb)
2881        let function = match &self.tokens[self.current].kind {
2882            TokenType::ProperName(sym) | TokenType::Noun(sym) | TokenType::Adjective(sym) => {
2883                let s = *sym;
2884                self.advance();
2885                s
2886            }
2887            TokenType::Verb { .. } | TokenType::Ambiguous { .. } => {
2888                let s = self.tokens[self.current].lexeme;
2889                self.advance();
2890                s
2891            }
2892            _ => {
2893                return Err(ParseError {
2894                    kind: ParseErrorKind::ExpectedKeyword { keyword: "function name".to_string() },
2895                    span: self.current_span(),
2896                });
2897            }
2898        };
2899
2900        // Optional arguments in parentheses or with "with" keyword
2901        let args = if self.check(&TokenType::LParen) {
2902            self.parse_call_arguments()?
2903        } else if self.check_word("with") {
2904            self.advance(); // consume "with"
2905            let mut args = Vec::new();
2906            let arg = self.parse_imperative_expr()?;
2907            args.push(arg);
2908            // Handle additional args separated by "and"
2909            while self.check(&TokenType::And) {
2910                self.advance();
2911                let arg = self.parse_imperative_expr()?;
2912                args.push(arg);
2913            }
2914            args
2915        } else {
2916            Vec::new()
2917        };
2918
2919        Ok(Stmt::LaunchTask { function, args })
2920    }
2921
2922    /// Phase 54: Parse Send into pipe statement
2923    /// Syntax: Send value into pipe.
2924    fn parse_send_pipe_statement(&mut self) -> ParseResult<Stmt<'a>> {
2925        self.advance(); // consume "Send"
2926
2927        // Parse value expression
2928        let value = self.parse_imperative_expr()?;
2929
2930        // Expect "into"
2931        if !self.check(&TokenType::Into) {
2932            return Err(ParseError {
2933                kind: ParseErrorKind::ExpectedKeyword { keyword: "into".to_string() },
2934                span: self.current_span(),
2935            });
2936        }
2937        self.advance();
2938
2939        // Parse pipe expression
2940        let pipe = self.parse_imperative_expr()?;
2941
2942        Ok(Stmt::SendPipe { value, pipe })
2943    }
2944
2945    /// Phase 54: Parse Receive from pipe statement
2946    /// Syntax: Receive x from pipe.
2947    fn parse_receive_pipe_statement(&mut self) -> ParseResult<Stmt<'a>> {
2948        self.advance(); // consume "Receive"
2949
2950        // Get variable name - use expect_identifier which handles various token types
2951        let var = self.expect_identifier()?;
2952
2953        // Expect "from"
2954        if !self.check(&TokenType::From) && !self.check_preposition_is("from") {
2955            return Err(ParseError {
2956                kind: ParseErrorKind::ExpectedKeyword { keyword: "from".to_string() },
2957                span: self.current_span(),
2958            });
2959        }
2960        self.advance();
2961
2962        // Parse pipe expression
2963        let pipe = self.parse_imperative_expr()?;
2964
2965        Ok(Stmt::ReceivePipe { var, pipe })
2966    }
2967
2968    /// Phase 54: Parse Try statement (non-blocking send/receive)
2969    /// Syntax: Try to send x into pipe. OR Try to receive x from pipe.
2970    fn parse_try_statement(&mut self) -> ParseResult<Stmt<'a>> {
2971        self.advance(); // consume "Try"
2972
2973        // Expect "to"
2974        if !self.check(&TokenType::To) && !self.check_preposition_is("to") {
2975            return Err(ParseError {
2976                kind: ParseErrorKind::ExpectedKeyword { keyword: "to".to_string() },
2977                span: self.current_span(),
2978            });
2979        }
2980        self.advance();
2981
2982        // Check if send or receive
2983        if self.check(&TokenType::Send) {
2984            self.advance(); // consume "Send"
2985            let value = self.parse_imperative_expr()?;
2986
2987            if !self.check(&TokenType::Into) {
2988                return Err(ParseError {
2989                    kind: ParseErrorKind::ExpectedKeyword { keyword: "into".to_string() },
2990                    span: self.current_span(),
2991                });
2992            }
2993            self.advance();
2994
2995            let pipe = self.parse_imperative_expr()?;
2996            Ok(Stmt::TrySendPipe { value, pipe, result: None })
2997        } else if self.check(&TokenType::Receive) {
2998            self.advance(); // consume "Receive"
2999
3000            let var = self.expect_identifier()?;
3001
3002            if !self.check(&TokenType::From) && !self.check_preposition_is("from") {
3003                return Err(ParseError {
3004                    kind: ParseErrorKind::ExpectedKeyword { keyword: "from".to_string() },
3005                    span: self.current_span(),
3006                });
3007            }
3008            self.advance();
3009
3010            let pipe = self.parse_imperative_expr()?;
3011            Ok(Stmt::TryReceivePipe { var, pipe })
3012        } else {
3013            Err(ParseError {
3014                kind: ParseErrorKind::ExpectedKeyword { keyword: "send or receive".to_string() },
3015                span: self.current_span(),
3016            })
3017        }
3018    }
3019
3020    /// Shared helper: consume `Escape to <Language>: Indent EscapeBlock Dedent`.
3021    /// Returns (language, code, span).
3022    fn parse_escape_body(&mut self) -> ParseResult<(crate::intern::Symbol, crate::intern::Symbol, crate::token::Span)> {
3023        let start_span = self.current_span();
3024        self.advance(); // consume "Escape"
3025
3026        // Expect "to"
3027        if !self.check(&TokenType::To) && !self.check_preposition_is("to") {
3028            return Err(ParseError {
3029                kind: ParseErrorKind::Custom(
3030                    "Expected 'to' after 'Escape'. Syntax: Escape to Rust:".to_string()
3031                ),
3032                span: self.current_span(),
3033            });
3034        }
3035        self.advance(); // consume "to"
3036
3037        // Parse language name — "Rust" will be tokenized as ProperName
3038        let language = match &self.peek().kind {
3039            TokenType::ProperName(sym) => {
3040                let s = *sym;
3041                self.advance();
3042                s
3043            }
3044            TokenType::Noun(sym) | TokenType::Adjective(sym) => {
3045                let s = *sym;
3046                self.advance();
3047                s
3048            }
3049            _ => {
3050                return Err(ParseError {
3051                    kind: ParseErrorKind::Custom(
3052                        "Expected language name after 'Escape to'. Currently only 'Rust' is supported.".to_string()
3053                    ),
3054                    span: self.current_span(),
3055                });
3056            }
3057        };
3058
3059        // Validate: only "Rust" is supported for now
3060        if !language.is(self.interner, "Rust") {
3061            let lang_str = self.interner.resolve(language);
3062            return Err(ParseError {
3063                kind: ParseErrorKind::Custom(
3064                    format!("Unsupported escape target '{}'. Only 'Rust' is supported.", lang_str)
3065                ),
3066                span: self.current_span(),
3067            });
3068        }
3069
3070        // Expect colon
3071        if !self.check(&TokenType::Colon) {
3072            return Err(ParseError {
3073                kind: ParseErrorKind::Custom(
3074                    "Expected ':' after 'Escape to Rust'. Syntax: Escape to Rust:".to_string()
3075                ),
3076                span: self.current_span(),
3077            });
3078        }
3079        self.advance(); // consume ":"
3080
3081        // Expect Indent (the indented block follows)
3082        if !self.check(&TokenType::Indent) {
3083            return Err(ParseError {
3084                kind: ParseErrorKind::Custom(
3085                    "Expected indented block after 'Escape to Rust:'.".to_string()
3086                ),
3087                span: self.current_span(),
3088            });
3089        }
3090        self.advance(); // consume Indent
3091
3092        // Expect the raw EscapeBlock token
3093        let code = match &self.peek().kind {
3094            TokenType::EscapeBlock(sym) => {
3095                let s = *sym;
3096                self.advance();
3097                s
3098            }
3099            _ => {
3100                return Err(ParseError {
3101                    kind: ParseErrorKind::Custom(
3102                        "Escape block body is empty or malformed.".to_string()
3103                    ),
3104                    span: self.current_span(),
3105                });
3106            }
3107        };
3108
3109        // Expect Dedent (block ends)
3110        if self.check(&TokenType::Dedent) {
3111            self.advance();
3112        }
3113
3114        let end_span = self.previous().span;
3115        Ok((language, code, crate::token::Span::new(start_span.start, end_span.end)))
3116    }
3117
3118    /// Parse an escape hatch block: `Escape to Rust: <indented raw code>`
3119    fn parse_escape_statement(&mut self) -> ParseResult<Stmt<'a>> {
3120        let (language, code, span) = self.parse_escape_body()?;
3121        Ok(Stmt::Escape { language, code, span })
3122    }
3123
3124    /// Parse an escape hatch expression: `Escape to Rust: <indented raw code>`
3125    /// Used in expression position: `Let x: Int be Escape to Rust:`
3126    fn parse_escape_expr(&mut self) -> ParseResult<&'a Expr<'a>> {
3127        let (language, code, _span) = self.parse_escape_body()?;
3128        Ok(self.ctx.alloc_imperative_expr(Expr::Escape { language, code }))
3129    }
3130
3131    /// Parse a `## Requires` block into a list of `Stmt::Require` nodes.
3132    /// Loops until the next block header or EOF, parsing one dependency per line.
3133    fn parse_requires_block(&mut self) -> ParseResult<Vec<Stmt<'a>>> {
3134        let mut deps = Vec::new();
3135
3136        loop {
3137            // Stop at next block header or EOF
3138            if self.is_at_end() {
3139                break;
3140            }
3141            if matches!(self.peek().kind, TokenType::BlockHeader { .. }) {
3142                break;
3143            }
3144
3145            // Skip whitespace tokens
3146            if self.check(&TokenType::Indent)
3147                || self.check(&TokenType::Dedent)
3148                || self.check(&TokenType::Newline)
3149            {
3150                self.advance();
3151                continue;
3152            }
3153
3154            // Each dependency line starts with an article ("The")
3155            if matches!(self.peek().kind, TokenType::Article(_)) {
3156                let dep = self.parse_require_line()?;
3157                deps.push(dep);
3158                continue;
3159            }
3160
3161            // Skip unexpected tokens (defensive)
3162            self.advance();
3163        }
3164
3165        Ok(deps)
3166    }
3167
3168    /// Parse a single dependency line:
3169    /// `The "serde" crate version "1.0" with features "derive" and "std" for serialization.`
3170    fn parse_require_line(&mut self) -> ParseResult<Stmt<'a>> {
3171        let start_span = self.current_span();
3172
3173        // Expect article "The"
3174        if !matches!(self.peek().kind, TokenType::Article(_)) {
3175            return Err(crate::error::ParseError {
3176                kind: crate::error::ParseErrorKind::Custom(
3177                    "Expected 'The' to begin a dependency declaration.".to_string(),
3178                ),
3179                span: self.current_span(),
3180            });
3181        }
3182        self.advance(); // consume "The"
3183
3184        // Expect string literal for crate name
3185        let crate_name = if let TokenType::StringLiteral(sym) = self.peek().kind {
3186            let s = sym;
3187            self.advance();
3188            s
3189        } else {
3190            return Err(crate::error::ParseError {
3191                kind: crate::error::ParseErrorKind::Custom(
3192                    "Expected a string literal for the crate name, e.g. \"serde\".".to_string(),
3193                ),
3194                span: self.current_span(),
3195            });
3196        };
3197
3198        // Expect word "crate"
3199        if !self.check_word("crate") {
3200            return Err(crate::error::ParseError {
3201                kind: crate::error::ParseErrorKind::Custom(
3202                    "Expected the word 'crate' after the crate name.".to_string(),
3203                ),
3204                span: self.current_span(),
3205            });
3206        }
3207        self.advance(); // consume "crate"
3208
3209        // Expect word "version"
3210        if !self.check_word("version") {
3211            return Err(crate::error::ParseError {
3212                kind: crate::error::ParseErrorKind::Custom(
3213                    "Expected 'version' after 'crate'.".to_string(),
3214                ),
3215                span: self.current_span(),
3216            });
3217        }
3218        self.advance(); // consume "version"
3219
3220        // Expect string literal for version
3221        let version = if let TokenType::StringLiteral(sym) = self.peek().kind {
3222            let s = sym;
3223            self.advance();
3224            s
3225        } else {
3226            return Err(crate::error::ParseError {
3227                kind: crate::error::ParseErrorKind::Custom(
3228                    "Expected a string literal for the version, e.g. \"1.0\".".to_string(),
3229                ),
3230                span: self.current_span(),
3231            });
3232        };
3233
3234        // Optional: "with features ..."
3235        let mut features = Vec::new();
3236        if self.check_preposition_is("with") {
3237            self.advance(); // consume "with"
3238
3239            // Expect word "features"
3240            if !self.check_word("features") {
3241                return Err(crate::error::ParseError {
3242                    kind: crate::error::ParseErrorKind::Custom(
3243                        "Expected 'features' after 'with'.".to_string(),
3244                    ),
3245                    span: self.current_span(),
3246                });
3247            }
3248            self.advance(); // consume "features"
3249
3250            // Parse first feature string
3251            if let TokenType::StringLiteral(sym) = self.peek().kind {
3252                features.push(sym);
3253                self.advance();
3254            } else {
3255                return Err(crate::error::ParseError {
3256                    kind: crate::error::ParseErrorKind::Custom(
3257                        "Expected a string literal for a feature name.".to_string(),
3258                    ),
3259                    span: self.current_span(),
3260                });
3261            }
3262
3263            // Parse additional features separated by "and"
3264            while self.check(&TokenType::And) {
3265                self.advance(); // consume "and"
3266                if let TokenType::StringLiteral(sym) = self.peek().kind {
3267                    features.push(sym);
3268                    self.advance();
3269                } else {
3270                    return Err(crate::error::ParseError {
3271                        kind: crate::error::ParseErrorKind::Custom(
3272                            "Expected a string literal for a feature name after 'and'.".to_string(),
3273                        ),
3274                        span: self.current_span(),
3275                    });
3276                }
3277            }
3278        }
3279
3280        // Optional: "for <description...>" — consume until period
3281        if self.check(&TokenType::For) {
3282            self.advance(); // consume "for"
3283            while !self.check(&TokenType::Period) && !self.check(&TokenType::EOF)
3284                && !self.check(&TokenType::Newline)
3285                && !matches!(self.peek().kind, TokenType::BlockHeader { .. })
3286            {
3287                self.advance();
3288            }
3289        }
3290
3291        // Consume trailing period
3292        if self.check(&TokenType::Period) {
3293            self.advance();
3294        }
3295
3296        let end_span = self.previous().span;
3297
3298        Ok(Stmt::Require {
3299            crate_name,
3300            version,
3301            features,
3302            span: crate::token::Span::new(start_span.start, end_span.end),
3303        })
3304    }
3305
3306    /// Phase 54: Parse Stop statement
3307    /// Syntax: Stop handle.
3308    fn parse_stop_statement(&mut self) -> ParseResult<Stmt<'a>> {
3309        self.advance(); // consume "Stop"
3310
3311        let handle = self.parse_imperative_expr()?;
3312
3313        Ok(Stmt::StopTask { handle })
3314    }
3315
3316    /// Phase 54: Parse Select statement
3317    /// Syntax:
3318    /// Await the first of:
3319    ///     Receive x from pipe:
3320    ///         ...
3321    ///     After N seconds:
3322    ///         ...
3323    fn parse_select_statement(&mut self) -> ParseResult<Stmt<'a>> {
3324        use crate::ast::stmt::SelectBranch;
3325
3326        self.advance(); // consume "Await"
3327
3328        // Expect "the"
3329        if !self.check_article() {
3330            return Err(ParseError {
3331                kind: ParseErrorKind::ExpectedKeyword { keyword: "the".to_string() },
3332                span: self.current_span(),
3333            });
3334        }
3335        self.advance();
3336
3337        // Expect "first"
3338        if !self.check_word("first") {
3339            return Err(ParseError {
3340                kind: ParseErrorKind::ExpectedKeyword { keyword: "first".to_string() },
3341                span: self.current_span(),
3342            });
3343        }
3344        self.advance();
3345
3346        // Expect "of"
3347        if !self.check_preposition_is("of") {
3348            return Err(ParseError {
3349                kind: ParseErrorKind::ExpectedKeyword { keyword: "of".to_string() },
3350                span: self.current_span(),
3351            });
3352        }
3353        self.advance();
3354
3355        // Expect colon
3356        if !self.check(&TokenType::Colon) {
3357            return Err(ParseError {
3358                kind: ParseErrorKind::ExpectedKeyword { keyword: ":".to_string() },
3359                span: self.current_span(),
3360            });
3361        }
3362        self.advance();
3363
3364        // Expect indent
3365        if !self.check(&TokenType::Indent) {
3366            return Err(ParseError {
3367                kind: ParseErrorKind::ExpectedStatement,
3368                span: self.current_span(),
3369            });
3370        }
3371        self.advance();
3372
3373        // Parse branches
3374        let mut branches = Vec::new();
3375        while !self.check(&TokenType::Dedent) && !self.is_at_end() {
3376            let branch = self.parse_select_branch()?;
3377            branches.push(branch);
3378        }
3379
3380        // Consume dedent
3381        if self.check(&TokenType::Dedent) {
3382            self.advance();
3383        }
3384
3385        Ok(Stmt::Select { branches })
3386    }
3387
3388    /// Phase 54: Parse a single select branch
3389    fn parse_select_branch(&mut self) -> ParseResult<crate::ast::stmt::SelectBranch<'a>> {
3390        use crate::ast::stmt::SelectBranch;
3391
3392        if self.check(&TokenType::Receive) {
3393            self.advance(); // consume "Receive"
3394
3395            let var = match &self.tokens[self.current].kind {
3396                TokenType::ProperName(sym) | TokenType::Noun(sym) | TokenType::Adjective(sym) => {
3397                    let s = *sym;
3398                    self.advance();
3399                    s
3400                }
3401                _ => {
3402                    return Err(ParseError {
3403                        kind: ParseErrorKind::ExpectedKeyword { keyword: "variable name".to_string() },
3404                        span: self.current_span(),
3405                    });
3406                }
3407            };
3408
3409            if !self.check(&TokenType::From) && !self.check_preposition_is("from") {
3410                return Err(ParseError {
3411                    kind: ParseErrorKind::ExpectedKeyword { keyword: "from".to_string() },
3412                    span: self.current_span(),
3413                });
3414            }
3415            self.advance();
3416
3417            let pipe = self.parse_imperative_expr()?;
3418
3419            // Expect colon
3420            if !self.check(&TokenType::Colon) {
3421                return Err(ParseError {
3422                    kind: ParseErrorKind::ExpectedKeyword { keyword: ":".to_string() },
3423                    span: self.current_span(),
3424                });
3425            }
3426            self.advance();
3427
3428            // Parse body
3429            let body = self.parse_indented_block()?;
3430
3431            Ok(SelectBranch::Receive { var, pipe, body })
3432        } else if self.check_word("after") {
3433            self.advance(); // consume "After"
3434
3435            let milliseconds = self.parse_imperative_expr()?;
3436
3437            // Skip "seconds" or "milliseconds" if present
3438            if self.check_word("seconds") || self.check_word("milliseconds") {
3439                self.advance();
3440            }
3441
3442            // Expect colon
3443            if !self.check(&TokenType::Colon) {
3444                return Err(ParseError {
3445                    kind: ParseErrorKind::ExpectedKeyword { keyword: ":".to_string() },
3446                    span: self.current_span(),
3447                });
3448            }
3449            self.advance();
3450
3451            // Parse body
3452            let body = self.parse_indented_block()?;
3453
3454            Ok(SelectBranch::Timeout { milliseconds, body })
3455        } else {
3456            Err(ParseError {
3457                kind: ParseErrorKind::ExpectedKeyword { keyword: "Receive or After".to_string() },
3458                span: self.current_span(),
3459            })
3460        }
3461    }
3462
3463    /// Phase 54: Parse an indented block of statements
3464    fn parse_indented_block(&mut self) -> ParseResult<crate::ast::stmt::Block<'a>> {
3465        // Expect indent
3466        if !self.check(&TokenType::Indent) {
3467            return Err(ParseError {
3468                kind: ParseErrorKind::ExpectedStatement,
3469                span: self.current_span(),
3470            });
3471        }
3472        self.advance();
3473
3474        let mut stmts = Vec::new();
3475        while !self.check(&TokenType::Dedent) && !self.is_at_end() {
3476            let stmt = self.parse_statement()?;
3477            stmts.push(stmt);
3478            if self.check(&TokenType::Period) {
3479                self.advance();
3480            }
3481        }
3482
3483        // Consume dedent
3484        if self.check(&TokenType::Dedent) {
3485            self.advance();
3486        }
3487
3488        let block = self.ctx.stmts.expect("imperative arenas not initialized")
3489            .alloc_slice(stmts.into_iter());
3490
3491        Ok(block)
3492    }
3493
3494    fn parse_give_statement(&mut self) -> ParseResult<Stmt<'a>> {
3495        self.advance(); // consume "Give"
3496
3497        // Parse the object being given: "x" or "the data"
3498        let object = self.parse_imperative_expr()?;
3499
3500        // Expect "to" preposition (can be TokenType::To when followed by verb-like word)
3501        if !self.check_to_preposition() {
3502            return Err(ParseError {
3503                kind: ParseErrorKind::ExpectedKeyword { keyword: "to".to_string() },
3504                span: self.current_span(),
3505            });
3506        }
3507        self.advance(); // consume "to"
3508
3509        // Parse the recipient: "processor" or "the console"
3510        let recipient = self.parse_imperative_expr()?;
3511
3512        // Mark variable as Moved after Give
3513        if let Expr::Identifier(sym) = object {
3514            self.world_state.set_ownership_by_var(*sym, crate::drs::OwnershipState::Moved);
3515        }
3516
3517        Ok(Stmt::Give { object, recipient })
3518    }
3519
3520    fn parse_show_statement(&mut self) -> ParseResult<Stmt<'a>> {
3521        self.advance(); // consume "Show"
3522
3523        // Parse the object being shown - use parse_condition to support
3524        // comparisons (x is less than y) and boolean operators (a and b)
3525        let object = self.parse_condition()?;
3526
3527        // Optional "to" preposition - if not present, default to "show" function
3528        // Note: Use check_to_preposition() to handle both TokenType::To (when followed by verb)
3529        // and TokenType::Preposition("to")
3530        let recipient = if self.check_to_preposition() {
3531            self.advance(); // consume "to"
3532
3533            // Phase 10: "Show x to console." or "Show x to the console."
3534            // is idiomatic for printing to stdout - use default show function
3535            if self.check_article() {
3536                self.advance(); // skip "the"
3537            }
3538            if self.check(&TokenType::Console) {
3539                self.advance(); // consume "console"
3540                let show_sym = self.interner.intern("show");
3541                self.ctx.alloc_imperative_expr(Expr::Identifier(show_sym))
3542            } else {
3543                // Parse the recipient: custom function
3544                self.parse_imperative_expr()?
3545            }
3546        } else {
3547            // Default recipient: the runtime "show" function
3548            let show_sym = self.interner.intern("show");
3549            self.ctx.alloc_imperative_expr(Expr::Identifier(show_sym))
3550        };
3551
3552        // Mark variable as Borrowed after Show
3553        if let Expr::Identifier(sym) = object {
3554            self.world_state.set_ownership_by_var(*sym, crate::drs::OwnershipState::Borrowed);
3555        }
3556
3557        Ok(Stmt::Show { object, recipient })
3558    }
3559
3560    /// Phase 43D: Parse Push statement for collection operations
3561    /// Syntax: Push x to items.
3562    fn parse_push_statement(&mut self) -> ParseResult<Stmt<'a>> {
3563        self.advance(); // consume "Push"
3564
3565        // Parse the value being pushed
3566        let value = self.parse_imperative_expr()?;
3567
3568        // Expect "to" (can be keyword or preposition)
3569        if !self.check(&TokenType::To) && !self.check_preposition_is("to") {
3570            return Err(ParseError {
3571                kind: ParseErrorKind::ExpectedKeyword { keyword: "to".to_string() },
3572                span: self.current_span(),
3573            });
3574        }
3575        self.advance(); // consume "to"
3576
3577        // Parse the collection
3578        let collection = self.parse_imperative_expr()?;
3579
3580        Ok(Stmt::Push { value, collection })
3581    }
3582
3583    /// Phase 43D: Parse Pop statement for collection operations
3584    /// Syntax: Pop from items. OR Pop from items into y.
3585    fn parse_pop_statement(&mut self) -> ParseResult<Stmt<'a>> {
3586        self.advance(); // consume "Pop"
3587
3588        // Expect "from" - can be keyword token or preposition
3589        if !self.check(&TokenType::From) && !self.check_preposition_is("from") {
3590            return Err(ParseError {
3591                kind: ParseErrorKind::ExpectedKeyword { keyword: "from".to_string() },
3592                span: self.current_span(),
3593            });
3594        }
3595        self.advance(); // consume "from"
3596
3597        // Parse the collection
3598        let collection = self.parse_imperative_expr()?;
3599
3600        // Check for optional "into" binding (can be Into keyword or preposition)
3601        let into = if self.check(&TokenType::Into) || self.check_preposition_is("into") {
3602            self.advance(); // consume "into"
3603
3604            // Parse variable name
3605            if let TokenType::Noun(sym) | TokenType::ProperName(sym) = &self.peek().kind {
3606                let sym = *sym;
3607                self.advance();
3608                Some(sym)
3609            } else if let Some(token) = self.tokens.get(self.current) {
3610                // Also handle identifier-like tokens
3611                let sym = token.lexeme;
3612                self.advance();
3613                Some(sym)
3614            } else {
3615                return Err(ParseError {
3616                    kind: ParseErrorKind::ExpectedIdentifier,
3617                    span: self.current_span(),
3618                });
3619            }
3620        } else {
3621            None
3622        };
3623
3624        Ok(Stmt::Pop { collection, into })
3625    }
3626
3627    /// Parse Add statement for Set insertion
3628    /// Syntax: Add x to set.
3629    fn parse_add_statement(&mut self) -> ParseResult<Stmt<'a>> {
3630        self.advance(); // consume "Add"
3631
3632        // Parse the value to add
3633        let value = self.parse_imperative_expr()?;
3634
3635        // Expect "to" preposition
3636        if !self.check_preposition_is("to") && !self.check(&TokenType::To) {
3637            return Err(ParseError {
3638                kind: ParseErrorKind::ExpectedKeyword { keyword: "to".to_string() },
3639                span: self.current_span(),
3640            });
3641        }
3642        self.advance(); // consume "to"
3643
3644        // Parse the collection expression
3645        let collection = self.parse_imperative_expr()?;
3646
3647        Ok(Stmt::Add { value, collection })
3648    }
3649
3650    /// Parse Remove statement for Set deletion
3651    /// Syntax: Remove x from set.
3652    fn parse_remove_statement(&mut self) -> ParseResult<Stmt<'a>> {
3653        self.advance(); // consume "Remove"
3654
3655        // Parse the value to remove
3656        let value = self.parse_imperative_expr()?;
3657
3658        // Expect "from" preposition
3659        if !self.check(&TokenType::From) && !self.check_preposition_is("from") {
3660            return Err(ParseError {
3661                kind: ParseErrorKind::ExpectedKeyword { keyword: "from".to_string() },
3662                span: self.current_span(),
3663            });
3664        }
3665        self.advance(); // consume "from"
3666
3667        // Parse the collection expression
3668        let collection = self.parse_imperative_expr()?;
3669
3670        Ok(Stmt::Remove { value, collection })
3671    }
3672
3673    /// Phase 10: Parse Read statement for console/file input
3674    /// Syntax: Read <var> from the console.
3675    ///         Read <var> from file <path>.
3676    fn parse_read_statement(&mut self) -> ParseResult<Stmt<'a>> {
3677        self.advance(); // consume "Read"
3678
3679        // Get the variable name
3680        let var = self.expect_identifier()?;
3681
3682        // Expect "from" preposition
3683        if !self.check(&TokenType::From) && !self.check_preposition_is("from") {
3684            return Err(ParseError {
3685                kind: ParseErrorKind::ExpectedKeyword { keyword: "from".to_string() },
3686                span: self.current_span(),
3687            });
3688        }
3689        self.advance(); // consume "from"
3690
3691        // Skip optional article "the"
3692        if self.check_article() {
3693            self.advance();
3694        }
3695
3696        // Determine source: console or file
3697        let source = if self.check(&TokenType::Console) {
3698            self.advance(); // consume "console"
3699            ReadSource::Console
3700        } else if self.check(&TokenType::File) {
3701            self.advance(); // consume "file"
3702            let path = self.parse_imperative_expr()?;
3703            ReadSource::File(path)
3704        } else {
3705            return Err(ParseError {
3706                kind: ParseErrorKind::ExpectedKeyword { keyword: "console or file".to_string() },
3707                span: self.current_span(),
3708            });
3709        };
3710
3711        Ok(Stmt::ReadFrom { var, source })
3712    }
3713
3714    /// Phase 10: Parse Write statement for file output
3715    /// Syntax: Write <content> to file <path>.
3716    fn parse_write_statement(&mut self) -> ParseResult<Stmt<'a>> {
3717        self.advance(); // consume "Write"
3718
3719        // Parse the content expression
3720        let content = self.parse_imperative_expr()?;
3721
3722        // Expect "to" (can be keyword or preposition)
3723        if !self.check(&TokenType::To) && !self.check_preposition_is("to") {
3724            return Err(ParseError {
3725                kind: ParseErrorKind::ExpectedKeyword { keyword: "to".to_string() },
3726                span: self.current_span(),
3727            });
3728        }
3729        self.advance(); // consume "to"
3730
3731        // Expect "file" keyword
3732        if !self.check(&TokenType::File) {
3733            return Err(ParseError {
3734                kind: ParseErrorKind::ExpectedKeyword { keyword: "file".to_string() },
3735                span: self.current_span(),
3736            });
3737        }
3738        self.advance(); // consume "file"
3739
3740        // Parse the path expression
3741        let path = self.parse_imperative_expr()?;
3742
3743        Ok(Stmt::WriteFile { content, path })
3744    }
3745
3746    /// Phase 8.5: Parse Zone statement for memory arena blocks
3747    /// Syntax variants:
3748    ///   - Inside a new zone called "Scratch":
3749    ///   - Inside a zone called "Buffer" of size 1 MB:
3750    ///   - Inside a zone called "Data" mapped from "file.bin":
3751    fn parse_zone_statement(&mut self) -> ParseResult<Stmt<'a>> {
3752        self.advance(); // consume "Inside"
3753
3754        // Optional article "a"
3755        if self.check_article() {
3756            self.advance();
3757        }
3758
3759        // Optional "new"
3760        if self.check(&TokenType::New) {
3761            self.advance();
3762        }
3763
3764        // Expect "zone"
3765        if !self.check(&TokenType::Zone) {
3766            return Err(ParseError {
3767                kind: ParseErrorKind::ExpectedKeyword { keyword: "zone".to_string() },
3768                span: self.current_span(),
3769            });
3770        }
3771        self.advance(); // consume "zone"
3772
3773        // Expect "called"
3774        if !self.check(&TokenType::Called) {
3775            return Err(ParseError {
3776                kind: ParseErrorKind::ExpectedKeyword { keyword: "called".to_string() },
3777                span: self.current_span(),
3778            });
3779        }
3780        self.advance(); // consume "called"
3781
3782        // Parse zone name (can be string literal or identifier)
3783        let name = match &self.peek().kind {
3784            TokenType::StringLiteral(sym) => {
3785                let s = *sym;
3786                self.advance();
3787                s
3788            }
3789            TokenType::ProperName(sym) | TokenType::Noun(sym) | TokenType::Adjective(sym) => {
3790                let s = *sym;
3791                self.advance();
3792                s
3793            }
3794            _ => {
3795                // Try to use the lexeme directly as an identifier
3796                let token = self.peek().clone();
3797                self.advance();
3798                token.lexeme
3799            }
3800        };
3801
3802        let mut capacity = None;
3803        let mut source_file = None;
3804
3805        // Check for "mapped from" (file-backed zone)
3806        if self.check(&TokenType::Mapped) {
3807            self.advance(); // consume "mapped"
3808
3809            // Expect "from"
3810            if !self.check(&TokenType::From) && !self.check_preposition_is("from") {
3811                return Err(ParseError {
3812                    kind: ParseErrorKind::ExpectedKeyword { keyword: "from".to_string() },
3813                    span: self.current_span(),
3814                });
3815            }
3816            self.advance(); // consume "from"
3817
3818            // Parse file path (must be string literal)
3819            if let TokenType::StringLiteral(path) = &self.peek().kind {
3820                source_file = Some(*path);
3821                self.advance();
3822            } else {
3823                return Err(ParseError {
3824                    kind: ParseErrorKind::ExpectedKeyword { keyword: "file path string".to_string() },
3825                    span: self.current_span(),
3826                });
3827            }
3828        }
3829        // Check for "of size N Unit" (sized heap zone)
3830        else if self.check_of_preposition() {
3831            self.advance(); // consume "of"
3832
3833            // Expect "size"
3834            if !self.check(&TokenType::Size) {
3835                return Err(ParseError {
3836                    kind: ParseErrorKind::ExpectedKeyword { keyword: "size".to_string() },
3837                    span: self.current_span(),
3838                });
3839            }
3840            self.advance(); // consume "size"
3841
3842            // Parse size number
3843            let size_value = match &self.peek().kind {
3844                TokenType::Number(sym) => {
3845                    let num_str = self.interner.resolve(*sym);
3846                    let val = num_str.replace('_', "").parse::<usize>().unwrap_or(0);
3847                    self.advance();
3848                    val
3849                }
3850                TokenType::Cardinal(n) => {
3851                    let val = *n as usize;
3852                    self.advance();
3853                    val
3854                }
3855                _ => {
3856                    return Err(ParseError {
3857                        kind: ParseErrorKind::ExpectedNumber,
3858                        span: self.current_span(),
3859                    });
3860                }
3861            };
3862
3863            // Parse unit (KB, MB, GB, or B)
3864            let unit_multiplier = self.parse_size_unit()?;
3865            capacity = Some(size_value * unit_multiplier);
3866        }
3867
3868        // Expect colon
3869        if !self.check(&TokenType::Colon) {
3870            return Err(ParseError {
3871                kind: ParseErrorKind::ExpectedKeyword { keyword: ":".to_string() },
3872                span: self.current_span(),
3873            });
3874        }
3875        self.advance(); // consume ":"
3876
3877        // Expect indent
3878        if !self.check(&TokenType::Indent) {
3879            return Err(ParseError {
3880                kind: ParseErrorKind::ExpectedStatement,
3881                span: self.current_span(),
3882            });
3883        }
3884        self.advance(); // consume Indent
3885
3886        // Parse body statements
3887        let mut body_stmts = Vec::new();
3888        while !self.check(&TokenType::Dedent) && !self.is_at_end() {
3889            let stmt = self.parse_statement()?;
3890            body_stmts.push(stmt);
3891            if self.check(&TokenType::Period) {
3892                self.advance();
3893            }
3894        }
3895
3896        // Consume dedent
3897        if self.check(&TokenType::Dedent) {
3898            self.advance();
3899        }
3900
3901        let body = self.ctx.stmts.expect("imperative arenas not initialized")
3902            .alloc_slice(body_stmts.into_iter());
3903
3904        Ok(Stmt::Zone { name, capacity, source_file, body })
3905    }
3906
3907    /// Parse size unit (B, KB, MB, GB) and return multiplier
3908    fn parse_size_unit(&mut self) -> ParseResult<usize> {
3909        let token = self.peek().clone();
3910        let unit_str = self.interner.resolve(token.lexeme).to_uppercase();
3911        self.advance();
3912
3913        match unit_str.as_str() {
3914            "B" | "BYTES" | "BYTE" => Ok(1),
3915            "KB" | "KILOBYTE" | "KILOBYTES" => Ok(1024),
3916            "MB" | "MEGABYTE" | "MEGABYTES" => Ok(1024 * 1024),
3917            "GB" | "GIGABYTE" | "GIGABYTES" => Ok(1024 * 1024 * 1024),
3918            _ => Err(ParseError {
3919                kind: ParseErrorKind::ExpectedKeyword {
3920                    keyword: "size unit (B, KB, MB, GB)".to_string(),
3921                },
3922                span: token.span,
3923            }),
3924        }
3925    }
3926
3927    /// Phase 9: Parse concurrent execution block (async, I/O-bound)
3928    ///
3929    /// Syntax:
3930    /// ```logos
3931    /// Attempt all of the following:
3932    ///     Call fetch_user with id.
3933    ///     Call fetch_orders with id.
3934    /// ```
3935    fn parse_concurrent_block(&mut self) -> ParseResult<Stmt<'a>> {
3936        self.advance(); // consume "Attempt"
3937
3938        // Expect "all"
3939        if !self.check(&TokenType::All) {
3940            return Err(ParseError {
3941                kind: ParseErrorKind::ExpectedKeyword { keyword: "all".to_string() },
3942                span: self.current_span(),
3943            });
3944        }
3945        self.advance(); // consume "all"
3946
3947        // Expect "of" (preposition)
3948        if !self.check_of_preposition() {
3949            return Err(ParseError {
3950                kind: ParseErrorKind::ExpectedKeyword { keyword: "of".to_string() },
3951                span: self.current_span(),
3952            });
3953        }
3954        self.advance(); // consume "of"
3955
3956        // Expect "the"
3957        if !self.check_article() {
3958            return Err(ParseError {
3959                kind: ParseErrorKind::ExpectedKeyword { keyword: "the".to_string() },
3960                span: self.current_span(),
3961            });
3962        }
3963        self.advance(); // consume "the"
3964
3965        // Expect "following"
3966        if !self.check(&TokenType::Following) {
3967            return Err(ParseError {
3968                kind: ParseErrorKind::ExpectedKeyword { keyword: "following".to_string() },
3969                span: self.current_span(),
3970            });
3971        }
3972        self.advance(); // consume "following"
3973
3974        // Expect colon
3975        if !self.check(&TokenType::Colon) {
3976            return Err(ParseError {
3977                kind: ParseErrorKind::ExpectedKeyword { keyword: ":".to_string() },
3978                span: self.current_span(),
3979            });
3980        }
3981        self.advance(); // consume ":"
3982
3983        // Expect indent
3984        if !self.check(&TokenType::Indent) {
3985            return Err(ParseError {
3986                kind: ParseErrorKind::ExpectedStatement,
3987                span: self.current_span(),
3988            });
3989        }
3990        self.advance(); // consume Indent
3991
3992        // Parse body statements
3993        let mut task_stmts = Vec::new();
3994        while !self.check(&TokenType::Dedent) && !self.is_at_end() {
3995            let stmt = self.parse_statement()?;
3996            task_stmts.push(stmt);
3997            if self.check(&TokenType::Period) {
3998                self.advance();
3999            }
4000        }
4001
4002        // Consume dedent
4003        if self.check(&TokenType::Dedent) {
4004            self.advance();
4005        }
4006
4007        let tasks = self.ctx.stmts.expect("imperative arenas not initialized")
4008            .alloc_slice(task_stmts.into_iter());
4009
4010        Ok(Stmt::Concurrent { tasks })
4011    }
4012
4013    /// Phase 9: Parse parallel execution block (CPU-bound)
4014    ///
4015    /// Syntax:
4016    /// ```logos
4017    /// Simultaneously:
4018    ///     Call compute_hash with data1.
4019    ///     Call compute_hash with data2.
4020    /// ```
4021    fn parse_parallel_block(&mut self) -> ParseResult<Stmt<'a>> {
4022        self.advance(); // consume "Simultaneously"
4023
4024        // Expect colon
4025        if !self.check(&TokenType::Colon) {
4026            return Err(ParseError {
4027                kind: ParseErrorKind::ExpectedKeyword { keyword: ":".to_string() },
4028                span: self.current_span(),
4029            });
4030        }
4031        self.advance(); // consume ":"
4032
4033        // Expect indent
4034        if !self.check(&TokenType::Indent) {
4035            return Err(ParseError {
4036                kind: ParseErrorKind::ExpectedStatement,
4037                span: self.current_span(),
4038            });
4039        }
4040        self.advance(); // consume Indent
4041
4042        // Parse body statements
4043        let mut task_stmts = Vec::new();
4044        while !self.check(&TokenType::Dedent) && !self.is_at_end() {
4045            let stmt = self.parse_statement()?;
4046            task_stmts.push(stmt);
4047            if self.check(&TokenType::Period) {
4048                self.advance();
4049            }
4050        }
4051
4052        // Consume dedent
4053        if self.check(&TokenType::Dedent) {
4054            self.advance();
4055        }
4056
4057        let tasks = self.ctx.stmts.expect("imperative arenas not initialized")
4058            .alloc_slice(task_stmts.into_iter());
4059
4060        Ok(Stmt::Parallel { tasks })
4061    }
4062
4063    /// Phase 33: Parse Inspect statement for pattern matching
4064    /// Syntax: Inspect target:
4065    ///             If it is a Variant [(bindings)]:
4066    ///                 body...
4067    ///             Otherwise:
4068    ///                 body...
4069    fn parse_inspect_statement(&mut self) -> ParseResult<Stmt<'a>> {
4070        self.advance(); // consume "Inspect"
4071
4072        // Parse target expression
4073        let target = self.parse_imperative_expr()?;
4074
4075        // Expect colon
4076        if !self.check(&TokenType::Colon) {
4077            return Err(ParseError {
4078                kind: ParseErrorKind::ExpectedKeyword { keyword: ":".to_string() },
4079                span: self.current_span(),
4080            });
4081        }
4082        self.advance(); // consume ":"
4083
4084        // Expect indent
4085        if !self.check(&TokenType::Indent) {
4086            return Err(ParseError {
4087                kind: ParseErrorKind::ExpectedStatement,
4088                span: self.current_span(),
4089            });
4090        }
4091        self.advance(); // consume Indent
4092
4093        let mut arms = Vec::new();
4094        let mut has_otherwise = false;
4095
4096        // Parse match arms until dedent
4097        while !self.check(&TokenType::Dedent) && !self.is_at_end() {
4098            if self.check(&TokenType::Otherwise) {
4099                // Parse "Otherwise:" default arm
4100                self.advance(); // consume "Otherwise"
4101
4102                if !self.check(&TokenType::Colon) {
4103                    return Err(ParseError {
4104                        kind: ParseErrorKind::ExpectedKeyword { keyword: ":".to_string() },
4105                        span: self.current_span(),
4106                    });
4107                }
4108                self.advance(); // consume ":"
4109
4110                // Handle both inline (Otherwise: stmt.) and block body
4111                let body_stmts = if self.check(&TokenType::Indent) {
4112                    self.advance(); // consume Indent
4113                    let mut stmts = Vec::new();
4114                    while !self.check(&TokenType::Dedent) && !self.is_at_end() {
4115                        let stmt = self.parse_statement()?;
4116                        stmts.push(stmt);
4117                        if self.check(&TokenType::Period) {
4118                            self.advance();
4119                        }
4120                    }
4121                    if self.check(&TokenType::Dedent) {
4122                        self.advance();
4123                    }
4124                    stmts
4125                } else {
4126                    // Inline body: "Otherwise: Show x."
4127                    let stmt = self.parse_statement()?;
4128                    if self.check(&TokenType::Period) {
4129                        self.advance();
4130                    }
4131                    vec![stmt]
4132                };
4133
4134                let body = self.ctx.stmts.expect("imperative arenas not initialized")
4135                    .alloc_slice(body_stmts.into_iter());
4136
4137                arms.push(MatchArm { enum_name: None, variant: None, bindings: vec![], body });
4138                has_otherwise = true;
4139                break;
4140            }
4141
4142            if self.check(&TokenType::If) {
4143                // Parse "If it is a VariantName [(bindings)]:"
4144                let arm = self.parse_match_arm()?;
4145                arms.push(arm);
4146            } else if self.check(&TokenType::When) || self.check_word("When") {
4147                // Parse "When Variant [(bindings)]:" (concise syntax)
4148                let arm = self.parse_when_arm()?;
4149                arms.push(arm);
4150            } else if self.check(&TokenType::Newline) {
4151                // Skip newlines between arms
4152                self.advance();
4153            } else {
4154                // Skip unexpected tokens
4155                self.advance();
4156            }
4157        }
4158
4159        // Consume final dedent
4160        if self.check(&TokenType::Dedent) {
4161            self.advance();
4162        }
4163
4164        Ok(Stmt::Inspect { target, arms, has_otherwise })
4165    }
4166
4167    /// Parse a single match arm: "If it is a Variant [(field: binding)]:"
4168    fn parse_match_arm(&mut self) -> ParseResult<MatchArm<'a>> {
4169        self.advance(); // consume "If"
4170
4171        // Expect "it"
4172        if !self.check_word("it") {
4173            return Err(ParseError {
4174                kind: ParseErrorKind::ExpectedKeyword { keyword: "it".to_string() },
4175                span: self.current_span(),
4176            });
4177        }
4178        self.advance(); // consume "it"
4179
4180        // Expect "is"
4181        if !self.check(&TokenType::Is) {
4182            return Err(ParseError {
4183                kind: ParseErrorKind::ExpectedKeyword { keyword: "is".to_string() },
4184                span: self.current_span(),
4185            });
4186        }
4187        self.advance(); // consume "is"
4188
4189        // Consume article "a" or "an"
4190        if self.check_article() {
4191            self.advance();
4192        }
4193
4194        // Get variant name
4195        let variant = self.expect_identifier()?;
4196
4197        // Look up the enum name for this variant
4198        let enum_name = self.find_variant(variant);
4199
4200        // Optional: "(field)" or "(field: binding)" or "(f1, f2: b2)"
4201        let bindings = if self.check(&TokenType::LParen) {
4202            self.parse_pattern_bindings()?
4203        } else {
4204            vec![]
4205        };
4206
4207        // Expect colon
4208        if !self.check(&TokenType::Colon) {
4209            return Err(ParseError {
4210                kind: ParseErrorKind::ExpectedKeyword { keyword: ":".to_string() },
4211                span: self.current_span(),
4212            });
4213        }
4214        self.advance(); // consume ":"
4215
4216        // Expect indent
4217        if !self.check(&TokenType::Indent) {
4218            return Err(ParseError {
4219                kind: ParseErrorKind::ExpectedStatement,
4220                span: self.current_span(),
4221            });
4222        }
4223        self.advance(); // consume Indent
4224
4225        // Parse body statements
4226        let mut body_stmts = Vec::new();
4227        while !self.check(&TokenType::Dedent) && !self.is_at_end() {
4228            let stmt = self.parse_statement()?;
4229            body_stmts.push(stmt);
4230            if self.check(&TokenType::Period) {
4231                self.advance();
4232            }
4233        }
4234
4235        // Consume dedent
4236        if self.check(&TokenType::Dedent) {
4237            self.advance();
4238        }
4239
4240        let body = self.ctx.stmts.expect("imperative arenas not initialized")
4241            .alloc_slice(body_stmts.into_iter());
4242
4243        Ok(MatchArm { enum_name, variant: Some(variant), bindings, body })
4244    }
4245
4246    /// Parse a concise match arm: "When Variant [(bindings)]:" or "When Variant: stmt."
4247    fn parse_when_arm(&mut self) -> ParseResult<MatchArm<'a>> {
4248        self.advance(); // consume "When"
4249
4250        // Get variant name
4251        let variant = self.expect_identifier()?;
4252
4253        // Look up the enum name and variant definition for this variant
4254        let (enum_name, variant_fields) = self.type_registry
4255            .as_ref()
4256            .and_then(|r| r.find_variant(variant).map(|(enum_name, vdef)| {
4257                let fields: Vec<_> = vdef.fields.iter().map(|f| f.name).collect();
4258                (Some(enum_name), fields)
4259            }))
4260            .unwrap_or((None, vec![]));
4261
4262        // Optional: "(binding)" or "(b1, b2)" - positional bindings
4263        let bindings = if self.check(&TokenType::LParen) {
4264            let raw_bindings = self.parse_when_bindings()?;
4265            // Map positional bindings to actual field names
4266            raw_bindings.into_iter().enumerate().map(|(i, binding)| {
4267                let field = variant_fields.get(i).copied().unwrap_or(binding);
4268                (field, binding)
4269            }).collect()
4270        } else {
4271            vec![]
4272        };
4273
4274        // Expect colon
4275        if !self.check(&TokenType::Colon) {
4276            return Err(ParseError {
4277                kind: ParseErrorKind::ExpectedKeyword { keyword: ":".to_string() },
4278                span: self.current_span(),
4279            });
4280        }
4281        self.advance(); // consume ":"
4282
4283        // Handle both inline body (When Variant: stmt.) and block body
4284        let body_stmts = if self.check(&TokenType::Indent) {
4285            self.advance(); // consume Indent
4286            let mut stmts = Vec::new();
4287            while !self.check(&TokenType::Dedent) && !self.is_at_end() {
4288                let stmt = self.parse_statement()?;
4289                stmts.push(stmt);
4290                if self.check(&TokenType::Period) {
4291                    self.advance();
4292                }
4293            }
4294            if self.check(&TokenType::Dedent) {
4295                self.advance();
4296            }
4297            stmts
4298        } else {
4299            // Inline body: "When Red: Show x."
4300            let stmt = self.parse_statement()?;
4301            if self.check(&TokenType::Period) {
4302                self.advance();
4303            }
4304            vec![stmt]
4305        };
4306
4307        let body = self.ctx.stmts.expect("imperative arenas not initialized")
4308            .alloc_slice(body_stmts.into_iter());
4309
4310        Ok(MatchArm { enum_name, variant: Some(variant), bindings, body })
4311    }
4312
4313    /// Parse concise When bindings: "(r)" or "(w, h)" - just binding variable names
4314    fn parse_when_bindings(&mut self) -> ParseResult<Vec<Symbol>> {
4315        self.advance(); // consume '('
4316        let mut bindings = Vec::new();
4317
4318        loop {
4319            let binding = self.expect_identifier()?;
4320            bindings.push(binding);
4321
4322            if !self.check(&TokenType::Comma) {
4323                break;
4324            }
4325            self.advance(); // consume ','
4326        }
4327
4328        if !self.check(&TokenType::RParen) {
4329            return Err(ParseError {
4330                kind: ParseErrorKind::ExpectedKeyword { keyword: ")".to_string() },
4331                span: self.current_span(),
4332            });
4333        }
4334        self.advance(); // consume ')'
4335
4336        Ok(bindings)
4337    }
4338
4339    /// Parse pattern bindings: "(field)" or "(field: binding)" or "(f1, f2: b2)"
4340    fn parse_pattern_bindings(&mut self) -> ParseResult<Vec<(Symbol, Symbol)>> {
4341        self.advance(); // consume '('
4342        let mut bindings = Vec::new();
4343
4344        loop {
4345            let field = self.expect_identifier()?;
4346            let binding = if self.check(&TokenType::Colon) {
4347                self.advance(); // consume ":"
4348                self.expect_identifier()?
4349            } else {
4350                field // field name = binding name
4351            };
4352            bindings.push((field, binding));
4353
4354            if !self.check(&TokenType::Comma) {
4355                break;
4356            }
4357            self.advance(); // consume ','
4358        }
4359
4360        if !self.check(&TokenType::RParen) {
4361            return Err(ParseError {
4362                kind: ParseErrorKind::ExpectedKeyword { keyword: ")".to_string() },
4363                span: self.current_span(),
4364            });
4365        }
4366        self.advance(); // consume ')'
4367
4368        Ok(bindings)
4369    }
4370
4371    /// Parse constructor fields: "with field1 value1 [and field2 value2]..."
4372    /// Example: "with radius 10" or "with x 10 and y 20"
4373    /// Used for both variant constructors and struct initialization
4374    fn parse_constructor_fields(&mut self) -> ParseResult<Vec<(Symbol, &'a Expr<'a>)>> {
4375        use crate::ast::Expr;
4376        let mut fields = Vec::new();
4377
4378        // Consume "with"
4379        self.advance();
4380
4381        loop {
4382            // Parse field name
4383            let field_name = self.expect_identifier()?;
4384
4385            // Parse field value expression
4386            let value = self.parse_imperative_expr()?;
4387
4388            fields.push((field_name, value));
4389
4390            // Check for "and" to continue
4391            if self.check(&TokenType::And) {
4392                self.advance(); // consume "and"
4393                continue;
4394            }
4395            break;
4396        }
4397
4398        Ok(fields)
4399    }
4400
4401    /// Alias for variant constructors (backwards compat)
4402    fn parse_variant_constructor_fields(&mut self) -> ParseResult<Vec<(Symbol, &'a Expr<'a>)>> {
4403        self.parse_constructor_fields()
4404    }
4405
4406    /// Alias for struct initialization
4407    fn parse_struct_init_fields(&mut self) -> ParseResult<Vec<(Symbol, &'a Expr<'a>)>> {
4408        self.parse_constructor_fields()
4409    }
4410
4411    /// Phase 34: Parse generic type arguments for constructor instantiation
4412    /// Parses "of Int" or "of Int and Text" after a generic type name
4413    /// Returns empty Vec for non-generic types
4414    fn parse_generic_type_args(&mut self, type_name: Symbol) -> ParseResult<Vec<TypeExpr<'a>>> {
4415        // Only parse type args if the type is a known generic
4416        if !self.is_generic_type(type_name) {
4417            return Ok(vec![]);
4418        }
4419
4420        // Expect "of" preposition
4421        if !self.check_preposition_is("of") {
4422            return Ok(vec![]);  // Generic type without arguments - will use defaults
4423        }
4424        self.advance(); // consume "of"
4425
4426        let mut type_args = Vec::new();
4427        loop {
4428            // Bug fix: Parse full type expression to support nested types like "Seq of (Seq of Int)"
4429            let type_arg = self.parse_type_expression()?;
4430            type_args.push(type_arg);
4431
4432            // Check for "and" or "to" to continue (for multi-param generics like "Map of Text to Int")
4433            if self.check(&TokenType::And) || self.check_to_preposition() {
4434                self.advance(); // consume separator
4435                continue;
4436            }
4437            break;
4438        }
4439
4440        Ok(type_args)
4441    }
4442
4443    /// Skip type definition content until next block header
4444    /// Used for TypeDef blocks (## A Point has:, ## A Color is one of:)
4445    /// The actual parsing is done by DiscoveryPass
4446    fn skip_type_def_content(&mut self) {
4447        while !self.is_at_end() {
4448            // Stop at next block header
4449            if matches!(
4450                self.tokens.get(self.current),
4451                Some(Token { kind: TokenType::BlockHeader { .. }, .. })
4452            ) {
4453                break;
4454            }
4455            self.advance();
4456        }
4457    }
4458
4459    /// Phase 63: Parse theorem block
4460    /// Syntax:
4461    ///   ## Theorem: Name
4462    ///   Given: Premise 1.
4463    ///   Given: Premise 2.
4464    ///   Prove: Goal.
4465    ///   Proof: Auto.
4466    fn parse_theorem_block(&mut self) -> ParseResult<Stmt<'a>> {
4467        use crate::ast::theorem::{TheoremBlock, ProofStrategy};
4468
4469        // Skip newlines and indentation
4470        self.skip_whitespace_tokens();
4471
4472        // Parse theorem name: expect "Name" after the ##Theorem header
4473        // The header has already been consumed; expect Colon then Identifier
4474        // Note: In some cases the colon might have been consumed with the header.
4475        // Let's be flexible and check for both.
4476        if self.check(&TokenType::Colon) {
4477            self.advance();
4478        }
4479
4480        // Skip whitespace again
4481        self.skip_whitespace_tokens();
4482
4483        // Get theorem name - should be an identifier (Noun, ProperName, etc.)
4484        let name = if let Some(token) = self.tokens.get(self.current) {
4485            match &token.kind {
4486                TokenType::Noun(_)
4487                | TokenType::ProperName(_)
4488                | TokenType::Verb { .. }
4489                | TokenType::Adjective(_) => {
4490                    let name = self.interner.resolve(token.lexeme).to_string();
4491                    self.advance();
4492                    name
4493                }
4494                _ => {
4495                    // Use the lexeme directly for unrecognized tokens
4496                    let lexeme = self.interner.resolve(token.lexeme);
4497                    if !lexeme.is_empty() && lexeme.chars().next().map(|c| c.is_alphanumeric()).unwrap_or(false) {
4498                        let name = lexeme.to_string();
4499                        self.advance();
4500                        name
4501                    } else {
4502                        "Anonymous".to_string()
4503                    }
4504                }
4505            }
4506        } else {
4507            "Anonymous".to_string()
4508        };
4509
4510        self.skip_whitespace_tokens();
4511
4512        // Skip period after name if present
4513        if self.check(&TokenType::Period) {
4514            self.advance();
4515        }
4516
4517        self.skip_whitespace_tokens();
4518
4519        // Parse premises (Given: statements)
4520        // Each premise is a sentence that can introduce referents for subsequent premises
4521        let mut premises = Vec::new();
4522        while self.check(&TokenType::Given) {
4523            self.advance(); // consume "Given"
4524
4525            // Expect colon
4526            if self.check(&TokenType::Colon) {
4527                self.advance();
4528            }
4529
4530            self.skip_whitespace_tokens();
4531
4532            // Parse the logic expression for this premise
4533            let premise_expr = self.parse_sentence()?;
4534            premises.push(premise_expr);
4535
4536            // Mark sentence boundary - this enables discourse mode and populates telescope
4537            // so pronouns in subsequent premises can resolve to referents from this premise
4538            self.world_state.end_sentence();
4539
4540            // Consume trailing period if present
4541            if self.check(&TokenType::Period) {
4542                self.advance();
4543            }
4544
4545            self.skip_whitespace_tokens();
4546        }
4547
4548        // Parse goal (Prove: statement)
4549        let goal = if self.check(&TokenType::Prove) {
4550            self.advance(); // consume "Prove"
4551
4552            if self.check(&TokenType::Colon) {
4553                self.advance();
4554            }
4555
4556            self.skip_whitespace_tokens();
4557
4558            let goal_expr = self.parse_sentence()?;
4559
4560            if self.check(&TokenType::Period) {
4561                self.advance();
4562            }
4563
4564            goal_expr
4565        } else {
4566            return Err(ParseError {
4567                kind: ParseErrorKind::ExpectedKeyword { keyword: "Prove".to_string() },
4568                span: self.current_span(),
4569            });
4570        };
4571
4572        self.skip_whitespace_tokens();
4573
4574        // Parse proof strategy (Proof: Auto.)
4575        let strategy = if self.check(&TokenType::BlockHeader { block_type: crate::token::BlockType::Proof }) {
4576            self.advance();
4577            self.skip_whitespace_tokens();
4578
4579            if self.check(&TokenType::Colon) {
4580                self.advance();
4581            }
4582
4583            self.skip_whitespace_tokens();
4584
4585            if self.check(&TokenType::Auto) {
4586                self.advance();
4587                ProofStrategy::Auto
4588            } else {
4589                // For now, default to Auto if we can't parse the strategy
4590                ProofStrategy::Auto
4591            }
4592        } else {
4593            // No explicit proof strategy, default to Auto
4594            ProofStrategy::Auto
4595        };
4596
4597        // Consume trailing period if present
4598        if self.check(&TokenType::Period) {
4599            self.advance();
4600        }
4601
4602        let theorem = TheoremBlock {
4603            name,
4604            premises,
4605            goal,
4606            strategy,
4607        };
4608
4609        Ok(Stmt::Theorem(theorem))
4610    }
4611
4612    /// Skip whitespace tokens (newlines, indentation)
4613    fn skip_whitespace_tokens(&mut self) {
4614        while self.check(&TokenType::Newline) || self.check(&TokenType::Indent) || self.check(&TokenType::Dedent) {
4615            self.advance();
4616        }
4617    }
4618
4619    /// Phase 32: Parse function definition after `## To` header
4620    /// Phase 32/38: Parse function definition
4621    /// Syntax: [To] [native] name (a: Type) [and (b: Type)] [-> ReturnType]
4622    ///         body statements... (only if not native)
4623    fn parse_function_def(&mut self) -> ParseResult<Stmt<'a>> {
4624        // Consume "To" if present (when called from parse_statement)
4625        if self.check(&TokenType::To) || self.check_preposition_is("to") {
4626            self.advance();
4627        }
4628
4629        // Phase 38: Check for native modifier (prefix style: "## To native funcname ...")
4630        let mut is_native = if self.check(&TokenType::Native) {
4631            self.advance(); // consume "native"
4632            true
4633        } else {
4634            false
4635        };
4636
4637        // Parse function name (first identifier after ## To [native])
4638        let name = self.expect_identifier()?;
4639
4640        // Parse parameters: (name: Type) groups separated by "and", or comma-separated in one group
4641        let mut params = Vec::new();
4642        while self.check(&TokenType::LParen) {
4643            self.advance(); // consume (
4644
4645            // Handle empty parameter list: ()
4646            if self.check(&TokenType::RParen) {
4647                self.advance(); // consume )
4648                break;
4649            }
4650
4651            // Parse parameters in this group (possibly comma-separated)
4652            loop {
4653                let param_name = self.expect_identifier()?;
4654
4655                // Expect colon
4656                if !self.check(&TokenType::Colon) {
4657                    return Err(ParseError {
4658                        kind: ParseErrorKind::ExpectedKeyword { keyword: ":".to_string() },
4659                        span: self.current_span(),
4660                    });
4661                }
4662                self.advance(); // consume :
4663
4664                // Phase 38: Parse full type expression instead of simple identifier
4665                let param_type_expr = self.parse_type_expression()?;
4666                let param_type = self.ctx.alloc_type_expr(param_type_expr);
4667
4668                params.push((param_name, param_type));
4669
4670                // Check for comma (more params in this group) or ) (end of group)
4671                if self.check(&TokenType::Comma) {
4672                    self.advance(); // consume ,
4673                    continue;
4674                }
4675                break;
4676            }
4677
4678            // Expect )
4679            if !self.check(&TokenType::RParen) {
4680                return Err(ParseError {
4681                    kind: ParseErrorKind::ExpectedKeyword { keyword: ")".to_string() },
4682                    span: self.current_span(),
4683                });
4684            }
4685            self.advance(); // consume )
4686
4687            // Check for "and", preposition, or "from" between parameter groups
4688            // Allows: "## To withdraw (amount: Int) from (balance: Int)"
4689            if self.check_word("and") || self.check_preposition() || self.check(&TokenType::From) {
4690                self.advance();
4691            }
4692        }
4693
4694        // Phase 38: Parse optional return type -> Type
4695        let return_type = if self.check(&TokenType::Arrow) {
4696            self.advance(); // consume ->
4697            let ret_type_expr = self.parse_type_expression()?;
4698            Some(self.ctx.alloc_type_expr(ret_type_expr))
4699        } else {
4700            None
4701        };
4702
4703        // FFI: Parse optional suffix modifiers: "is native <path>", "is exported [for <target>]"
4704        let mut native_path: Option<Symbol> = None;
4705        let mut is_exported = false;
4706        let mut export_target: Option<Symbol> = None;
4707
4708        if self.check_word("is") {
4709            self.advance(); // consume "is"
4710            if self.check(&TokenType::Native) {
4711                // "is native" suffix style with required path string
4712                self.advance(); // consume "native"
4713                is_native = true;
4714                if let TokenType::StringLiteral(sym) = self.peek().kind {
4715                    native_path = Some(sym);
4716                    self.advance(); // consume the path string
4717                } else {
4718                    return Err(ParseError {
4719                        kind: ParseErrorKind::Custom(
4720                            "Expected a string literal for native function path (e.g., is native \"reqwest::blocking::get\")".to_string()
4721                        ),
4722                        span: self.current_span(),
4723                    });
4724                }
4725            } else if self.check_word("exported") {
4726                // "is exported [for <target>]"
4727                self.advance(); // consume "exported"
4728                is_exported = true;
4729                if self.check_word("for") {
4730                    self.advance(); // consume "for"
4731                    let target_sym = self.expect_identifier()?;
4732                    let target_str = self.interner.resolve(target_sym);
4733                    if !target_str.eq_ignore_ascii_case("c") && !target_str.eq_ignore_ascii_case("wasm") {
4734                        return Err(ParseError {
4735                            kind: ParseErrorKind::Custom(
4736                                format!("Unsupported export target \"{}\". Supported targets are \"c\" and \"wasm\".", target_str)
4737                            ),
4738                            span: self.current_span(),
4739                        });
4740                    }
4741                    export_target = Some(target_sym);
4742                }
4743            }
4744        }
4745
4746        // Phase 38: Native functions have no body
4747        if is_native {
4748            // Consume trailing period or newline if present
4749            if self.check(&TokenType::Period) {
4750                self.advance();
4751            }
4752            if self.check(&TokenType::Newline) {
4753                self.advance();
4754            }
4755
4756            // Return with empty body
4757            let empty_body = self.ctx.stmts.expect("imperative arenas not initialized")
4758                .alloc_slice(std::iter::empty());
4759
4760            return Ok(Stmt::FunctionDef {
4761                name,
4762                params,
4763                body: empty_body,
4764                return_type,
4765                is_native: true,
4766                native_path,
4767                is_exported: false,
4768                export_target: None,
4769            });
4770        }
4771
4772        // Non-native: expect colon after parameter list / return type
4773        if !self.check(&TokenType::Colon) {
4774            return Err(ParseError {
4775                kind: ParseErrorKind::ExpectedKeyword { keyword: ":".to_string() },
4776                span: self.current_span(),
4777            });
4778        }
4779        self.advance(); // consume :
4780
4781        // Expect indent for function body
4782        if !self.check(&TokenType::Indent) {
4783            return Err(ParseError {
4784                kind: ParseErrorKind::ExpectedStatement,
4785                span: self.current_span(),
4786            });
4787        }
4788        self.advance(); // consume Indent
4789
4790        // Parse body statements
4791        let mut body_stmts = Vec::new();
4792        while !self.check(&TokenType::Dedent) && !self.is_at_end() {
4793            // Skip newlines between statements
4794            if self.check(&TokenType::Newline) {
4795                self.advance();
4796                continue;
4797            }
4798            // Stop if we hit another block header
4799            if matches!(self.peek().kind, TokenType::BlockHeader { .. }) {
4800                break;
4801            }
4802            let stmt = self.parse_statement()?;
4803            body_stmts.push(stmt);
4804            if self.check(&TokenType::Period) {
4805                self.advance();
4806            }
4807        }
4808
4809        // Consume dedent if present
4810        if self.check(&TokenType::Dedent) {
4811            self.advance();
4812        }
4813
4814        // Allocate body in arena
4815        let body = self.ctx.stmts.expect("imperative arenas not initialized")
4816            .alloc_slice(body_stmts.into_iter());
4817
4818        Ok(Stmt::FunctionDef {
4819            name,
4820            params,
4821            body,
4822            return_type,
4823            is_native: false,
4824            native_path: None,
4825            is_exported,
4826            export_target,
4827        })
4828    }
4829
4830    /// Parse a primary expression (literal, identifier, index, slice, list, etc.)
4831    fn parse_primary_expr(&mut self) -> ParseResult<&'a Expr<'a>> {
4832        use crate::ast::{Expr, Literal};
4833
4834        let token = self.peek().clone();
4835        match &token.kind {
4836            // Phase 31: Constructor expression "new TypeName" or "a new TypeName"
4837            // Phase 33: Extended for variant constructors "new Circle with radius 10"
4838            // Phase 34: Extended for generic instantiation "new Box of Int"
4839            TokenType::New => {
4840                self.advance(); // consume "new"
4841                let base_type_name = self.expect_identifier()?;
4842
4843                // Phase 36: Check for "from Module" qualification
4844                let type_name = if self.check(&TokenType::From) {
4845                    self.advance(); // consume "from"
4846                    let module_name = self.expect_identifier()?;
4847                    let module_str = self.interner.resolve(module_name);
4848                    let base_str = self.interner.resolve(base_type_name);
4849                    let qualified = format!("{}::{}", module_str, base_str);
4850                    self.interner.intern(&qualified)
4851                } else {
4852                    base_type_name
4853                };
4854
4855                // Phase 33: Check if this is a variant constructor
4856                if let Some(enum_name) = self.find_variant(type_name) {
4857                    // Parse optional "with field value" pairs
4858                    let fields = if self.check_word("with") {
4859                        self.parse_variant_constructor_fields()?
4860                    } else {
4861                        vec![]
4862                    };
4863                    let base = self.ctx.alloc_imperative_expr(Expr::NewVariant {
4864                        enum_name,
4865                        variant: type_name,
4866                        fields,
4867                    });
4868                    return self.parse_field_access_chain(base);
4869                }
4870
4871                // Phase 34: Parse generic type arguments "of Int" or "of Int and Text"
4872                let type_args = self.parse_generic_type_args(type_name)?;
4873
4874                // Parse optional "with field value" pairs for struct initialization
4875                // But NOT "with capacity" — that's a pre-allocation hint handled by parse_let_statement
4876                let init_fields = if self.check_word("with") && !self.peek_word_at(1, "capacity") {
4877                    self.parse_struct_init_fields()?
4878                } else {
4879                    vec![]
4880                };
4881
4882                let base = self.ctx.alloc_imperative_expr(Expr::New { type_name, type_args, init_fields });
4883                return self.parse_field_access_chain(base);
4884            }
4885
4886            // Phase 31: Handle "a new TypeName" pattern OR single-letter identifier
4887            // Phase 33: Extended for variant constructors "a new Circle with radius 10"
4888            // Phase 34: Extended for generic instantiation "a new Box of Int"
4889            TokenType::Article(_) => {
4890                // Phase 48: Check if followed by Manifest or Chunk token
4891                // Pattern: "the manifest of Zone" or "the chunk at N in Zone"
4892                if let Some(next) = self.tokens.get(self.current + 1) {
4893                    if matches!(next.kind, TokenType::Manifest) {
4894                        self.advance(); // consume "the"
4895                        // Delegate to Manifest handling
4896                        return self.parse_primary_expr();
4897                    }
4898                    if matches!(next.kind, TokenType::Chunk) {
4899                        self.advance(); // consume "the"
4900                        // Delegate to Chunk handling
4901                        return self.parse_primary_expr();
4902                    }
4903                    if matches!(next.kind, TokenType::Length) {
4904                        self.advance(); // consume "the"
4905                        return self.parse_primary_expr();
4906                    }
4907                }
4908                // Check if followed by New token
4909                if let Some(next) = self.tokens.get(self.current + 1) {
4910                    if matches!(next.kind, TokenType::New) {
4911                        self.advance(); // consume article "a"/"an"
4912                        self.advance(); // consume "new"
4913                        let base_type_name = self.expect_identifier()?;
4914
4915                        // Phase 36: Check for "from Module" qualification
4916                        let type_name = if self.check(&TokenType::From) {
4917                            self.advance(); // consume "from"
4918                            let module_name = self.expect_identifier()?;
4919                            let module_str = self.interner.resolve(module_name);
4920                            let base_str = self.interner.resolve(base_type_name);
4921                            let qualified = format!("{}::{}", module_str, base_str);
4922                            self.interner.intern(&qualified)
4923                        } else {
4924                            base_type_name
4925                        };
4926
4927                        // Phase 33: Check if this is a variant constructor
4928                        if let Some(enum_name) = self.find_variant(type_name) {
4929                            // Parse optional "with field value" pairs
4930                            let fields = if self.check_word("with") {
4931                                self.parse_variant_constructor_fields()?
4932                            } else {
4933                                vec![]
4934                            };
4935                            let base = self.ctx.alloc_imperative_expr(Expr::NewVariant {
4936                                enum_name,
4937                                variant: type_name,
4938                                fields,
4939                            });
4940                            return self.parse_field_access_chain(base);
4941                        }
4942
4943                        // Phase 34: Parse generic type arguments "of Int" or "of Int and Text"
4944                        let type_args = self.parse_generic_type_args(type_name)?;
4945
4946                        // Parse optional "with field value" pairs for struct initialization
4947                        // But NOT "with capacity" — that's a pre-allocation hint handled by parse_let_statement
4948                        let init_fields = if self.check_word("with") && !self.peek_word_at(1, "capacity") {
4949                            self.parse_struct_init_fields()?
4950                        } else {
4951                            vec![]
4952                        };
4953
4954                        let base = self.ctx.alloc_imperative_expr(Expr::New { type_name, type_args, init_fields });
4955                        return self.parse_field_access_chain(base);
4956                    }
4957                }
4958                // Phase 32: Treat as identifier (single-letter var like "a", "b")
4959                let sym = token.lexeme;
4960                self.advance();
4961                let base = self.ctx.alloc_imperative_expr(Expr::Identifier(sym));
4962                return self.parse_field_access_chain(base);
4963            }
4964
4965            // Index access: "item N of collection" or "item i of collection"
4966            TokenType::Item => {
4967                self.advance(); // consume "item"
4968
4969                // Grand Challenge: Parse index as expression (number, identifier, or parenthesized)
4970                let index = if let TokenType::Number(sym) = &self.peek().kind {
4971                    // Literal number - check for zero index at compile time
4972                    let sym = *sym;
4973                    self.advance();
4974                    let num_str = self.interner.resolve(sym);
4975                    let index_val = num_str.parse::<i64>().unwrap_or(0);
4976
4977                    // Index 0 Guard: LOGOS uses 1-based indexing
4978                    if index_val == 0 {
4979                        return Err(ParseError {
4980                            kind: ParseErrorKind::ZeroIndex,
4981                            span: self.current_span(),
4982                        });
4983                    }
4984
4985                    self.ctx.alloc_imperative_expr(
4986                        Expr::Literal(crate::ast::Literal::Number(index_val))
4987                    )
4988                } else if self.check(&TokenType::LParen) {
4989                    // Parenthesized expression like (mid + 1)
4990                    self.advance(); // consume '('
4991                    let inner = self.parse_imperative_expr()?;
4992                    if !self.check(&TokenType::RParen) {
4993                        return Err(ParseError {
4994                            kind: ParseErrorKind::ExpectedKeyword { keyword: ")".to_string() },
4995                            span: self.current_span(),
4996                        });
4997                    }
4998                    self.advance(); // consume ')'
4999                    inner
5000                } else if let TokenType::StringLiteral(sym) = self.peek().kind {
5001                    // Phase 57B: String literal key for Map access like item "iron" of prices
5002                    let sym = sym;
5003                    self.advance();
5004                    self.ctx.alloc_imperative_expr(Expr::Literal(crate::ast::Literal::Text(sym)))
5005                } else if !self.check_preposition_is("of") {
5006                    // Check for boolean literals before treating as variable
5007                    let word = self.interner.resolve(self.peek().lexeme);
5008                    if word == "true" {
5009                        self.advance();
5010                        self.ctx.alloc_imperative_expr(Expr::Literal(crate::ast::Literal::Boolean(true)))
5011                    } else if word == "false" {
5012                        self.advance();
5013                        self.ctx.alloc_imperative_expr(Expr::Literal(crate::ast::Literal::Boolean(false)))
5014                    } else {
5015                        // Variable identifier like i, j, idx (any token that's not "of")
5016                        let sym = self.peek().lexeme;
5017                        self.advance();
5018                        self.ctx.alloc_imperative_expr(Expr::Identifier(sym))
5019                    }
5020                } else {
5021                    return Err(ParseError {
5022                        kind: ParseErrorKind::ExpectedExpression,
5023                        span: self.current_span(),
5024                    });
5025                };
5026
5027                // Expect "of"
5028                if !self.check_preposition_is("of") {
5029                    return Err(ParseError {
5030                        kind: ParseErrorKind::ExpectedKeyword { keyword: "of".to_string() },
5031                        span: self.current_span(),
5032                    });
5033                }
5034                self.advance(); // consume "of"
5035
5036                // Parse collection as primary expression (identifier or field chain)
5037                // Using primary_expr instead of imperative_expr prevents consuming operators
5038                let collection = self.parse_primary_expr()?;
5039
5040                Ok(self.ctx.alloc_imperative_expr(Expr::Index {
5041                    collection,
5042                    index,
5043                }))
5044            }
5045
5046            // Slice access: "items N through M of collection"
5047            // OR variable named "items" - disambiguate by checking if next token starts an expression
5048            TokenType::Items => {
5049                // Peek ahead to determine if this is slice syntax or variable usage
5050                // Slice syntax: "items" followed by number or paren (clear indicators of index)
5051                // Variable: "items" followed by something else (operator, dot, etc.)
5052                let is_slice_syntax = if let Some(next) = self.tokens.get(self.current + 1) {
5053                    matches!(next.kind, TokenType::Number(_) | TokenType::LParen)
5054                } else {
5055                    false
5056                };
5057
5058                if !is_slice_syntax {
5059                    // Treat "items" as a variable identifier
5060                    let sym = token.lexeme;
5061                    self.advance();
5062                    let base = self.ctx.alloc_imperative_expr(Expr::Identifier(sym));
5063                    return self.parse_field_access_chain(base);
5064                }
5065
5066                self.advance(); // consume "items"
5067
5068                // Grand Challenge: Parse start index as expression (number, identifier, or parenthesized)
5069                let start = if let TokenType::Number(sym) = &self.peek().kind {
5070                    // Literal number - check for zero index at compile time
5071                    let sym = *sym;
5072                    self.advance();
5073                    let num_str = self.interner.resolve(sym);
5074                    let start_val = num_str.parse::<i64>().unwrap_or(0);
5075
5076                    // Index 0 Guard for start
5077                    if start_val == 0 {
5078                        return Err(ParseError {
5079                            kind: ParseErrorKind::ZeroIndex,
5080                            span: self.current_span(),
5081                        });
5082                    }
5083
5084                    self.ctx.alloc_imperative_expr(
5085                        Expr::Literal(crate::ast::Literal::Number(start_val))
5086                    )
5087                } else if self.check(&TokenType::LParen) {
5088                    // Parenthesized expression like (mid + 1)
5089                    self.advance(); // consume '('
5090                    let inner = self.parse_imperative_expr()?;
5091                    if !self.check(&TokenType::RParen) {
5092                        return Err(ParseError {
5093                            kind: ParseErrorKind::ExpectedKeyword { keyword: ")".to_string() },
5094                            span: self.current_span(),
5095                        });
5096                    }
5097                    self.advance(); // consume ')'
5098                    inner
5099                } else if !self.check_preposition_is("through") {
5100                    // Variable identifier like mid, idx
5101                    let sym = self.peek().lexeme;
5102                    self.advance();
5103                    self.ctx.alloc_imperative_expr(Expr::Identifier(sym))
5104                } else {
5105                    return Err(ParseError {
5106                        kind: ParseErrorKind::ExpectedExpression,
5107                        span: self.current_span(),
5108                    });
5109                };
5110
5111                // Expect "through"
5112                if !self.check_preposition_is("through") {
5113                    return Err(ParseError {
5114                        kind: ParseErrorKind::ExpectedKeyword { keyword: "through".to_string() },
5115                        span: self.current_span(),
5116                    });
5117                }
5118                self.advance(); // consume "through"
5119
5120                // Grand Challenge: Parse end index as expression (number, identifier, or parenthesized)
5121                let end = if let TokenType::Number(sym) = &self.peek().kind {
5122                    // Literal number - check for zero index at compile time
5123                    let sym = *sym;
5124                    self.advance();
5125                    let num_str = self.interner.resolve(sym);
5126                    let end_val = num_str.parse::<i64>().unwrap_or(0);
5127
5128                    // Index 0 Guard for end
5129                    if end_val == 0 {
5130                        return Err(ParseError {
5131                            kind: ParseErrorKind::ZeroIndex,
5132                            span: self.current_span(),
5133                        });
5134                    }
5135
5136                    self.ctx.alloc_imperative_expr(
5137                        Expr::Literal(crate::ast::Literal::Number(end_val))
5138                    )
5139                } else if self.check(&TokenType::LParen) {
5140                    // Parenthesized expression like (mid + 1)
5141                    self.advance(); // consume '('
5142                    let inner = self.parse_imperative_expr()?;
5143                    if !self.check(&TokenType::RParen) {
5144                        return Err(ParseError {
5145                            kind: ParseErrorKind::ExpectedKeyword { keyword: ")".to_string() },
5146                            span: self.current_span(),
5147                        });
5148                    }
5149                    self.advance(); // consume ')'
5150                    inner
5151                } else if !self.check_preposition_is("of") {
5152                    // Variable identifier like n, length
5153                    let sym = self.peek().lexeme;
5154                    self.advance();
5155                    self.ctx.alloc_imperative_expr(Expr::Identifier(sym))
5156                } else {
5157                    return Err(ParseError {
5158                        kind: ParseErrorKind::ExpectedExpression,
5159                        span: self.current_span(),
5160                    });
5161                };
5162
5163                // "of collection" is now optional - collection can be inferred from context
5164                // (e.g., "items 1 through mid" when items is the local variable)
5165                let collection = if self.check_preposition_is("of") {
5166                    self.advance(); // consume "of"
5167                    self.parse_imperative_expr()?
5168                } else {
5169                    // The variable is the collection itself (already consumed as "items")
5170                    // Re-intern "items" to use as the collection identifier
5171                    let items_sym = self.interner.intern("items");
5172                    self.ctx.alloc_imperative_expr(Expr::Identifier(items_sym))
5173                };
5174
5175                Ok(self.ctx.alloc_imperative_expr(Expr::Slice {
5176                    collection,
5177                    start,
5178                    end,
5179                }))
5180            }
5181
5182            // List literal: [1, 2, 3]
5183            TokenType::LBracket => {
5184                self.advance(); // consume "["
5185
5186                let mut items = Vec::new();
5187                if !self.check(&TokenType::RBracket) {
5188                    loop {
5189                        items.push(self.parse_imperative_expr()?);
5190                        if !self.check(&TokenType::Comma) {
5191                            break;
5192                        }
5193                        self.advance(); // consume ","
5194                    }
5195                }
5196
5197                if !self.check(&TokenType::RBracket) {
5198                    return Err(ParseError {
5199                        kind: ParseErrorKind::ExpectedKeyword { keyword: "]".to_string() },
5200                        span: self.current_span(),
5201                    });
5202                }
5203                self.advance(); // consume "]"
5204
5205                // Check for typed empty list: [] of Int
5206                if items.is_empty() && self.check_word("of") {
5207                    self.advance(); // consume "of"
5208                    let type_name = self.expect_identifier()?;
5209                    // Generate: Seq::<Type>::default()
5210                    let seq_sym = self.interner.intern("Seq");
5211                    return Ok(self.ctx.alloc_imperative_expr(Expr::New {
5212                        type_name: seq_sym,
5213                        type_args: vec![TypeExpr::Named(type_name)],
5214                        init_fields: vec![],
5215                    }));
5216                }
5217
5218                Ok(self.ctx.alloc_imperative_expr(Expr::List(items)))
5219            }
5220
5221            TokenType::Number(sym) => {
5222                let num_str = self.interner.resolve(*sym).to_string();
5223                self.advance();
5224
5225                // Check if followed by CalendarUnit → Span literal
5226                if let TokenType::CalendarUnit(unit) = self.peek().kind {
5227                    return self.parse_span_literal_from_num(&num_str);
5228                }
5229
5230                // Check if it's a float (contains decimal point)
5231                if num_str.contains('.') {
5232                    let num = num_str.parse::<f64>().unwrap_or(0.0);
5233                    Ok(self.ctx.alloc_imperative_expr(Expr::Literal(Literal::Float(num))))
5234                } else {
5235                    let num = num_str.parse::<i64>().unwrap_or(0);
5236                    Ok(self.ctx.alloc_imperative_expr(Expr::Literal(Literal::Number(num))))
5237                }
5238            }
5239
5240            // Phase 33: String literals
5241            TokenType::StringLiteral(sym) => {
5242                self.advance();
5243                Ok(self.ctx.alloc_imperative_expr(Expr::Literal(Literal::Text(*sym))))
5244            }
5245
5246            // Character literals
5247            TokenType::CharLiteral(sym) => {
5248                let char_str = self.interner.resolve(*sym);
5249                let ch = char_str.chars().next().unwrap_or('\0');
5250                self.advance();
5251                Ok(self.ctx.alloc_imperative_expr(Expr::Literal(Literal::Char(ch))))
5252            }
5253
5254            // Duration literals: 500ms, 2s, 50ns
5255            TokenType::DurationLiteral { nanos, .. } => {
5256                let nanos = *nanos;
5257                self.advance();
5258                Ok(self.ctx.alloc_imperative_expr(Expr::Literal(Literal::Duration(nanos))))
5259            }
5260
5261            // Date literals: 2026-05-20
5262            // Also handles "DATE at TIME" → Moment
5263            TokenType::DateLiteral { days } => {
5264                let days = *days;
5265                self.advance();
5266
5267                // Check for "at TIME" to create a Moment
5268                if self.check(&TokenType::At) {
5269                    self.advance(); // consume "at"
5270
5271                    // Expect a TimeLiteral
5272                    if let TokenType::TimeLiteral { nanos_from_midnight } = self.peek().kind {
5273                        let time_nanos = nanos_from_midnight;
5274                        self.advance(); // consume time literal
5275
5276                        // Convert to Moment: days * 86400 * 1e9 + time_nanos
5277                        let moment_nanos = (days as i64) * 86_400_000_000_000 + time_nanos;
5278                        return Ok(self.ctx.alloc_imperative_expr(Expr::Literal(Literal::Moment(moment_nanos))));
5279                    } else {
5280                        return Err(ParseError {
5281                            kind: ParseErrorKind::ExpectedExpression,
5282                            span: self.current_span(),
5283                        });
5284                    }
5285                }
5286
5287                Ok(self.ctx.alloc_imperative_expr(Expr::Literal(Literal::Date(days))))
5288            }
5289
5290            // Time-of-day literals: 4pm, 9:30am, noon, midnight
5291            TokenType::TimeLiteral { nanos_from_midnight } => {
5292                let nanos = *nanos_from_midnight;
5293                self.advance();
5294                Ok(self.ctx.alloc_imperative_expr(Expr::Literal(Literal::Time(nanos))))
5295            }
5296
5297            // Handle 'nothing' literal
5298            TokenType::Nothing => {
5299                self.advance();
5300                Ok(self.ctx.alloc_imperative_expr(Expr::Literal(Literal::Nothing)))
5301            }
5302
5303            // Option constructors: "some <expr>" → Some(expr), "none" → None
5304            TokenType::Some => {
5305                self.advance(); // consume "some"
5306                let value = self.parse_imperative_expr()?;
5307                Ok(self.ctx.alloc_imperative_expr(Expr::OptionSome { value }))
5308            }
5309
5310            // Phase 43D: Length expression: "length of items" or "length(items)"
5311            TokenType::Length => {
5312                let func_name = self.peek().lexeme;
5313
5314                // Check for function call syntax: length(x)
5315                if self.tokens.get(self.current + 1)
5316                    .map(|t| matches!(t.kind, TokenType::LParen))
5317                    .unwrap_or(false)
5318                {
5319                    self.advance(); // consume "length"
5320                    return self.parse_call_expr(func_name);
5321                }
5322
5323                self.advance(); // consume "length"
5324
5325                // Expect "of" for natural syntax
5326                if !self.check_preposition_is("of") {
5327                    return Err(ParseError {
5328                        kind: ParseErrorKind::ExpectedKeyword { keyword: "of".to_string() },
5329                        span: self.current_span(),
5330                    });
5331                }
5332                self.advance(); // consume "of"
5333
5334                let collection = self.parse_imperative_expr()?;
5335                Ok(self.ctx.alloc_imperative_expr(Expr::Length { collection }))
5336            }
5337
5338            // Phase 43D: Copy expression: "copy of slice" or "copy(slice)"
5339            TokenType::Copy => {
5340                let func_name = self.peek().lexeme;
5341
5342                // Check for function call syntax: copy(x)
5343                if self.tokens.get(self.current + 1)
5344                    .map(|t| matches!(t.kind, TokenType::LParen))
5345                    .unwrap_or(false)
5346                {
5347                    self.advance(); // consume "copy"
5348                    return self.parse_call_expr(func_name);
5349                }
5350
5351                self.advance(); // consume "copy"
5352
5353                // Expect "of" for natural syntax
5354                if !self.check_preposition_is("of") {
5355                    return Err(ParseError {
5356                        kind: ParseErrorKind::ExpectedKeyword { keyword: "of".to_string() },
5357                        span: self.current_span(),
5358                    });
5359                }
5360                self.advance(); // consume "of"
5361
5362                let expr = self.parse_imperative_expr()?;
5363                Ok(self.ctx.alloc_imperative_expr(Expr::Copy { expr }))
5364            }
5365
5366            // Phase 48: Manifest expression: "manifest of Zone"
5367            TokenType::Manifest => {
5368                self.advance(); // consume "manifest"
5369
5370                // Expect "of"
5371                if !self.check_preposition_is("of") {
5372                    return Err(ParseError {
5373                        kind: ParseErrorKind::ExpectedKeyword { keyword: "of".to_string() },
5374                        span: self.current_span(),
5375                    });
5376                }
5377                self.advance(); // consume "of"
5378
5379                let zone = self.parse_imperative_expr()?;
5380                Ok(self.ctx.alloc_imperative_expr(Expr::ManifestOf { zone }))
5381            }
5382
5383            // Phase 48: Chunk expression: "chunk at N in Zone"
5384            TokenType::Chunk => {
5385                self.advance(); // consume "chunk"
5386
5387                // Expect "at"
5388                if !self.check(&TokenType::At) {
5389                    return Err(ParseError {
5390                        kind: ParseErrorKind::ExpectedKeyword { keyword: "at".to_string() },
5391                        span: self.current_span(),
5392                    });
5393                }
5394                self.advance(); // consume "at"
5395
5396                let index = self.parse_imperative_expr()?;
5397
5398                // Expect "in"
5399                if !self.check_preposition_is("in") && !self.check(&TokenType::In) {
5400                    return Err(ParseError {
5401                        kind: ParseErrorKind::ExpectedKeyword { keyword: "in".to_string() },
5402                        span: self.current_span(),
5403                    });
5404                }
5405                self.advance(); // consume "in"
5406
5407                let zone = self.parse_imperative_expr()?;
5408                Ok(self.ctx.alloc_imperative_expr(Expr::ChunkAt { index, zone }))
5409            }
5410
5411            // Handle verbs in expression context:
5412            // - "empty" is a literal Nothing
5413            // - Other verbs can be function names (e.g., read, write)
5414            TokenType::Verb { lemma, .. } => {
5415                let word = self.interner.resolve(*lemma).to_lowercase();
5416                if word == "empty" {
5417                    self.advance();
5418                    return Ok(self.ctx.alloc_imperative_expr(Expr::Literal(Literal::Nothing)));
5419                }
5420                // Phase 38: Allow verbs to be used as function calls
5421                let sym = token.lexeme;
5422                self.advance();
5423                if self.check(&TokenType::LParen) {
5424                    return self.parse_call_expr(sym);
5425                }
5426                // Treat as identifier reference
5427                self.verify_identifier_access(sym)?;
5428                let base = self.ctx.alloc_imperative_expr(Expr::Identifier(sym));
5429                self.parse_field_access_chain(base)
5430            }
5431
5432            // Phase 38: Adverbs as identifiers (e.g., "now" for time functions)
5433            TokenType::TemporalAdverb(_) | TokenType::ScopalAdverb(_) | TokenType::Adverb(_) => {
5434                let sym = token.lexeme;
5435                self.advance();
5436                if self.check(&TokenType::LParen) {
5437                    return self.parse_call_expr(sym);
5438                }
5439                // Treat as identifier reference (e.g., "Let t be now.")
5440                self.verify_identifier_access(sym)?;
5441                let base = self.ctx.alloc_imperative_expr(Expr::Identifier(sym));
5442                self.parse_field_access_chain(base)
5443            }
5444
5445            // Phase 10: IO keywords as function calls (e.g., "read", "write", "file")
5446            // Phase 57: Add/Remove keywords as function calls
5447            TokenType::Read | TokenType::Write | TokenType::File | TokenType::Console |
5448            TokenType::Add | TokenType::Remove => {
5449                let sym = token.lexeme;
5450                self.advance();
5451                if self.check(&TokenType::LParen) {
5452                    return self.parse_call_expr(sym);
5453                }
5454                // Treat as identifier reference
5455                self.verify_identifier_access(sym)?;
5456                let base = self.ctx.alloc_imperative_expr(Expr::Identifier(sym));
5457                self.parse_field_access_chain(base)
5458            }
5459
5460            // Unified identifier handling - all identifier-like tokens get verified
5461            // First check for boolean/special literals before treating as variable
5462            TokenType::Noun(sym) | TokenType::ProperName(sym) | TokenType::Adjective(sym) => {
5463                let sym = *sym;
5464                let word = self.interner.resolve(sym);
5465
5466                // Check for boolean literals
5467                if word == "true" {
5468                    self.advance();
5469                    return Ok(self.ctx.alloc_imperative_expr(Expr::Literal(Literal::Boolean(true))));
5470                }
5471                if word == "false" {
5472                    self.advance();
5473                    return Ok(self.ctx.alloc_imperative_expr(Expr::Literal(Literal::Boolean(false))));
5474                }
5475
5476                // Check for 'empty' - treat as unit value for collections
5477                if word == "empty" {
5478                    self.advance();
5479                    return Ok(self.ctx.alloc_imperative_expr(Expr::Literal(Literal::Nothing)));
5480                }
5481
5482                // Option None literal: "none" → None
5483                if word == "none" {
5484                    self.advance();
5485                    return Ok(self.ctx.alloc_imperative_expr(Expr::OptionNone));
5486                }
5487
5488                // Don't verify as variable - might be a function call or enum variant
5489                self.advance();
5490
5491                // Phase 32: Check for function call: identifier(args)
5492                if self.check(&TokenType::LParen) {
5493                    return self.parse_call_expr(sym);
5494                }
5495
5496                // Phase 33: Check if this is a bare enum variant (e.g., "North" for Direction)
5497                if let Some(enum_name) = self.find_variant(sym) {
5498                    let fields = if self.check_word("with") {
5499                        self.parse_variant_constructor_fields()?
5500                    } else {
5501                        vec![]
5502                    };
5503                    let base = self.ctx.alloc_imperative_expr(Expr::NewVariant {
5504                        enum_name,
5505                        variant: sym,
5506                        fields,
5507                    });
5508                    return self.parse_field_access_chain(base);
5509                }
5510
5511                // Centralized verification for undefined/moved checks (only for variables)
5512                self.verify_identifier_access(sym)?;
5513                let base = self.ctx.alloc_imperative_expr(Expr::Identifier(sym));
5514                // Phase 31: Check for field access via possessive
5515                self.parse_field_access_chain(base)
5516            }
5517
5518            // Pronouns can be variable names in code context ("i", "it")
5519            TokenType::Pronoun { .. } => {
5520                let sym = token.lexeme;
5521                self.advance();
5522                let base = self.ctx.alloc_imperative_expr(Expr::Identifier(sym));
5523                // Phase 31: Check for field access via possessive
5524                self.parse_field_access_chain(base)
5525            }
5526
5527            // Phase 49: CRDT keywords can be function names (Merge, Increase)
5528            TokenType::Merge | TokenType::Increase => {
5529                let sym = token.lexeme;
5530                self.advance();
5531
5532                // Check for function call: Merge(args)
5533                if self.check(&TokenType::LParen) {
5534                    return self.parse_call_expr(sym);
5535                }
5536
5537                let base = self.ctx.alloc_imperative_expr(Expr::Identifier(sym));
5538                self.parse_field_access_chain(base)
5539            }
5540
5541            // Escape hatch in expression position: `Escape to Rust:`
5542            // Lookahead: if followed by "to", parse as escape expression.
5543            // Otherwise, treat as identifier (variable named "escape").
5544            TokenType::Escape => {
5545                if self.tokens.get(self.current + 1).map_or(false, |t|
5546                    matches!(t.kind, TokenType::To) || {
5547                        if let TokenType::Preposition(sym) = t.kind {
5548                            sym.is(self.interner, "to")
5549                        } else {
5550                            false
5551                        }
5552                    }
5553                ) {
5554                    return self.parse_escape_expr();
5555                }
5556                // Fall through to identifier handling
5557                let sym = token.lexeme;
5558                self.advance();
5559                if self.check(&TokenType::LParen) {
5560                    return self.parse_call_expr(sym);
5561                }
5562                self.verify_identifier_access(sym)?;
5563                let base = self.ctx.alloc_imperative_expr(Expr::Identifier(sym));
5564                self.parse_field_access_chain(base)
5565            }
5566
5567            // Keywords that can also be used as identifiers in expression context
5568            // These are contextual keywords - they have special meaning in specific positions
5569            // but can be used as variable names elsewhere
5570            TokenType::Values |    // "values" - can be a variable name
5571            TokenType::Both |      // correlative: "both X and Y"
5572            TokenType::Either |    // correlative: "either X or Y"
5573            TokenType::Combined |  // string concat: "combined with"
5574            TokenType::Shared => { // CRDT modifier
5575                let sym = token.lexeme;
5576                self.advance();
5577
5578                // Check for function call
5579                if self.check(&TokenType::LParen) {
5580                    return self.parse_call_expr(sym);
5581                }
5582
5583                self.verify_identifier_access(sym)?;
5584                let base = self.ctx.alloc_imperative_expr(Expr::Identifier(sym));
5585                self.parse_field_access_chain(base)
5586            }
5587
5588            // Handle ambiguous tokens that might be identifiers or function calls
5589            TokenType::Ambiguous { primary, alternatives } => {
5590                // Always use lexeme for identifier access - preserves original casing
5591                // (using verb lemma can give wrong casing like "Result" instead of "result")
5592                let sym = token.lexeme;
5593
5594                // Check if this token can be used as identifier (has Noun/Verb/etc. interpretation)
5595                let is_identifier_token = match &**primary {
5596                    TokenType::Noun(_) | TokenType::Adjective(_) | TokenType::ProperName(_) |
5597                    TokenType::Verb { .. } => true,
5598                    _ => alternatives.iter().any(|t| matches!(t,
5599                        TokenType::Noun(_) | TokenType::Adjective(_) | TokenType::ProperName(_) |
5600                        TokenType::Verb { .. }
5601                    ))
5602                };
5603
5604                if is_identifier_token {
5605                    self.advance();
5606
5607                    // Check for function call: ambiguous_name(args)
5608                    if self.check(&TokenType::LParen) {
5609                        return self.parse_call_expr(sym);
5610                    }
5611
5612                    self.verify_identifier_access(sym)?;
5613                    let base = self.ctx.alloc_imperative_expr(Expr::Identifier(sym));
5614                    // Phase 31: Check for field access via possessive
5615                    self.parse_field_access_chain(base)
5616                } else {
5617                    Err(ParseError {
5618                        kind: ParseErrorKind::ExpectedExpression,
5619                        span: self.current_span(),
5620                    })
5621                }
5622            }
5623
5624            // Parenthesized expression, tuple literal, or closure
5625            TokenType::LParen => {
5626                // Try closure parse first using speculative parsing.
5627                // Closure syntax: `(name: Type, ...) -> expr` or `() -> expr`
5628                if let Some(closure) = self.try_parse(|p| p.parse_closure_expr()) {
5629                    return Ok(closure);
5630                }
5631
5632                // Not a closure — parse as parenthesized expression or tuple
5633                self.advance(); // consume '('
5634                let first = self.parse_imperative_expr()?;
5635
5636                // Check if this is a tuple (has comma) or just grouping
5637                if self.check(&TokenType::Comma) {
5638                    // It's a tuple - parse remaining elements
5639                    let mut items = vec![first];
5640                    while self.check(&TokenType::Comma) {
5641                        self.advance(); // consume ","
5642                        items.push(self.parse_imperative_expr()?);
5643                    }
5644
5645                    if !self.check(&TokenType::RParen) {
5646                        return Err(ParseError {
5647                            kind: ParseErrorKind::ExpectedKeyword { keyword: ")".to_string() },
5648                            span: self.current_span(),
5649                        });
5650                    }
5651                    self.advance(); // consume ')'
5652
5653                    let base = self.ctx.alloc_imperative_expr(Expr::Tuple(items));
5654                    self.parse_field_access_chain(base)
5655                } else {
5656                    // Just a parenthesized expression
5657                    if !self.check(&TokenType::RParen) {
5658                        return Err(ParseError {
5659                            kind: ParseErrorKind::ExpectedKeyword { keyword: ")".to_string() },
5660                            span: self.current_span(),
5661                        });
5662                    }
5663                    self.advance(); // consume ')'
5664                    Ok(first)
5665                }
5666            }
5667
5668            // "Call funcName with args" as an expression
5669            TokenType::Call => {
5670                self.advance(); // consume "Call"
5671                let function = match &self.peek().kind {
5672                    TokenType::Noun(sym) | TokenType::Adjective(sym) => {
5673                        let s = *sym;
5674                        self.advance();
5675                        s
5676                    }
5677                    TokenType::Verb { .. } | TokenType::Ambiguous { .. } => {
5678                        let s = self.peek().lexeme;
5679                        self.advance();
5680                        s
5681                    }
5682                    _ => {
5683                        return Err(ParseError {
5684                            kind: ParseErrorKind::ExpectedIdentifier,
5685                            span: self.current_span(),
5686                        });
5687                    }
5688                };
5689                let args = if self.check_preposition_is("with") {
5690                    self.advance(); // consume "with"
5691                    self.parse_call_arguments()?
5692                } else {
5693                    Vec::new()
5694                };
5695                Ok(self.ctx.alloc_imperative_expr(Expr::Call { function, args }))
5696            }
5697
5698            _ => {
5699                Err(ParseError {
5700                    kind: ParseErrorKind::ExpectedExpression,
5701                    span: self.current_span(),
5702                })
5703            }
5704        }
5705    }
5706
5707    /// Parse a closure expression: `(params) -> expr` or `(params) ->:` block.
5708    /// Called speculatively — will fail (and rollback) if not a closure.
5709    fn parse_closure_expr(&mut self) -> ParseResult<&'a Expr<'a>> {
5710        use crate::ast::stmt::ClosureBody;
5711
5712        // Expect '('
5713        if !self.check(&TokenType::LParen) {
5714            return Err(ParseError {
5715                kind: ParseErrorKind::ExpectedExpression,
5716                span: self.current_span(),
5717            });
5718        }
5719        self.advance(); // consume '('
5720
5721        // Parse parameter list
5722        let mut params = Vec::new();
5723        if !self.check(&TokenType::RParen) {
5724            // First parameter: name: Type
5725            let name = self.expect_identifier()?;
5726            if !self.check(&TokenType::Colon) {
5727                return Err(ParseError {
5728                    kind: ParseErrorKind::ExpectedKeyword { keyword: ":".to_string() },
5729                    span: self.current_span(),
5730                });
5731            }
5732            self.advance(); // consume ':'
5733            let ty = self.parse_type_expression()?;
5734            let ty_ref = self.ctx.alloc_type_expr(ty);
5735            params.push((name, ty_ref));
5736
5737            // Additional parameters
5738            while self.check(&TokenType::Comma) {
5739                self.advance(); // consume ','
5740                let name = self.expect_identifier()?;
5741                if !self.check(&TokenType::Colon) {
5742                    return Err(ParseError {
5743                        kind: ParseErrorKind::ExpectedKeyword { keyword: ":".to_string() },
5744                        span: self.current_span(),
5745                    });
5746                }
5747                self.advance(); // consume ':'
5748                let ty = self.parse_type_expression()?;
5749                let ty_ref = self.ctx.alloc_type_expr(ty);
5750                params.push((name, ty_ref));
5751            }
5752        }
5753
5754        // Expect ')'
5755        if !self.check(&TokenType::RParen) {
5756            return Err(ParseError {
5757                kind: ParseErrorKind::ExpectedKeyword { keyword: ")".to_string() },
5758                span: self.current_span(),
5759            });
5760        }
5761        self.advance(); // consume ')'
5762
5763        // Expect '->'
5764        if !self.check(&TokenType::Arrow) {
5765            return Err(ParseError {
5766                kind: ParseErrorKind::ExpectedKeyword { keyword: "->".to_string() },
5767                span: self.current_span(),
5768            });
5769        }
5770        self.advance(); // consume '->'
5771
5772        // Check for block body (->:) vs expression body (-> expr)
5773        let body = if self.check(&TokenType::Colon) {
5774            self.advance(); // consume ':'
5775            // Parse indented block
5776            if !self.check(&TokenType::Indent) {
5777                return Err(ParseError {
5778                    kind: ParseErrorKind::ExpectedStatement,
5779                    span: self.current_span(),
5780                });
5781            }
5782            self.advance(); // consume Indent
5783
5784            let mut block_stmts = Vec::new();
5785            while !self.check(&TokenType::Dedent) && !self.is_at_end() {
5786                let stmt = self.parse_statement()?;
5787                block_stmts.push(stmt);
5788                if self.check(&TokenType::Period) {
5789                    self.advance();
5790                }
5791            }
5792            if self.check(&TokenType::Dedent) {
5793                self.advance(); // consume Dedent
5794            }
5795
5796            let block = self.ctx.stmts.expect("imperative arenas not initialized")
5797                .alloc_slice(block_stmts.into_iter());
5798            ClosureBody::Block(block)
5799        } else {
5800            // Single expression body — use parse_condition to support comparisons and boolean ops
5801            let expr = self.parse_condition()?;
5802            ClosureBody::Expression(expr)
5803        };
5804
5805        Ok(self.ctx.alloc_imperative_expr(Expr::Closure {
5806            params,
5807            body,
5808            return_type: None,
5809        }))
5810    }
5811
5812    /// Parse a complete imperative expression including binary operators.
5813    /// Uses precedence climbing for correct associativity and precedence.
5814    fn parse_imperative_expr(&mut self) -> ParseResult<&'a Expr<'a>> {
5815        self.parse_additive_expr()
5816    }
5817
5818    /// Parse additive expressions (+, -, combined with, union, intersection, contains) - left-to-right associative
5819    fn parse_additive_expr(&mut self) -> ParseResult<&'a Expr<'a>> {
5820        let mut left = self.parse_multiplicative_expr()?;
5821
5822        loop {
5823            match &self.peek().kind {
5824                TokenType::Plus => {
5825                    self.advance();
5826                    let right = self.parse_multiplicative_expr()?;
5827                    left = self.ctx.alloc_imperative_expr(Expr::BinaryOp {
5828                        op: BinaryOpKind::Add,
5829                        left,
5830                        right,
5831                    });
5832                }
5833                TokenType::Minus => {
5834                    self.advance();
5835                    let right = self.parse_multiplicative_expr()?;
5836                    left = self.ctx.alloc_imperative_expr(Expr::BinaryOp {
5837                        op: BinaryOpKind::Subtract,
5838                        left,
5839                        right,
5840                    });
5841                }
5842                // Phase 53: "combined with" for string concatenation
5843                TokenType::Combined => {
5844                    self.advance(); // consume "combined"
5845                    // Expect "with" (preposition)
5846                    if !self.check_preposition_is("with") {
5847                        return Err(ParseError {
5848                            kind: ParseErrorKind::ExpectedKeyword { keyword: "with".to_string() },
5849                            span: self.current_span(),
5850                        });
5851                    }
5852                    self.advance(); // consume "with"
5853                    let right = self.parse_multiplicative_expr()?;
5854                    left = self.ctx.alloc_imperative_expr(Expr::BinaryOp {
5855                        op: BinaryOpKind::Concat,
5856                        left,
5857                        right,
5858                    });
5859                }
5860                // Set operations: union, intersection
5861                TokenType::Union => {
5862                    self.advance(); // consume "union"
5863                    let right = self.parse_multiplicative_expr()?;
5864                    left = self.ctx.alloc_imperative_expr(Expr::Union {
5865                        left,
5866                        right,
5867                    });
5868                }
5869                TokenType::Intersection => {
5870                    self.advance(); // consume "intersection"
5871                    let right = self.parse_multiplicative_expr()?;
5872                    left = self.ctx.alloc_imperative_expr(Expr::Intersection {
5873                        left,
5874                        right,
5875                    });
5876                }
5877                // Set membership: "set contains value"
5878                TokenType::Contains => {
5879                    self.advance(); // consume "contains"
5880                    let value = self.parse_multiplicative_expr()?;
5881                    left = self.ctx.alloc_imperative_expr(Expr::Contains {
5882                        collection: left,
5883                        value,
5884                    });
5885                }
5886                _ => break,
5887            }
5888        }
5889
5890        Ok(left)
5891    }
5892
5893    /// Parse unary expressions (currently just unary minus)
5894    fn parse_unary_expr(&mut self) -> ParseResult<&'a Expr<'a>> {
5895        use crate::ast::{Expr, Literal};
5896
5897        if self.check(&TokenType::Minus) {
5898            self.advance(); // consume '-'
5899            let operand = self.parse_unary_expr()?; // recursive for --5
5900            // Implement as 0 - operand (no UnaryOp variant in Expr)
5901            return Ok(self.ctx.alloc_imperative_expr(Expr::BinaryOp {
5902                op: BinaryOpKind::Subtract,
5903                left: self.ctx.alloc_imperative_expr(Expr::Literal(Literal::Number(0))),
5904                right: operand,
5905            }));
5906        }
5907        self.parse_primary_expr()
5908    }
5909
5910    /// Parse multiplicative expressions (*, /, %) - left-to-right associative
5911    fn parse_multiplicative_expr(&mut self) -> ParseResult<&'a Expr<'a>> {
5912        let mut left = self.parse_unary_expr()?;
5913
5914        loop {
5915            let op = match &self.peek().kind {
5916                TokenType::Star => {
5917                    self.advance();
5918                    BinaryOpKind::Multiply
5919                }
5920                TokenType::Slash => {
5921                    self.advance();
5922                    BinaryOpKind::Divide
5923                }
5924                TokenType::Percent => {
5925                    self.advance();
5926                    BinaryOpKind::Modulo
5927                }
5928                _ => break,
5929            };
5930            let right = self.parse_unary_expr()?;
5931            left = self.ctx.alloc_imperative_expr(Expr::BinaryOp {
5932                op,
5933                left,
5934                right,
5935            });
5936        }
5937
5938        Ok(left)
5939    }
5940
5941    /// Try to parse a binary operator (+, -, *, /)
5942    fn try_parse_binary_op(&mut self) -> Option<BinaryOpKind> {
5943        match &self.peek().kind {
5944            TokenType::Plus => {
5945                self.advance();
5946                Some(BinaryOpKind::Add)
5947            }
5948            TokenType::Minus => {
5949                self.advance();
5950                Some(BinaryOpKind::Subtract)
5951            }
5952            TokenType::Star => {
5953                self.advance();
5954                Some(BinaryOpKind::Multiply)
5955            }
5956            TokenType::Slash => {
5957                self.advance();
5958                Some(BinaryOpKind::Divide)
5959            }
5960            _ => None,
5961        }
5962    }
5963
5964    /// Parse a Span literal starting from a number that was already consumed.
5965    /// Handles patterns like: "3 days", "2 months", "1 year and 3 days"
5966    fn parse_span_literal_from_num(&mut self, first_num_str: &str) -> ParseResult<&'a Expr<'a>> {
5967        use crate::ast::Literal;
5968        use crate::token::CalendarUnit;
5969
5970        let first_num = first_num_str.parse::<i32>().unwrap_or(0);
5971
5972        // We expect a CalendarUnit after the number
5973        let unit = match self.peek().kind {
5974            TokenType::CalendarUnit(u) => u,
5975            _ => {
5976                return Err(ParseError {
5977                    kind: ParseErrorKind::ExpectedKeyword { keyword: "calendar unit (day, week, month, year)".to_string() },
5978                    span: self.current_span(),
5979                });
5980            }
5981        };
5982        self.advance(); // consume the CalendarUnit
5983
5984        // Accumulate months and days
5985        let mut total_months: i32 = 0;
5986        let mut total_days: i32 = 0;
5987
5988        // Apply the first unit
5989        match unit {
5990            CalendarUnit::Day => total_days += first_num,
5991            CalendarUnit::Week => total_days += first_num * 7,
5992            CalendarUnit::Month => total_months += first_num,
5993            CalendarUnit::Year => total_months += first_num * 12,
5994        }
5995
5996        // Check for "and" followed by more Number + CalendarUnit
5997        while self.check(&TokenType::And) {
5998            self.advance(); // consume "and"
5999
6000            // Expect another Number
6001            let next_num = match &self.peek().kind {
6002                TokenType::Number(sym) => {
6003                    let num_str = self.interner.resolve(*sym).to_string();
6004                    self.advance();
6005                    num_str.parse::<i32>().unwrap_or(0)
6006                }
6007                _ => break, // Not a number, backtrack is complex so just stop
6008            };
6009
6010            // Expect another CalendarUnit
6011            let next_unit = match self.peek().kind {
6012                TokenType::CalendarUnit(u) => {
6013                    self.advance();
6014                    u
6015                }
6016                _ => break, // Not a unit, backtrack is complex so just stop
6017            };
6018
6019            // Apply the unit
6020            match next_unit {
6021                CalendarUnit::Day => total_days += next_num,
6022                CalendarUnit::Week => total_days += next_num * 7,
6023                CalendarUnit::Month => total_months += next_num,
6024                CalendarUnit::Year => total_months += next_num * 12,
6025            }
6026        }
6027
6028        Ok(self.ctx.alloc_imperative_expr(Expr::Literal(Literal::Span {
6029            months: total_months,
6030            days: total_days,
6031        })))
6032    }
6033
6034    /// Phase 32: Parse function call expression: f(x, y, ...)
6035    fn parse_call_expr(&mut self, function: Symbol) -> ParseResult<&'a Expr<'a>> {
6036        use crate::ast::Expr;
6037
6038        self.advance(); // consume '('
6039
6040        let mut args = Vec::new();
6041        if !self.check(&TokenType::RParen) {
6042            loop {
6043                args.push(self.parse_imperative_expr()?);
6044                if !self.check(&TokenType::Comma) {
6045                    break;
6046                }
6047                self.advance(); // consume ','
6048            }
6049        }
6050
6051        if !self.check(&TokenType::RParen) {
6052            return Err(ParseError {
6053                kind: ParseErrorKind::ExpectedKeyword { keyword: ")".to_string() },
6054                span: self.current_span(),
6055            });
6056        }
6057        self.advance(); // consume ')'
6058
6059        Ok(self.ctx.alloc_imperative_expr(Expr::Call { function, args }))
6060    }
6061
6062    /// Phase 31: Parse field access chain via possessive ('s) and bracket indexing
6063    /// Handles patterns like: p's x, p's x's y, items[1], items[i]'s field
6064    fn parse_field_access_chain(&mut self, base: &'a Expr<'a>) -> ParseResult<&'a Expr<'a>> {
6065        use crate::ast::Expr;
6066
6067        let mut result = base;
6068
6069        // Keep parsing field accesses and bracket indexing
6070        loop {
6071            if self.check(&TokenType::Possessive) {
6072                // Field access: p's x
6073                self.advance(); // consume "'s"
6074                let field = self.expect_identifier()?;
6075                result = self.ctx.alloc_imperative_expr(Expr::FieldAccess {
6076                    object: result,
6077                    field,
6078                });
6079            } else if self.check(&TokenType::LBracket) {
6080                // Bracket indexing: items[1], items[i]
6081                self.advance(); // consume "["
6082                let index = self.parse_imperative_expr()?;
6083
6084                if !self.check(&TokenType::RBracket) {
6085                    return Err(ParseError {
6086                        kind: ParseErrorKind::ExpectedKeyword { keyword: "]".to_string() },
6087                        span: self.current_span(),
6088                    });
6089                }
6090                self.advance(); // consume "]"
6091
6092                result = self.ctx.alloc_imperative_expr(Expr::Index {
6093                    collection: result,
6094                    index,
6095                });
6096            } else {
6097                break;
6098            }
6099        }
6100
6101        Ok(result)
6102    }
6103
6104    /// Centralized verification for identifier access in imperative mode.
6105    /// Checks for use-after-move errors on known variables.
6106    fn verify_identifier_access(&self, sym: Symbol) -> ParseResult<()> {
6107        if self.mode != ParserMode::Imperative {
6108            return Ok(());
6109        }
6110
6111        // Check if variable has been moved
6112        if let Some(crate::drs::OwnershipState::Moved) = self.world_state.get_ownership_by_var(sym) {
6113            return Err(ParseError {
6114                kind: ParseErrorKind::UseAfterMove {
6115                    name: self.interner.resolve(sym).to_string()
6116                },
6117                span: self.current_span(),
6118            });
6119        }
6120
6121        Ok(())
6122    }
6123
6124    fn expect_identifier(&mut self) -> ParseResult<Symbol> {
6125        let token = self.peek().clone();
6126        match &token.kind {
6127            // Standard identifiers
6128            TokenType::Noun(sym) | TokenType::ProperName(sym) | TokenType::Adjective(sym) => {
6129                self.advance();
6130                Ok(*sym)
6131            }
6132            // Verbs can be variable names in code context ("empty", "run", etc.)
6133            // Use raw lexeme to preserve original casing
6134            TokenType::Verb { .. } => {
6135                let sym = token.lexeme;
6136                self.advance();
6137                Ok(sym)
6138            }
6139            // Phase 32: Articles can be single-letter identifiers (a, an)
6140            TokenType::Article(_) => {
6141                let sym = token.lexeme;
6142                self.advance();
6143                Ok(sym)
6144            }
6145            // Overloaded tokens that are valid identifiers in code context
6146            TokenType::Pronoun { .. } |  // "i", "it"
6147            TokenType::Items |           // "items"
6148            TokenType::Values |          // "values"
6149            TokenType::Item |            // "item"
6150            TokenType::Nothing |         // "nothing"
6151            // Phase 38: Adverbs can be function names (now, sleep, etc.)
6152            TokenType::TemporalAdverb(_) |
6153            TokenType::ScopalAdverb(_) |
6154            TokenType::Adverb(_) |
6155            // Phase 10: IO keywords can be function names (read, write, file, console)
6156            TokenType::Read |
6157            TokenType::Write |
6158            TokenType::File |
6159            TokenType::Console |
6160            // Phase 49: CRDT keywords can be type/function names
6161            TokenType::Merge |
6162            TokenType::Increase |
6163            TokenType::Decrease |
6164            // Phase 49b: CRDT type keywords can be type names
6165            TokenType::Tally |
6166            TokenType::SharedSet |
6167            TokenType::SharedSequence |
6168            TokenType::CollaborativeSequence |
6169            // Phase 54: "first", "second", etc. can be variable names
6170            // Phase 57: "add", "remove" can be function names
6171            TokenType::Add |
6172            TokenType::Remove |
6173            TokenType::First |
6174            // Correlative conjunctions and other keywords usable as identifiers
6175            TokenType::Both |            // "both" (correlative: both X and Y)
6176            TokenType::Either |          // "either" (correlative: either X or Y)
6177            TokenType::Combined |        // "combined" (string concat: combined with)
6178            TokenType::Shared |          // "shared" (CRDT type modifier)
6179            // Calendar units can be type/variable names (Day, Week, Month, Year)
6180            TokenType::CalendarUnit(_) |
6181            // Phase 103: Focus particles can be variant names (Just, Only, Even)
6182            TokenType::Focus(_) |
6183            // Escape hatch keyword can be a variable name
6184            TokenType::Escape => {
6185                // Use the raw lexeme (interned string) as the symbol
6186                let sym = token.lexeme;
6187                self.advance();
6188                Ok(sym)
6189            }
6190            TokenType::Ambiguous { .. } => {
6191                // For ambiguous tokens, always use the raw lexeme to preserve original casing
6192                // (using verb lemma can give wrong casing like "State" instead of "state")
6193                let sym = token.lexeme;
6194                self.advance();
6195                Ok(sym)
6196            }
6197            _ => Err(ParseError {
6198                kind: ParseErrorKind::ExpectedIdentifier,
6199                span: self.current_span(),
6200            }),
6201        }
6202    }
6203
6204    fn consume_content_word_for_relative(&mut self) -> ParseResult<Symbol> {
6205        let t = self.advance().clone();
6206        match t.kind {
6207            TokenType::Noun(s) | TokenType::Adjective(s) => Ok(s),
6208            TokenType::ProperName(s) => Ok(s),
6209            TokenType::Verb { lemma, .. } => Ok(lemma),
6210            other => Err(ParseError {
6211                kind: ParseErrorKind::ExpectedContentWord { found: other },
6212                span: self.current_span(),
6213            }),
6214        }
6215    }
6216
6217    fn check_modal(&self) -> bool {
6218        matches!(
6219            self.peek().kind,
6220            TokenType::Must
6221                | TokenType::Shall
6222                | TokenType::Should
6223                | TokenType::Can
6224                | TokenType::May
6225                | TokenType::Cannot
6226                | TokenType::Could
6227                | TokenType::Would
6228                | TokenType::Might
6229        )
6230    }
6231
6232    fn check_pronoun(&self) -> bool {
6233        match &self.peek().kind {
6234            TokenType::Pronoun { case, .. } => {
6235                // In noun_priority_mode, possessive pronouns start NPs, not standalone objects
6236                if self.noun_priority_mode && matches!(case, Case::Possessive) {
6237                    return false;
6238                }
6239                true
6240            }
6241            TokenType::Ambiguous { primary, alternatives } => {
6242                // In noun_priority_mode, if there's a possessive alternative, prefer noun path
6243                if self.noun_priority_mode {
6244                    let has_possessive = matches!(**primary, TokenType::Pronoun { case: Case::Possessive, .. })
6245                        || alternatives.iter().any(|t| matches!(t, TokenType::Pronoun { case: Case::Possessive, .. }));
6246                    if has_possessive {
6247                        return false;
6248                    }
6249                }
6250                matches!(**primary, TokenType::Pronoun { .. })
6251                    || alternatives.iter().any(|t| matches!(t, TokenType::Pronoun { .. }))
6252            }
6253            _ => false,
6254        }
6255    }
6256
6257    fn parse_atom(&mut self) -> ParseResult<&'a LogicExpr<'a>> {
6258        // Handle Focus particles: "Only John loves Mary", "Even John ran"
6259        if self.check_focus() {
6260            return self.parse_focus();
6261        }
6262
6263        // Handle mass noun measure: "Much water flows", "Little time remains"
6264        if self.check_measure() {
6265            return self.parse_measure();
6266        }
6267
6268        if self.check_quantifier() {
6269            self.advance();
6270            return self.parse_quantified();
6271        }
6272
6273        if self.check_npi_quantifier() {
6274            return self.parse_npi_quantified();
6275        }
6276
6277        if self.check_temporal_npi() {
6278            return self.parse_temporal_npi();
6279        }
6280
6281        if self.match_token(&[TokenType::LParen]) {
6282            let expr = self.parse_sentence()?;
6283            self.consume(TokenType::RParen)?;
6284            return Ok(expr);
6285        }
6286
6287        // Handle pronoun as subject
6288        if self.check_pronoun() {
6289            let token = self.advance().clone();
6290            let (gender, number) = match &token.kind {
6291                TokenType::Pronoun { gender, number, .. } => (*gender, *number),
6292                TokenType::Ambiguous { primary, alternatives } => {
6293                    if let TokenType::Pronoun { gender, number, .. } = **primary {
6294                        (gender, number)
6295                    } else {
6296                        alternatives.iter().find_map(|t| {
6297                            if let TokenType::Pronoun { gender, number, .. } = t {
6298                                Some((*gender, *number))
6299                            } else {
6300                                None
6301                            }
6302                        }).unwrap_or((Gender::Unknown, Number::Singular))
6303                    }
6304                }
6305                _ => (Gender::Unknown, Number::Singular),
6306            };
6307
6308            let token_text = self.interner.resolve(token.lexeme);
6309
6310            // Weather verb + expletive "it" detection: "it rains" → ∃e(Rain(e))
6311            // Must check BEFORE pronoun resolution since "it" resolves to "?"
6312            if token_text.eq_ignore_ascii_case("it") && self.check_verb() {
6313                if let TokenType::Verb { lemma, time, .. } = &self.peek().kind {
6314                    let lemma_str = self.interner.resolve(*lemma);
6315                    if Lexer::is_weather_verb(lemma_str) {
6316                        let verb = *lemma;
6317                        let verb_time = *time;
6318                        self.advance(); // consume the weather verb
6319
6320                        let event_var = self.get_event_var();
6321                        let suppress_existential = self.drs.in_conditional_antecedent();
6322                        if suppress_existential {
6323                            let event_class = self.interner.intern("Event");
6324                            self.drs.introduce_referent(event_var, event_class, Gender::Neuter, Number::Singular);
6325                        }
6326                        let neo_event = self.ctx.exprs.alloc(LogicExpr::NeoEvent(Box::new(NeoEventData {
6327                            event_var,
6328                            verb,
6329                            roles: self.ctx.roles.alloc_slice(vec![]), // No thematic roles
6330                            modifiers: self.ctx.syms.alloc_slice(vec![]),
6331                            suppress_existential,
6332                            world: None,
6333                        })));
6334
6335                        return Ok(match verb_time {
6336                            Time::Past => self.ctx.exprs.alloc(LogicExpr::Temporal {
6337                                operator: TemporalOperator::Past,
6338                                body: neo_event,
6339                            }),
6340                            Time::Future => self.ctx.exprs.alloc(LogicExpr::Temporal {
6341                                operator: TemporalOperator::Future,
6342                                body: neo_event,
6343                            }),
6344                            _ => neo_event,
6345                        });
6346                    }
6347                }
6348            }
6349
6350            // Handle deictic pronouns that don't need discourse resolution
6351            let resolved = if token_text.eq_ignore_ascii_case("i") {
6352                ResolvedPronoun::Constant(self.interner.intern("Speaker"))
6353            } else if token_text.eq_ignore_ascii_case("you") {
6354                ResolvedPronoun::Constant(self.interner.intern("Addressee"))
6355            } else {
6356                // Try discourse resolution for anaphoric pronouns
6357                self.resolve_pronoun(gender, number)?
6358            };
6359
6360            // Check for performative: "I promise that..." or "I promise to..."
6361            if self.check_performative() {
6362                if let TokenType::Performative(act) = self.advance().kind.clone() {
6363                    let sym = match resolved {
6364                        ResolvedPronoun::Variable(s) | ResolvedPronoun::Constant(s) => s,
6365                    };
6366                    // Check for infinitive complement: "I promise to come"
6367                    if self.check(&TokenType::To) {
6368                        self.advance(); // consume "to"
6369
6370                        if self.check_verb() {
6371                            let infinitive_verb = self.consume_verb();
6372
6373                            let content = self.ctx.exprs.alloc(LogicExpr::Predicate {
6374                                name: infinitive_verb,
6375                                args: self.ctx.terms.alloc_slice([Term::Constant(sym)]),
6376                                world: None,
6377                            });
6378
6379                            return Ok(self.ctx.exprs.alloc(LogicExpr::SpeechAct {
6380                                performer: sym,
6381                                act_type: act,
6382                                content,
6383                            }));
6384                        }
6385                    }
6386
6387                    // Skip "that" if present
6388                    if self.check(&TokenType::That) {
6389                        self.advance();
6390                    }
6391                    let content = self.parse_sentence()?;
6392                    return Ok(self.ctx.exprs.alloc(LogicExpr::SpeechAct {
6393                        performer: sym,
6394                        act_type: act,
6395                        content,
6396                    }));
6397                }
6398            }
6399
6400            // Continue parsing verb phrase with resolved subject
6401            // Use as_var=true for bound variables, as_var=false for constants
6402            return match resolved {
6403                ResolvedPronoun::Variable(sym) => self.parse_predicate_with_subject_as_var(sym),
6404                ResolvedPronoun::Constant(sym) => self.parse_predicate_with_subject(sym),
6405            };
6406        }
6407
6408        // Consume "both" correlative marker if present: "both X and Y"
6409        // The existing try_parse_plural_subject will handle the "X and Y" pattern
6410        let _had_both = self.match_token(&[TokenType::Both]);
6411
6412        let subject = self.parse_noun_phrase(true)?;
6413
6414        // Introduce subject NP to DRS for cross-sentence pronoun resolution (accommodation)
6415        // This allows "A man walked. He fell." to work
6416        // Use noun as both variable and noun_class (like proper names) so pronouns resolve to it
6417        // NOTE: Definite NPs are NOT introduced here - they go through wrap_with_definiteness
6418        // where bridging anaphora can link them to prior wholes (e.g., "I bought a car. The engine smoked.")
6419        if subject.definiteness == Some(Definiteness::Indefinite)
6420            || subject.definiteness == Some(Definiteness::Distal) {
6421            let gender = Self::infer_noun_gender(self.interner.resolve(subject.noun));
6422            let number = if Self::is_plural_noun(self.interner.resolve(subject.noun)) {
6423                Number::Plural
6424            } else {
6425                Number::Singular
6426            };
6427            // Use noun as variable so pronoun resolution returns the noun name
6428            self.drs.introduce_referent(subject.noun, subject.noun, gender, number);
6429        }
6430
6431        // Handle plural subjects: "John and Mary verb"
6432        if self.check(&TokenType::And) {
6433            match self.try_parse_plural_subject(&subject) {
6434                Ok(Some(result)) => return Ok(result),
6435                Ok(None) => {} // Not a plural subject, continue
6436                Err(e) => return Err(e), // Semantic error (e.g., respectively mismatch)
6437            }
6438        }
6439
6440        // Handle scopal adverbs: "John almost died"
6441        if self.check_scopal_adverb() {
6442            return self.parse_scopal_adverb(&subject);
6443        }
6444
6445        // Handle topicalization: "The cake, John ate." - first NP is object, not subject
6446        if self.check(&TokenType::Comma) {
6447            let saved_pos = self.current;
6448            self.advance(); // consume comma
6449
6450            // Check if followed by pronoun subject (e.g., "The book, he read.")
6451            if self.check_pronoun() {
6452                let topic_attempt = self.try_parse(|p| {
6453                    let token = p.peek().clone();
6454                    let pronoun_features = match &token.kind {
6455                        TokenType::Pronoun { gender, number, .. } => Some((*gender, *number)),
6456                        TokenType::Ambiguous { primary, alternatives } => {
6457                            if let TokenType::Pronoun { gender, number, .. } = **primary {
6458                                Some((gender, number))
6459                            } else {
6460                                alternatives.iter().find_map(|t| {
6461                                    if let TokenType::Pronoun { gender, number, .. } = t {
6462                                        Some((*gender, *number))
6463                                    } else {
6464                                        None
6465                                    }
6466                                })
6467                            }
6468                        }
6469                        _ => None,
6470                    };
6471
6472                    if let Some((gender, number)) = pronoun_features {
6473                        p.advance(); // consume pronoun
6474                        let resolved = p.resolve_pronoun(gender, number)?;
6475                        let resolved_term = match resolved {
6476                            ResolvedPronoun::Variable(s) => Term::Variable(s),
6477                            ResolvedPronoun::Constant(s) => Term::Constant(s),
6478                        };
6479
6480                        if p.check_verb() {
6481                            let verb = p.consume_verb();
6482                            let predicate = p.ctx.exprs.alloc(LogicExpr::Predicate {
6483                                name: verb,
6484                                args: p.ctx.terms.alloc_slice([
6485                                    resolved_term,
6486                                    Term::Constant(subject.noun),
6487                                ]),
6488                                world: None,
6489                            });
6490                            p.wrap_with_definiteness_full(&subject, predicate)
6491                        } else {
6492                            Err(ParseError {
6493                                kind: ParseErrorKind::ExpectedVerb { found: p.peek().kind.clone() },
6494                                span: p.current_span(),
6495                            })
6496                        }
6497                    } else {
6498                        Err(ParseError {
6499                            kind: ParseErrorKind::ExpectedContentWord { found: token.kind },
6500                            span: p.current_span(),
6501                        })
6502                    }
6503                });
6504
6505                if let Some(result) = topic_attempt {
6506                    return Ok(result);
6507                }
6508            }
6509
6510            // Check if followed by another NP and then a verb (topicalization pattern)
6511            if self.check_content_word() {
6512                let topic_attempt = self.try_parse(|p| {
6513                    let real_subject = p.parse_noun_phrase(true)?;
6514                    if p.check_verb() {
6515                        let verb = p.consume_verb();
6516                        let predicate = p.ctx.exprs.alloc(LogicExpr::Predicate {
6517                            name: verb,
6518                            args: p.ctx.terms.alloc_slice([
6519                                Term::Constant(real_subject.noun),
6520                                Term::Constant(subject.noun),
6521                            ]),
6522                            world: None,
6523                        });
6524                        p.wrap_with_definiteness_full(&subject, predicate)
6525                    } else {
6526                        Err(ParseError {
6527                            kind: ParseErrorKind::ExpectedVerb { found: p.peek().kind.clone() },
6528                            span: p.current_span(),
6529                        })
6530                    }
6531                });
6532
6533                if let Some(result) = topic_attempt {
6534                    return Ok(result);
6535                }
6536            }
6537
6538            // Restore position if topicalization didn't match
6539            self.current = saved_pos;
6540        }
6541
6542        // Handle relative clause after subject: "The cat that the dog chased ran."
6543        let mut relative_clause: Option<(Symbol, &'a LogicExpr<'a>)> = None;
6544        if self.check(&TokenType::That) || self.check(&TokenType::Who) {
6545            self.advance();
6546            let var_name = self.next_var_name();
6547            let rel_pred = self.parse_relative_clause(var_name)?;
6548            relative_clause = Some((var_name, rel_pred));
6549        } else if matches!(self.peek().kind, TokenType::Article(_)) && self.is_contact_clause_pattern() {
6550            // Contact clause (reduced relative): "The cat the dog chased ran."
6551            // NP + NP + Verb pattern indicates embedded relative without explicit "that"
6552            let var_name = self.next_var_name();
6553            let rel_pred = self.parse_relative_clause(var_name)?;
6554            relative_clause = Some((var_name, rel_pred));
6555        }
6556
6557        // Handle main verb after relative clause: "The cat that the dog chased ran."
6558        if let Some((var_name, rel_clause)) = relative_clause {
6559            if self.check_verb() {
6560                let (verb, verb_time, _, _) = self.consume_verb_with_metadata();
6561                let var_term = Term::Variable(var_name);
6562
6563                let event_var = self.get_event_var();
6564                let suppress_existential = self.drs.in_conditional_antecedent();
6565                let mut modifiers = vec![];
6566                if verb_time == Time::Past {
6567                    modifiers.push(self.interner.intern("Past"));
6568                }
6569                let main_pred = self.ctx.exprs.alloc(LogicExpr::NeoEvent(Box::new(NeoEventData {
6570                    event_var,
6571                    verb,
6572                    roles: self.ctx.roles.alloc_slice(vec![
6573                        (ThematicRole::Agent, var_term),
6574                    ]),
6575                    modifiers: self.ctx.syms.alloc_slice(modifiers),
6576                    suppress_existential,
6577                    world: None,
6578                })));
6579
6580                let type_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
6581                    name: subject.noun,
6582                    args: self.ctx.terms.alloc_slice([Term::Variable(var_name)]),
6583                    world: None,
6584                });
6585
6586                let inner = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
6587                    left: type_pred,
6588                    op: TokenType::And,
6589                    right: rel_clause,
6590                });
6591
6592                let body = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
6593                    left: inner,
6594                    op: TokenType::And,
6595                    right: main_pred,
6596                });
6597
6598                return Ok(self.ctx.exprs.alloc(LogicExpr::Quantifier {
6599                    kind: QuantifierKind::Existential,
6600                    variable: var_name,
6601                    body,
6602                    island_id: self.current_island,
6603                }));
6604            }
6605
6606            // No main verb - just the relative clause: "The cat that runs" as a complete NP
6607            // Build: ∃x(Cat(x) ∧ Runs(x) ∧ ∀y(Cat(y) → y=x))
6608            if self.is_at_end() || self.check(&TokenType::Period) || self.check(&TokenType::Comma) {
6609                let type_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
6610                    name: subject.noun,
6611                    args: self.ctx.terms.alloc_slice([Term::Variable(var_name)]),
6612                    world: None,
6613                });
6614
6615                let body = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
6616                    left: type_pred,
6617                    op: TokenType::And,
6618                    right: rel_clause,
6619                });
6620
6621                // Add uniqueness for definite description
6622                let uniqueness_body = if subject.definiteness == Some(Definiteness::Definite) {
6623                    let y_var = self.next_var_name();
6624                    let type_pred_y = self.ctx.exprs.alloc(LogicExpr::Predicate {
6625                        name: subject.noun,
6626                        args: self.ctx.terms.alloc_slice([Term::Variable(y_var)]),
6627                        world: None,
6628                    });
6629                    let identity = self.ctx.exprs.alloc(LogicExpr::Identity {
6630                        left: self.ctx.terms.alloc(Term::Variable(y_var)),
6631                        right: self.ctx.terms.alloc(Term::Variable(var_name)),
6632                    });
6633                    let uniqueness_cond = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
6634                        left: type_pred_y,
6635                        op: TokenType::If,
6636                        right: identity,
6637                    });
6638                    let uniqueness = self.ctx.exprs.alloc(LogicExpr::Quantifier {
6639                        kind: QuantifierKind::Universal,
6640                        variable: y_var,
6641                        body: uniqueness_cond,
6642                        island_id: self.current_island,
6643                    });
6644                    self.ctx.exprs.alloc(LogicExpr::BinaryOp {
6645                        left: body,
6646                        op: TokenType::And,
6647                        right: uniqueness,
6648                    })
6649                } else {
6650                    body
6651                };
6652
6653                return Ok(self.ctx.exprs.alloc(LogicExpr::Quantifier {
6654                    kind: QuantifierKind::Existential,
6655                    variable: var_name,
6656                    body: uniqueness_body,
6657                    island_id: self.current_island,
6658                }));
6659            }
6660
6661            // Re-store for copula handling below
6662            relative_clause = Some((var_name, rel_clause));
6663        }
6664
6665        // Identity check: "Clark is equal to Superman"
6666        if self.check(&TokenType::Identity) {
6667            self.advance();
6668            let right = self.consume_content_word()?;
6669            return Ok(self.ctx.exprs.alloc(LogicExpr::Identity {
6670                left: self.ctx.terms.alloc(Term::Constant(subject.noun)),
6671                right: self.ctx.terms.alloc(Term::Constant(right)),
6672            }));
6673        }
6674
6675        if self.check_modal() {
6676            if let Some((var_name, rel_clause)) = relative_clause {
6677                let modal_pred = self.parse_aspect_chain_with_term(Term::Variable(var_name))?;
6678
6679                let type_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
6680                    name: subject.noun,
6681                    args: self.ctx.terms.alloc_slice([Term::Variable(var_name)]),
6682                    world: None,
6683                });
6684
6685                let inner = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
6686                    left: type_pred,
6687                    op: TokenType::And,
6688                    right: rel_clause,
6689                });
6690
6691                let body = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
6692                    left: inner,
6693                    op: TokenType::And,
6694                    right: modal_pred,
6695                });
6696
6697                return Ok(self.ctx.exprs.alloc(LogicExpr::Quantifier {
6698                    kind: QuantifierKind::Existential,
6699                    variable: var_name,
6700                    body,
6701                    island_id: self.current_island,
6702                }));
6703            }
6704
6705            let modal_pred = self.parse_aspect_chain(subject.noun)?;
6706            return self.wrap_with_definiteness_full(&subject, modal_pred);
6707        }
6708
6709        if self.check(&TokenType::Is) || self.check(&TokenType::Are)
6710            || self.check(&TokenType::Was) || self.check(&TokenType::Were)
6711        {
6712            let copula_time = if self.check(&TokenType::Was) || self.check(&TokenType::Were) {
6713                Time::Past
6714            } else {
6715                Time::Present
6716            };
6717            self.advance();
6718
6719            // Check for negation: "was not caught", "is not happy"
6720            let is_negated = self.check(&TokenType::Not);
6721            if is_negated {
6722                self.advance(); // consume "not"
6723            }
6724
6725            // Check for Number token (measure phrase) before comparative or adjective
6726            // "John is 2 inches taller than Mary" or "The rope is 5 meters long"
6727            if self.check_number() {
6728                let measure = self.parse_measure_phrase()?;
6729
6730                // Check if followed by comparative: "2 inches taller than"
6731                if self.check_comparative() {
6732                    return self.parse_comparative(&subject, copula_time, Some(measure));
6733                }
6734
6735                // Check for dimensional adjective: "5 meters long"
6736                if self.check_content_word() {
6737                    let adj = self.consume_content_word()?;
6738                    let result = self.ctx.exprs.alloc(LogicExpr::Predicate {
6739                        name: adj,
6740                        args: self.ctx.terms.alloc_slice([
6741                            Term::Constant(subject.noun),
6742                            *measure,
6743                        ]),
6744                        world: None,
6745                    });
6746                    return self.wrap_with_definiteness_full(&subject, result);
6747                }
6748
6749                // Bare measure phrase: "The temperature is 98.6 degrees."
6750                // Output: Identity(subject, measure)
6751                if self.check(&TokenType::Period) || self.is_at_end() {
6752                    // In imperative mode, reject "x is 5" - suggest "x equals 5"
6753                    if self.mode == ParserMode::Imperative {
6754                        let variable = self.interner.resolve(subject.noun).to_string();
6755                        let value = if let Term::Value { kind, .. } = measure {
6756                            format!("{:?}", kind)
6757                        } else {
6758                            "value".to_string()
6759                        };
6760                        return Err(ParseError {
6761                            kind: ParseErrorKind::IsValueEquality { variable, value },
6762                            span: self.current_span(),
6763                        });
6764                    }
6765                    let result = self.ctx.exprs.alloc(LogicExpr::Identity {
6766                        left: self.ctx.terms.alloc(Term::Constant(subject.noun)),
6767                        right: measure,
6768                    });
6769                    return self.wrap_with_definiteness_full(&subject, result);
6770                }
6771            }
6772
6773            // Check for comparative: "is taller than"
6774            if self.check_comparative() {
6775                return self.parse_comparative(&subject, copula_time, None);
6776            }
6777
6778            // Check for existential "is": "God is." - bare copula followed by period/EOF
6779            if self.check(&TokenType::Period) || self.is_at_end() {
6780                let var = self.next_var_name();
6781                let body = self.ctx.exprs.alloc(LogicExpr::Identity {
6782                    left: self.ctx.terms.alloc(Term::Variable(var)),
6783                    right: self.ctx.terms.alloc(Term::Constant(subject.noun)),
6784                });
6785                return Ok(self.ctx.exprs.alloc(LogicExpr::Quantifier {
6786                    kind: QuantifierKind::Existential,
6787                    variable: var,
6788                    body,
6789                    island_id: self.current_island,
6790                }));
6791            }
6792
6793            // Check for superlative: "is the tallest man"
6794            if self.check(&TokenType::Article(Definiteness::Definite)) {
6795                let saved_pos = self.current;
6796                self.advance();
6797                if self.check_superlative() {
6798                    return self.parse_superlative(&subject);
6799                }
6800                self.current = saved_pos;
6801            }
6802
6803            // Check for predicate NP: "Juliet is the sun" or "John is a man"
6804            if self.check_article() {
6805                let predicate_np = self.parse_noun_phrase(true)?;
6806                let predicate_noun = predicate_np.noun;
6807
6808                // Phase 41: Event adjective reading
6809                // "beautiful dancer" in event mode → ∃e(Dance(e) ∧ Agent(e, x) ∧ Beautiful(e))
6810                if self.event_reading_mode {
6811                    let noun_str = self.interner.resolve(predicate_noun);
6812                    if let Some(base_verb) = lexicon::lookup_agentive_noun(noun_str) {
6813                        // Check if any adjective can modify events
6814                        let event_adj = predicate_np.adjectives.iter().find(|adj| {
6815                            lexicon::is_event_modifier_adjective(self.interner.resolve(**adj))
6816                        });
6817
6818                        if let Some(&adj_sym) = event_adj {
6819                            // Build event reading: ∃e(Verb(e) ∧ Agent(e, subject) ∧ Adj(e))
6820                            let verb_sym = self.interner.intern(base_verb);
6821                            let event_var = self.get_event_var();
6822
6823                            let verb_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
6824                                name: verb_sym,
6825                                args: self.ctx.terms.alloc_slice([Term::Variable(event_var)]),
6826                                world: None,
6827                            });
6828
6829                            let agent_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
6830                                name: self.interner.intern("Agent"),
6831                                args: self.ctx.terms.alloc_slice([
6832                                    Term::Variable(event_var),
6833                                    Term::Constant(subject.noun),
6834                                ]),
6835                                world: None,
6836                            });
6837
6838                            let adj_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
6839                                name: adj_sym,
6840                                args: self.ctx.terms.alloc_slice([Term::Variable(event_var)]),
6841                                world: None,
6842                            });
6843
6844                            // Conjoin: Verb(e) ∧ Agent(e, x)
6845                            let verb_agent = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
6846                                left: verb_pred,
6847                                op: TokenType::And,
6848                                right: agent_pred,
6849                            });
6850
6851                            // Conjoin: (Verb(e) ∧ Agent(e, x)) ∧ Adj(e)
6852                            let body = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
6853                                left: verb_agent,
6854                                op: TokenType::And,
6855                                right: adj_pred,
6856                            });
6857
6858                            // Wrap in existential: ∃e(...)
6859                            let event_reading = self.ctx.exprs.alloc(LogicExpr::Quantifier {
6860                                kind: QuantifierKind::Existential,
6861                                variable: event_var,
6862                                body,
6863                                island_id: self.current_island,
6864                            });
6865
6866                            return self.wrap_with_definiteness(subject.definiteness, subject.noun, event_reading);
6867                        }
6868                    }
6869                }
6870
6871                let subject_sort = lexicon::lookup_sort(self.interner.resolve(subject.noun));
6872                let predicate_sort = lexicon::lookup_sort(self.interner.resolve(predicate_noun));
6873
6874                if let (Some(s_sort), Some(p_sort)) = (subject_sort, predicate_sort) {
6875                    if !s_sort.is_compatible_with(p_sort) && !p_sort.is_compatible_with(s_sort) {
6876                        let metaphor = self.ctx.exprs.alloc(LogicExpr::Metaphor {
6877                            tenor: self.ctx.terms.alloc(Term::Constant(subject.noun)),
6878                            vehicle: self.ctx.terms.alloc(Term::Constant(predicate_noun)),
6879                        });
6880                        return self.wrap_with_definiteness(subject.definiteness, subject.noun, metaphor);
6881                    }
6882                }
6883
6884                // Default: intersective reading for adjectives
6885                // Build Adj1(x) ∧ Adj2(x) ∧ ... ∧ Noun(x)
6886                let mut predicates: Vec<&'a LogicExpr<'a>> = Vec::new();
6887
6888                // Add adjective predicates
6889                for &adj_sym in predicate_np.adjectives {
6890                    let adj_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
6891                        name: adj_sym,
6892                        args: self.ctx.terms.alloc_slice([Term::Constant(subject.noun)]),
6893                        world: None,
6894                    });
6895                    predicates.push(adj_pred);
6896                }
6897
6898                // Add noun predicate
6899                let noun_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
6900                    name: predicate_noun,
6901                    args: self.ctx.terms.alloc_slice([Term::Constant(subject.noun)]),
6902                    world: None,
6903                });
6904                predicates.push(noun_pred);
6905
6906                // Conjoin all predicates
6907                let result = if predicates.len() == 1 {
6908                    predicates[0]
6909                } else {
6910                    let mut combined = predicates[0];
6911                    for pred in &predicates[1..] {
6912                        combined = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
6913                            left: combined,
6914                            op: TokenType::And,
6915                            right: *pred,
6916                        });
6917                    }
6918                    combined
6919                };
6920
6921                return self.wrap_with_definiteness(subject.definiteness, subject.noun, result);
6922            }
6923
6924            // After copula, prefer Adjective over simple-aspect Verb for ambiguous tokens
6925            // "is open" (Adj: state) is standard; "is open" (Verb: habitual) is ungrammatical here
6926            let prefer_adjective = if let TokenType::Ambiguous { primary, alternatives } = &self.peek().kind {
6927                let is_simple_verb = if let TokenType::Verb { aspect, .. } = **primary {
6928                    aspect == Aspect::Simple
6929                } else {
6930                    false
6931                };
6932                let has_adj_alt = alternatives.iter().any(|t| matches!(t, TokenType::Adjective(_)));
6933                is_simple_verb && has_adj_alt
6934            } else {
6935                false
6936            };
6937
6938            if !prefer_adjective && self.check_verb() {
6939                let (verb, _verb_time, verb_aspect, verb_class) = self.consume_verb_with_metadata();
6940
6941                // Stative verbs cannot be progressive
6942                if verb_class.is_stative() && verb_aspect == Aspect::Progressive {
6943                    return Err(ParseError {
6944                        kind: ParseErrorKind::StativeProgressiveConflict,
6945                        span: self.current_span(),
6946                    });
6947                }
6948
6949                // Collect any prepositional phrases before "by" (for ditransitives)
6950                // "given to Mary by John" → goal = Mary, then agent = John
6951                let mut goal_args: Vec<Term<'a>> = Vec::new();
6952                while self.check_to_preposition() {
6953                    self.advance(); // consume "to"
6954                    let goal = self.parse_noun_phrase(true)?;
6955                    goal_args.push(self.noun_phrase_to_term(&goal));
6956                }
6957
6958                // Check for passive: "was loved by John" or "was given to Mary by John"
6959                if self.check_by_preposition() {
6960                    self.advance(); // consume "by"
6961                    let agent = self.parse_noun_phrase(true)?;
6962
6963                    // Build args: agent, theme (subject), then any goals
6964                    let mut args = vec![
6965                        self.noun_phrase_to_term(&agent),
6966                        self.noun_phrase_to_term(&subject),
6967                    ];
6968                    args.extend(goal_args);
6969
6970                    let predicate = self.ctx.exprs.alloc(LogicExpr::Predicate {
6971                        name: verb,
6972                        args: self.ctx.terms.alloc_slice(args),
6973                        world: None,
6974                    });
6975
6976                    let with_time = if copula_time == Time::Past {
6977                        self.ctx.exprs.alloc(LogicExpr::Temporal {
6978                            operator: TemporalOperator::Past,
6979                            body: predicate,
6980                        })
6981                    } else {
6982                        predicate
6983                    };
6984
6985                    return self.wrap_with_definiteness(subject.definiteness, subject.noun, with_time);
6986                }
6987
6988                // Agentless passive: "The book was read" → ∃x.Read(x, Book)
6989                // For DEFINITE subjects ("The butler was caught"), use simpler reading
6990                // without existential over implicit agent: Past(catch(butler))
6991                // This makes negation cleaner for theorem proving: ¬Past(catch(butler))
6992                if copula_time == Time::Past && verb_aspect == Aspect::Simple
6993                    && subject.definiteness != Some(Definiteness::Definite) {
6994                    // Indefinite agentless passive - treat as existential over implicit agent
6995                    let var_name = self.next_var_name();
6996                    let predicate = self.ctx.exprs.alloc(LogicExpr::Predicate {
6997                        name: verb,
6998                        args: self.ctx.terms.alloc_slice([
6999                            Term::Variable(var_name),
7000                            Term::Constant(subject.noun),
7001                        ]),
7002                        world: None,
7003                    });
7004
7005                    let type_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
7006                        name: subject.noun,
7007                        args: self.ctx.terms.alloc_slice([Term::Variable(var_name)]),
7008                        world: None,
7009                    });
7010
7011                    let temporal = self.ctx.exprs.alloc(LogicExpr::Temporal {
7012                        operator: TemporalOperator::Past,
7013                        body: predicate,
7014                    });
7015
7016                    let body = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
7017                        left: type_pred,
7018                        op: TokenType::And,
7019                        right: temporal,
7020                    });
7021
7022                    let result = self.ctx.exprs.alloc(LogicExpr::Quantifier {
7023                        kind: QuantifierKind::Existential,
7024                        variable: var_name,
7025                        body,
7026                        island_id: self.current_island,
7027                    });
7028
7029                    // Apply negation if "was not caught"
7030                    if is_negated {
7031                        return Ok(self.ctx.exprs.alloc(LogicExpr::UnaryOp {
7032                            op: TokenType::Not,
7033                            operand: result,
7034                        }));
7035                    }
7036                    return Ok(result);
7037                }
7038
7039                // Check if verb is an intensional predicate (e.g., "rising", "changing")
7040                // Intensional predicates take intensions, not extensions
7041                let verb_str = self.interner.resolve(verb).to_lowercase();
7042                let subject_term = if lexicon::is_intensional_predicate(&verb_str) {
7043                    Term::Intension(subject.noun)
7044                } else {
7045                    Term::Constant(subject.noun)
7046                };
7047
7048                let predicate = self.ctx.exprs.alloc(LogicExpr::Predicate {
7049                    name: verb,
7050                    args: self.ctx.terms.alloc_slice([subject_term]),
7051                    world: None,
7052                });
7053
7054                let with_aspect = if verb_aspect == Aspect::Progressive {
7055                    // Semelfactive + Progressive → Iterative
7056                    let operator = if verb_class == VerbClass::Semelfactive {
7057                        AspectOperator::Iterative
7058                    } else {
7059                        AspectOperator::Progressive
7060                    };
7061                    self.ctx.exprs.alloc(LogicExpr::Aspectual {
7062                        operator,
7063                        body: predicate,
7064                    })
7065                } else {
7066                    predicate
7067                };
7068
7069                let with_time = if copula_time == Time::Past {
7070                    self.ctx.exprs.alloc(LogicExpr::Temporal {
7071                        operator: TemporalOperator::Past,
7072                        body: with_aspect,
7073                    })
7074                } else {
7075                    with_aspect
7076                };
7077
7078                let final_expr = if is_negated {
7079                    self.ctx.exprs.alloc(LogicExpr::UnaryOp {
7080                        op: TokenType::Not,
7081                        operand: with_time,
7082                    })
7083                } else {
7084                    with_time
7085                };
7086
7087                // For DEFINITE subjects, return directly without Russellian wrapper
7088                // "The butler was caught" → Past(catch(butler)) not ∃x(butler(x) ∧ ∀y(...) ∧ catch(x))
7089                // This keeps the output simple for theorem proving
7090                if subject.definiteness == Some(Definiteness::Definite) {
7091                    return Ok(final_expr);
7092                }
7093
7094                return self.wrap_with_definiteness(subject.definiteness, subject.noun, final_expr);
7095            }
7096
7097            // Handle relative clause with copula: "The book that John read is good."
7098            if let Some((var_name, rel_clause)) = relative_clause {
7099                let var_term = Term::Variable(var_name);
7100                let pred_word = self.consume_content_word()?;
7101
7102                let main_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
7103                    name: pred_word,
7104                    args: self.ctx.terms.alloc_slice([var_term]),
7105                    world: None,
7106                });
7107
7108                let type_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
7109                    name: subject.noun,
7110                    args: self.ctx.terms.alloc_slice([Term::Variable(var_name)]),
7111                    world: None,
7112                });
7113
7114                let inner = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
7115                    left: type_pred,
7116                    op: TokenType::And,
7117                    right: rel_clause,
7118                });
7119
7120                let body = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
7121                    left: inner,
7122                    op: TokenType::And,
7123                    right: main_pred,
7124                });
7125
7126                return Ok(self.ctx.exprs.alloc(LogicExpr::Quantifier {
7127                    kind: QuantifierKind::Existential,
7128                    variable: var_name,
7129                    body,
7130                    island_id: self.current_island,
7131                }));
7132            }
7133
7134            // Note: is_negated was already set after copula consumption above
7135
7136            // Handle identity: "Clark is Superman" - NP copula ProperName → Identity
7137            // This enables Leibniz's Law: if Clark = Superman and mortal(Clark), then mortal(Superman)
7138            if let TokenType::ProperName(predicate_name) = self.peek().kind {
7139                self.advance(); // consume the proper name
7140                let identity = self.ctx.exprs.alloc(LogicExpr::Identity {
7141                    left: self.ctx.terms.alloc(Term::Constant(subject.noun)),
7142                    right: self.ctx.terms.alloc(Term::Constant(predicate_name)),
7143                });
7144                let result = if is_negated {
7145                    self.ctx.exprs.alloc(LogicExpr::UnaryOp {
7146                        op: TokenType::Not,
7147                        operand: identity,
7148                    })
7149                } else {
7150                    identity
7151                };
7152                return self.wrap_with_definiteness(subject.definiteness, subject.noun, result);
7153            }
7154
7155            // Handle "The king is bald" or "Alice is not guilty" - NP copula (not)? ADJ/NOUN
7156            // Also handles bare noun predicates like "Time is money"
7157            let predicate_name = self.consume_content_word()?;
7158
7159            // Check for sort violation (metaphor detection)
7160            let subject_sort = lexicon::lookup_sort(self.interner.resolve(subject.noun));
7161            let predicate_str = self.interner.resolve(predicate_name);
7162
7163            // Check ontology's predicate sort requirements (for adjectives like "happy")
7164            if let Some(s_sort) = subject_sort {
7165                if !crate::ontology::check_sort_compatibility(predicate_str, s_sort) {
7166                    let metaphor = self.ctx.exprs.alloc(LogicExpr::Metaphor {
7167                        tenor: self.ctx.terms.alloc(Term::Constant(subject.noun)),
7168                        vehicle: self.ctx.terms.alloc(Term::Constant(predicate_name)),
7169                    });
7170                    return self.wrap_with_definiteness(subject.definiteness, subject.noun, metaphor);
7171                }
7172            }
7173
7174            // Check copular NP predicate sort compatibility (for "Time is money")
7175            let predicate_sort = lexicon::lookup_sort(predicate_str);
7176            if let (Some(s_sort), Some(p_sort)) = (subject_sort, predicate_sort) {
7177                if s_sort != p_sort && !s_sort.is_compatible_with(p_sort) && !p_sort.is_compatible_with(s_sort) {
7178                    let metaphor = self.ctx.exprs.alloc(LogicExpr::Metaphor {
7179                        tenor: self.ctx.terms.alloc(Term::Constant(subject.noun)),
7180                        vehicle: self.ctx.terms.alloc(Term::Constant(predicate_name)),
7181                    });
7182                    return self.wrap_with_definiteness(subject.definiteness, subject.noun, metaphor);
7183                }
7184            }
7185
7186            let predicate = self.ctx.exprs.alloc(LogicExpr::Predicate {
7187                name: predicate_name,
7188                args: self.ctx.terms.alloc_slice([Term::Constant(subject.noun)]),
7189                world: None,
7190            });
7191
7192            // Apply negation if "is not"
7193            let result = if is_negated {
7194                self.ctx.exprs.alloc(LogicExpr::UnaryOp {
7195                    op: TokenType::Not,
7196                    operand: predicate,
7197                })
7198            } else {
7199                predicate
7200            };
7201            return self.wrap_with_definiteness(subject.definiteness, subject.noun, result);
7202        }
7203
7204        // Handle auxiliary: set pending_time, handle negation
7205        // BUT: "did it" should be parsed as verb "do" with object "it"
7206        // We lookahead to check if this is truly an auxiliary usage
7207        if self.check_auxiliary() && self.is_true_auxiliary_usage() {
7208            let aux_time = if let TokenType::Auxiliary(time) = self.advance().kind {
7209                time
7210            } else {
7211                Time::None
7212            };
7213            self.pending_time = Some(aux_time);
7214
7215            // Handle negation: "John did not see dogs"
7216            if self.match_token(&[TokenType::Not]) {
7217                self.negative_depth += 1;
7218
7219                // Skip "ever" if present: "John did not ever run"
7220                if self.check(&TokenType::Ever) {
7221                    self.advance();
7222                }
7223
7224                // Check for verb or "do" (TokenType::Do is separate from TokenType::Verb)
7225                if self.check_verb() || self.check(&TokenType::Do) {
7226                    let verb = if self.check(&TokenType::Do) {
7227                        self.advance(); // consume "do"
7228                        self.interner.intern("Do")
7229                    } else {
7230                        self.consume_verb()
7231                    };
7232                    let subject_term = self.noun_phrase_to_term(&subject);
7233
7234                    // Check for NPI object first: "John did not see anything"
7235                    if self.check_npi_object() {
7236                        let npi_token = self.advance().kind.clone();
7237                        let obj_var = self.next_var_name();
7238
7239                        let restriction_name = match npi_token {
7240                            TokenType::Anything => "Thing",
7241                            TokenType::Anyone => "Person",
7242                            _ => "Thing",
7243                        };
7244
7245                        let restriction_sym = self.interner.intern(restriction_name);
7246                        let obj_restriction = self.ctx.exprs.alloc(LogicExpr::Predicate {
7247                            name: restriction_sym,
7248                            args: self.ctx.terms.alloc_slice([Term::Variable(obj_var)]),
7249                            world: None,
7250                        });
7251
7252                        let verb_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
7253                            name: verb,
7254                            args: self.ctx.terms.alloc_slice([subject_term.clone(), Term::Variable(obj_var)]),
7255                            world: None,
7256                        });
7257
7258                        let body = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
7259                            left: obj_restriction,
7260                            op: TokenType::And,
7261                            right: verb_pred,
7262                        });
7263
7264                        let quantified = self.ctx.exprs.alloc(LogicExpr::Quantifier {
7265                            kind: QuantifierKind::Existential,
7266                            variable: obj_var,
7267                            body,
7268                            island_id: self.current_island,
7269                        });
7270
7271                        let effective_time = self.pending_time.take().unwrap_or(Time::None);
7272                        let with_time = match effective_time {
7273                            Time::Past => self.ctx.exprs.alloc(LogicExpr::Temporal {
7274                                operator: TemporalOperator::Past,
7275                                body: quantified,
7276                            }),
7277                            Time::Future => self.ctx.exprs.alloc(LogicExpr::Temporal {
7278                                operator: TemporalOperator::Future,
7279                                body: quantified,
7280                            }),
7281                            _ => quantified,
7282                        };
7283
7284                        self.negative_depth -= 1;
7285                        return Ok(self.ctx.exprs.alloc(LogicExpr::UnaryOp {
7286                            op: TokenType::Not,
7287                            operand: with_time,
7288                        }));
7289                    }
7290
7291                    // Check for quantifier object: "John did not see any dogs"
7292                    if self.check_quantifier() {
7293                        let quantifier_token = self.advance().kind.clone();
7294                        let object_np = self.parse_noun_phrase(false)?;
7295                        let obj_var = self.next_var_name();
7296
7297                        let obj_restriction = self.ctx.exprs.alloc(LogicExpr::Predicate {
7298                            name: object_np.noun,
7299                            args: self.ctx.terms.alloc_slice([Term::Variable(obj_var)]),
7300                            world: None,
7301                        });
7302
7303                        let verb_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
7304                            name: verb,
7305                            args: self.ctx.terms.alloc_slice([subject_term.clone(), Term::Variable(obj_var)]),
7306                            world: None,
7307                        });
7308
7309                        let (kind, body) = match quantifier_token {
7310                            TokenType::Any => {
7311                                if self.is_negative_context() {
7312                                    (
7313                                        QuantifierKind::Existential,
7314                                        self.ctx.exprs.alloc(LogicExpr::BinaryOp {
7315                                            left: obj_restriction,
7316                                            op: TokenType::And,
7317                                            right: verb_pred,
7318                                        }),
7319                                    )
7320                                } else {
7321                                    (
7322                                        QuantifierKind::Universal,
7323                                        self.ctx.exprs.alloc(LogicExpr::BinaryOp {
7324                                            left: obj_restriction,
7325                                            op: TokenType::If,
7326                                            right: verb_pred,
7327                                        }),
7328                                    )
7329                                }
7330                            }
7331                            TokenType::Some => (
7332                                QuantifierKind::Existential,
7333                                self.ctx.exprs.alloc(LogicExpr::BinaryOp {
7334                                    left: obj_restriction,
7335                                    op: TokenType::And,
7336                                    right: verb_pred,
7337                                }),
7338                            ),
7339                            TokenType::All => (
7340                                QuantifierKind::Universal,
7341                                self.ctx.exprs.alloc(LogicExpr::BinaryOp {
7342                                    left: obj_restriction,
7343                                    op: TokenType::If,
7344                                    right: verb_pred,
7345                                }),
7346                            ),
7347                            _ => (
7348                                QuantifierKind::Existential,
7349                                self.ctx.exprs.alloc(LogicExpr::BinaryOp {
7350                                    left: obj_restriction,
7351                                    op: TokenType::And,
7352                                    right: verb_pred,
7353                                }),
7354                            ),
7355                        };
7356
7357                        let quantified = self.ctx.exprs.alloc(LogicExpr::Quantifier {
7358                            kind,
7359                            variable: obj_var,
7360                            body,
7361                            island_id: self.current_island,
7362                        });
7363
7364                        let effective_time = self.pending_time.take().unwrap_or(Time::None);
7365                        let with_time = match effective_time {
7366                            Time::Past => self.ctx.exprs.alloc(LogicExpr::Temporal {
7367                                operator: TemporalOperator::Past,
7368                                body: quantified,
7369                            }),
7370                            Time::Future => self.ctx.exprs.alloc(LogicExpr::Temporal {
7371                                operator: TemporalOperator::Future,
7372                                body: quantified,
7373                            }),
7374                            _ => quantified,
7375                        };
7376
7377                        self.negative_depth -= 1;
7378                        return Ok(self.ctx.exprs.alloc(LogicExpr::UnaryOp {
7379                            op: TokenType::Not,
7380                            operand: with_time,
7381                        }));
7382                    }
7383
7384                    let mut roles: Vec<(ThematicRole, Term<'a>)> = vec![(ThematicRole::Agent, subject_term)];
7385
7386                    // Add temporal modifier from pending_time
7387                    let effective_time = self.pending_time.take().unwrap_or(Time::None);
7388                    let mut modifiers: Vec<Symbol> = vec![];
7389                    match effective_time {
7390                        Time::Past => modifiers.push(self.interner.intern("Past")),
7391                        Time::Future => modifiers.push(self.interner.intern("Future")),
7392                        _ => {}
7393                    }
7394
7395                    // Check for object: NP, article+NP, or pronoun (like "it")
7396                    if self.check_content_word() || self.check_article() || self.check_pronoun() {
7397                        if self.check_pronoun() {
7398                            // Handle pronoun object like "it" in "did not do it"
7399                            let pronoun_token = self.advance();
7400                            let pronoun_sym = pronoun_token.lexeme;
7401                            roles.push((ThematicRole::Theme, Term::Constant(pronoun_sym)));
7402                        } else {
7403                            let object = self.parse_noun_phrase(false)?;
7404                            let object_term = self.noun_phrase_to_term(&object);
7405                            roles.push((ThematicRole::Theme, object_term));
7406                        }
7407                    }
7408
7409                    let event_var = self.get_event_var();
7410                    let suppress_existential = self.drs.in_conditional_antecedent();
7411                    if suppress_existential {
7412                        let event_class = self.interner.intern("Event");
7413                        self.drs.introduce_referent(event_var, event_class, Gender::Neuter, Number::Singular);
7414                    }
7415                    let neo_event = self.ctx.exprs.alloc(LogicExpr::NeoEvent(Box::new(NeoEventData {
7416                        event_var,
7417                        verb,
7418                        roles: self.ctx.roles.alloc_slice(roles),
7419                        modifiers: self.ctx.syms.alloc_slice(modifiers),
7420                        suppress_existential,
7421                        world: None,
7422                    })));
7423
7424                    self.negative_depth -= 1;
7425                    return Ok(self.ctx.exprs.alloc(LogicExpr::UnaryOp {
7426                        op: TokenType::Not,
7427                        operand: neo_event,
7428                    }));
7429                }
7430
7431                self.negative_depth -= 1;
7432            }
7433            // Non-negated auxiliary: pending_time is set, fall through to normal verb handling
7434        }
7435
7436        // Check for presupposition triggers: "stopped", "started", "regrets", "knows"
7437        // Factive verbs like "know" only trigger presupposition with clausal complements
7438        // "John knows that..." → presupposition, "John knows Mary" → regular verb
7439        // Only trigger presupposition if followed by a gerund (e.g., "stopped smoking")
7440        // "John stopped." alone should parse as intransitive verb, not presupposition
7441        if self.check_presup_trigger() && !self.is_followed_by_np_object() && self.is_followed_by_gerund() {
7442            let presup_kind = match self.advance().kind {
7443                TokenType::PresupTrigger(kind) => kind,
7444                TokenType::Verb { lemma, .. } => {
7445                    let s = self.interner.resolve(lemma).to_lowercase();
7446                    crate::lexicon::lookup_presup_trigger(&s)
7447                        .expect("Lexicon mismatch: Verb flagged as trigger but lookup failed")
7448                }
7449                _ => panic!("Expected presupposition trigger"),
7450            };
7451            return self.parse_presupposition(&subject, presup_kind);
7452        }
7453
7454        // Handle bare plurals: "Birds fly." → Gen x. Bird(x) → Fly(x)
7455        let noun_str = self.interner.resolve(subject.noun);
7456        let is_bare_plural = subject.definiteness.is_none()
7457            && subject.possessor.is_none()
7458            && Self::is_plural_noun(noun_str)
7459            && self.check_verb();
7460
7461        if is_bare_plural {
7462            let var_name = self.next_var_name();
7463            let (verb, verb_time, verb_aspect, _) = self.consume_verb_with_metadata();
7464
7465            let type_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
7466                name: subject.noun,
7467                args: self.ctx.terms.alloc_slice([Term::Variable(var_name)]),
7468                world: None,
7469            });
7470
7471            let mut args = vec![Term::Variable(var_name)];
7472            if self.check_content_word() {
7473                let object = self.parse_noun_phrase(false)?;
7474                args.push(self.noun_phrase_to_term(&object));
7475            }
7476
7477            let verb_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
7478                name: verb,
7479                args: self.ctx.terms.alloc_slice(args),
7480                world: None,
7481            });
7482
7483            let effective_time = self.pending_time.take().unwrap_or(verb_time);
7484            let with_time = match effective_time {
7485                Time::Past => self.ctx.exprs.alloc(LogicExpr::Temporal {
7486                    operator: TemporalOperator::Past,
7487                    body: verb_pred,
7488                }),
7489                Time::Future => self.ctx.exprs.alloc(LogicExpr::Temporal {
7490                    operator: TemporalOperator::Future,
7491                    body: verb_pred,
7492                }),
7493                _ => verb_pred,
7494            };
7495
7496            let with_aspect = if verb_aspect == Aspect::Progressive {
7497                self.ctx.exprs.alloc(LogicExpr::Aspectual {
7498                    operator: AspectOperator::Progressive,
7499                    body: with_time,
7500                })
7501            } else {
7502                with_time
7503            };
7504
7505            let body = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
7506                left: type_pred,
7507                op: TokenType::If,
7508                right: with_aspect,
7509            });
7510
7511            return Ok(self.ctx.exprs.alloc(LogicExpr::Quantifier {
7512                kind: QuantifierKind::Generic,
7513                variable: var_name,
7514                body,
7515                island_id: self.current_island,
7516            }));
7517        }
7518
7519        // Handle do-support: "John does not exist" or "John does run"
7520        if self.check(&TokenType::Does) || self.check(&TokenType::Do) {
7521            self.advance(); // consume does/do
7522            let is_negated = self.match_token(&[TokenType::Not]);
7523
7524            if self.check_verb() {
7525                let verb = self.consume_verb();
7526                let verb_lemma = self.interner.resolve(verb).to_lowercase();
7527
7528                // Check for embedded wh-clause with negation: "I don't know who"
7529                if self.check_wh_word() {
7530                    let wh_token = self.advance().kind.clone();
7531                    let is_who = matches!(wh_token, TokenType::Who);
7532                    let is_what = matches!(wh_token, TokenType::What);
7533
7534                    let is_sluicing = self.is_at_end() ||
7535                        self.check(&TokenType::Period) ||
7536                        self.check(&TokenType::Comma);
7537
7538                    if is_sluicing {
7539                        if let Some(template) = self.last_event_template.clone() {
7540                            let wh_var = self.next_var_name();
7541                            let subject_term = self.noun_phrase_to_term(&subject);
7542
7543                            let roles: Vec<_> = if is_who {
7544                                std::iter::once((ThematicRole::Agent, Term::Variable(wh_var)))
7545                                    .chain(template.non_agent_roles.iter().cloned())
7546                                    .collect()
7547                            } else if is_what {
7548                                vec![
7549                                    (ThematicRole::Agent, subject_term.clone()),
7550                                    (ThematicRole::Theme, Term::Variable(wh_var)),
7551                                ]
7552                            } else {
7553                                std::iter::once((ThematicRole::Agent, Term::Variable(wh_var)))
7554                                    .chain(template.non_agent_roles.iter().cloned())
7555                                    .collect()
7556                            };
7557
7558                            let event_var = self.get_event_var();
7559                            let suppress_existential = self.drs.in_conditional_antecedent();
7560                            if suppress_existential {
7561                                let event_class = self.interner.intern("Event");
7562                                self.drs.introduce_referent(event_var, event_class, Gender::Neuter, Number::Singular);
7563                            }
7564                            let reconstructed = self.ctx.exprs.alloc(LogicExpr::NeoEvent(Box::new(NeoEventData {
7565                                event_var,
7566                                verb: template.verb,
7567                                roles: self.ctx.roles.alloc_slice(roles),
7568                                modifiers: self.ctx.syms.alloc_slice(template.modifiers.clone()),
7569                                suppress_existential,
7570                                world: None,
7571                            })));
7572
7573                            let question = self.ctx.exprs.alloc(LogicExpr::Question {
7574                                wh_variable: wh_var,
7575                                body: reconstructed,
7576                            });
7577
7578                            let know_event_var = self.get_event_var();
7579                            let suppress_existential2 = self.drs.in_conditional_antecedent();
7580                            if suppress_existential2 {
7581                                let event_class = self.interner.intern("Event");
7582                                self.drs.introduce_referent(know_event_var, event_class, Gender::Neuter, Number::Singular);
7583                            }
7584                            let know_event = self.ctx.exprs.alloc(LogicExpr::NeoEvent(Box::new(NeoEventData {
7585                                event_var: know_event_var,
7586                                verb,
7587                                roles: self.ctx.roles.alloc_slice(vec![
7588                                    (ThematicRole::Agent, subject_term),
7589                                    (ThematicRole::Theme, Term::Proposition(question)),
7590                                ]),
7591                                modifiers: self.ctx.syms.alloc_slice(vec![]),
7592                                suppress_existential: suppress_existential2,
7593                                world: None,
7594                            })));
7595
7596                            let result = if is_negated {
7597                                self.ctx.exprs.alloc(LogicExpr::UnaryOp {
7598                                    op: TokenType::Not,
7599                                    operand: know_event,
7600                                })
7601                            } else {
7602                                know_event
7603                            };
7604
7605                            return self.wrap_with_definiteness_full(&subject, result);
7606                        }
7607                    }
7608                }
7609
7610                // Special handling for "exist" with negation
7611                if verb_lemma == "exist" && is_negated {
7612                    // "The King of France does not exist" -> ¬∃x(KingOfFrance(x))
7613                    let var_name = self.next_var_name();
7614                    let restriction = self.ctx.exprs.alloc(LogicExpr::Predicate {
7615                        name: subject.noun,
7616                        args: self.ctx.terms.alloc_slice([Term::Variable(var_name)]),
7617                        world: None,
7618                    });
7619                    let exists = self.ctx.exprs.alloc(LogicExpr::Quantifier {
7620                        kind: QuantifierKind::Existential,
7621                        variable: var_name,
7622                        body: restriction,
7623                        island_id: self.current_island,
7624                    });
7625                    return Ok(self.ctx.exprs.alloc(LogicExpr::UnaryOp {
7626                        op: TokenType::Not,
7627                        operand: exists,
7628                    }));
7629                }
7630
7631                // Regular do-support: "John does run" or "John does not run"
7632                // Also handles transitive: "John does not shave any man"
7633                let subject_term = self.noun_phrase_to_term(&subject);
7634                let modifiers: Vec<Symbol> = vec![];
7635
7636                // Check for reflexive object
7637                if self.check(&TokenType::Reflexive) {
7638                    self.advance();
7639                    let roles = vec![
7640                        (ThematicRole::Agent, subject_term.clone()),
7641                        (ThematicRole::Theme, subject_term),
7642                    ];
7643                    let event_var = self.get_event_var();
7644                    let suppress_existential = self.drs.in_conditional_antecedent();
7645                    if suppress_existential {
7646                        let event_class = self.interner.intern("Event");
7647                        self.drs.introduce_referent(event_var, event_class, Gender::Neuter, Number::Singular);
7648                    }
7649                    let neo_event = self.ctx.exprs.alloc(LogicExpr::NeoEvent(Box::new(NeoEventData {
7650                        event_var,
7651                        verb,
7652                        roles: self.ctx.roles.alloc_slice(roles),
7653                        modifiers: self.ctx.syms.alloc_slice(modifiers),
7654                        suppress_existential,
7655                        world: None,
7656                    })));
7657
7658                    let result = if is_negated {
7659                        self.ctx.exprs.alloc(LogicExpr::UnaryOp {
7660                            op: TokenType::Not,
7661                            operand: neo_event,
7662                        })
7663                    } else {
7664                        neo_event
7665                    };
7666                    return self.wrap_with_definiteness_full(&subject, result);
7667                }
7668
7669                // Check for quantified object: "does not shave any man"
7670                if self.check_npi_quantifier() || self.check_quantifier() || self.check_article() {
7671                    let (obj_quantifier, was_definite_article) = if self.check_npi_quantifier() {
7672                        // "any" is an NPI quantifier in negative contexts
7673                        let tok = self.advance().kind.clone();
7674                        (Some(tok), false)
7675                    } else if self.check_quantifier() {
7676                        (Some(self.advance().kind.clone()), false)
7677                    } else {
7678                        let art = self.advance().kind.clone();
7679                        if let TokenType::Article(def) = art {
7680                            if def == Definiteness::Indefinite {
7681                                (Some(TokenType::Some), false)
7682                            } else {
7683                                (None, true)
7684                            }
7685                        } else {
7686                            (None, false)
7687                        }
7688                    };
7689
7690                    let object_np = self.parse_noun_phrase(false)?;
7691                    let obj_var = self.next_var_name();
7692
7693                    let type_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
7694                        name: object_np.noun,
7695                        args: self.ctx.terms.alloc_slice([Term::Variable(obj_var)]),
7696                        world: None,
7697                    });
7698
7699                    // Check for relative clause on object
7700                    let obj_restriction = if self.check(&TokenType::That) || self.check(&TokenType::Who) {
7701                        self.advance();
7702                        let rel_clause = self.parse_relative_clause(obj_var)?;
7703                        self.ctx.exprs.alloc(LogicExpr::BinaryOp {
7704                            left: type_pred,
7705                            op: TokenType::And,
7706                            right: rel_clause,
7707                        })
7708                    } else {
7709                        type_pred
7710                    };
7711
7712                    let event_var = self.get_event_var();
7713                    let suppress_existential = self.drs.in_conditional_antecedent();
7714                    if suppress_existential {
7715                        let event_class = self.interner.intern("Event");
7716                        self.drs.introduce_referent(event_var, event_class, Gender::Neuter, Number::Singular);
7717                    }
7718
7719                    let roles = vec![
7720                        (ThematicRole::Agent, subject_term),
7721                        (ThematicRole::Theme, Term::Variable(obj_var)),
7722                    ];
7723
7724                    let neo_event = self.ctx.exprs.alloc(LogicExpr::NeoEvent(Box::new(NeoEventData {
7725                        event_var,
7726                        verb,
7727                        roles: self.ctx.roles.alloc_slice(roles),
7728                        modifiers: self.ctx.syms.alloc_slice(modifiers),
7729                        suppress_existential,
7730                        world: None,
7731                    })));
7732
7733                    // Build quantified expression
7734                    // For "does not shave any man" with negation + any:
7735                    // ¬∃x(Man(x) ∧ Shave(barber, x)) = "there is no man the barber shaves"
7736                    let quantifier_kind = match &obj_quantifier {
7737                        Some(TokenType::Any) if is_negated => QuantifierKind::Existential,
7738                        Some(TokenType::All) => QuantifierKind::Universal,
7739                        Some(TokenType::No) => QuantifierKind::Universal,
7740                        _ => QuantifierKind::Existential,
7741                    };
7742
7743                    let obj_body = match &obj_quantifier {
7744                        Some(TokenType::All) => self.ctx.exprs.alloc(LogicExpr::BinaryOp {
7745                            left: obj_restriction,
7746                            op: TokenType::If,
7747                            right: neo_event,
7748                        }),
7749                        Some(TokenType::No) => {
7750                            let neg = self.ctx.exprs.alloc(LogicExpr::UnaryOp {
7751                                op: TokenType::Not,
7752                                operand: neo_event,
7753                            });
7754                            self.ctx.exprs.alloc(LogicExpr::BinaryOp {
7755                                left: obj_restriction,
7756                                op: TokenType::If,
7757                                right: neg,
7758                            })
7759                        }
7760                        _ => self.ctx.exprs.alloc(LogicExpr::BinaryOp {
7761                            left: obj_restriction,
7762                            op: TokenType::And,
7763                            right: neo_event,
7764                        }),
7765                    };
7766
7767                    let obj_quantified = self.ctx.exprs.alloc(LogicExpr::Quantifier {
7768                        kind: quantifier_kind,
7769                        variable: obj_var,
7770                        body: obj_body,
7771                        island_id: self.current_island,
7772                    });
7773
7774                    // Apply negation at sentence level for "does not ... any"
7775                    let result = if is_negated && matches!(obj_quantifier, Some(TokenType::Any)) {
7776                        self.ctx.exprs.alloc(LogicExpr::UnaryOp {
7777                            op: TokenType::Not,
7778                            operand: obj_quantified,
7779                        })
7780                    } else if is_negated {
7781                        // For other quantifiers, negate the whole thing
7782                        self.ctx.exprs.alloc(LogicExpr::UnaryOp {
7783                            op: TokenType::Not,
7784                            operand: obj_quantified,
7785                        })
7786                    } else {
7787                        obj_quantified
7788                    };
7789
7790                    return self.wrap_with_definiteness_full(&subject, result);
7791                }
7792
7793                // Intransitive: "John does (not) run"
7794                let roles: Vec<(ThematicRole, Term<'a>)> = vec![(ThematicRole::Agent, subject_term)];
7795                let event_var = self.get_event_var();
7796                let suppress_existential = self.drs.in_conditional_antecedent();
7797                if suppress_existential {
7798                    let event_class = self.interner.intern("Event");
7799                    self.drs.introduce_referent(event_var, event_class, Gender::Neuter, Number::Singular);
7800                }
7801
7802                let neo_event = self.ctx.exprs.alloc(LogicExpr::NeoEvent(Box::new(NeoEventData {
7803                    event_var,
7804                    verb,
7805                    roles: self.ctx.roles.alloc_slice(roles),
7806                    modifiers: self.ctx.syms.alloc_slice(modifiers),
7807                    suppress_existential,
7808                    world: None,
7809                })));
7810
7811                if is_negated {
7812                    return Ok(self.ctx.exprs.alloc(LogicExpr::UnaryOp {
7813                        op: TokenType::Not,
7814                        operand: neo_event,
7815                    }));
7816                }
7817                return Ok(neo_event);
7818            }
7819        }
7820
7821        // Garden path detection: "The horse raced past the barn fell."
7822        // If we have a definite NP + past verb + more content + another verb,
7823        // try reduced relative interpretation
7824        // Skip if pending_time is set (auxiliary like "will" was just consumed)
7825        // Skip if verb is has/have/had (perfect aspect, not reduced relative)
7826        let is_perfect_aux = if self.check_verb() {
7827            let word = self.interner.resolve(self.peek().lexeme).to_lowercase();
7828            word == "has" || word == "have" || word == "had"
7829        } else {
7830            false
7831        };
7832        if subject.definiteness == Some(Definiteness::Definite) && self.check_verb() && self.pending_time.is_none() && !is_perfect_aux {
7833            let saved_pos = self.current;
7834
7835            // Try parsing as reduced relative: first verb is modifier, look for main verb after
7836            if let Some(garden_path_result) = self.try_parse(|p| {
7837                let (modifier_verb, _modifier_time, _, _) = p.consume_verb_with_metadata();
7838
7839                // Collect any PP modifiers on the reduced relative
7840                let mut pp_mods: Vec<&'a LogicExpr<'a>> = Vec::new();
7841                while p.check_preposition() {
7842                    let prep = if let TokenType::Preposition(prep) = p.advance().kind {
7843                        prep
7844                    } else {
7845                        break;
7846                    };
7847                    if p.check_article() || p.check_content_word() {
7848                        let pp_obj = p.parse_noun_phrase(false)?;
7849                        let pp_pred = p.ctx.exprs.alloc(LogicExpr::Predicate {
7850                            name: prep,
7851                            args: p.ctx.terms.alloc_slice([Term::Variable(p.interner.intern("x")), Term::Constant(pp_obj.noun)]),
7852                            world: None,
7853                        });
7854                        pp_mods.push(pp_pred);
7855                    }
7856                }
7857
7858                // Now check if there's ANOTHER verb (the real main verb)
7859                if !p.check_verb() {
7860                    return Err(ParseError {
7861                        kind: ParseErrorKind::ExpectedVerb { found: p.peek().kind.clone() },
7862                        span: p.current_span(),
7863                    });
7864                }
7865
7866                let (main_verb, main_time, _, _) = p.consume_verb_with_metadata();
7867
7868                // Build: ∃x((Horse(x) ∧ ∀y(Horse(y) → y=x)) ∧ Raced(x) ∧ Past(x, Barn) ∧ Fell(x))
7869                let var = p.interner.intern("x");
7870
7871                // Type predicate
7872                let type_pred = p.ctx.exprs.alloc(LogicExpr::Predicate {
7873                    name: subject.noun,
7874                    args: p.ctx.terms.alloc_slice([Term::Variable(var)]),
7875                    world: None,
7876                });
7877
7878                // Modifier verb predicate (reduced relative)
7879                let mod_pred = p.ctx.exprs.alloc(LogicExpr::Predicate {
7880                    name: modifier_verb,
7881                    args: p.ctx.terms.alloc_slice([Term::Variable(var)]),
7882                    world: None,
7883                });
7884
7885                // Main verb predicate
7886                let main_pred = p.ctx.exprs.alloc(LogicExpr::Predicate {
7887                    name: main_verb,
7888                    args: p.ctx.terms.alloc_slice([Term::Variable(var)]),
7889                    world: None,
7890                });
7891
7892                // Combine type + modifier
7893                let mut body = p.ctx.exprs.alloc(LogicExpr::BinaryOp {
7894                    left: type_pred,
7895                    op: TokenType::And,
7896                    right: mod_pred,
7897                });
7898
7899                // Add PP modifiers
7900                for pp in pp_mods {
7901                    body = p.ctx.exprs.alloc(LogicExpr::BinaryOp {
7902                        left: body,
7903                        op: TokenType::And,
7904                        right: pp,
7905                    });
7906                }
7907
7908                // Add main predicate
7909                body = p.ctx.exprs.alloc(LogicExpr::BinaryOp {
7910                    left: body,
7911                    op: TokenType::And,
7912                    right: main_pred,
7913                });
7914
7915                // Wrap with temporal if needed
7916                let with_time = match main_time {
7917                    Time::Past => p.ctx.exprs.alloc(LogicExpr::Temporal {
7918                        operator: TemporalOperator::Past,
7919                        body,
7920                    }),
7921                    Time::Future => p.ctx.exprs.alloc(LogicExpr::Temporal {
7922                        operator: TemporalOperator::Future,
7923                        body,
7924                    }),
7925                    _ => body,
7926                };
7927
7928                // Wrap in existential quantifier for definite
7929                Ok(p.ctx.exprs.alloc(LogicExpr::Quantifier {
7930                    kind: QuantifierKind::Existential,
7931                    variable: var,
7932                    body: with_time,
7933                    island_id: p.current_island,
7934                }))
7935            }) {
7936                return Ok(garden_path_result);
7937            }
7938
7939            // Restore position if garden path didn't work
7940            self.current = saved_pos;
7941        }
7942
7943        if self.check_modal() {
7944            return self.parse_aspect_chain(subject.noun);
7945        }
7946
7947        // Handle "has/have/had" perfect aspect: "John has run"
7948        if self.check_content_word() {
7949            let word = self.interner.resolve(self.peek().lexeme).to_lowercase();
7950            if word == "has" || word == "have" || word == "had" {
7951                // Lookahead to distinguish perfect aspect ("has eaten") from possession ("has 3 children")
7952                let is_perfect_aspect = if self.current + 1 < self.tokens.len() {
7953                    let next_token = &self.tokens[self.current + 1].kind;
7954                    matches!(
7955                        next_token,
7956                        TokenType::Verb { .. } | TokenType::Not
7957                    ) && !matches!(next_token, TokenType::Number(_))
7958                } else {
7959                    false
7960                };
7961                if is_perfect_aspect {
7962                    return self.parse_aspect_chain(subject.noun);
7963                }
7964                // Otherwise fall through to verb parsing below
7965            }
7966        }
7967
7968        // Handle TokenType::Had for past perfect: "John had run"
7969        if self.check(&TokenType::Had) {
7970            return self.parse_aspect_chain(subject.noun);
7971        }
7972
7973        // Handle "never" temporal negation: "John never runs"
7974        if self.check(&TokenType::Never) {
7975            self.advance();
7976            let verb = self.consume_verb();
7977            let subject_term = self.noun_phrase_to_term(&subject);
7978            let verb_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
7979                name: verb,
7980                args: self.ctx.terms.alloc_slice([subject_term]),
7981                world: None,
7982            });
7983            let result = self.ctx.exprs.alloc(LogicExpr::UnaryOp {
7984                op: TokenType::Not,
7985                operand: verb_pred,
7986            });
7987            return self.wrap_with_definiteness_full(&subject, result);
7988        }
7989
7990        if self.check_verb() {
7991            let (mut verb, verb_time, verb_aspect, verb_class) = self.consume_verb_with_metadata();
7992
7993            // Check for verb sort violation (metaphor detection)
7994            let subject_sort = lexicon::lookup_sort(self.interner.resolve(subject.noun));
7995            let verb_str = self.interner.resolve(verb);
7996            if let Some(s_sort) = subject_sort {
7997                if !crate::ontology::check_sort_compatibility(verb_str, s_sort) {
7998                    let metaphor = self.ctx.exprs.alloc(LogicExpr::Metaphor {
7999                        tenor: self.ctx.terms.alloc(Term::Constant(subject.noun)),
8000                        vehicle: self.ctx.terms.alloc(Term::Constant(verb)),
8001                    });
8002                    return self.wrap_with_definiteness(subject.definiteness, subject.noun, metaphor);
8003                }
8004            }
8005
8006            // Check for control verb + infinitive
8007            if self.is_control_verb(verb) {
8008                return self.parse_control_structure(&subject, verb, verb_time);
8009            }
8010
8011            // If we have a relative clause, use variable binding
8012            if let Some((var_name, rel_clause)) = relative_clause {
8013                let main_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
8014                    name: verb,
8015                    args: self.ctx.terms.alloc_slice([Term::Variable(var_name)]),
8016                    world: None,
8017                });
8018
8019                let effective_time = self.pending_time.take().unwrap_or(verb_time);
8020                let with_time = match effective_time {
8021                    Time::Past => self.ctx.exprs.alloc(LogicExpr::Temporal {
8022                        operator: TemporalOperator::Past,
8023                        body: main_pred,
8024                    }),
8025                    Time::Future => self.ctx.exprs.alloc(LogicExpr::Temporal {
8026                        operator: TemporalOperator::Future,
8027                        body: main_pred,
8028                    }),
8029                    _ => main_pred,
8030                };
8031
8032                // Build: ∃x(Type(x) ∧ RelClause(x) ∧ MainPred(x))
8033                let type_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
8034                    name: subject.noun,
8035                    args: self.ctx.terms.alloc_slice([Term::Variable(var_name)]),
8036                    world: None,
8037                });
8038
8039                let inner = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
8040                    left: type_pred,
8041                    op: TokenType::And,
8042                    right: rel_clause,
8043                });
8044
8045                let body = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
8046                    left: inner,
8047                    op: TokenType::And,
8048                    right: with_time,
8049                });
8050
8051                return Ok(self.ctx.exprs.alloc(LogicExpr::Quantifier {
8052                    kind: QuantifierKind::Existential,
8053                    variable: var_name,
8054                    body,
8055                    island_id: self.current_island,
8056                }));
8057            }
8058
8059            let subject_term = self.noun_phrase_to_term(&subject);
8060            let mut args = vec![subject_term.clone()];
8061
8062            let unknown = self.interner.intern("?");
8063
8064            // Check for embedded wh-clause: "I know who/what"
8065            if self.check_wh_word() {
8066                let wh_token = self.advance().kind.clone();
8067
8068                // Determine wh-type for slot matching
8069                let is_who = matches!(wh_token, TokenType::Who);
8070                let is_what = matches!(wh_token, TokenType::What);
8071
8072                // Check for sluicing: wh-word followed by terminator
8073                let is_sluicing = self.is_at_end() ||
8074                    self.check(&TokenType::Period) ||
8075                    self.check(&TokenType::Comma);
8076
8077                if is_sluicing {
8078                    // Reconstruct from template
8079                    if let Some(template) = self.last_event_template.clone() {
8080                        let wh_var = self.next_var_name();
8081
8082                        // Build roles with wh-variable in appropriate slot
8083                        let roles: Vec<_> = if is_who {
8084                            // "who" replaces Agent
8085                            std::iter::once((ThematicRole::Agent, Term::Variable(wh_var)))
8086                                .chain(template.non_agent_roles.iter().cloned())
8087                                .collect()
8088                        } else if is_what {
8089                            // "what" replaces Theme - use Agent from context, Theme is variable
8090                            vec![
8091                                (ThematicRole::Agent, subject_term.clone()),
8092                                (ThematicRole::Theme, Term::Variable(wh_var)),
8093                            ]
8094                        } else {
8095                            // Default: wh-variable as Agent
8096                            std::iter::once((ThematicRole::Agent, Term::Variable(wh_var)))
8097                                .chain(template.non_agent_roles.iter().cloned())
8098                                .collect()
8099                        };
8100
8101                        let event_var = self.get_event_var();
8102                        let suppress_existential = self.drs.in_conditional_antecedent();
8103                        if suppress_existential {
8104                            let event_class = self.interner.intern("Event");
8105                            self.drs.introduce_referent(event_var, event_class, Gender::Neuter, Number::Singular);
8106                        }
8107                        let reconstructed = self.ctx.exprs.alloc(LogicExpr::NeoEvent(Box::new(NeoEventData {
8108                            event_var,
8109                            verb: template.verb,
8110                            roles: self.ctx.roles.alloc_slice(roles),
8111                            modifiers: self.ctx.syms.alloc_slice(template.modifiers.clone()),
8112                            suppress_existential,
8113                            world: None,
8114                        })));
8115
8116                        let question = self.ctx.exprs.alloc(LogicExpr::Question {
8117                            wh_variable: wh_var,
8118                            body: reconstructed,
8119                        });
8120
8121                        // Build: Know(subject, question)
8122                        let know_event_var = self.get_event_var();
8123                        let suppress_existential2 = self.drs.in_conditional_antecedent();
8124                        if suppress_existential2 {
8125                            let event_class = self.interner.intern("Event");
8126                            self.drs.introduce_referent(know_event_var, event_class, Gender::Neuter, Number::Singular);
8127                        }
8128                        let know_event = self.ctx.exprs.alloc(LogicExpr::NeoEvent(Box::new(NeoEventData {
8129                            event_var: know_event_var,
8130                            verb,
8131                            roles: self.ctx.roles.alloc_slice(vec![
8132                                (ThematicRole::Agent, subject_term),
8133                                (ThematicRole::Theme, Term::Proposition(question)),
8134                            ]),
8135                            modifiers: self.ctx.syms.alloc_slice(vec![]),
8136                            suppress_existential: suppress_existential2,
8137                            world: None,
8138                        })));
8139
8140                        return self.wrap_with_definiteness_full(&subject, know_event);
8141                    }
8142                }
8143
8144                // Non-sluicing embedded question: "I know who runs"
8145                let embedded = self.parse_embedded_wh_clause()?;
8146                let question = self.ctx.exprs.alloc(LogicExpr::Question {
8147                    wh_variable: self.interner.intern("x"),
8148                    body: embedded,
8149                });
8150
8151                // Build: Know(subject, question)
8152                let know_event_var = self.get_event_var();
8153                let suppress_existential = self.drs.in_conditional_antecedent();
8154                if suppress_existential {
8155                    let event_class = self.interner.intern("Event");
8156                    self.drs.introduce_referent(know_event_var, event_class, Gender::Neuter, Number::Singular);
8157                }
8158                let know_event = self.ctx.exprs.alloc(LogicExpr::NeoEvent(Box::new(NeoEventData {
8159                    event_var: know_event_var,
8160                    verb,
8161                    roles: self.ctx.roles.alloc_slice(vec![
8162                        (ThematicRole::Agent, subject_term),
8163                        (ThematicRole::Theme, Term::Proposition(question)),
8164                    ]),
8165                    modifiers: self.ctx.syms.alloc_slice(vec![]),
8166                    suppress_existential,
8167                    world: None,
8168                })));
8169
8170                return self.wrap_with_definiteness_full(&subject, know_event);
8171            }
8172
8173            let mut object_term: Option<Term<'a>> = None;
8174            let mut second_object_term: Option<Term<'a>> = None;
8175            let mut object_superlative: Option<(Symbol, Symbol)> = None; // (adjective, noun)
8176            if self.check(&TokenType::Reflexive) {
8177                self.advance();
8178                let term = self.noun_phrase_to_term(&subject);
8179                object_term = Some(term.clone());
8180                args.push(term);
8181
8182                // Check for distanced phrasal verb particle: "gave himself up"
8183                if let TokenType::Particle(particle_sym) = self.peek().kind {
8184                    let verb_str = self.interner.resolve(verb).to_lowercase();
8185                    let particle_str = self.interner.resolve(particle_sym).to_lowercase();
8186                    if let Some((phrasal_lemma, _class)) = crate::lexicon::lookup_phrasal_verb(&verb_str, &particle_str) {
8187                        self.advance();
8188                        verb = self.interner.intern(phrasal_lemma);
8189                    }
8190                }
8191            } else if self.check_pronoun() {
8192                let token = self.advance().clone();
8193                if let TokenType::Pronoun { gender, number, .. } = token.kind {
8194                    let resolved = self.resolve_pronoun(gender, number)?;
8195                    let term = match resolved {
8196                        ResolvedPronoun::Variable(s) => Term::Variable(s),
8197                        ResolvedPronoun::Constant(s) => Term::Constant(s),
8198                    };
8199                    object_term = Some(term.clone());
8200                    args.push(term);
8201
8202                    // Check for distanced phrasal verb particle: "gave it up"
8203                    if let TokenType::Particle(particle_sym) = self.peek().kind {
8204                        let verb_str = self.interner.resolve(verb).to_lowercase();
8205                        let particle_str = self.interner.resolve(particle_sym).to_lowercase();
8206                        if let Some((phrasal_lemma, _class)) = crate::lexicon::lookup_phrasal_verb(&verb_str, &particle_str) {
8207                            self.advance();
8208                            verb = self.interner.intern(phrasal_lemma);
8209                        }
8210                    }
8211                }
8212            } else if self.check_quantifier() || self.check_article() {
8213                // Quantified object: "John loves every woman" or "John saw a dog"
8214                let (obj_quantifier, was_definite_article) = if self.check_quantifier() {
8215                    (Some(self.advance().kind.clone()), false)
8216                } else {
8217                    let art = self.advance().kind.clone();
8218                    if let TokenType::Article(def) = art {
8219                        if def == Definiteness::Indefinite {
8220                            (Some(TokenType::Some), false)
8221                        } else {
8222                            (None, true)  // Was a definite article
8223                        }
8224                    } else {
8225                        (None, false)
8226                    }
8227                };
8228
8229                let object_np = self.parse_noun_phrase(false)?;
8230
8231                // Capture superlative info for constraint generation
8232                if let Some(adj) = object_np.superlative {
8233                    object_superlative = Some((adj, object_np.noun));
8234                }
8235
8236                // Check for distanced phrasal verb particle: "gave the book up"
8237                if let TokenType::Particle(particle_sym) = self.peek().kind {
8238                    let verb_str = self.interner.resolve(verb).to_lowercase();
8239                    let particle_str = self.interner.resolve(particle_sym).to_lowercase();
8240                    if let Some((phrasal_lemma, _class)) = crate::lexicon::lookup_phrasal_verb(&verb_str, &particle_str) {
8241                        self.advance(); // consume the particle
8242                        verb = self.interner.intern(phrasal_lemma);
8243                    }
8244                }
8245
8246                if let Some(obj_q) = obj_quantifier {
8247                    // Check for opaque verb with indefinite object (de dicto reading)
8248                    // For verbs like "seek", "want", "believe" with indefinite objects,
8249                    // use Term::Intension to represent the intensional (concept) reading
8250                    let verb_str = self.interner.resolve(verb).to_lowercase();
8251                    let is_opaque = lexicon::lookup_verb_db(&verb_str)
8252                        .map(|meta| meta.features.contains(&lexicon::Feature::Opaque))
8253                        .unwrap_or(false);
8254
8255                    if is_opaque && matches!(obj_q, TokenType::Some) {
8256                        // De dicto reading: use Term::Intension for the theme
8257                        let intension_term = Term::Intension(object_np.noun);
8258
8259                        // Register intensional entity for anaphora resolution
8260                        let event_var = self.get_event_var();
8261                        let mut modifiers = self.collect_adverbs();
8262                        let effective_time = self.pending_time.take().unwrap_or(verb_time);
8263                        match effective_time {
8264                            Time::Past => modifiers.push(self.interner.intern("Past")),
8265                            Time::Future => modifiers.push(self.interner.intern("Future")),
8266                            _ => {}
8267                        }
8268
8269                        let subject_term_for_event = self.noun_phrase_to_term(&subject);
8270                        let roles = vec![
8271                            (ThematicRole::Agent, subject_term_for_event),
8272                            (ThematicRole::Theme, intension_term),
8273                        ];
8274
8275                        let suppress_existential = self.drs.in_conditional_antecedent();
8276                        if suppress_existential {
8277                            let event_class = self.interner.intern("Event");
8278                            self.drs.introduce_referent(event_var, event_class, Gender::Neuter, Number::Singular);
8279                        }
8280                        let neo_event = self.ctx.exprs.alloc(LogicExpr::NeoEvent(Box::new(NeoEventData {
8281                            event_var,
8282                            verb,
8283                            roles: self.ctx.roles.alloc_slice(roles),
8284                            modifiers: self.ctx.syms.alloc_slice(modifiers),
8285                            suppress_existential,
8286                            world: None,
8287                        })));
8288
8289                        return self.wrap_with_definiteness_full(&subject, neo_event);
8290                    }
8291
8292                    let obj_var = self.next_var_name();
8293
8294                    // Introduce object referent in DRS for cross-sentence anaphora
8295                    let obj_gender = Self::infer_noun_gender(self.interner.resolve(object_np.noun));
8296                    let obj_number = if Self::is_plural_noun(self.interner.resolve(object_np.noun)) {
8297                        Number::Plural
8298                    } else {
8299                        Number::Singular
8300                    };
8301                    // Definite descriptions presuppose existence, so they should be globally accessible
8302                    if object_np.definiteness == Some(Definiteness::Definite) {
8303                        self.drs.introduce_referent_with_source(obj_var, object_np.noun, obj_gender, obj_number, ReferentSource::MainClause);
8304                    } else {
8305                        self.drs.introduce_referent(obj_var, object_np.noun, obj_gender, obj_number);
8306                    }
8307
8308                    let type_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
8309                        name: object_np.noun,
8310                        args: self.ctx.terms.alloc_slice([Term::Variable(obj_var)]),
8311                        world: None,
8312                    });
8313
8314                    let obj_restriction = if self.check(&TokenType::That) || self.check(&TokenType::Who) {
8315                        self.advance();
8316                        let rel_clause = self.parse_relative_clause(obj_var)?;
8317                        self.ctx.exprs.alloc(LogicExpr::BinaryOp {
8318                            left: type_pred,
8319                            op: TokenType::And,
8320                            right: rel_clause,
8321                        })
8322                    } else {
8323                        type_pred
8324                    };
8325
8326                    let event_var = self.get_event_var();
8327                    let mut modifiers = self.collect_adverbs();
8328                    let effective_time = self.pending_time.take().unwrap_or(verb_time);
8329                    match effective_time {
8330                        Time::Past => modifiers.push(self.interner.intern("Past")),
8331                        Time::Future => modifiers.push(self.interner.intern("Future")),
8332                        _ => {}
8333                    }
8334
8335                    let subject_term_for_event = self.noun_phrase_to_term(&subject);
8336                    let roles = vec![
8337                        (ThematicRole::Agent, subject_term_for_event),
8338                        (ThematicRole::Theme, Term::Variable(obj_var)),
8339                    ];
8340
8341                    // Capture template with object type for ellipsis reconstruction
8342                    // Use the object noun type instead of variable for reconstruction
8343                    let template_roles = vec![
8344                        (ThematicRole::Agent, subject_term_for_event),
8345                        (ThematicRole::Theme, Term::Constant(object_np.noun)),
8346                    ];
8347                    self.capture_event_template(verb, &template_roles, &modifiers);
8348
8349                    let suppress_existential = self.drs.in_conditional_antecedent();
8350                    if suppress_existential {
8351                        let event_class = self.interner.intern("Event");
8352                        self.drs.introduce_referent(event_var, event_class, Gender::Neuter, Number::Singular);
8353                    }
8354                    let neo_event = self.ctx.exprs.alloc(LogicExpr::NeoEvent(Box::new(NeoEventData {
8355                        event_var,
8356                        verb,
8357                        roles: self.ctx.roles.alloc_slice(roles),
8358                        modifiers: self.ctx.syms.alloc_slice(modifiers),
8359                        suppress_existential,
8360                        world: None,
8361                    })));
8362
8363                    let obj_kind = match obj_q {
8364                        TokenType::All => QuantifierKind::Universal,
8365                        TokenType::Some => QuantifierKind::Existential,
8366                        TokenType::No => QuantifierKind::Universal,
8367                        TokenType::Most => QuantifierKind::Most,
8368                        TokenType::Few => QuantifierKind::Few,
8369                        TokenType::Many => QuantifierKind::Many,
8370                        TokenType::Cardinal(n) => QuantifierKind::Cardinal(n),
8371                        TokenType::AtLeast(n) => QuantifierKind::AtLeast(n),
8372                        TokenType::AtMost(n) => QuantifierKind::AtMost(n),
8373                        _ => QuantifierKind::Existential,
8374                    };
8375
8376                    let obj_body = match obj_q {
8377                        TokenType::All => self.ctx.exprs.alloc(LogicExpr::BinaryOp {
8378                            left: obj_restriction,
8379                            op: TokenType::If,
8380                            right: neo_event,
8381                        }),
8382                        TokenType::No => {
8383                            let neg = self.ctx.exprs.alloc(LogicExpr::UnaryOp {
8384                                op: TokenType::Not,
8385                                operand: neo_event,
8386                            });
8387                            self.ctx.exprs.alloc(LogicExpr::BinaryOp {
8388                                left: obj_restriction,
8389                                op: TokenType::If,
8390                                right: neg,
8391                            })
8392                        }
8393                        _ => self.ctx.exprs.alloc(LogicExpr::BinaryOp {
8394                            left: obj_restriction,
8395                            op: TokenType::And,
8396                            right: neo_event,
8397                        }),
8398                    };
8399
8400                    // Wrap object with its quantifier
8401                    let obj_quantified = self.ctx.exprs.alloc(LogicExpr::Quantifier {
8402                        kind: obj_kind,
8403                        variable: obj_var,
8404                        body: obj_body,
8405                        island_id: self.current_island,
8406                    });
8407
8408                    // Now wrap the SUBJECT (don't skip it with early return!)
8409                    return self.wrap_with_definiteness_full(&subject, obj_quantified);
8410                } else {
8411                    // Definite object NP (e.g., "the house")
8412                    // Introduce to DRS for cross-sentence bridging anaphora
8413                    // E.g., "John entered the house. The door was open." - door bridges to house
8414                    // Note: was_definite_article is true because the article was consumed before parse_noun_phrase
8415                    if was_definite_article {
8416                        let obj_gender = Self::infer_noun_gender(self.interner.resolve(object_np.noun));
8417                        let obj_number = if Self::is_plural_noun(self.interner.resolve(object_np.noun)) {
8418                            Number::Plural
8419                        } else {
8420                            Number::Singular
8421                        };
8422                        // Definite descriptions presuppose existence, so they should be globally accessible
8423                        self.drs.introduce_referent_with_source(object_np.noun, object_np.noun, obj_gender, obj_number, ReferentSource::MainClause);
8424                    }
8425
8426                    let term = self.noun_phrase_to_term(&object_np);
8427                    object_term = Some(term.clone());
8428                    args.push(term);
8429                }
8430            } else if self.check_focus() {
8431                let focus_kind = if let TokenType::Focus(k) = self.advance().kind {
8432                    k
8433                } else {
8434                    FocusKind::Only
8435                };
8436
8437                let event_var = self.get_event_var();
8438                let mut modifiers = self.collect_adverbs();
8439                let effective_time = self.pending_time.take().unwrap_or(verb_time);
8440                match effective_time {
8441                    Time::Past => modifiers.push(self.interner.intern("Past")),
8442                    Time::Future => modifiers.push(self.interner.intern("Future")),
8443                    _ => {}
8444                }
8445
8446                let subject_term_for_event = self.noun_phrase_to_term(&subject);
8447
8448                if self.check_preposition() {
8449                    let prep_token = self.advance().clone();
8450                    let prep_name = if let TokenType::Preposition(sym) = prep_token.kind {
8451                        sym
8452                    } else {
8453                        self.interner.intern("to")
8454                    };
8455                    let pp_obj = self.parse_noun_phrase(false)?;
8456                    let pp_obj_term = Term::Constant(pp_obj.noun);
8457
8458                    let roles = vec![(ThematicRole::Agent, subject_term_for_event)];
8459                    let suppress_existential = self.drs.in_conditional_antecedent();
8460                    if suppress_existential {
8461                        let event_class = self.interner.intern("Event");
8462                        self.drs.introduce_referent(event_var, event_class, Gender::Neuter, Number::Singular);
8463                    }
8464                    let neo_event = self.ctx.exprs.alloc(LogicExpr::NeoEvent(Box::new(NeoEventData {
8465                        event_var,
8466                        verb,
8467                        roles: self.ctx.roles.alloc_slice(roles),
8468                        modifiers: self.ctx.syms.alloc_slice(modifiers),
8469                        suppress_existential,
8470                        world: None,
8471                    })));
8472
8473                    let pp_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
8474                        name: prep_name,
8475                        args: self.ctx.terms.alloc_slice([Term::Variable(event_var), pp_obj_term]),
8476                        world: None,
8477                    });
8478
8479                    let with_pp = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
8480                        left: neo_event,
8481                        op: TokenType::And,
8482                        right: pp_pred,
8483                    });
8484
8485                    let focused_ref = self.ctx.terms.alloc(pp_obj_term);
8486                    return Ok(self.ctx.exprs.alloc(LogicExpr::Focus {
8487                        kind: focus_kind,
8488                        focused: focused_ref,
8489                        scope: with_pp,
8490                    }));
8491                }
8492
8493                let focused_np = self.parse_noun_phrase(false)?;
8494                let focused_term = self.noun_phrase_to_term(&focused_np);
8495                args.push(focused_term.clone());
8496
8497                let roles = vec![
8498                    (ThematicRole::Agent, subject_term_for_event),
8499                    (ThematicRole::Theme, focused_term.clone()),
8500                ];
8501
8502                let suppress_existential = self.drs.in_conditional_antecedent();
8503                if suppress_existential {
8504                    let event_class = self.interner.intern("Event");
8505                    self.drs.introduce_referent(event_var, event_class, Gender::Neuter, Number::Singular);
8506                }
8507                let neo_event = self.ctx.exprs.alloc(LogicExpr::NeoEvent(Box::new(NeoEventData {
8508                    event_var,
8509                    verb,
8510                    roles: self.ctx.roles.alloc_slice(roles),
8511                    modifiers: self.ctx.syms.alloc_slice(modifiers),
8512                    suppress_existential,
8513                    world: None,
8514                })));
8515
8516                let focused_ref = self.ctx.terms.alloc(focused_term);
8517                return Ok(self.ctx.exprs.alloc(LogicExpr::Focus {
8518                    kind: focus_kind,
8519                    focused: focused_ref,
8520                    scope: neo_event,
8521                }));
8522            } else if self.check_number() {
8523                // Handle "has 3 children" or "has cardinality aleph_0"
8524                let measure = self.parse_measure_phrase()?;
8525
8526                // If there's a noun after the measure (for "3 children" where children wasn't a unit)
8527                if self.check_content_word() {
8528                    let noun_sym = self.consume_content_word()?;
8529                    // Build: Has(Subject, 3, Children) where 3 is the count
8530                    let count_term = *measure;
8531                    object_term = Some(count_term.clone());
8532                    args.push(count_term);
8533                    second_object_term = Some(Term::Constant(noun_sym));
8534                    args.push(Term::Constant(noun_sym));
8535                } else {
8536                    // Just the measure: "has cardinality 5"
8537                    object_term = Some(*measure);
8538                    args.push(*measure);
8539                }
8540            } else if self.check_content_word() || self.check_article() {
8541                let object = self.parse_noun_phrase(false)?;
8542                if let Some(adj) = object.superlative {
8543                    object_superlative = Some((adj, object.noun));
8544                }
8545
8546                // Collect all objects for potential "respectively" handling
8547                let mut all_objects: Vec<Symbol> = vec![object.noun];
8548
8549                // Check for coordinated objects: "Tom and Jerry and Bob"
8550                while self.check(&TokenType::And) {
8551                    let saved = self.current;
8552                    self.advance(); // consume "and"
8553                    if self.check_content_word() || self.check_article() {
8554                        let next_obj = match self.parse_noun_phrase(false) {
8555                            Ok(np) => np,
8556                            Err(_) => {
8557                                self.current = saved;
8558                                break;
8559                            }
8560                        };
8561                        all_objects.push(next_obj.noun);
8562                    } else {
8563                        self.current = saved;
8564                        break;
8565                    }
8566                }
8567
8568                // Check for "respectively" with single subject
8569                if self.check(&TokenType::Respectively) {
8570                    let respectively_span = self.peek().span;
8571                    // Single subject with multiple objects + respectively = error
8572                    if all_objects.len() > 1 {
8573                        return Err(ParseError {
8574                            kind: ParseErrorKind::RespectivelyLengthMismatch {
8575                                subject_count: 1,
8576                                object_count: all_objects.len(),
8577                            },
8578                            span: respectively_span,
8579                        });
8580                    }
8581                    // Single subject, single object + respectively is valid (trivially pairwise)
8582                    self.advance(); // consume "respectively"
8583                }
8584
8585                // Use the first object (or only object) for normal processing
8586                let term = self.noun_phrase_to_term(&object);
8587                object_term = Some(term.clone());
8588                args.push(term.clone());
8589
8590                // For multiple objects without "respectively", use group semantics
8591                if all_objects.len() > 1 {
8592                    let obj_members: Vec<Term<'a>> = all_objects.iter()
8593                        .map(|o| Term::Constant(*o))
8594                        .collect();
8595                    let obj_group = Term::Group(self.ctx.terms.alloc_slice(obj_members));
8596                    // Replace the single object with the group
8597                    args.pop();
8598                    args.push(obj_group);
8599                }
8600
8601                // Check for distanced phrasal verb particle: "gave the book up"
8602                if let TokenType::Particle(particle_sym) = self.peek().kind {
8603                    let verb_str = self.interner.resolve(verb).to_lowercase();
8604                    let particle_str = self.interner.resolve(particle_sym).to_lowercase();
8605                    if let Some((phrasal_lemma, _class)) = crate::lexicon::lookup_phrasal_verb(&verb_str, &particle_str) {
8606                        self.advance(); // consume the particle
8607                        verb = self.interner.intern(phrasal_lemma);
8608                    }
8609                }
8610
8611                // Check for "has cardinality aleph_0" pattern: noun followed by number
8612                if self.check_number() {
8613                    let measure = self.parse_measure_phrase()?;
8614                    second_object_term = Some(*measure);
8615                    args.push(*measure);
8616                }
8617                // Check for ditransitive: "John gave Mary a book"
8618                else {
8619                    let verb_str = self.interner.resolve(verb);
8620                    if Lexer::is_ditransitive_verb(verb_str) && (self.check_content_word() || self.check_article()) {
8621                        let second_np = self.parse_noun_phrase(false)?;
8622                        let second_term = self.noun_phrase_to_term(&second_np);
8623                        second_object_term = Some(second_term.clone());
8624                        args.push(second_term);
8625                    }
8626                }
8627            }
8628
8629            let mut pp_predicates: Vec<&'a LogicExpr<'a>> = Vec::new();
8630            while self.check_preposition() || self.check_to() {
8631                let prep_token = self.advance().clone();
8632                let prep_name = if let TokenType::Preposition(sym) = prep_token.kind {
8633                    sym
8634                } else if matches!(prep_token.kind, TokenType::To) {
8635                    self.interner.intern("To")
8636                } else {
8637                    continue;
8638                };
8639
8640                let pp_obj_term = if self.check(&TokenType::Reflexive) {
8641                    self.advance();
8642                    self.noun_phrase_to_term(&subject)
8643                } else if self.check_pronoun() {
8644                    let token = self.advance().clone();
8645                    if let TokenType::Pronoun { gender, number, .. } = token.kind {
8646                        let resolved = self.resolve_pronoun(gender, number)?;
8647                        match resolved {
8648                            ResolvedPronoun::Variable(s) => Term::Variable(s),
8649                            ResolvedPronoun::Constant(s) => Term::Constant(s),
8650                        }
8651                    } else {
8652                        continue;
8653                    }
8654                } else if self.check_content_word() || self.check_article() {
8655                    let prep_obj = self.parse_noun_phrase(false)?;
8656                    self.noun_phrase_to_term(&prep_obj)
8657                } else {
8658                    continue;
8659                };
8660
8661                if self.pp_attach_to_noun {
8662                    if let Some(ref obj) = object_term {
8663                        // NP-attachment: PP modifies the object noun
8664                        let pp_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
8665                            name: prep_name,
8666                            args: self.ctx.terms.alloc_slice([obj.clone(), pp_obj_term]),
8667                            world: None,
8668                        });
8669                        pp_predicates.push(pp_pred);
8670                    } else {
8671                        args.push(pp_obj_term);
8672                    }
8673                } else {
8674                    // VP-attachment: PP modifies the event (instrument/manner)
8675                    let event_sym = self.get_event_var();
8676                    let pp_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
8677                        name: prep_name,
8678                        args: self.ctx.terms.alloc_slice([Term::Variable(event_sym), pp_obj_term]),
8679                        world: None,
8680                    });
8681                    pp_predicates.push(pp_pred);
8682                }
8683            }
8684
8685            // Check for trailing relative clause on object NP: "the girl with the telescope that laughed"
8686            if self.check(&TokenType::That) || self.check(&TokenType::Who) {
8687                self.advance();
8688                let rel_var = self.next_var_name();
8689                let rel_pred = self.parse_relative_clause(rel_var)?;
8690                pp_predicates.push(rel_pred);
8691            }
8692
8693            // Collect any trailing adverbs FIRST (before building NeoEvent)
8694            let mut modifiers = self.collect_adverbs();
8695
8696            // Add temporal modifier as part of event semantics
8697            let effective_time = self.pending_time.take().unwrap_or(verb_time);
8698            match effective_time {
8699                Time::Past => modifiers.push(self.interner.intern("Past")),
8700                Time::Future => modifiers.push(self.interner.intern("Future")),
8701                _ => {}
8702            }
8703
8704            // Add aspect modifier if applicable
8705            if verb_aspect == Aspect::Progressive {
8706                modifiers.push(self.interner.intern("Progressive"));
8707            } else if verb_aspect == Aspect::Perfect {
8708                modifiers.push(self.interner.intern("Perfect"));
8709            }
8710
8711            // Build thematic roles for Neo-Davidsonian event semantics
8712            let mut roles: Vec<(ThematicRole, Term<'a>)> = Vec::new();
8713
8714            // Check if verb is unaccusative (intransitive subject is Theme, not Agent)
8715            let verb_str_for_check = self.interner.resolve(verb).to_lowercase();
8716            let is_unaccusative = crate::lexicon::lookup_verb_db(&verb_str_for_check)
8717                .map(|meta| meta.features.contains(&crate::lexicon::Feature::Unaccusative))
8718                .unwrap_or(false);
8719
8720            // Unaccusative verbs used intransitively: subject is Theme
8721            let has_object = object_term.is_some() || second_object_term.is_some();
8722            let subject_role = if is_unaccusative && !has_object {
8723                ThematicRole::Theme
8724            } else {
8725                ThematicRole::Agent
8726            };
8727
8728            roles.push((subject_role, subject_term));
8729            if let Some(second_obj) = second_object_term {
8730                // Ditransitive: first object is Recipient, second is Theme
8731                if let Some(first_obj) = object_term {
8732                    roles.push((ThematicRole::Recipient, first_obj));
8733                }
8734                roles.push((ThematicRole::Theme, second_obj));
8735            } else if let Some(obj) = object_term {
8736                // Normal transitive: object is Theme
8737                roles.push((ThematicRole::Theme, obj));
8738            }
8739
8740            // Create event variable
8741            let event_var = self.get_event_var();
8742
8743            // Capture template for ellipsis reconstruction before consuming roles
8744            self.capture_event_template(verb, &roles, &modifiers);
8745
8746            // Create NeoEvent structure with all modifiers including time/aspect
8747            let suppress_existential = self.drs.in_conditional_antecedent();
8748            if suppress_existential {
8749                let event_class = self.interner.intern("Event");
8750                self.drs.introduce_referent(event_var, event_class, Gender::Neuter, Number::Singular);
8751            }
8752            let neo_event = self.ctx.exprs.alloc(LogicExpr::NeoEvent(Box::new(NeoEventData {
8753                event_var,
8754                verb,
8755                roles: self.ctx.roles.alloc_slice(roles),
8756                modifiers: self.ctx.syms.alloc_slice(modifiers),
8757                suppress_existential,
8758                world: None,
8759            })));
8760
8761            // Combine with PP predicates if any
8762            let with_pps = if pp_predicates.is_empty() {
8763                neo_event
8764            } else {
8765                let mut combined = neo_event;
8766                for pp in pp_predicates {
8767                    combined = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
8768                        left: combined,
8769                        op: TokenType::And,
8770                        right: pp,
8771                    });
8772                }
8773                combined
8774            };
8775
8776            // Apply aspectual operators based on verb class
8777            let with_aspect = if verb_aspect == Aspect::Progressive {
8778                // Semelfactive + Progressive → Iterative
8779                if verb_class == crate::lexicon::VerbClass::Semelfactive {
8780                    self.ctx.exprs.alloc(LogicExpr::Aspectual {
8781                        operator: AspectOperator::Iterative,
8782                        body: with_pps,
8783                    })
8784                } else {
8785                    // Other verbs + Progressive → Progressive
8786                    self.ctx.exprs.alloc(LogicExpr::Aspectual {
8787                        operator: AspectOperator::Progressive,
8788                        body: with_pps,
8789                    })
8790                }
8791            } else if verb_aspect == Aspect::Perfect {
8792                self.ctx.exprs.alloc(LogicExpr::Aspectual {
8793                    operator: AspectOperator::Perfect,
8794                    body: with_pps,
8795                })
8796            } else if effective_time == Time::Present && verb_aspect == Aspect::Simple {
8797                // Non-state verbs in simple present get Habitual reading
8798                if !verb_class.is_stative() {
8799                    self.ctx.exprs.alloc(LogicExpr::Aspectual {
8800                        operator: AspectOperator::Habitual,
8801                        body: with_pps,
8802                    })
8803                } else {
8804                    // State verbs in present: direct predication
8805                    with_pps
8806                }
8807            } else {
8808                with_pps
8809            };
8810
8811            let with_adverbs = with_aspect;
8812
8813            // Check for temporal anchor adverb at end of sentence
8814            let with_temporal = if self.check_temporal_adverb() {
8815                let anchor = if let TokenType::TemporalAdverb(adv) = self.advance().kind.clone() {
8816                    adv
8817                } else {
8818                    panic!("Expected temporal adverb");
8819                };
8820                self.ctx.exprs.alloc(LogicExpr::TemporalAnchor {
8821                    anchor,
8822                    body: with_adverbs,
8823                })
8824            } else {
8825                with_adverbs
8826            };
8827
8828            let wrapped = self.wrap_with_definiteness_full(&subject, with_temporal)?;
8829
8830            // Add superlative constraint for object NP if applicable
8831            if let Some((adj, noun)) = object_superlative {
8832                let superlative_expr = self.ctx.exprs.alloc(LogicExpr::Superlative {
8833                    adjective: adj,
8834                    subject: self.ctx.terms.alloc(Term::Constant(noun)),
8835                    domain: noun,
8836                });
8837                return Ok(self.ctx.exprs.alloc(LogicExpr::BinaryOp {
8838                    left: wrapped,
8839                    op: TokenType::And,
8840                    right: superlative_expr,
8841                }));
8842            }
8843
8844            return Ok(wrapped);
8845        }
8846
8847        Ok(self.ctx.exprs.alloc(LogicExpr::Atom(subject.noun)))
8848    }
8849
8850    fn check_preposition(&self) -> bool {
8851        matches!(self.peek().kind, TokenType::Preposition(_))
8852    }
8853
8854    fn check_by_preposition(&self) -> bool {
8855        if let TokenType::Preposition(p) = self.peek().kind {
8856            p.is(self.interner, "by")
8857        } else {
8858            false
8859        }
8860    }
8861
8862    fn check_preposition_is(&self, word: &str) -> bool {
8863        if let TokenType::Preposition(p) = self.peek().kind {
8864            p.is(self.interner, word)
8865        } else {
8866            false
8867        }
8868    }
8869
8870    /// Check if current token is a word (noun/adj/verb lexeme) matching the given string
8871    fn check_word(&self, word: &str) -> bool {
8872        let token = self.peek();
8873        let lexeme = self.interner.resolve(token.lexeme);
8874        lexeme.eq_ignore_ascii_case(word)
8875    }
8876
8877    fn peek_word_at(&self, offset: usize, word: &str) -> bool {
8878        if self.current + offset >= self.tokens.len() {
8879            return false;
8880        }
8881        let token = &self.tokens[self.current + offset];
8882        let lexeme = self.interner.resolve(token.lexeme);
8883        lexeme.eq_ignore_ascii_case(word)
8884    }
8885
8886    fn check_to_preposition(&self) -> bool {
8887        match self.peek().kind {
8888            TokenType::To => true,
8889            TokenType::Preposition(p) => p.is(self.interner, "to"),
8890            _ => false,
8891        }
8892    }
8893
8894    fn check_content_word(&self) -> bool {
8895        match &self.peek().kind {
8896            TokenType::Noun(_)
8897            | TokenType::Adjective(_)
8898            | TokenType::NonIntersectiveAdjective(_)
8899            | TokenType::Verb { .. }
8900            | TokenType::ProperName(_)
8901            | TokenType::Article(_) => true,
8902            TokenType::Ambiguous { primary, alternatives } => {
8903                Self::is_content_word_type(primary)
8904                    || alternatives.iter().any(Self::is_content_word_type)
8905            }
8906            _ => false,
8907        }
8908    }
8909
8910    fn is_content_word_type(t: &TokenType) -> bool {
8911        matches!(
8912            t,
8913            TokenType::Noun(_)
8914                | TokenType::Adjective(_)
8915                | TokenType::NonIntersectiveAdjective(_)
8916                | TokenType::Verb { .. }
8917                | TokenType::ProperName(_)
8918                | TokenType::Article(_)
8919        )
8920    }
8921
8922    fn check_verb(&self) -> bool {
8923        match &self.peek().kind {
8924            TokenType::Verb { .. } => true,
8925            TokenType::Ambiguous { primary, alternatives } => {
8926                if self.noun_priority_mode {
8927                    return false;
8928                }
8929                matches!(**primary, TokenType::Verb { .. })
8930                    || alternatives.iter().any(|t| matches!(t, TokenType::Verb { .. }))
8931            }
8932            _ => false,
8933        }
8934    }
8935
8936    fn check_adverb(&self) -> bool {
8937        matches!(self.peek().kind, TokenType::Adverb(_))
8938    }
8939
8940    fn check_performative(&self) -> bool {
8941        matches!(self.peek().kind, TokenType::Performative(_))
8942    }
8943
8944    fn collect_adverbs(&mut self) -> Vec<Symbol> {
8945        let mut adverbs = Vec::new();
8946        while self.check_adverb() {
8947            if let TokenType::Adverb(adv) = self.advance().kind.clone() {
8948                adverbs.push(adv);
8949            }
8950            // Skip "and" between adverbs
8951            if self.check(&TokenType::And) {
8952                self.advance();
8953            }
8954        }
8955        adverbs
8956    }
8957
8958    fn check_auxiliary(&self) -> bool {
8959        matches!(self.peek().kind, TokenType::Auxiliary(_))
8960    }
8961
8962    /// Check if the current auxiliary is being used as a true auxiliary (followed by "not" or verb)
8963    /// vs being used as a main verb (like "did" in "did it").
8964    ///
8965    /// "did not bark" → auxiliary usage (emphatic past + negation)
8966    /// "did run" → auxiliary usage (emphatic past)
8967    /// "did it" → main verb usage (past of "do" + object)
8968    fn is_true_auxiliary_usage(&self) -> bool {
8969        if self.current + 1 >= self.tokens.len() {
8970            return false;
8971        }
8972
8973        let next_token = &self.tokens[self.current + 1].kind;
8974
8975        // If followed by "not", it's auxiliary usage
8976        if matches!(next_token, TokenType::Not) {
8977            return true;
8978        }
8979
8980        // If followed by a verb, it's auxiliary usage
8981        if matches!(next_token, TokenType::Verb { .. }) {
8982            return true;
8983        }
8984
8985        // If followed by pronoun (it, him, her, etc.), article, or noun, it's main verb usage
8986        if matches!(
8987            next_token,
8988            TokenType::Pronoun { .. }
8989                | TokenType::Article(_)
8990                | TokenType::Noun(_)
8991                | TokenType::ProperName(_)
8992        ) {
8993            return false;
8994        }
8995
8996        // Default to auxiliary usage for backward compatibility
8997        true
8998    }
8999
9000    /// Check if we have an Auxiliary token that should be treated as a main verb.
9001    /// This is true for "did" when followed by an object (e.g., "the butler did it").
9002    fn check_auxiliary_as_main_verb(&self) -> bool {
9003        if let TokenType::Auxiliary(Time::Past) = self.peek().kind {
9004            // Check if followed by pronoun, article, or noun (object)
9005            if self.current + 1 < self.tokens.len() {
9006                let next = &self.tokens[self.current + 1].kind;
9007                matches!(
9008                    next,
9009                    TokenType::Pronoun { .. }
9010                        | TokenType::Article(_)
9011                        | TokenType::Noun(_)
9012                        | TokenType::ProperName(_)
9013                )
9014            } else {
9015                false
9016            }
9017        } else {
9018            false
9019        }
9020    }
9021
9022    /// Parse "did" as the main verb "do" (past tense) with a transitive object.
9023    /// This handles constructions like "the butler did it" → Do(e) ∧ Agent(e, butler) ∧ Theme(e, it)
9024    fn parse_do_as_main_verb(&mut self, subject_term: Term<'a>) -> ParseResult<&'a LogicExpr<'a>> {
9025        // Consume the auxiliary token (we're treating it as past tense "do")
9026        let aux_token = self.advance();
9027        let verb_time = if let TokenType::Auxiliary(time) = aux_token.kind {
9028            time
9029        } else {
9030            Time::Past
9031        };
9032
9033        // Intern "Do" as the verb lemma
9034        let verb = self.interner.intern("Do");
9035
9036        // Parse the object - handle pronouns specially
9037        let object_term = if let TokenType::Pronoun { .. } = self.peek().kind {
9038            // Pronoun object (like "it" in "did it")
9039            self.advance();
9040            // For "it", we use a generic placeholder or resolved referent
9041            // In the context of "did it", "it" often refers to "the crime" or "the act"
9042            let it_sym = self.interner.intern("it");
9043            Term::Constant(it_sym)
9044        } else {
9045            let object = self.parse_noun_phrase(false)?;
9046            self.noun_phrase_to_term(&object)
9047        };
9048
9049        // Build Neo-Davidsonian event structure
9050        let event_var = self.get_event_var();
9051        let suppress_existential = self.drs.in_conditional_antecedent();
9052
9053        let mut modifiers = Vec::new();
9054        if verb_time == Time::Past {
9055            modifiers.push(self.interner.intern("Past"));
9056        } else if verb_time == Time::Future {
9057            modifiers.push(self.interner.intern("Future"));
9058        }
9059
9060        let neo_event = self.ctx.exprs.alloc(LogicExpr::NeoEvent(Box::new(NeoEventData {
9061            event_var,
9062            verb,
9063            roles: self.ctx.roles.alloc_slice(vec![
9064                (ThematicRole::Agent, subject_term),
9065                (ThematicRole::Theme, object_term),
9066            ]),
9067            modifiers: self.ctx.syms.alloc_slice(modifiers),
9068            suppress_existential,
9069            world: None,
9070        })));
9071
9072        Ok(neo_event)
9073    }
9074
9075    fn check_to(&self) -> bool {
9076        matches!(self.peek().kind, TokenType::To)
9077    }
9078
9079    /// Look ahead in the token stream for modal subordinating verbs (would, could, should, might).
9080    /// These verbs allow modal subordination: continuing a hypothetical context from a prior sentence.
9081    /// E.g., "A wolf might enter. It would eat you." - "would" subordinates to "might".
9082    fn has_modal_subordination_ahead(&self) -> bool {
9083        // Modal subordination verbs: would, could, should, might
9084        // These allow access to hypothetical entities from prior modal sentences
9085        for i in self.current..self.tokens.len() {
9086            match &self.tokens[i].kind {
9087                TokenType::Would | TokenType::Could | TokenType::Should | TokenType::Might => {
9088                    return true;
9089                }
9090                // Stop looking at sentence boundary
9091                TokenType::Period | TokenType::EOF => break,
9092                _ => {}
9093            }
9094        }
9095        false
9096    }
9097
9098    fn consume_verb(&mut self) -> Symbol {
9099        let t = self.advance().clone();
9100        match t.kind {
9101            TokenType::Verb { lemma, .. } => lemma,
9102            TokenType::Ambiguous { primary, .. } => match *primary {
9103                TokenType::Verb { lemma, .. } => lemma,
9104                _ => panic!("Expected verb in Ambiguous primary, got {:?}", primary),
9105            },
9106            _ => panic!("Expected verb, got {:?}", t.kind),
9107        }
9108    }
9109
9110    fn consume_verb_with_metadata(&mut self) -> (Symbol, Time, Aspect, VerbClass) {
9111        let t = self.advance().clone();
9112        match t.kind {
9113            TokenType::Verb { lemma, time, aspect, class } => (lemma, time, aspect, class),
9114            TokenType::Ambiguous { primary, .. } => match *primary {
9115                TokenType::Verb { lemma, time, aspect, class } => (lemma, time, aspect, class),
9116                _ => panic!("Expected verb in Ambiguous primary, got {:?}", primary),
9117            },
9118            _ => panic!("Expected verb, got {:?}", t.kind),
9119        }
9120    }
9121
9122    fn match_token(&mut self, types: &[TokenType]) -> bool {
9123        for t in types {
9124            if self.check(t) {
9125                self.advance();
9126                return true;
9127            }
9128        }
9129        false
9130    }
9131
9132    fn check_quantifier(&self) -> bool {
9133        matches!(
9134            self.peek().kind,
9135            TokenType::All
9136                | TokenType::No
9137                | TokenType::Some
9138                | TokenType::Any
9139                | TokenType::Most
9140                | TokenType::Few
9141                | TokenType::Many
9142                | TokenType::Cardinal(_)
9143                | TokenType::AtLeast(_)
9144                | TokenType::AtMost(_)
9145        )
9146    }
9147
9148    fn check_npi_quantifier(&self) -> bool {
9149        matches!(
9150            self.peek().kind,
9151            TokenType::Nobody | TokenType::Nothing | TokenType::NoOne
9152        )
9153    }
9154
9155    fn check_npi_object(&self) -> bool {
9156        matches!(
9157            self.peek().kind,
9158            TokenType::Anything | TokenType::Anyone
9159        )
9160    }
9161
9162    fn check_temporal_npi(&self) -> bool {
9163        matches!(
9164            self.peek().kind,
9165            TokenType::Ever | TokenType::Never
9166        )
9167    }
9168
9169    fn parse_npi_quantified(&mut self) -> ParseResult<&'a LogicExpr<'a>> {
9170        let npi_token = self.advance().kind.clone();
9171        let var_name = self.next_var_name();
9172
9173        let (restriction_name, is_person) = match npi_token {
9174            TokenType::Nobody | TokenType::NoOne => ("Person", true),
9175            TokenType::Nothing => ("Thing", false),
9176            _ => ("Thing", false),
9177        };
9178
9179        let restriction_sym = self.interner.intern(restriction_name);
9180        let subject_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
9181            name: restriction_sym,
9182            args: self.ctx.terms.alloc_slice([Term::Variable(var_name)]),
9183            world: None,
9184        });
9185
9186        self.negative_depth += 1;
9187
9188        let verb = self.consume_verb();
9189
9190        if self.check_npi_object() {
9191            let obj_npi_token = self.advance().kind.clone();
9192            let obj_var = self.next_var_name();
9193
9194            let obj_restriction_name = match obj_npi_token {
9195                TokenType::Anything => "Thing",
9196                TokenType::Anyone => "Person",
9197                _ => "Thing",
9198            };
9199
9200            let obj_restriction_sym = self.interner.intern(obj_restriction_name);
9201            let obj_restriction = self.ctx.exprs.alloc(LogicExpr::Predicate {
9202                name: obj_restriction_sym,
9203                args: self.ctx.terms.alloc_slice([Term::Variable(obj_var)]),
9204                world: None,
9205            });
9206
9207            let verb_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
9208                name: verb,
9209                args: self.ctx.terms.alloc_slice([Term::Variable(var_name), Term::Variable(obj_var)]),
9210                world: None,
9211            });
9212
9213            let verb_and_obj = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
9214                left: obj_restriction,
9215                op: TokenType::And,
9216                right: verb_pred,
9217            });
9218
9219            let inner_existential = self.ctx.exprs.alloc(LogicExpr::Quantifier {
9220                kind: crate::ast::QuantifierKind::Existential,
9221                variable: obj_var,
9222                body: verb_and_obj,
9223                island_id: self.current_island,
9224            });
9225
9226            self.negative_depth -= 1;
9227
9228            let negated = self.ctx.exprs.alloc(LogicExpr::UnaryOp {
9229                op: TokenType::Not,
9230                operand: inner_existential,
9231            });
9232
9233            let body = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
9234                left: subject_pred,
9235                op: TokenType::If,
9236                right: negated,
9237            });
9238
9239            return Ok(self.ctx.exprs.alloc(LogicExpr::Quantifier {
9240                kind: crate::ast::QuantifierKind::Universal,
9241                variable: var_name,
9242                body,
9243                island_id: self.current_island,
9244            }));
9245        }
9246
9247        let verb_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
9248            name: verb,
9249            args: self.ctx.terms.alloc_slice([Term::Variable(var_name)]),
9250            world: None,
9251        });
9252
9253        self.negative_depth -= 1;
9254
9255        let negated_verb = self.ctx.exprs.alloc(LogicExpr::UnaryOp {
9256            op: TokenType::Not,
9257            operand: verb_pred,
9258        });
9259
9260        let body = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
9261            left: subject_pred,
9262            op: TokenType::If,
9263            right: negated_verb,
9264        });
9265
9266        Ok(self.ctx.exprs.alloc(LogicExpr::Quantifier {
9267            kind: crate::ast::QuantifierKind::Universal,
9268            variable: var_name,
9269            body,
9270            island_id: self.current_island,
9271        }))
9272    }
9273
9274    fn parse_temporal_npi(&mut self) -> ParseResult<&'a LogicExpr<'a>> {
9275        let npi_token = self.advance().kind.clone();
9276        let is_never = matches!(npi_token, TokenType::Never);
9277
9278        let subject = self.parse_noun_phrase(true)?;
9279
9280        if is_never {
9281            self.negative_depth += 1;
9282        }
9283
9284        let verb = self.consume_verb();
9285        let verb_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
9286            name: verb,
9287            args: self.ctx.terms.alloc_slice([Term::Constant(subject.noun)]),
9288            world: None,
9289        });
9290
9291        if is_never {
9292            self.negative_depth -= 1;
9293            Ok(self.ctx.exprs.alloc(LogicExpr::UnaryOp {
9294                op: TokenType::Not,
9295                operand: verb_pred,
9296            }))
9297        } else {
9298            Ok(verb_pred)
9299        }
9300    }
9301
9302    fn check(&self, kind: &TokenType) -> bool {
9303        if self.is_at_end() {
9304            return false;
9305        }
9306        std::mem::discriminant(&self.peek().kind) == std::mem::discriminant(kind)
9307    }
9308
9309    fn check_any(&self, kinds: &[TokenType]) -> bool {
9310        if self.is_at_end() {
9311            return false;
9312        }
9313        let current = std::mem::discriminant(&self.peek().kind);
9314        kinds.iter().any(|k| std::mem::discriminant(k) == current)
9315    }
9316
9317    fn check_article(&self) -> bool {
9318        matches!(self.peek().kind, TokenType::Article(_))
9319    }
9320
9321    fn advance(&mut self) -> &Token {
9322        if !self.is_at_end() {
9323            self.current += 1;
9324        }
9325        self.previous()
9326    }
9327
9328    fn is_at_end(&self) -> bool {
9329        self.peek().kind == TokenType::EOF
9330    }
9331
9332    fn peek(&self) -> &Token {
9333        &self.tokens[self.current]
9334    }
9335
9336    /// Phase 35: Check if the next token (after current) is a string literal.
9337    /// Used to distinguish causal `because` from Trust's `because "reason"`.
9338    fn peek_next_is_string_literal(&self) -> bool {
9339        self.tokens.get(self.current + 1)
9340            .map(|t| matches!(t.kind, TokenType::StringLiteral(_)))
9341            .unwrap_or(false)
9342    }
9343
9344    fn previous(&self) -> &Token {
9345        &self.tokens[self.current - 1]
9346    }
9347
9348    fn current_span(&self) -> crate::token::Span {
9349        self.peek().span
9350    }
9351
9352    fn consume(&mut self, kind: TokenType) -> ParseResult<&Token> {
9353        if self.check(&kind) {
9354            Ok(self.advance())
9355        } else {
9356            Err(ParseError {
9357                kind: ParseErrorKind::UnexpectedToken {
9358                    expected: kind,
9359                    found: self.peek().kind.clone(),
9360                },
9361                span: self.current_span(),
9362            })
9363        }
9364    }
9365
9366    fn consume_content_word(&mut self) -> ParseResult<Symbol> {
9367        let t = self.advance().clone();
9368        match t.kind {
9369            TokenType::Noun(s) | TokenType::Adjective(s) | TokenType::NonIntersectiveAdjective(s) => Ok(s),
9370            // Phase 35: Allow single-letter articles (a, an) to be used as variable names
9371            TokenType::Article(_) => Ok(t.lexeme),
9372            // Phase 35: Allow numeric literals as content words (e.g., "equal to 42")
9373            TokenType::Number(s) => Ok(s),
9374            TokenType::ProperName(s) => {
9375                // In imperative mode, proper names are variable references that must be defined
9376                if self.mode == ParserMode::Imperative {
9377                    if !self.drs.has_referent_by_variable(s) {
9378                        return Err(ParseError {
9379                            kind: ParseErrorKind::UndefinedVariable {
9380                                name: self.interner.resolve(s).to_string()
9381                            },
9382                            span: t.span,
9383                        });
9384                    }
9385                    return Ok(s);
9386                }
9387
9388                // Declarative mode: auto-register proper names as entities
9389                let s_str = self.interner.resolve(s);
9390                let gender = Self::infer_gender(s_str);
9391
9392                // Register in DRS for cross-sentence anaphora resolution
9393                self.drs.introduce_proper_name(s, s, gender);
9394
9395                Ok(s)
9396            }
9397            TokenType::Verb { lemma, .. } => Ok(lemma),
9398            TokenType::Ambiguous { primary, .. } => {
9399                match *primary {
9400                    TokenType::Noun(s) | TokenType::Adjective(s) | TokenType::NonIntersectiveAdjective(s) => Ok(s),
9401                    TokenType::Verb { lemma, .. } => Ok(lemma),
9402                    TokenType::ProperName(s) => {
9403                        // In imperative mode, proper names must be defined
9404                        if self.mode == ParserMode::Imperative {
9405                            if !self.drs.has_referent_by_variable(s) {
9406                                return Err(ParseError {
9407                                    kind: ParseErrorKind::UndefinedVariable {
9408                                        name: self.interner.resolve(s).to_string()
9409                                    },
9410                                    span: t.span,
9411                                });
9412                            }
9413                            return Ok(s);
9414                        }
9415                        // Register proper name in DRS for ambiguous tokens too
9416                        let s_str = self.interner.resolve(s);
9417                        let gender = Self::infer_gender(s_str);
9418                        self.drs.introduce_proper_name(s, s, gender);
9419                        Ok(s)
9420                    }
9421                    _ => Err(ParseError {
9422                        kind: ParseErrorKind::ExpectedContentWord { found: *primary },
9423                        span: self.current_span(),
9424                    }),
9425                }
9426            }
9427            other => Err(ParseError {
9428                kind: ParseErrorKind::ExpectedContentWord { found: other },
9429                span: self.current_span(),
9430            }),
9431        }
9432    }
9433
9434    fn consume_copula(&mut self) -> ParseResult<()> {
9435        if self.match_token(&[TokenType::Is, TokenType::Are, TokenType::Was, TokenType::Were]) {
9436            Ok(())
9437        } else {
9438            Err(ParseError {
9439                kind: ParseErrorKind::ExpectedCopula,
9440                span: self.current_span(),
9441            })
9442        }
9443    }
9444
9445    fn check_comparative(&self) -> bool {
9446        matches!(self.peek().kind, TokenType::Comparative(_))
9447    }
9448
9449    fn is_contact_clause_pattern(&self) -> bool {
9450        // Detect "The cat [the dog chased] ran" pattern
9451        // Also handles nested: "The rat [the cat [the dog chased] ate] died"
9452        let mut pos = self.current;
9453
9454        // Skip the article we're at
9455        if pos < self.tokens.len() && matches!(self.tokens[pos].kind, TokenType::Article(_)) {
9456            pos += 1;
9457        } else {
9458            return false;
9459        }
9460
9461        // Skip adjectives
9462        while pos < self.tokens.len() && matches!(self.tokens[pos].kind, TokenType::Adjective(_)) {
9463            pos += 1;
9464        }
9465
9466        // Must have noun/proper name (embedded subject)
9467        if pos < self.tokens.len() && matches!(self.tokens[pos].kind, TokenType::Noun(_) | TokenType::ProperName(_) | TokenType::Adjective(_)) {
9468            pos += 1;
9469        } else {
9470            return false;
9471        }
9472
9473        // Must have verb OR another article (nested contact clause) after
9474        pos < self.tokens.len() && matches!(self.tokens[pos].kind, TokenType::Verb { .. } | TokenType::Article(_))
9475    }
9476
9477    fn check_superlative(&self) -> bool {
9478        matches!(self.peek().kind, TokenType::Superlative(_))
9479    }
9480
9481    fn check_scopal_adverb(&self) -> bool {
9482        matches!(self.peek().kind, TokenType::ScopalAdverb(_))
9483    }
9484
9485    fn check_temporal_adverb(&self) -> bool {
9486        matches!(self.peek().kind, TokenType::TemporalAdverb(_))
9487    }
9488
9489    fn check_non_intersective_adjective(&self) -> bool {
9490        matches!(self.peek().kind, TokenType::NonIntersectiveAdjective(_))
9491    }
9492
9493    fn check_focus(&self) -> bool {
9494        matches!(self.peek().kind, TokenType::Focus(_))
9495    }
9496
9497    fn check_measure(&self) -> bool {
9498        matches!(self.peek().kind, TokenType::Measure(_))
9499    }
9500
9501    fn check_presup_trigger(&self) -> bool {
9502        match &self.peek().kind {
9503            TokenType::PresupTrigger(_) => true,
9504            TokenType::Verb { lemma, .. } => {
9505                let s = self.interner.resolve(*lemma).to_lowercase();
9506                crate::lexicon::lookup_presup_trigger(&s).is_some()
9507            }
9508            _ => false,
9509        }
9510    }
9511
9512    fn is_followed_by_np_object(&self) -> bool {
9513        if self.current + 1 >= self.tokens.len() {
9514            return false;
9515        }
9516        let next = &self.tokens[self.current + 1].kind;
9517        matches!(next,
9518            TokenType::ProperName(_) |
9519            TokenType::Article(_) |
9520            TokenType::Noun(_) |
9521            TokenType::Pronoun { .. } |
9522            TokenType::Reflexive |
9523            TokenType::Who |
9524            TokenType::What |
9525            TokenType::Where |
9526            TokenType::When |
9527            TokenType::Why
9528        )
9529    }
9530
9531    fn is_followed_by_gerund(&self) -> bool {
9532        if self.current + 1 >= self.tokens.len() {
9533            return false;
9534        }
9535        matches!(self.tokens[self.current + 1].kind, TokenType::Verb { .. })
9536    }
9537
9538    // =========================================================================
9539    // Phase 46: Agent System Parsing
9540    // =========================================================================
9541
9542    /// Parse spawn statement: "Spawn a Worker called 'w1'."
9543    fn parse_spawn_statement(&mut self) -> ParseResult<Stmt<'a>> {
9544        self.advance(); // consume "Spawn"
9545
9546        // Expect article (a/an)
9547        if !self.check_article() {
9548            return Err(ParseError {
9549                kind: ParseErrorKind::ExpectedKeyword { keyword: "a/an".to_string() },
9550                span: self.current_span(),
9551            });
9552        }
9553        self.advance(); // consume article
9554
9555        // Get agent type name (Noun or ProperName)
9556        let agent_type = match &self.tokens[self.current].kind {
9557            TokenType::Noun(sym) | TokenType::ProperName(sym) => {
9558                let s = *sym;
9559                self.advance();
9560                s
9561            }
9562            _ => {
9563                return Err(ParseError {
9564                    kind: ParseErrorKind::ExpectedKeyword { keyword: "agent type".to_string() },
9565                    span: self.current_span(),
9566                });
9567            }
9568        };
9569
9570        // Expect "called"
9571        if !self.check(&TokenType::Called) {
9572            return Err(ParseError {
9573                kind: ParseErrorKind::ExpectedKeyword { keyword: "called".to_string() },
9574                span: self.current_span(),
9575            });
9576        }
9577        self.advance(); // consume "called"
9578
9579        // Get agent name (string literal)
9580        let name = if let TokenType::StringLiteral(sym) = &self.tokens[self.current].kind {
9581            let s = *sym;
9582            self.advance();
9583            s
9584        } else {
9585            return Err(ParseError {
9586                kind: ParseErrorKind::ExpectedKeyword { keyword: "agent name".to_string() },
9587                span: self.current_span(),
9588            });
9589        };
9590
9591        Ok(Stmt::Spawn { agent_type, name })
9592    }
9593
9594    /// Parse send statement: "Send Ping to 'agent'."
9595    fn parse_send_statement(&mut self) -> ParseResult<Stmt<'a>> {
9596        self.advance(); // consume "Send"
9597
9598        // Parse message expression
9599        let message = self.parse_imperative_expr()?;
9600
9601        // Expect "to"
9602        if !self.check_preposition_is("to") {
9603            return Err(ParseError {
9604                kind: ParseErrorKind::ExpectedKeyword { keyword: "to".to_string() },
9605                span: self.current_span(),
9606            });
9607        }
9608        self.advance(); // consume "to"
9609
9610        // Parse destination expression
9611        let destination = self.parse_imperative_expr()?;
9612
9613        Ok(Stmt::SendMessage { message, destination })
9614    }
9615
9616    /// Parse await statement: "Await response from 'agent' into result."
9617    fn parse_await_statement(&mut self) -> ParseResult<Stmt<'a>> {
9618        self.advance(); // consume "Await"
9619
9620        // Skip optional "response" word
9621        if self.check_word("response") {
9622            self.advance();
9623        }
9624
9625        // Expect "from" (can be keyword or preposition)
9626        if !self.check(&TokenType::From) && !self.check_preposition_is("from") {
9627            return Err(ParseError {
9628                kind: ParseErrorKind::ExpectedKeyword { keyword: "from".to_string() },
9629                span: self.current_span(),
9630            });
9631        }
9632        self.advance(); // consume "from"
9633
9634        // Parse source expression
9635        let source = self.parse_imperative_expr()?;
9636
9637        // Expect "into"
9638        if !self.check_word("into") {
9639            return Err(ParseError {
9640                kind: ParseErrorKind::ExpectedKeyword { keyword: "into".to_string() },
9641                span: self.current_span(),
9642            });
9643        }
9644        self.advance(); // consume "into"
9645
9646        // Get variable name (Noun, ProperName, or Adjective - can be any content word)
9647        let into = match &self.tokens[self.current].kind {
9648            TokenType::Noun(sym) | TokenType::ProperName(sym) | TokenType::Adjective(sym) => {
9649                let s = *sym;
9650                self.advance();
9651                s
9652            }
9653            // Also accept lexemes from other token types if they look like identifiers
9654            _ if self.check_content_word() => {
9655                let sym = self.tokens[self.current].lexeme;
9656                self.advance();
9657                sym
9658            }
9659            _ => {
9660                return Err(ParseError {
9661                    kind: ParseErrorKind::ExpectedKeyword { keyword: "variable name".to_string() },
9662                    span: self.current_span(),
9663                });
9664            }
9665        };
9666
9667        Ok(Stmt::AwaitMessage { source, into })
9668    }
9669
9670    // =========================================================================
9671    // Phase 49: CRDT Statement Parsing
9672    // =========================================================================
9673
9674    /// Parse merge statement: "Merge remote into local." or "Merge remote's field into local's field."
9675    fn parse_merge_statement(&mut self) -> ParseResult<Stmt<'a>> {
9676        self.advance(); // consume "Merge"
9677
9678        // Parse source expression
9679        let source = self.parse_imperative_expr()?;
9680
9681        // Expect "into"
9682        if !self.check_word("into") {
9683            return Err(ParseError {
9684                kind: ParseErrorKind::ExpectedKeyword { keyword: "into".to_string() },
9685                span: self.current_span(),
9686            });
9687        }
9688        self.advance(); // consume "into"
9689
9690        // Parse target expression
9691        let target = self.parse_imperative_expr()?;
9692
9693        Ok(Stmt::MergeCrdt { source, target })
9694    }
9695
9696    /// Parse increase statement: "Increase local's points by 10."
9697    fn parse_increase_statement(&mut self) -> ParseResult<Stmt<'a>> {
9698        self.advance(); // consume "Increase"
9699
9700        // Parse object with field access (e.g., "local's points")
9701        let expr = self.parse_imperative_expr()?;
9702
9703        // Must be a field access
9704        let (object, field) = if let Expr::FieldAccess { object, field } = expr {
9705            (object, field)
9706        } else {
9707            return Err(ParseError {
9708                kind: ParseErrorKind::ExpectedKeyword { keyword: "field access (e.g., 'x's count')".to_string() },
9709                span: self.current_span(),
9710            });
9711        };
9712
9713        // Expect "by"
9714        if !self.check_preposition_is("by") {
9715            return Err(ParseError {
9716                kind: ParseErrorKind::ExpectedKeyword { keyword: "by".to_string() },
9717                span: self.current_span(),
9718            });
9719        }
9720        self.advance(); // consume "by"
9721
9722        // Parse amount
9723        let amount = self.parse_imperative_expr()?;
9724
9725        Ok(Stmt::IncreaseCrdt { object, field: *field, amount })
9726    }
9727
9728    /// Parse decrease statement: "Decrease game's score by 5."
9729    fn parse_decrease_statement(&mut self) -> ParseResult<Stmt<'a>> {
9730        self.advance(); // consume "Decrease"
9731
9732        // Parse object with field access (e.g., "game's score")
9733        let expr = self.parse_imperative_expr()?;
9734
9735        // Must be a field access
9736        let (object, field) = if let Expr::FieldAccess { object, field } = expr {
9737            (object, field)
9738        } else {
9739            return Err(ParseError {
9740                kind: ParseErrorKind::ExpectedKeyword { keyword: "field access (e.g., 'x's count')".to_string() },
9741                span: self.current_span(),
9742            });
9743        };
9744
9745        // Expect "by"
9746        if !self.check_preposition_is("by") {
9747            return Err(ParseError {
9748                kind: ParseErrorKind::ExpectedKeyword { keyword: "by".to_string() },
9749                span: self.current_span(),
9750            });
9751        }
9752        self.advance(); // consume "by"
9753
9754        // Parse amount
9755        let amount = self.parse_imperative_expr()?;
9756
9757        Ok(Stmt::DecreaseCrdt { object, field: *field, amount })
9758    }
9759
9760    /// Parse append statement: "Append value to sequence."
9761    fn parse_append_statement(&mut self) -> ParseResult<Stmt<'a>> {
9762        self.advance(); // consume "Append"
9763
9764        // Parse value to append
9765        let value = self.parse_imperative_expr()?;
9766
9767        // Expect "to" (can be TokenType::To or a preposition)
9768        if !self.check(&TokenType::To) && !self.check_preposition_is("to") {
9769            return Err(ParseError {
9770                kind: ParseErrorKind::ExpectedKeyword { keyword: "to".to_string() },
9771                span: self.current_span(),
9772            });
9773        }
9774        self.advance(); // consume "to"
9775
9776        // Parse sequence expression
9777        let sequence = self.parse_imperative_expr()?;
9778
9779        Ok(Stmt::AppendToSequence { sequence, value })
9780    }
9781
9782    /// Parse resolve statement: "Resolve page's title to value."
9783    fn parse_resolve_statement(&mut self) -> ParseResult<Stmt<'a>> {
9784        self.advance(); // consume "Resolve"
9785
9786        // Parse object with field access (e.g., "page's title")
9787        let expr = self.parse_imperative_expr()?;
9788
9789        // Must be a field access
9790        let (object, field) = if let Expr::FieldAccess { object, field } = expr {
9791            (object, field)
9792        } else {
9793            return Err(ParseError {
9794                kind: ParseErrorKind::ExpectedKeyword { keyword: "field access (e.g., 'x's title')".to_string() },
9795                span: self.current_span(),
9796            });
9797        };
9798
9799        // Expect "to" (can be TokenType::To or a preposition)
9800        if !self.check(&TokenType::To) && !self.check_preposition_is("to") {
9801            return Err(ParseError {
9802                kind: ParseErrorKind::ExpectedKeyword { keyword: "to".to_string() },
9803                span: self.current_span(),
9804            });
9805        }
9806        self.advance(); // consume "to"
9807
9808        // Parse value
9809        let value = self.parse_imperative_expr()?;
9810
9811        Ok(Stmt::ResolveConflict { object, field: *field, value })
9812    }
9813
9814}
9815