Skip to main content

logicaffeine_language/parser/
mod.rs

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