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