Skip to main content

logicaffeine_language/parser/
mod.rs

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