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