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