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