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