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