Skip to main content

logicaffeine_language/parser/
mod.rs

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