1mod 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, CompressionCodec, SendLayout, LogicExpr, NeoEventData, NumberKind, QuantifierKind, TemporalOperator, Term, ThematicRole, Stmt, Expr, Literal, TypeExpr, BinaryOpKind, MatchArm};
77use crate::optimization::{by_keyword, pin_from_str, OptimizationConfig, PinSet};
78use crate::ast::stmt::{ReadSource, Pattern};
79use std::collections::HashSet;
80use crate::drs::{Case, Gender, Number, ReferentSource};
81use crate::drs::{Drs, BoxType, WorldState};
82use crate::error::{ParseError, ParseErrorKind};
83use logicaffeine_base::{Interner, Symbol, SymbolEq};
84use crate::lexer::Lexer;
85use crate::lexicon::{self, Aspect, Definiteness, Time, VerbClass};
86use crate::token::{BlockType, FocusKind, Span, Token, TokenType};
87
88pub(super) type ParseResult<T> = Result<T, ParseError>;
89
90use std::ops::{Deref, DerefMut};
91
92#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
94pub enum ParserMode {
95 #[default]
97 Declarative,
98 Imperative,
100}
101
102#[derive(Debug, Clone, Copy)]
104pub(super) enum CopulaTemporal {
105 Always,
106 Never,
107 Eventually,
108}
109
110#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
115pub enum NegativeScopeMode {
116 #[default]
119 Narrow,
120 Wide,
123}
124
125#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
133pub enum ModalPreference {
134 #[default]
136 Default,
137 Epistemic,
139 Deontic,
141}
142
143#[derive(Debug, Clone, Copy)]
148pub enum ResolvedPronoun {
149 Variable(Symbol),
151 Constant(Symbol),
153}
154
155#[derive(Clone)]
156struct ParserCheckpoint {
157 pos: usize,
158 var_counter: usize,
159 bindings_len: usize,
160 island: u32,
161 time: Option<Time>,
162 negative_depth: u32,
163}
164
165pub struct ParserGuard<'p, 'a, 'ctx, 'int> {
198 parser: &'p mut Parser<'a, 'ctx, 'int>,
199 checkpoint: ParserCheckpoint,
200 committed: bool,
201}
202
203impl<'p, 'a, 'ctx, 'int> ParserGuard<'p, 'a, 'ctx, 'int> {
204 pub fn commit(mut self) {
206 self.committed = true;
207 }
208}
209
210impl<'p, 'a, 'ctx, 'int> Drop for ParserGuard<'p, 'a, 'ctx, 'int> {
211 fn drop(&mut self) {
212 if !self.committed {
213 self.parser.restore(self.checkpoint.clone());
214 }
215 }
216}
217
218impl<'p, 'a, 'ctx, 'int> Deref for ParserGuard<'p, 'a, 'ctx, 'int> {
219 type Target = Parser<'a, 'ctx, 'int>;
220 fn deref(&self) -> &Self::Target {
221 self.parser
222 }
223}
224
225impl<'p, 'a, 'ctx, 'int> DerefMut for ParserGuard<'p, 'a, 'ctx, 'int> {
226 fn deref_mut(&mut self) -> &mut Self::Target {
227 self.parser
228 }
229}
230
231#[derive(Clone, Debug)]
236pub struct EventTemplate<'a> {
237 pub verb: Symbol,
239 pub agent: Option<Term<'a>>,
242 pub non_agent_roles: Vec<(ThematicRole, Term<'a>)>,
244 pub modifiers: Vec<Symbol>,
246}
247
248pub struct Parser<'a, 'ctx, 'int> {
265 pub(super) tokens: Vec<Token>,
267 pub(super) current: usize,
269 pub(super) program_opt_flags: OptimizationConfig,
273 pub(super) program_tier_pins: PinSet,
277 pub(super) var_counter: usize,
279 pub(super) user_bound: std::collections::HashSet<Symbol>,
284 pub(super) pending_time: Option<Time>,
286 pub(super) donkey_bindings: Vec<(Symbol, Symbol, bool, bool)>,
288 pub(super) interner: &'int mut Interner,
290 pub(super) ctx: AstContext<'a>,
292 pub(super) current_island: u32,
294 pub(super) pp_attach_to_noun: bool,
296 pub(super) filler_gap: Option<Symbol>,
298 pub(super) negative_depth: u32,
300 pub(super) discourse_event_var: Option<Symbol>,
302 pub(super) last_event_template: Option<EventTemplate<'a>>,
304 pub(super) pragmatic: bool,
309 pub(super) noun_priority_mode: bool,
311 pub(super) collective_mode: bool,
313 pub(super) distributive_marker: bool,
317 pub(super) pending_cardinal: Option<u32>,
319 pub(super) mode: ParserMode,
321 pub(super) type_registry: Option<TypeRegistry>,
323 pub(super) event_reading_mode: bool,
325 pub(super) drs: Drs,
327 pub(super) negative_scope_mode: NegativeScopeMode,
329 pub(super) modal_preference: ModalPreference,
331 pub(super) world_state: &'ctx mut WorldState,
333 pub(super) in_negative_quantifier: bool,
335 pub(super) pending_partitive: Option<(u32, &'a LogicExpr<'a>, Symbol)>,
340 pub(super) pending_subject_restriction: Option<(Symbol, &'a LogicExpr<'a>)>,
348 pub(super) nominal_np_context: bool,
358 pub(super) contracts: std::collections::HashMap<String, (i64, i64)>,
363 pub(super) stmt_spans: Vec<Span>,
368 pub(super) recursion_depth: usize,
374}
375
376impl<'a, 'ctx, 'int> Parser<'a, 'ctx, 'int> {
377 pub fn new(
381 mut tokens: Vec<Token>,
382 world_state: &'ctx mut WorldState,
383 interner: &'int mut Interner,
384 ctx: AstContext<'a>,
385 types: TypeRegistry,
386 ) -> Self {
387 if !matches!(tokens.last().map(|t| &t.kind), Some(TokenType::EOF)) {
392 let end = tokens.last().map(|t| t.span.end).unwrap_or(0);
393 let empty = interner.intern("");
394 tokens.push(Token::new(TokenType::EOF, empty, Span::new(end, end)));
395 }
396 Parser {
397 tokens,
398 current: 0,
399 contracts: std::collections::HashMap::new(),
400 program_opt_flags: OptimizationConfig::all_on(),
401 program_tier_pins: PinSet::none(),
402 var_counter: 0,
403 user_bound: std::collections::HashSet::new(),
404 pending_time: None,
405 donkey_bindings: Vec::new(),
406 interner,
407 ctx,
408 current_island: 0,
409 pp_attach_to_noun: false,
410 filler_gap: None,
411 negative_depth: 0,
412 discourse_event_var: None,
413 last_event_template: None,
414 pragmatic: false,
415 noun_priority_mode: false,
416 collective_mode: false,
417 distributive_marker: false,
418 pending_cardinal: None,
419 mode: ParserMode::Declarative,
420 type_registry: Some(types),
421 event_reading_mode: false,
422 drs: Drs::new(), negative_scope_mode: NegativeScopeMode::default(),
424 modal_preference: ModalPreference::default(),
425 pending_subject_restriction: None,
426 nominal_np_context: false,
427 world_state,
428 in_negative_quantifier: false,
429 pending_partitive: None,
430 stmt_spans: Vec::new(),
431 recursion_depth: 0,
432 }
433 }
434
435 pub fn stmt_spans(&self) -> &[Span] {
438 &self.stmt_spans
439 }
440
441 fn record_stmt_span(&mut self, start_tok: usize) {
445 let start = self
446 .tokens
447 .get(start_tok)
448 .map(|t| t.span.start)
449 .unwrap_or(0);
450 let end = self
451 .tokens
452 .get(self.current.saturating_sub(1))
453 .map(|t| t.span.end)
454 .unwrap_or(start);
455 self.stmt_spans.push(Span::new(start, end));
456 }
457
458 pub fn set_discourse_event_var(&mut self, var: Symbol) {
459 self.discourse_event_var = Some(var);
460 }
461
462 pub fn drs_mut(&mut self) -> &mut Drs {
464 &mut self.world_state.drs
465 }
466
467 pub fn drs_ref(&self) -> &Drs {
469 &self.world_state.drs
470 }
471
472 pub fn swap_drs_with_world_state(&mut self) {
476 std::mem::swap(&mut self.drs, &mut self.world_state.drs);
477 }
478
479 pub fn has_world_state(&self) -> bool {
481 true
482 }
483
484 pub fn mode(&self) -> ParserMode {
485 self.mode
486 }
487
488 pub fn is_known_type(&self, sym: Symbol) -> bool {
491 self.type_registry
492 .as_ref()
493 .map(|r| r.is_type(sym))
494 .unwrap_or(false)
495 }
496
497 pub fn is_generic_type(&self, sym: Symbol) -> bool {
500 self.type_registry
501 .as_ref()
502 .map(|r| r.is_generic(sym))
503 .unwrap_or(false)
504 }
505
506 fn get_generic_param_count(&self, sym: Symbol) -> Option<usize> {
508 use crate::analysis::TypeDef;
509 self.type_registry.as_ref().and_then(|r| {
510 match r.get(sym) {
511 Some(TypeDef::Generic { param_count }) => Some(*param_count),
512 _ => None,
513 }
514 })
515 }
516
517 fn find_variant(&self, sym: Symbol) -> Option<Symbol> {
519 self.type_registry
520 .as_ref()
521 .and_then(|r| r.find_variant(sym).map(|(enum_name, _)| enum_name))
522 }
523
524 fn consume_type_name(&mut self) -> ParseResult<Symbol> {
526 let t = self.advance().clone();
527 match t.kind {
528 TokenType::Noun(s) | TokenType::Adjective(s) => Ok(s),
529 TokenType::ProperName(s) => Ok(s),
530 TokenType::Verb { .. } => Ok(t.lexeme),
532 TokenType::Tally => Ok(self.interner.intern("Tally")),
534 TokenType::SharedSet => Ok(self.interner.intern("SharedSet")),
535 TokenType::SharedSequence => Ok(self.interner.intern("SharedSequence")),
536 TokenType::CollaborativeSequence => Ok(self.interner.intern("CollaborativeSequence")),
537 TokenType::SharedMap => Ok(self.interner.intern("SharedMap")),
538 TokenType::Divergent => Ok(self.interner.intern("Divergent")),
539 TokenType::Article(_) => Ok(t.lexeme),
541 other => Err(ParseError {
542 kind: ParseErrorKind::ExpectedContentWord { found: other },
543 span: self.current_span(),
544 }),
545 }
546 }
547
548 fn parse_type_expression(&mut self) -> ParseResult<TypeExpr<'a>> {
553 use noun::NounParsing;
554
555 if self.check_word("fn") {
557 if let Some(next) = self.tokens.get(self.current + 1) {
558 if matches!(next.kind, TokenType::LParen) {
559 self.advance(); self.advance(); let mut inputs = Vec::new();
564 if !self.check(&TokenType::RParen) {
565 inputs.push(self.parse_type_expression()?);
566 while self.check(&TokenType::Comma) {
567 self.advance(); inputs.push(self.parse_type_expression()?);
569 }
570 }
571
572 if !self.check(&TokenType::RParen) {
573 return Err(ParseError {
574 kind: ParseErrorKind::ExpectedKeyword { keyword: ")".to_string() },
575 span: self.current_span(),
576 });
577 }
578 self.advance(); if !self.check(&TokenType::Arrow) {
582 return Err(ParseError {
583 kind: ParseErrorKind::ExpectedKeyword { keyword: "->".to_string() },
584 span: self.current_span(),
585 });
586 }
587 self.advance(); let output = self.parse_type_expression()?;
590 let output_ref = self.ctx.alloc_type_expr(output);
591 let inputs_ref = self.ctx.alloc_type_exprs(inputs);
592 return Ok(TypeExpr::Function { inputs: inputs_ref, output: output_ref });
593 }
594 }
595 }
596
597 if self.check(&TokenType::LParen) {
599 self.advance(); let inner = self.parse_type_expression()?;
601 if !self.check(&TokenType::RParen) {
602 return Err(ParseError {
603 kind: ParseErrorKind::ExpectedKeyword { keyword: ")".to_string() },
604 span: self.current_span(),
605 });
606 }
607 self.advance(); return Ok(inner);
609 }
610
611 if self.check(&TokenType::Persistent) {
613 self.advance(); let inner = self.parse_type_expression()?;
615 let inner_ref = self.ctx.alloc_type_expr(inner);
616 return Ok(TypeExpr::Persistent { inner: inner_ref });
617 }
618
619 let mut base = self.consume_type_name()?;
621
622 let base_name = self.interner.resolve(base);
624 if base_name == "SharedSet" || base_name == "ORSet" {
625 if self.check(&TokenType::LParen) {
626 self.advance(); if self.check(&TokenType::RemoveWins) {
628 self.advance(); base = self.interner.intern("SharedSet_RemoveWins");
630 } else if self.check(&TokenType::AddWins) {
631 self.advance(); base = self.interner.intern("SharedSet_AddWins");
634 }
635 if !self.check(&TokenType::RParen) {
636 return Err(ParseError {
637 kind: ParseErrorKind::ExpectedKeyword { keyword: ")".to_string() },
638 span: self.current_span(),
639 });
640 }
641 self.advance(); }
643 }
644
645 let base_name = self.interner.resolve(base);
647 if base_name == "SharedSequence" || base_name == "RGA" {
648 if self.check(&TokenType::LParen) {
649 self.advance(); if self.check(&TokenType::YATA) {
651 self.advance(); base = self.interner.intern("SharedSequence_YATA");
653 }
654 if !self.check(&TokenType::RParen) {
655 return Err(ParseError {
656 kind: ParseErrorKind::ExpectedKeyword { keyword: ")".to_string() },
657 span: self.current_span(),
658 });
659 }
660 self.advance(); }
662 }
663
664 let base_type = if self.check(&TokenType::From) {
666 self.advance(); let module_name = self.consume_type_name()?;
668 let module_str = self.interner.resolve(module_name);
669 let base_str = self.interner.resolve(base);
670 let qualified = format!("{}::{}", module_str, base_str);
671 let qualified_sym = self.interner.intern(&qualified);
672 TypeExpr::Named(qualified_sym)
673 } else {
674 let base_name = self.interner.resolve(base);
676 let base_is_quantity = base_name == "Quantity";
680 let param_count = self.get_generic_param_count(base)
681 .or_else(|| match base_name {
682 "Result" => Some(2), "Option" | "Maybe" => Some(1), "Seq" | "List" | "Vec" => Some(1), "Set" | "HashSet" => Some(1), "Map" | "HashMap" => Some(2), "Pair" => Some(2), "Triple" => Some(3), "SharedSet" | "ORSet" | "SharedSet_AddWins" | "SharedSet_RemoveWins" => Some(1),
692 "SharedSequence" | "RGA" | "SharedSequence_YATA" | "CollaborativeSequence" => Some(1),
693 "SharedMap" | "ORMap" => Some(2), "Divergent" | "MVRegister" => Some(1), _ => None,
696 });
697
698 if let Some(count) = param_count {
700 let has_preposition = self.check_of_preposition() || self.check_preposition_is("from");
701 let maybe_direct = !has_preposition && base_name == "Maybe" && matches!(
703 self.peek().kind,
704 TokenType::Noun(_) | TokenType::Adjective(_) | TokenType::ProperName(_) | TokenType::Verb { .. }
705 );
706 if has_preposition || maybe_direct {
707 if has_preposition {
708 self.advance(); }
710
711 let mut params = Vec::new();
712 for i in 0..count {
713 if i > 0 {
714 if self.check(&TokenType::And) || self.check_to_preposition() || self.check(&TokenType::Comma) {
716 self.advance();
717 }
718 }
719 let param = if base_is_quantity {
723 let dim_sym = self.peek().lexeme;
724 self.advance();
725 TypeExpr::Named(dim_sym)
726 } else {
727 self.parse_type_expression()?
728 };
729 params.push(param);
730 }
731
732 let params_slice = self.ctx.alloc_type_exprs(params);
733 TypeExpr::Generic { base, params: params_slice }
734 } else {
735 let is_primitive = self.type_registry.as_ref().map(|r| r.is_type(base)).unwrap_or(false)
737 || matches!(
738 base_name,
739 "Int" | "Nat" | "Text" | "Bool" | "Boolean" | "Real" | "Unit"
740 | "Word8" | "Word16" | "Word32" | "Word64" | "Lanes8Word32"
741 | "Lanes4Word32" | "Lanes16Word8" | "Lanes4Word64" | "Lanes16Word16"
742 );
743 if is_primitive {
744 TypeExpr::Primitive(base)
745 } else {
746 TypeExpr::Named(base)
747 }
748 }
749 } else {
750 let is_primitive = self.type_registry.as_ref().map(|r| r.is_type(base)).unwrap_or(false)
752 || matches!(
753 base_name,
754 "Int" | "Nat" | "Text" | "Bool" | "Boolean" | "Real" | "Unit"
755 | "Word8" | "Word16" | "Word32" | "Word64" | "Lanes8Word32"
756 | "Lanes4Word32" | "Lanes16Word8" | "Lanes4Word64" | "Lanes16Word16"
757 );
758 if is_primitive {
759 TypeExpr::Primitive(base)
760 } else {
761 TypeExpr::Named(base)
763 }
764 }
765 };
766
767 if self.check(&TokenType::Where) {
769 self.advance(); let predicate_expr = self.parse_condition()?;
773
774 let bound_var = self.extract_bound_var(&predicate_expr)
776 .unwrap_or_else(|| self.interner.intern("it"));
777
778 let predicate = self.expr_to_logic_predicate(&predicate_expr, bound_var)
780 .ok_or_else(|| ParseError {
781 kind: ParseErrorKind::InvalidRefinementPredicate,
782 span: self.peek().span,
783 })?;
784
785 let base_alloc = self.ctx.alloc_type_expr(base_type);
787
788 return Ok(TypeExpr::Refinement { base: base_alloc, var: bound_var, predicate });
789 }
790
791 Ok(base_type)
792 }
793
794 fn extract_bound_var(&self, expr: &Expr<'a>) -> Option<Symbol> {
796 match expr {
797 Expr::Identifier(sym) => Some(*sym),
798 Expr::BinaryOp { left, .. } => self.extract_bound_var(left),
799 _ => None,
800 }
801 }
802
803 fn expr_to_logic_predicate(&mut self, expr: &Expr<'a>, bound_var: Symbol) -> Option<&'a LogicExpr<'a>> {
806 match expr {
807 Expr::BinaryOp { op, left, right } => {
808 let pred_name = match op {
810 BinaryOpKind::Gt => "Greater",
811 BinaryOpKind::Lt => "Less",
812 BinaryOpKind::GtEq => "GreaterEqual",
813 BinaryOpKind::LtEq => "LessEqual",
814 BinaryOpKind::Eq => "Equal",
815 BinaryOpKind::NotEq => "NotEqual",
816 BinaryOpKind::And => {
817 let left_logic = self.expr_to_logic_predicate(left, bound_var)?;
819 let right_logic = self.expr_to_logic_predicate(right, bound_var)?;
820 return Some(self.ctx.exprs.alloc(LogicExpr::BinaryOp {
821 left: left_logic,
822 op: TokenType::And,
823 right: right_logic,
824 }));
825 }
826 BinaryOpKind::Or => {
827 let left_logic = self.expr_to_logic_predicate(left, bound_var)?;
828 let right_logic = self.expr_to_logic_predicate(right, bound_var)?;
829 return Some(self.ctx.exprs.alloc(LogicExpr::BinaryOp {
830 left: left_logic,
831 op: TokenType::Or,
832 right: right_logic,
833 }));
834 }
835 _ => return None, };
837 let pred_sym = self.interner.intern(pred_name);
838
839 let left_term = self.expr_to_term(left)?;
841 let right_term = self.expr_to_term(right)?;
842
843 let args = self.ctx.terms.alloc_slice([left_term, right_term]);
844 Some(self.ctx.exprs.alloc(LogicExpr::Predicate { name: pred_sym, args, world: None }))
845 }
846 _ => None,
847 }
848 }
849
850 fn expr_to_term(&mut self, expr: &Expr<'a>) -> Option<Term<'a>> {
852 match expr {
853 Expr::Identifier(sym) => Some(Term::Variable(*sym)),
854 Expr::Literal(lit) => {
855 match lit {
856 Literal::Number(n) => Some(Term::Value {
857 kind: NumberKind::Integer(*n),
858 unit: None,
859 dimension: None,
860 }),
861 Literal::Boolean(b) => {
862 let sym = self.interner.intern(if *b { "true" } else { "false" });
863 Some(Term::Constant(sym))
864 }
865 _ => None, }
867 }
868 _ => None,
869 }
870 }
871
872 pub fn process_block_headers(&mut self) {
873 use crate::token::BlockType;
874
875 while self.current < self.tokens.len() {
876 if let TokenType::BlockHeader { block_type } = &self.tokens[self.current].kind {
877 self.mode = match block_type {
878 BlockType::Main | BlockType::Function => ParserMode::Imperative,
879 BlockType::Theorem | BlockType::Definition | BlockType::Define | BlockType::Proof |
880 BlockType::Example | BlockType::Logic | BlockType::Note | BlockType::TypeDef |
881 BlockType::Policy | BlockType::Requires | BlockType::Axiom | BlockType::Theory |
882 BlockType::Hardware | BlockType::Property
883 | BlockType::SuspectedTypo { .. } => ParserMode::Declarative,
884 BlockType::No | BlockType::Tier => self.mode, };
886 self.current += 1;
887 } else {
888 break;
889 }
890 }
891 }
892
893 pub fn get_event_var(&mut self) -> Symbol {
894 self.discourse_event_var.unwrap_or_else(|| self.interner.intern("e"))
895 }
896
897 pub fn capture_event_template(&mut self, verb: Symbol, roles: &[(ThematicRole, Term<'a>)], modifiers: &[Symbol]) {
898 let non_agent_roles: Vec<_> = roles.iter()
899 .filter(|(role, _)| *role != ThematicRole::Agent)
900 .cloned()
901 .collect();
902 let agent = roles.iter()
903 .find(|(role, _)| *role == ThematicRole::Agent)
904 .map(|(_, t)| t.clone());
905 self.last_event_template = Some(EventTemplate {
906 verb,
907 agent,
908 non_agent_roles,
909 modifiers: modifiers.to_vec(),
910 });
911 }
912
913 pub(super) fn parse_whose_relative(&mut self, gap_var: Symbol) -> ParseResult<&'a LogicExpr<'a>> {
923 self.advance(); let possessed = self.parse_noun_phrase(false)?;
925 let m = self.next_var_name();
926 let noun_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
927 name: possessed.noun,
928 args: self.ctx.terms.alloc_slice([Term::Variable(m)]),
929 world: None,
930 });
931 let possesses = self.interner.intern("Possesses");
932 let poss_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
933 name: possesses,
934 args: self
935 .ctx
936 .terms
937 .alloc_slice([Term::Variable(gap_var), Term::Variable(m)]),
938 world: None,
939 });
940 let mut body = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
941 left: noun_pred,
942 op: TokenType::And,
943 right: poss_pred,
944 });
945 for &adj in possessed.adjectives {
946 let adj_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
947 name: adj,
948 args: self.ctx.terms.alloc_slice([Term::Variable(m)]),
949 world: None,
950 });
951 body = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
952 left: body,
953 op: TokenType::And,
954 right: adj_pred,
955 });
956 }
957 let vp = self.parse_predicate_with_subject_as_var(m)?;
958 body = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
959 left: body,
960 op: TokenType::And,
961 right: vp,
962 });
963 Ok(self.ctx.exprs.alloc(LogicExpr::Quantifier {
964 kind: QuantifierKind::Existential,
965 variable: m,
966 body,
967 island_id: self.current_island,
968 }))
969 }
970
971 pub(super) fn parse_where_relative(&mut self, gap_var: Symbol) -> ParseResult<&'a LogicExpr<'a>> {
972 self.advance(); let subj_sym = if self.check_pronoun() {
977 let lex = self.interner.resolve(self.peek().lexeme).to_string();
978 self.advance();
979 let mut chars = lex.chars();
980 let cap = match chars.next() {
981 Some(f) => f.to_uppercase().collect::<String>() + chars.as_str(),
982 None => lex,
983 };
984 self.interner.intern(&cap)
985 } else {
986 self.parse_noun_phrase(true)?.noun
987 };
988 let boundary = {
995 let mut found = None;
996 let mut k = self.current;
997 while let Some(tok) = self.tokens.get(k) {
998 match &tok.kind {
999 TokenType::Comma => {
1000 found = Some(k);
1001 break;
1002 }
1003 TokenType::And | TokenType::Or
1004 if matches!(
1005 self.tokens.get(k + 1).map(|t| &t.kind),
1006 Some(TokenType::Article(_))
1007 | Some(TokenType::ProperName(_))
1008 | Some(TokenType::All)
1009 | Some(TokenType::Some)
1010 | Some(TokenType::Any)
1011 | Some(TokenType::No)
1012 | Some(TokenType::Most)
1013 ) =>
1014 {
1015 found = Some(k);
1016 break;
1017 }
1018 TokenType::Period
1019 | TokenType::EOF
1020 | TokenType::Is
1021 | TokenType::Are
1022 | TokenType::Was
1023 | TokenType::Were => break,
1024 _ => k += 1,
1025 }
1026 }
1027 found
1028 };
1029 let saved_boundary = boundary.map(|i| (i, self.tokens[i].clone()));
1030 if let Some(i) = boundary {
1031 let span = self.tokens[i].span;
1032 self.tokens[i] = crate::token::Token::new(
1033 TokenType::Period,
1034 self.interner.intern("."),
1035 span,
1036 );
1037 }
1038 let inner_result = self.parse_predicate_with_subject(subj_sym);
1039 if let Some((i, tok)) = saved_boundary {
1040 self.tokens[i] = tok;
1041 }
1042 let inner = inner_result?;
1043 let ev = self.get_event_var();
1044 let loc = self.interner.intern("In");
1045 let loc_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
1046 name: loc,
1047 args: self
1048 .ctx
1049 .terms
1050 .alloc_slice([Term::Variable(ev), Term::Variable(gap_var)]),
1051 world: None,
1052 });
1053 Ok(self.ctx.exprs.alloc(LogicExpr::BinaryOp {
1054 left: inner,
1055 op: TokenType::And,
1056 right: loc_pred,
1057 }))
1058 }
1059
1060 fn parse_embedded_wh_clause(&mut self) -> ParseResult<&'a LogicExpr<'a>> {
1061 let var_name = self.interner.intern("x");
1063 let var_term = Term::Variable(var_name);
1064
1065 if self.check_verb() {
1066 let verb = self.consume_verb();
1068 let body = self.ctx.exprs.alloc(LogicExpr::Predicate {
1069 name: verb,
1070 args: self.ctx.terms.alloc_slice([var_term]),
1071 world: None,
1072 });
1073 return Ok(body);
1074 }
1075
1076 if self.check_content_word() || self.check_article() {
1077 let subject = self.parse_noun_phrase(true)?;
1079 if self.check_verb() {
1080 let verb = self.consume_verb();
1081 let body = self.ctx.exprs.alloc(LogicExpr::Predicate {
1082 name: verb,
1083 args: self.ctx.terms.alloc_slice([
1084 Term::Constant(subject.noun),
1085 var_term,
1086 ]),
1087 world: None,
1088 });
1089 return Ok(body);
1090 }
1091 }
1092
1093 Ok(self.ctx.exprs.alloc(LogicExpr::Atom(var_name)))
1095 }
1096
1097 pub fn set_pp_attachment_mode(&mut self, attach_to_noun: bool) {
1098 self.pp_attach_to_noun = attach_to_noun;
1099 }
1100
1101 pub fn set_noun_priority_mode(&mut self, mode: bool) {
1102 self.noun_priority_mode = mode;
1103 }
1104
1105 pub fn set_collective_mode(&mut self, mode: bool) {
1106 self.collective_mode = mode;
1107 }
1108
1109 pub fn set_distributive_marker(&mut self, on: bool) {
1113 self.distributive_marker = on;
1114 }
1115
1116 pub fn set_pragmatic_mode(&mut self, on: bool) {
1120 self.pragmatic = on;
1121 }
1122
1123 pub fn set_event_reading_mode(&mut self, mode: bool) {
1124 self.event_reading_mode = mode;
1125 }
1126
1127 pub fn set_negative_scope_mode(&mut self, mode: NegativeScopeMode) {
1128 self.negative_scope_mode = mode;
1129 }
1130
1131 pub fn set_modal_preference(&mut self, pref: ModalPreference) {
1132 self.modal_preference = pref;
1133 }
1134
1135 fn checkpoint(&self) -> ParserCheckpoint {
1136 ParserCheckpoint {
1137 pos: self.current,
1138 var_counter: self.var_counter,
1139 bindings_len: self.donkey_bindings.len(),
1140 island: self.current_island,
1141 time: self.pending_time,
1142 negative_depth: self.negative_depth,
1143 }
1144 }
1145
1146 fn restore(&mut self, cp: ParserCheckpoint) {
1147 self.current = cp.pos;
1148 self.var_counter = cp.var_counter;
1149 self.donkey_bindings.truncate(cp.bindings_len);
1150 self.current_island = cp.island;
1151 self.pending_time = cp.time;
1152 self.negative_depth = cp.negative_depth;
1153 }
1154
1155 fn is_negative_context(&self) -> bool {
1156 self.negative_depth % 2 == 1
1157 }
1158
1159 pub fn guard(&mut self) -> ParserGuard<'_, 'a, 'ctx, 'int> {
1160 ParserGuard {
1161 checkpoint: self.checkpoint(),
1162 parser: self,
1163 committed: false,
1164 }
1165 }
1166
1167 pub(super) fn try_parse<F, T>(&mut self, op: F) -> Option<T>
1168 where
1169 F: FnOnce(&mut Self) -> ParseResult<T>,
1170 {
1171 let cp = self.checkpoint();
1172 match op(self) {
1173 Ok(res) => Some(res),
1174 Err(_) => {
1175 self.restore(cp);
1176 None
1177 }
1178 }
1179 }
1180
1181 fn resolve_pronoun(&mut self, gender: Gender, number: Number) -> ParseResult<ResolvedPronoun> {
1182 if self.world_state.in_discourse_mode() && self.world_state.has_prior_modal_context() {
1187 if let Some(candidate) = self.world_state.resolve_via_telescope(gender) {
1190 return Ok(ResolvedPronoun::Variable(candidate.variable));
1191 }
1192 let blocked_candidates: Vec<_> = self.world_state.telescope_candidates()
1196 .iter()
1197 .filter(|c| c.in_modal_scope)
1198 .collect();
1199 if !blocked_candidates.is_empty() {
1200 let has_upcoming_modal = self.has_modal_subordination_ahead();
1203 if has_upcoming_modal {
1204 if let Some(candidate) = blocked_candidates.into_iter().find(|c| {
1206 c.gender == gender || gender == Gender::Unknown || c.gender == Gender::Unknown
1207 }) {
1208 return Ok(ResolvedPronoun::Variable(candidate.variable));
1209 }
1210 }
1211 return Err(ParseError {
1213 kind: ParseErrorKind::ScopeViolation(
1214 "Cannot access hypothetical entity from reality. Use modal subordination (e.g., 'would') to continue a hypothetical context.".to_string()
1215 ),
1216 span: self.current_span(),
1217 });
1218 }
1219 }
1221
1222 let current_box = self.drs.current_box_index();
1224 match self.drs.resolve_pronoun(current_box, gender, number) {
1225 Ok(sym) => {
1226 return Ok(if self.drs.is_rigid_referent(sym) {
1230 ResolvedPronoun::Constant(sym)
1231 } else {
1232 ResolvedPronoun::Variable(sym)
1233 });
1234 }
1235 Err(crate::drs::ScopeError::InaccessibleReferent { gender: g, reason, .. }) => {
1236 if self.world_state.in_discourse_mode() {
1240 if let Some(candidate) = self.world_state.resolve_via_telescope(g) {
1241 return Ok(ResolvedPronoun::Variable(candidate.variable));
1242 }
1243 }
1244 return Err(ParseError {
1246 kind: ParseErrorKind::ScopeViolation(reason),
1247 span: self.current_span(),
1248 });
1249 }
1250 Err(crate::drs::ScopeError::NoMatchingReferent { gender: g, number: n }) => {
1251 if !self.world_state.has_prior_modal_context() {
1253 if let Some(candidate) = self.world_state.resolve_via_telescope(g) {
1254 return Ok(ResolvedPronoun::Variable(candidate.variable));
1255 }
1256 }
1257
1258 if self.world_state.in_discourse_mode() {
1260 return Err(ParseError {
1261 kind: ParseErrorKind::UnresolvedPronoun {
1262 gender: g,
1263 number: n,
1264 },
1265 span: self.current_span(),
1266 });
1267 }
1268
1269 let deictic_name = match (g, n) {
1272 (Gender::Male, Number::Singular) => "Him",
1273 (Gender::Female, Number::Singular) => "Her",
1274 (Gender::Neuter, Number::Singular) => "It",
1275 (Gender::Male, Number::Plural) | (Gender::Female, Number::Plural) => "Them",
1276 (Gender::Neuter, Number::Plural) => "Them",
1277 (Gender::Unknown, _) => "Someone",
1278 };
1279 let sym = self.interner.intern(deictic_name);
1280 self.drs.introduce_referent_with_source(
1284 sym,
1285 sym,
1286 g,
1287 n,
1288 crate::drs::ReferentSource::ProperName,
1289 );
1290 return Ok(ResolvedPronoun::Constant(sym));
1291 }
1292 }
1293 }
1294
1295 fn resolve_donkey_pronoun(&mut self, gender: Gender) -> Option<Symbol> {
1296 for (noun_class, var_name, used, _wide_neg) in self.donkey_bindings.iter_mut().rev() {
1297 let noun_str = self.interner.resolve(*noun_class);
1298 let noun_gender = Self::infer_noun_gender(noun_str);
1299 if noun_gender == gender || gender == Gender::Neuter || noun_gender == Gender::Unknown {
1300 *used = true; return Some(*var_name);
1302 }
1303 }
1304 None
1305 }
1306
1307 fn infer_noun_gender(noun: &str) -> Gender {
1308 let lower = noun.to_lowercase();
1309 if lexicon::is_female_noun(&lower) {
1310 Gender::Female
1311 } else if lexicon::is_male_noun(&lower) {
1312 Gender::Male
1313 } else if lexicon::is_neuter_noun(&lower) {
1314 Gender::Neuter
1315 } else {
1316 Gender::Unknown
1317 }
1318 }
1319
1320 fn is_plural_noun(noun: &str) -> bool {
1321 let lower = noun.to_lowercase();
1322 if lexicon::is_proper_name(&lower) {
1324 return false;
1325 }
1326 if lexicon::is_irregular_plural(&lower) {
1327 return true;
1328 }
1329 lower.ends_with('s') && !lower.ends_with("ss") && lower.len() > 2
1330 }
1331
1332 fn singularize_noun(noun: &str) -> String {
1333 let lower = noun.to_lowercase();
1334 if let Some(singular) = lexicon::singularize(&lower) {
1335 return singular.to_string();
1336 }
1337 if lower.ends_with('s') && !lower.ends_with("ss") && lower.len() > 2 {
1338 let base = &lower[..lower.len() - 1];
1339 let mut chars: Vec<char> = base.chars().collect();
1340 if !chars.is_empty() {
1341 chars[0] = chars[0].to_uppercase().next().unwrap();
1342 }
1343 return chars.into_iter().collect();
1344 }
1345 let mut chars: Vec<char> = lower.chars().collect();
1346 if !chars.is_empty() {
1347 chars[0] = chars[0].to_uppercase().next().unwrap();
1348 }
1349 chars.into_iter().collect()
1350 }
1351
1352 fn infer_gender(name: &str) -> Gender {
1353 let lower = name.to_lowercase();
1354 if lexicon::is_male_name(&lower) {
1355 Gender::Male
1356 } else if lexicon::is_female_name(&lower) {
1357 Gender::Female
1358 } else {
1359 Gender::Unknown
1360 }
1361 }
1362
1363
1364 fn scalar_implicature(&mut self, expr: &'a LogicExpr<'a>) -> Option<&'a LogicExpr<'a>> {
1374 if let LogicExpr::Quantifier {
1375 kind: QuantifierKind::Existential | QuantifierKind::Most | QuantifierKind::Many,
1376 variable,
1377 body,
1378 island_id,
1379 } = expr
1380 {
1381 let alt_body = if let LogicExpr::BinaryOp {
1383 left,
1384 op: TokenType::And,
1385 right,
1386 } = body
1387 {
1388 self.ctx.exprs.alloc(LogicExpr::BinaryOp {
1389 left,
1390 op: TokenType::Implies,
1391 right,
1392 })
1393 } else {
1394 body
1395 };
1396 let universal = self.ctx.exprs.alloc(LogicExpr::Quantifier {
1397 kind: QuantifierKind::Universal,
1398 variable: *variable,
1399 body: alt_body,
1400 island_id: *island_id,
1401 });
1402 let negated = self.ctx.exprs.alloc(LogicExpr::UnaryOp {
1403 op: TokenType::Not,
1404 operand: universal,
1405 });
1406 Some(self.ctx.exprs.alloc(LogicExpr::Implicature {
1407 assertion: expr,
1408 implicature: negated,
1409 }))
1410 } else {
1411 None
1412 }
1413 }
1414
1415 fn coerce_agent(&mut self, np: &crate::ast::NounPhrase<'a>) -> Term<'a> {
1416 let base = self.noun_phrase_to_term(np);
1417 if crate::lexicon::is_institution_metonym(&self.interner.resolve(np.noun).to_lowercase()) {
1418 let gov = self.interner.intern("GovernmentOf");
1419 Term::Function(gov, self.ctx.terms.alloc_slice([base]))
1420 } else {
1421 base
1422 }
1423 }
1424
1425 fn next_var_name(&mut self) -> Symbol {
1426 const VARS: &[&str] = &["x", "y", "z", "w", "v", "u"];
1427 let idx = self.var_counter;
1428 self.var_counter += 1;
1429 if idx < VARS.len() {
1430 self.interner.intern(VARS[idx])
1431 } else {
1432 let name = format!("x{}", idx - VARS.len() + 1);
1433 self.interner.intern(&name)
1434 }
1435 }
1436
1437 fn parse_i64_numeral(&self, num_str: &str) -> ParseResult<i64> {
1443 self.parse_i64_numeral_signed(num_str, false)
1444 }
1445
1446 fn parse_i64_numeral_signed(&self, num_str: &str, negative: bool) -> ParseResult<i64> {
1450 let clean = num_str.replace('_', "");
1451 let sign = if negative { "-" } else { "" };
1452 let radix = |digits: &str, base: u32| -> Result<i64, ()> {
1459 if let Ok(v) = i64::from_str_radix(&format!("{}{}", sign, digits), base) {
1460 return Ok(v);
1461 }
1462 if !negative {
1463 if let Ok(u) = u64::from_str_radix(digits, base) {
1464 return Ok(u as i64);
1465 }
1466 }
1467 Err(())
1468 };
1469 let parsed = if let Some(hex) = clean.strip_prefix("0x").or_else(|| clean.strip_prefix("0X")) {
1470 radix(hex, 16)
1471 } else if let Some(bin) = clean.strip_prefix("0b").or_else(|| clean.strip_prefix("0B")) {
1472 radix(bin, 2)
1473 } else if let Some(oct) = clean.strip_prefix("0o").or_else(|| clean.strip_prefix("0O")) {
1474 radix(oct, 8)
1475 } else {
1476 format!("{}{}", sign, clean).parse::<i64>().map_err(|_| ())
1477 };
1478 parsed.map_err(|_| ParseError {
1479 kind: ParseErrorKind::ExpectedKeyword {
1480 keyword: format!(
1481 "a representable Int literal — `{}` does not fit the Int range (±9223372036854775807)",
1482 num_str
1483 ),
1484 },
1485 span: self.current_span(),
1486 })
1487 }
1488
1489 fn is_radix_numeral(num_str: &str) -> bool {
1493 let s = num_str.strip_prefix('_').unwrap_or(num_str);
1494 s.len() > 2
1495 && s.starts_with('0')
1496 && matches!(s.as_bytes()[1], b'x' | b'X' | b'b' | b'B' | b'o' | b'O')
1497 }
1498
1499 fn parse_index_numeral(&mut self, sym: Symbol) -> ParseResult<&'a Expr<'a>> {
1505 let num_str = self.interner.resolve(sym).to_string();
1506 if let Ok(n) = self.parse_i64_numeral(&num_str) {
1507 if n == 0 {
1508 return Err(ParseError {
1509 kind: ParseErrorKind::ZeroIndex,
1510 span: self.current_span(),
1511 });
1512 }
1513 return Ok(self
1514 .ctx
1515 .alloc_imperative_expr(Expr::Literal(crate::ast::Literal::Number(n))));
1516 }
1517 if let Ok(f) = num_str.parse::<f64>() {
1518 return Ok(self
1519 .ctx
1520 .alloc_imperative_expr(Expr::Literal(crate::ast::Literal::Float(f))));
1521 }
1522 Err(ParseError {
1523 kind: ParseErrorKind::ExpectedKeyword {
1524 keyword: format!("a numeric index (got '{}')", num_str),
1525 },
1526 span: self.current_span(),
1527 })
1528 }
1529
1530 fn fresh_desugar_temp(&mut self, tag: &str) -> Symbol {
1533 let idx = self.var_counter;
1534 self.var_counter += 1;
1535 self.interner.intern(&format!("__{}_{}", tag, idx))
1536 }
1537
1538 fn desugar_place_set_index(
1555 &mut self,
1556 collection: &'a Expr<'a>,
1557 index: &'a Expr<'a>,
1558 value: &'a Expr<'a>,
1559 ) -> Stmt<'a> {
1560 let (base, key) = match collection {
1561 Expr::Index { collection: base, index: key } => (*base, *key),
1562 _ => return Stmt::SetIndex { collection, index, value },
1563 };
1564 let t_idx = self.fresh_desugar_temp("place_i");
1565 let t_val = self.fresh_desugar_temp("place_v");
1566 let t_key = self.fresh_desugar_temp("place_k");
1567 let t_inner = self.fresh_desugar_temp("place_t");
1568 let idx_ref = self.ctx.alloc_imperative_expr(Expr::Identifier(t_idx));
1569 let val_ref = self.ctx.alloc_imperative_expr(Expr::Identifier(t_val));
1570 let key_ref = self.ctx.alloc_imperative_expr(Expr::Identifier(t_key));
1571 let inner_ref = self.ctx.alloc_imperative_expr(Expr::Identifier(t_inner));
1572 let read = self.ctx.alloc_imperative_expr(Expr::Index { collection: base, index: key_ref });
1573 let write_back = self.desugar_place_set_index(base, key_ref, inner_ref);
1574 let body = [
1575 Stmt::Let { var: t_idx, ty: None, value: index, mutable: false },
1576 Stmt::Let { var: t_val, ty: None, value, mutable: false },
1577 Stmt::Let { var: t_key, ty: None, value: key, mutable: false },
1578 Stmt::Let { var: t_inner, ty: None, value: read, mutable: true },
1579 Stmt::SetIndex { collection: inner_ref, index: idx_ref, value: val_ref },
1580 write_back,
1581 ];
1582 let body = self.ctx.stmts.expect("imperative arenas not initialized")
1583 .alloc_slice(body.into_iter());
1584 Stmt::Splice { body }
1585 }
1586
1587 fn desugar_place_push(&mut self, value: &'a Expr<'a>, collection: &'a Expr<'a>) -> Stmt<'a> {
1590 let (base, key) = match collection {
1591 Expr::Index { collection: base, index: key } => (*base, *key),
1592 _ => return Stmt::Push { value, collection },
1593 };
1594 let t_val = self.fresh_desugar_temp("place_v");
1595 let t_key = self.fresh_desugar_temp("place_k");
1596 let t_inner = self.fresh_desugar_temp("place_t");
1597 let val_ref = self.ctx.alloc_imperative_expr(Expr::Identifier(t_val));
1598 let key_ref = self.ctx.alloc_imperative_expr(Expr::Identifier(t_key));
1599 let inner_ref = self.ctx.alloc_imperative_expr(Expr::Identifier(t_inner));
1600 let read = self.ctx.alloc_imperative_expr(Expr::Index { collection: base, index: key_ref });
1601 let write_back = self.desugar_place_set_index(base, key_ref, inner_ref);
1602 let body = [
1603 Stmt::Let { var: t_val, ty: None, value, mutable: false },
1604 Stmt::Let { var: t_key, ty: None, value: key, mutable: false },
1605 Stmt::Let { var: t_inner, ty: None, value: read, mutable: true },
1606 Stmt::Push { value: val_ref, collection: inner_ref },
1607 write_back,
1608 ];
1609 let body = self.ctx.stmts.expect("imperative arenas not initialized")
1610 .alloc_slice(body.into_iter());
1611 Stmt::Splice { body }
1612 }
1613
1614 pub fn parse(&mut self) -> ParseResult<&'a LogicExpr<'a>> {
1631 let mut result = self.parse_prefix()?;
1632
1633 while self.check(&TokenType::While) {
1638 self.advance();
1639 let condition = if matches!(self.peek().kind, TokenType::Adjective(_))
1640 && matches!(
1641 self.tokens.get(self.current + 1).map(|t| &t.kind),
1642 Some(TokenType::Period) | Some(TokenType::EOF) | None
1643 ) {
1644 let adj = match self.advance().kind {
1645 TokenType::Adjective(a) => a,
1646 _ => unreachable!("guarded by the match above"),
1647 };
1648 let subject = Self::find_agent_term(result)
1649 .unwrap_or(Term::Constant(self.interner.intern("System")));
1650 &*self.ctx.exprs.alloc(LogicExpr::Predicate {
1651 name: adj,
1652 args: self.ctx.terms.alloc_slice([subject]),
1653 world: None,
1654 })
1655 } else {
1656 self.parse_sentence()?
1657 };
1658 if self.check(&TokenType::Period) {
1659 self.advance();
1660 }
1661 result = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
1662 left: condition,
1663 op: TokenType::Implies,
1664 right: result,
1665 });
1666 }
1667
1668 let at_any_time_from = if matches!(&self.peek().kind, TokenType::Preposition(p) if self.interner.resolve(*p).eq_ignore_ascii_case("at"))
1672 && matches!(
1673 self.tokens.get(self.current + 1).map(|t| &t.kind),
1674 Some(TokenType::Any)
1675 )
1676 && self
1677 .tokens
1678 .get(self.current + 2)
1679 .map(|t| {
1680 self.interner
1681 .resolve(t.lexeme)
1682 .eq_ignore_ascii_case("time")
1683 })
1684 .unwrap_or(false)
1685 {
1686 Some(3)
1688 } else if matches!(self.peek().kind, TokenType::Any)
1689 && self
1690 .tokens
1691 .get(self.current + 1)
1692 .map(|t| {
1693 self.interner
1694 .resolve(t.lexeme)
1695 .eq_ignore_ascii_case("time")
1696 })
1697 .unwrap_or(false)
1698 {
1699 Some(2)
1702 } else {
1703 None
1704 };
1705 if let Some(n) = at_any_time_from {
1706 for _ in 0..n {
1707 self.advance();
1708 }
1709 if self.check(&TokenType::Period) {
1710 self.advance();
1711 }
1712 result = self.ctx.exprs.alloc(LogicExpr::Temporal {
1713 operator: TemporalOperator::Always,
1714 body: result,
1715 });
1716 }
1717
1718 if !self.is_at_end() {
1721 return Err(ParseError {
1722 kind: crate::error::ParseErrorKind::TrailingTokens {
1723 found: self.peek().kind.clone(),
1724 },
1725 span: self.current_span(),
1726 });
1727 }
1728
1729 Ok(result)
1730 }
1731
1732 fn find_agent_term(expr: &'a LogicExpr<'a>) -> Option<Term<'a>> {
1735 match expr {
1736 LogicExpr::NeoEvent(data) => data
1737 .roles
1738 .iter()
1739 .find(|(role, _)| matches!(role, crate::ast::ThematicRole::Agent))
1740 .map(|(_, term)| term.clone()),
1741 LogicExpr::Modal { operand, .. } => Self::find_agent_term(operand),
1742 LogicExpr::UnaryOp { operand, .. } => Self::find_agent_term(operand),
1743 LogicExpr::Temporal { body, .. } => Self::find_agent_term(body),
1744 LogicExpr::Aspectual { body, .. } => Self::find_agent_term(body),
1745 LogicExpr::Quantifier { body, .. } => Self::find_agent_term(body),
1746 LogicExpr::BinaryOp { left, right, .. } => {
1747 Self::find_agent_term(left).or_else(|| Self::find_agent_term(right))
1748 }
1749 _ => None,
1750 }
1751 }
1752
1753 pub(super) fn parse_prefix(&mut self) -> ParseResult<&'a LogicExpr<'a>> {
1759 let mut result = self.parse_sentence()?;
1760
1761 while self.check(&TokenType::Period) || self.check(&TokenType::Exclamation) {
1764 self.advance(); if !self.is_at_end() {
1766 let next = self.parse_sentence()?;
1767 result = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
1768 left: result,
1769 op: TokenType::And,
1770 right: next,
1771 });
1772 }
1773 }
1774
1775 Ok(result)
1776 }
1777
1778 pub fn parse_pragmatic(&mut self) -> ParseResult<&'a LogicExpr<'a>> {
1783 self.pragmatic = true;
1784 let scalar_trigger = matches!(
1787 self.peek().kind,
1788 TokenType::Some | TokenType::Most | TokenType::Many
1789 );
1790 let result = self.parse()?;
1791 if scalar_trigger {
1792 if let Some(strengthened) = self.scalar_implicature(result) {
1793 return Ok(strengthened);
1794 }
1795 }
1796 Ok(result)
1797 }
1798
1799 pub fn parse_program(&mut self) -> ParseResult<Vec<Stmt<'a>>> {
1817 let mut statements = Vec::new();
1818 self.stmt_spans.clear();
1819 let mut in_definition_block = false;
1820 let mut pending_opt_flags = OptimizationConfig::all_on();
1821
1822 if self.mode == ParserMode::Declarative {
1824 }
1828
1829 while !self.is_at_end() {
1830 if let Some(Token { kind: TokenType::BlockHeader { block_type }, .. }) = self.tokens.get(self.current) {
1832 match block_type {
1833 BlockType::SuspectedTypo { found, suggestion } => {
1834 let found = self.interner.resolve(*found).to_string();
1835 let suggestion_str = self.interner.resolve(*suggestion);
1836 let mut canonical: String = suggestion_str.to_string();
1837 if let Some(c) = canonical.get_mut(0..1) {
1838 c.make_ascii_uppercase();
1839 }
1840 return Err(ParseError {
1841 kind: ParseErrorKind::ExpectedKeyword {
1842 keyword: format!(
1843 "a known header — `## {}` looks like a typo of `## {}` (if it is a prose heading, pick a name further from the code headers)",
1844 found, canonical
1845 ),
1846 },
1847 span: self.current_span(),
1848 });
1849 }
1850 BlockType::Definition => {
1851 in_definition_block = true;
1852 self.mode = ParserMode::Declarative;
1853 self.advance();
1854 continue;
1855 }
1856 BlockType::Main => {
1857 self.program_opt_flags =
1860 self.program_opt_flags.merged(&pending_opt_flags);
1861 pending_opt_flags = OptimizationConfig::all_on();
1862 in_definition_block = false;
1863 self.mode = ParserMode::Imperative;
1864 self.advance();
1865 continue;
1866 }
1867 BlockType::No => {
1868 self.advance(); if let Some(token) = self.tokens.get(self.current) {
1873 let word = self.interner.resolve(token.lexeme).to_lowercase();
1874 if word == "optimize" {
1875 pending_opt_flags = OptimizationConfig::all_off();
1876 } else if let Some(opt) = by_keyword(&word) {
1877 pending_opt_flags.set(opt, false);
1878 }
1879 self.advance(); }
1882 while self.check(&TokenType::Newline) {
1883 self.advance();
1884 }
1885 continue;
1886 }
1887 BlockType::Tier => {
1888 self.advance(); let kw = self
1894 .tokens
1895 .get(self.current)
1896 .map(|t| self.interner.resolve(t.lexeme).to_lowercase());
1897 if kw.is_some() {
1898 self.advance(); }
1900 let val = self
1901 .tokens
1902 .get(self.current)
1903 .map(|t| self.interner.resolve(t.lexeme).to_lowercase());
1904 if val.is_some() {
1905 self.advance(); }
1907 if let (Some(kw), Some(val)) = (kw, val) {
1908 if let (Some(opt), Some(pin)) = (by_keyword(&kw), pin_from_str(&val)) {
1909 self.program_tier_pins.set(opt, pin);
1910 }
1911 }
1913 while self.check(&TokenType::Newline) {
1914 self.advance();
1915 }
1916 continue;
1917 }
1918 BlockType::Function => {
1919 in_definition_block = false;
1920 self.mode = ParserMode::Imperative;
1921 let header_tok = self.current;
1922 self.advance();
1923 let flags = std::mem::take(&mut pending_opt_flags);
1925 let func_def = self.parse_function_def_with_flags(flags)?;
1926 statements.push(func_def);
1927 self.record_stmt_span(header_tok);
1928 continue;
1929 }
1930 BlockType::TypeDef => {
1931 self.advance();
1934 self.skip_type_def_content();
1935 continue;
1936 }
1937 BlockType::Policy => {
1938 in_definition_block = true; self.mode = ParserMode::Declarative;
1942 self.advance();
1943 continue;
1944 }
1945 BlockType::Hardware | BlockType::Property => {
1946 in_definition_block = true;
1949 self.mode = ParserMode::Declarative;
1950 self.advance();
1951 continue;
1952 }
1953 BlockType::Theorem => {
1954 in_definition_block = false;
1956 self.mode = ParserMode::Declarative;
1957 let header_tok = self.current;
1958 self.advance();
1959 let theorem = self.parse_theorem_block()?;
1960 statements.push(theorem);
1961 self.record_stmt_span(header_tok);
1962 continue;
1963 }
1964 BlockType::Define => {
1965 in_definition_block = false;
1967 self.mode = ParserMode::Declarative;
1968 let header_tok = self.current;
1969 self.advance();
1970 let definition = self.parse_define_block()?;
1971 statements.push(definition);
1972 self.record_stmt_span(header_tok);
1973 continue;
1974 }
1975 BlockType::Axiom => {
1976 in_definition_block = false;
1978 self.mode = ParserMode::Declarative;
1979 let header_tok = self.current;
1980 self.advance();
1981 let axiom = self.parse_axiom_block()?;
1982 statements.push(axiom);
1983 self.record_stmt_span(header_tok);
1984 continue;
1985 }
1986 BlockType::Theory => {
1987 in_definition_block = false;
1989 self.mode = ParserMode::Declarative;
1990 let header_tok = self.current;
1991 self.advance();
1992 let theory = self.parse_theory_block()?;
1993 statements.push(theory);
1994 self.record_stmt_span(header_tok);
1995 continue;
1996 }
1997 BlockType::Requires => {
1998 in_definition_block = false;
1999 self.mode = ParserMode::Declarative;
2000 let header_tok = self.current;
2001 self.advance();
2002 let deps = self.parse_requires_block()?;
2003 for _ in 0..deps.len() {
2004 self.record_stmt_span(header_tok);
2005 }
2006 statements.extend(deps);
2007 continue;
2008 }
2009 _ => {
2010 in_definition_block = false;
2012 self.mode = ParserMode::Declarative;
2013 self.advance();
2014 continue;
2015 }
2016 }
2017 }
2018
2019 if in_definition_block {
2021 self.advance();
2022 continue;
2023 }
2024
2025 if self.check(&TokenType::Indent) || self.check(&TokenType::Dedent) || self.check(&TokenType::Newline) {
2027 self.advance();
2028 continue;
2029 }
2030
2031 if self.mode == ParserMode::Imperative {
2033 if self.check_word("Accept") {
2037 self.parse_accept_contract()?;
2038 continue;
2039 }
2040 let start_tok = self.current;
2041 let stmt = self.parse_statement()?;
2042 statements.push(stmt);
2043
2044 if self.check(&TokenType::Period) {
2045 self.advance();
2046 }
2047 self.record_stmt_span(start_tok);
2048 } else {
2049 self.advance();
2051 }
2052 }
2053
2054 self.program_opt_flags = self.program_opt_flags.merged(&pending_opt_flags);
2057 debug_assert_eq!(
2058 self.stmt_spans.len(),
2059 statements.len(),
2060 "stmt_spans must stay aligned 1:1 with the statement list"
2061 );
2062
2063 crate::ast_depth::validate_program_depth(
2068 &statements,
2069 self.stmt_spans.first().copied().unwrap_or_else(|| self.current_span()),
2070 )?;
2071
2072 Ok(statements)
2073 }
2074
2075 pub(super) fn enter_recursion(&mut self) -> ParseResult<()> {
2079 self.recursion_depth += 1;
2080 let limit = crate::ast_depth::max_parse_recursion();
2081 if self.recursion_depth > limit {
2082 self.recursion_depth -= 1;
2083 return Err(ParseError {
2084 kind: ParseErrorKind::AstTooDeep { depth: limit + 1, max_depth: limit },
2085 span: self.current_span(),
2086 });
2087 }
2088 Ok(())
2089 }
2090
2091 pub(super) fn leave_recursion(&mut self) {
2093 self.recursion_depth = self.recursion_depth.saturating_sub(1);
2094 }
2095
2096 pub fn program_opt_flags(&self) -> OptimizationConfig {
2100 self.program_opt_flags
2101 }
2102
2103 pub fn program_tier_pins(&self) -> PinSet {
2107 self.program_tier_pins
2108 }
2109
2110 fn parse_statement(&mut self) -> ParseResult<Stmt<'a>> {
2115 self.enter_recursion()?;
2116 let result = self.parse_statement_inner();
2117 self.leave_recursion();
2118 result
2119 }
2120
2121 fn parse_statement_inner(&mut self) -> ParseResult<Stmt<'a>> {
2122 if self.check(&TokenType::To) || self.check_preposition_is("to") {
2125 return self.parse_function_def();
2126 }
2127 if self.check(&TokenType::Let) {
2128 return self.parse_let_statement();
2129 }
2130 if self.check(&TokenType::Mut) {
2133 return self.parse_equals_assignment(true);
2134 }
2135 if self.peek_equals_assignment() {
2138 return self.parse_equals_assignment(false);
2139 }
2140 if self.peek_compound_assignment() {
2142 return self.parse_compound_assignment();
2143 }
2144 if self.check(&TokenType::Set) {
2145 return self.parse_set_statement();
2146 }
2147 if self.check(&TokenType::Return) {
2148 return self.parse_return_statement();
2149 }
2150 if self.check(&TokenType::Break) {
2151 return self.parse_break_statement();
2152 }
2153 if self.check(&TokenType::If) {
2154 return self.parse_if_statement();
2155 }
2156 if self.check(&TokenType::Assert) {
2157 return self.parse_assert_statement();
2158 }
2159 if self.check(&TokenType::Require) {
2160 return self.parse_require_statement();
2161 }
2162 if self.check(&TokenType::Trust) {
2164 return self.parse_trust_statement();
2165 }
2166 if self.check(&TokenType::Check) {
2168 return self.parse_check_statement();
2169 }
2170 if self.check(&TokenType::Listen) {
2172 return self.parse_listen_statement();
2173 }
2174 if self.check(&TokenType::NetConnect) {
2175 return self.parse_connect_statement();
2176 }
2177 if self.check(&TokenType::Sleep) {
2178 return self.parse_sleep_statement();
2179 }
2180 if self.check_word("Run") {
2183 return self.parse_run_under_contract();
2184 }
2185 if self.check(&TokenType::Sync) {
2187 return self.parse_sync_statement();
2188 }
2189 if self.check(&TokenType::Mount) {
2191 return self.parse_mount_statement();
2192 }
2193 if self.check(&TokenType::While) {
2194 return self.parse_while_statement();
2195 }
2196 if self.check(&TokenType::Repeat) {
2197 return self.parse_repeat_statement();
2198 }
2199 if self.check(&TokenType::For) {
2201 return self.parse_for_statement();
2202 }
2203 if self.check(&TokenType::Call) {
2204 return self.parse_call_statement();
2205 }
2206 if self.check(&TokenType::Give) {
2207 return self.parse_give_statement();
2208 }
2209 if self.check(&TokenType::Show) {
2210 return self.parse_show_statement();
2211 }
2212 if self.check(&TokenType::Inspect) {
2214 return self.parse_inspect_statement();
2215 }
2216
2217 if self.check(&TokenType::Push) {
2219 return self.parse_push_statement();
2220 }
2221 if self.check(&TokenType::Pop) {
2222 return self.parse_pop_statement();
2223 }
2224 if self.check(&TokenType::Add) {
2226 return self.parse_add_statement();
2227 }
2228 if self.check(&TokenType::Remove) {
2229 return self.parse_remove_statement();
2230 }
2231
2232 if self.check(&TokenType::Inside) {
2234 return self.parse_zone_statement();
2235 }
2236
2237 if self.check(&TokenType::Attempt) {
2239 return self.parse_concurrent_block();
2240 }
2241 if self.check(&TokenType::Simultaneously) {
2242 return self.parse_parallel_block();
2243 }
2244
2245 if self.check(&TokenType::Read) {
2247 return self.parse_read_statement();
2248 }
2249 if self.check(&TokenType::Write) {
2250 return self.parse_write_statement();
2251 }
2252
2253 if self.check(&TokenType::Spawn) {
2255 return self.parse_spawn_statement();
2256 }
2257 if self.check_word("Stream") {
2258 return self.parse_stream_statement();
2259 }
2260 if self.check(&TokenType::Send) {
2261 if self.lookahead_contains_into() {
2263 return self.parse_send_pipe_statement();
2264 }
2265 return self.parse_send_statement();
2266 }
2267 if self.check(&TokenType::Await) {
2268 if self.lookahead_is_first_of() {
2270 return self.parse_select_statement();
2271 }
2272 return self.parse_await_statement();
2273 }
2274
2275 if self.check(&TokenType::Merge) {
2277 return self.parse_merge_statement();
2278 }
2279 if self.check(&TokenType::Increase) {
2280 return self.parse_increase_statement();
2281 }
2282 if self.check(&TokenType::Decrease) {
2284 return self.parse_decrease_statement();
2285 }
2286 if self.check(&TokenType::Append) {
2287 return self.parse_append_statement();
2288 }
2289 if self.check(&TokenType::Resolve) {
2290 return self.parse_resolve_statement();
2291 }
2292
2293 if self.check(&TokenType::Launch) {
2295 return self.parse_launch_statement();
2296 }
2297 if self.check(&TokenType::Stop) {
2298 return self.parse_stop_statement();
2299 }
2300 if self.check(&TokenType::Try) {
2301 return self.parse_try_statement();
2302 }
2303 if self.check(&TokenType::Receive) {
2304 return self.parse_receive_pipe_statement();
2305 }
2306
2307 if self.check(&TokenType::Escape) {
2309 return self.parse_escape_statement();
2310 }
2311
2312 if self.tokens.get(self.current + 1)
2316 .map(|t| matches!(t.kind, TokenType::LParen))
2317 .unwrap_or(false)
2318 {
2319 let function = self.peek().lexeme;
2321 self.advance(); let expr = self.parse_call_expr(function)?;
2325 if let Expr::Call { function, args } = expr {
2326 return Ok(Stmt::Call { function: *function, args: args.clone() });
2327 }
2328 }
2329
2330 if self
2336 .tokens
2337 .get(self.current + 1)
2338 .is_some_and(|t| matches!(t.kind, TokenType::Is))
2339 {
2340 if let Some(value_token) = self.tokens.get(self.current + 2) {
2341 if matches!(
2342 value_token.kind,
2343 TokenType::Number(_)
2344 | TokenType::StringLiteral(_)
2345 | TokenType::InterpolatedString(_)
2346 ) {
2347 let variable = self.interner.resolve(self.peek().lexeme).to_string();
2348 let value = self.interner.resolve(value_token.lexeme).to_string();
2349 let span = Span::new(self.peek().span.start, value_token.span.end);
2350 return Err(ParseError {
2351 kind: ParseErrorKind::IsValueEquality { variable, value },
2352 span,
2353 });
2354 }
2355 }
2356 }
2357
2358 Err(ParseError {
2359 kind: ParseErrorKind::ExpectedStatement,
2360 span: self.current_span(),
2361 })
2362 }
2363
2364 fn parse_if_statement(&mut self) -> ParseResult<Stmt<'a>> {
2365 self.advance(); let cond = self.parse_condition()?;
2369
2370 if self.check(&TokenType::Then) {
2372 self.advance();
2373 }
2374
2375 if !self.check(&TokenType::Colon) {
2377 return Err(ParseError {
2378 kind: ParseErrorKind::ExpectedKeyword { keyword: ":".to_string() },
2379 span: self.current_span(),
2380 });
2381 }
2382 self.advance(); let mut then_stmts = Vec::new();
2387 if self.check(&TokenType::Indent) {
2388 self.advance(); while !self.check(&TokenType::Dedent) && !self.is_at_end() {
2390 let stmt = self.parse_statement()?;
2391 then_stmts.push(stmt);
2392 if self.check(&TokenType::Period) {
2393 self.advance();
2394 }
2395 }
2396 if self.check(&TokenType::Dedent) {
2397 self.advance();
2398 }
2399 } else {
2400 let stmt = self.parse_statement()?;
2401 then_stmts.push(stmt);
2402 if self.check(&TokenType::Period) {
2403 self.advance();
2404 }
2405 }
2406
2407 let then_block = self.ctx.stmts.expect("imperative arenas not initialized")
2409 .alloc_slice(then_stmts.into_iter());
2410
2411 let else_block = if self.check(&TokenType::Otherwise) || self.check(&TokenType::Else) {
2413 self.advance(); if self.check(&TokenType::If) {
2417 let nested_if = self.parse_if_statement()?;
2419 let nested_slice = self.ctx.stmts.expect("imperative arenas not initialized")
2420 .alloc_slice(std::iter::once(nested_if));
2421 Some(nested_slice)
2422 } else {
2423 if !self.check(&TokenType::Colon) {
2425 return Err(ParseError {
2426 kind: ParseErrorKind::ExpectedKeyword { keyword: ":".to_string() },
2427 span: self.current_span(),
2428 });
2429 }
2430 self.advance(); let mut else_stmts = Vec::new();
2434 if self.check(&TokenType::Indent) {
2435 self.advance(); while !self.check(&TokenType::Dedent) && !self.is_at_end() {
2437 let stmt = self.parse_statement()?;
2438 else_stmts.push(stmt);
2439 if self.check(&TokenType::Period) {
2440 self.advance();
2441 }
2442 }
2443 if self.check(&TokenType::Dedent) {
2444 self.advance();
2445 }
2446 } else {
2447 let stmt = self.parse_statement()?;
2448 else_stmts.push(stmt);
2449 if self.check(&TokenType::Period) {
2450 self.advance();
2451 }
2452 }
2453
2454 Some(self.ctx.stmts.expect("imperative arenas not initialized")
2455 .alloc_slice(else_stmts.into_iter()))
2456 }
2457 } else if self.check(&TokenType::Elif) {
2458 self.advance(); let nested_if = self.parse_elif_as_if()?;
2462 let nested_slice = self.ctx.stmts.expect("imperative arenas not initialized")
2463 .alloc_slice(std::iter::once(nested_if));
2464 Some(nested_slice)
2465 } else {
2466 None
2467 };
2468
2469 Ok(Stmt::If {
2470 cond,
2471 then_block,
2472 else_block,
2473 })
2474 }
2475
2476 fn parse_elif_as_if(&mut self) -> ParseResult<Stmt<'a>> {
2479 let cond = self.parse_condition()?;
2481
2482 if !self.check(&TokenType::Colon) {
2484 return Err(ParseError {
2485 kind: ParseErrorKind::ExpectedKeyword { keyword: ":".to_string() },
2486 span: self.current_span(),
2487 });
2488 }
2489 self.advance(); let mut then_stmts = Vec::new();
2494 if self.check(&TokenType::Indent) {
2495 self.advance(); while !self.check(&TokenType::Dedent) && !self.is_at_end() {
2497 let stmt = self.parse_statement()?;
2498 then_stmts.push(stmt);
2499 if self.check(&TokenType::Period) {
2500 self.advance();
2501 }
2502 }
2503 if self.check(&TokenType::Dedent) {
2504 self.advance();
2505 }
2506 } else {
2507 let stmt = self.parse_statement()?;
2508 then_stmts.push(stmt);
2509 if self.check(&TokenType::Period) {
2510 self.advance();
2511 }
2512 }
2513
2514 let then_block = self.ctx.stmts.expect("imperative arenas not initialized")
2516 .alloc_slice(then_stmts.into_iter());
2517
2518 let else_block = if self.check(&TokenType::Otherwise) || self.check(&TokenType::Else) {
2520 self.advance(); if self.check(&TokenType::If) {
2524 let nested_if = self.parse_if_statement()?;
2525 let nested_slice = self.ctx.stmts.expect("imperative arenas not initialized")
2526 .alloc_slice(std::iter::once(nested_if));
2527 Some(nested_slice)
2528 } else {
2529 if !self.check(&TokenType::Colon) {
2531 return Err(ParseError {
2532 kind: ParseErrorKind::ExpectedKeyword { keyword: ":".to_string() },
2533 span: self.current_span(),
2534 });
2535 }
2536 self.advance(); let mut else_stmts = Vec::new();
2540 if self.check(&TokenType::Indent) {
2541 self.advance(); while !self.check(&TokenType::Dedent) && !self.is_at_end() {
2543 let stmt = self.parse_statement()?;
2544 else_stmts.push(stmt);
2545 if self.check(&TokenType::Period) {
2546 self.advance();
2547 }
2548 }
2549 if self.check(&TokenType::Dedent) {
2550 self.advance();
2551 }
2552 } else {
2553 let stmt = self.parse_statement()?;
2554 else_stmts.push(stmt);
2555 if self.check(&TokenType::Period) {
2556 self.advance();
2557 }
2558 }
2559
2560 Some(self.ctx.stmts.expect("imperative arenas not initialized")
2561 .alloc_slice(else_stmts.into_iter()))
2562 }
2563 } else if self.check(&TokenType::Elif) {
2564 self.advance(); let nested_if = self.parse_elif_as_if()?;
2566 let nested_slice = self.ctx.stmts.expect("imperative arenas not initialized")
2567 .alloc_slice(std::iter::once(nested_if));
2568 Some(nested_slice)
2569 } else {
2570 None
2571 };
2572
2573 Ok(Stmt::If {
2574 cond,
2575 then_block,
2576 else_block,
2577 })
2578 }
2579
2580 fn parse_while_statement(&mut self) -> ParseResult<Stmt<'a>> {
2581 self.advance(); let cond = self.parse_condition()?;
2584
2585 let decreasing = if self.check(&TokenType::LParen) {
2587 self.advance(); if !self.check_word("decreasing") {
2591 return Err(ParseError {
2592 kind: ParseErrorKind::ExpectedKeyword { keyword: "decreasing".to_string() },
2593 span: self.current_span(),
2594 });
2595 }
2596 self.advance(); let variant = self.parse_imperative_expr()?;
2599
2600 if !self.check(&TokenType::RParen) {
2601 return Err(ParseError {
2602 kind: ParseErrorKind::ExpectedKeyword { keyword: ")".to_string() },
2603 span: self.current_span(),
2604 });
2605 }
2606 self.advance(); Some(variant)
2609 } else {
2610 None
2611 };
2612
2613 if !self.check(&TokenType::Colon) {
2614 return Err(ParseError {
2615 kind: ParseErrorKind::ExpectedKeyword { keyword: ":".to_string() },
2616 span: self.current_span(),
2617 });
2618 }
2619 self.advance(); if !self.check(&TokenType::Indent) {
2622 return Err(ParseError {
2623 kind: ParseErrorKind::ExpectedStatement,
2624 span: self.current_span(),
2625 });
2626 }
2627 self.advance(); let mut body_stmts = Vec::new();
2630 while !self.check(&TokenType::Dedent) && !self.is_at_end() {
2631 let stmt = self.parse_statement()?;
2632 body_stmts.push(stmt);
2633 if self.check(&TokenType::Period) {
2634 self.advance();
2635 }
2636 }
2637
2638 if self.check(&TokenType::Dedent) {
2639 self.advance();
2640 }
2641
2642 let body = self.ctx.stmts.expect("imperative arenas not initialized")
2643 .alloc_slice(body_stmts.into_iter());
2644
2645 Ok(Stmt::While { cond, body, decreasing })
2646 }
2647
2648 fn parse_loop_pattern(&mut self) -> ParseResult<Pattern> {
2651 use crate::ast::stmt::Pattern;
2652
2653 if self.check(&TokenType::LParen) {
2655 self.advance(); let mut identifiers = Vec::new();
2658 loop {
2659 let id = self.expect_identifier()?;
2660 identifiers.push(id);
2661
2662 if self.check(&TokenType::Comma) {
2664 self.advance(); continue;
2666 }
2667 break;
2668 }
2669
2670 if !self.check(&TokenType::RParen) {
2672 return Err(ParseError {
2673 kind: ParseErrorKind::ExpectedKeyword { keyword: ")".to_string() },
2674 span: self.current_span(),
2675 });
2676 }
2677 self.advance(); Ok(Pattern::Tuple(identifiers))
2680 } else {
2681 let id = self.expect_identifier()?;
2683 Ok(Pattern::Identifier(id))
2684 }
2685 }
2686
2687 fn parse_repeat_statement(&mut self) -> ParseResult<Stmt<'a>> {
2688 self.advance(); if self.check_word("forever") {
2692 self.advance(); if !self.check(&TokenType::Colon) {
2694 return Err(ParseError { kind: ParseErrorKind::ExpectedKeyword { keyword: ":".to_string() }, span: self.current_span() });
2695 }
2696 self.advance(); if !self.check(&TokenType::Indent) {
2698 return Err(ParseError { kind: ParseErrorKind::ExpectedStatement, span: self.current_span() });
2699 }
2700 self.advance(); let mut body_stmts = Vec::new();
2702 while !self.check(&TokenType::Dedent) && !self.is_at_end() {
2703 let stmt = self.parse_statement()?;
2704 body_stmts.push(stmt);
2705 if self.check(&TokenType::Period) { self.advance(); }
2706 }
2707 if self.check(&TokenType::Dedent) { self.advance(); }
2708 let body = self.ctx.stmts.expect("imperative arenas not initialized").alloc_slice(body_stmts.into_iter());
2709 let cond = self.ctx.alloc_imperative_expr(Expr::Literal(crate::ast::Literal::Boolean(true)));
2710 return Ok(Stmt::While { cond, body, decreasing: None });
2711 }
2712
2713 if self.check(&TokenType::For) {
2715 self.advance();
2716 }
2717
2718 let pattern = self.parse_loop_pattern()?;
2720
2721 let iterable = if self.check(&TokenType::From) || self.check_preposition_is("from") {
2723 self.advance(); let start = self.parse_imperative_expr()?;
2725
2726 if !self.check(&TokenType::To) && !self.check_preposition_is("to") {
2728 return Err(ParseError {
2729 kind: ParseErrorKind::ExpectedKeyword { keyword: "to".to_string() },
2730 span: self.current_span(),
2731 });
2732 }
2733 self.advance();
2734
2735 let end = self.parse_imperative_expr()?;
2736 self.ctx.alloc_imperative_expr(Expr::Range { start, end })
2737 } else if self.check(&TokenType::In) || self.check_preposition_is("in") {
2738 self.advance(); self.parse_imperative_expr()?
2740 } else {
2741 return Err(ParseError {
2742 kind: ParseErrorKind::ExpectedKeyword { keyword: "in or from".to_string() },
2743 span: self.current_span(),
2744 });
2745 };
2746
2747 if !self.check(&TokenType::Colon) {
2749 return Err(ParseError {
2750 kind: ParseErrorKind::ExpectedKeyword { keyword: ":".to_string() },
2751 span: self.current_span(),
2752 });
2753 }
2754 self.advance();
2755
2756 if !self.check(&TokenType::Indent) {
2758 return Err(ParseError {
2759 kind: ParseErrorKind::ExpectedStatement,
2760 span: self.current_span(),
2761 });
2762 }
2763 self.advance();
2764
2765 let mut body_stmts = Vec::new();
2767 while !self.check(&TokenType::Dedent) && !self.is_at_end() {
2768 let stmt = self.parse_statement()?;
2769 body_stmts.push(stmt);
2770 if self.check(&TokenType::Period) {
2771 self.advance();
2772 }
2773 }
2774
2775 if self.check(&TokenType::Dedent) {
2776 self.advance();
2777 }
2778
2779 let body = self.ctx.stmts.expect("imperative arenas not initialized")
2780 .alloc_slice(body_stmts.into_iter());
2781
2782 Ok(Stmt::Repeat { pattern, iterable, body })
2783 }
2784
2785 fn parse_for_statement(&mut self) -> ParseResult<Stmt<'a>> {
2788 self.advance(); let pattern = self.parse_loop_pattern()?;
2792
2793 let iterable = if self.check(&TokenType::From) || self.check_preposition_is("from") {
2795 self.advance(); let start = self.parse_imperative_expr()?;
2797
2798 if !self.check(&TokenType::To) && !self.check_preposition_is("to") {
2800 return Err(ParseError {
2801 kind: ParseErrorKind::ExpectedKeyword { keyword: "to".to_string() },
2802 span: self.current_span(),
2803 });
2804 }
2805 self.advance();
2806
2807 let end = self.parse_imperative_expr()?;
2808 self.ctx.alloc_imperative_expr(Expr::Range { start, end })
2809 } else if self.check(&TokenType::In) || self.check_preposition_is("in") {
2810 self.advance(); self.parse_imperative_expr()?
2812 } else {
2813 return Err(ParseError {
2814 kind: ParseErrorKind::ExpectedKeyword { keyword: "in or from".to_string() },
2815 span: self.current_span(),
2816 });
2817 };
2818
2819 if !self.check(&TokenType::Colon) {
2821 return Err(ParseError {
2822 kind: ParseErrorKind::ExpectedKeyword { keyword: ":".to_string() },
2823 span: self.current_span(),
2824 });
2825 }
2826 self.advance();
2827
2828 if !self.check(&TokenType::Indent) {
2830 return Err(ParseError {
2831 kind: ParseErrorKind::ExpectedStatement,
2832 span: self.current_span(),
2833 });
2834 }
2835 self.advance();
2836
2837 let mut body_stmts = Vec::new();
2839 while !self.check(&TokenType::Dedent) && !self.is_at_end() {
2840 let stmt = self.parse_statement()?;
2841 body_stmts.push(stmt);
2842 if self.check(&TokenType::Period) {
2843 self.advance();
2844 }
2845 }
2846
2847 if self.check(&TokenType::Dedent) {
2848 self.advance();
2849 }
2850
2851 let body = self.ctx.stmts.expect("imperative arenas not initialized")
2852 .alloc_slice(body_stmts.into_iter());
2853
2854 Ok(Stmt::Repeat { pattern, iterable, body })
2855 }
2856
2857 fn parse_call_statement(&mut self) -> ParseResult<Stmt<'a>> {
2858 self.advance(); let function = match &self.peek().kind {
2864 TokenType::Noun(sym) | TokenType::Adjective(sym) => {
2865 let s = *sym;
2866 self.advance();
2867 s
2868 }
2869 TokenType::Verb { .. } | TokenType::Ambiguous { .. } => {
2870 let s = self.peek().lexeme;
2872 self.advance();
2873 s
2874 }
2875 _ => {
2876 return Err(ParseError {
2877 kind: ParseErrorKind::ExpectedIdentifier,
2878 span: self.current_span(),
2879 });
2880 }
2881 };
2882
2883 let args = if self.check_preposition_is("with") {
2885 self.advance(); self.parse_call_arguments()?
2887 } else {
2888 Vec::new()
2889 };
2890
2891 Ok(Stmt::Call { function, args })
2892 }
2893
2894 fn parse_call_arguments(&mut self) -> ParseResult<Vec<&'a Expr<'a>>> {
2895 let mut args = Vec::new();
2896
2897 let arg = self.parse_call_arg()?;
2899 args.push(arg);
2900
2901 while self.check(&TokenType::And) || self.check(&TokenType::Comma) {
2903 self.advance(); if self.check(&TokenType::RParen) {
2906 break;
2907 }
2908 let arg = self.parse_call_arg()?;
2909 args.push(arg);
2910 }
2911
2912 Ok(args)
2913 }
2914
2915 fn parse_call_arg(&mut self) -> ParseResult<&'a Expr<'a>> {
2916 if self.check(&TokenType::Give) {
2918 self.advance(); let value = self.parse_comparison()?;
2920 return Ok(self.ctx.alloc_imperative_expr(Expr::Give { value }));
2921 }
2922
2923 self.parse_comparison()
2926 }
2927
2928 fn parse_condition(&mut self) -> ParseResult<&'a Expr<'a>> {
2929 let expr = self.parse_or_condition()?;
2932 if self.check(&TokenType::In) || self.check_preposition_is("in") {
2938 let zone_sym = match self.tokens.get(self.current + 1).map(|t| &t.kind) {
2941 Some(TokenType::StringLiteral(s)) => Some(*s),
2942 _ => None,
2943 };
2944 if let Some(zone_sym) = zone_sym {
2945 self.advance(); self.advance(); let zone = self.ctx.alloc_imperative_expr(Expr::Literal(crate::ast::Literal::Text(zone_sym)));
2948 let func = self.interner.intern("in_zone");
2949 return Ok(self
2950 .ctx
2951 .alloc_imperative_expr(Expr::Call { function: func, args: vec![expr, zone] }));
2952 }
2953 let unit_lexeme = self.tokens.get(self.current + 1).and_then(|t| {
2954 if matches!(t.kind, TokenType::Identifier | TokenType::Noun(_) | TokenType::Adjective(_)) {
2955 Some(t.lexeme)
2956 } else {
2957 None
2958 }
2959 });
2960 if let Some(unit_lexeme) = unit_lexeme {
2961 if logicaffeine_base::quantity::units::by_name(self.interner.resolve(unit_lexeme)).is_some() {
2962 self.advance(); self.advance(); let unit_expr = self
2965 .ctx
2966 .alloc_imperative_expr(crate::ast::Expr::Literal(crate::ast::Literal::Text(unit_lexeme)));
2967 let func = self.interner.intern("convert");
2968 return Ok(self
2969 .ctx
2970 .alloc_imperative_expr(crate::ast::Expr::Call { function: func, args: vec![expr, unit_expr] }));
2971 }
2972 }
2973 let code_lexeme = self.tokens.get(self.current + 1).and_then(|t| {
2977 if matches!(
2978 t.kind,
2979 TokenType::Identifier | TokenType::Noun(_) | TokenType::ProperName(_) | TokenType::Adjective(_)
2980 ) {
2981 Some(t.lexeme)
2982 } else {
2983 None
2984 }
2985 });
2986 if let Some(code_lexeme) = code_lexeme {
2987 if logicaffeine_base::money::currency::by_code(self.interner.resolve(code_lexeme)).is_some() {
2988 self.advance(); self.advance(); let code_expr = self
2991 .ctx
2992 .alloc_imperative_expr(crate::ast::Expr::Literal(crate::ast::Literal::Text(code_lexeme)));
2993 let func = self.interner.intern("to_currency");
2994 return Ok(self
2995 .ctx
2996 .alloc_imperative_expr(crate::ast::Expr::Call { function: func, args: vec![expr, code_expr] }));
2997 }
2998 }
2999 }
3000 Ok(expr)
3001 }
3002
3003 fn parse_or_condition(&mut self) -> ParseResult<&'a Expr<'a>> {
3005 let mut left = self.parse_and_condition()?;
3006
3007 while self.check(&TokenType::Or) || self.check_word("or") {
3008 self.advance();
3009 let right = self.parse_and_condition()?;
3010 left = self.ctx.alloc_imperative_expr(Expr::BinaryOp {
3011 op: BinaryOpKind::Or,
3012 left,
3013 right,
3014 });
3015 }
3016
3017 Ok(left)
3018 }
3019
3020 fn parse_and_condition(&mut self) -> ParseResult<&'a Expr<'a>> {
3022 let mut left = self.parse_comparison()?;
3023
3024 while self.check(&TokenType::And) || self.check_word("and") {
3025 self.advance();
3026 let right = self.parse_comparison()?;
3027 left = self.ctx.alloc_imperative_expr(Expr::BinaryOp {
3028 op: BinaryOpKind::And,
3029 left,
3030 right,
3031 });
3032 }
3033
3034 Ok(left)
3035 }
3036
3037 fn in_introduces_conversion(&self) -> bool {
3042 match self.tokens.get(self.current + 1) {
3043 Some(t) => match &t.kind {
3044 TokenType::StringLiteral(_) => true,
3045 TokenType::Identifier | TokenType::Noun(_) | TokenType::ProperName(_) | TokenType::Adjective(_) => {
3046 if self.user_bound.contains(&t.lexeme) {
3051 return false;
3052 }
3053 let name = self.interner.resolve(t.lexeme);
3054 logicaffeine_base::quantity::units::by_name(name).is_some()
3055 || logicaffeine_base::money::currency::by_code(name).is_some()
3056 }
3057 _ => false,
3058 },
3059 None => false,
3060 }
3061 }
3062
3063 fn parse_comparison(&mut self) -> ParseResult<&'a Expr<'a>> {
3065 if self.check(&TokenType::Not) || self.check_word("not") {
3067 self.advance(); let operand = self.parse_comparison()?; return Ok(self.ctx.alloc_imperative_expr(Expr::Not { operand }));
3070 }
3071
3072 let left = self.parse_xor_expr()?;
3073
3074 if self.check(&TokenType::In) && !self.in_introduces_conversion() {
3084 self.advance(); let collection = self.parse_xor_expr()?;
3086 return Ok(self.ctx.alloc_imperative_expr(Expr::Contains { collection, value: left }));
3087 }
3088 if (self.check(&TokenType::Not) || self.check_word("not"))
3089 && matches!(
3090 self.tokens.get(self.current + 1).map(|t| &t.kind),
3091 Some(TokenType::In)
3092 )
3093 {
3094 self.advance(); self.advance(); let collection = self.parse_xor_expr()?;
3097 let contains = self.ctx.alloc_imperative_expr(Expr::Contains { collection, value: left });
3098 return Ok(self.ctx.alloc_imperative_expr(Expr::Not { operand: contains }));
3099 }
3100
3101 let op = if self.check(&TokenType::Equals) {
3103 self.advance();
3104 Some(BinaryOpKind::Eq)
3105 } else if self.check(&TokenType::Identity) {
3106 self.advance();
3108 Some(BinaryOpKind::Eq)
3109 } else if self.check_word("is") {
3110 let saved_pos = self.current;
3112 self.advance(); if self.check_word("even") || self.check_word("odd") {
3119 let is_odd = self.check_word("odd");
3120 self.advance(); let two = self.ctx.alloc_imperative_expr(Expr::Literal(crate::ast::Literal::Number(2)));
3122 let rem = self.ctx.alloc_imperative_expr(Expr::BinaryOp {
3123 op: BinaryOpKind::Modulo, left, right: two,
3124 });
3125 let want = self.ctx.alloc_imperative_expr(Expr::Literal(
3126 crate::ast::Literal::Number(if is_odd { 1 } else { 0 }),
3127 ));
3128 return Ok(self.ctx.alloc_imperative_expr(Expr::BinaryOp {
3129 op: BinaryOpKind::Eq, left: rem, right: want,
3130 }));
3131 }
3132 if self.check_word("divisible") {
3133 self.advance(); if self.check_word("by") || self.check_preposition_is("by") {
3135 self.advance(); let divisor = self.parse_xor_expr()?;
3137 let rem = self.ctx.alloc_imperative_expr(Expr::BinaryOp {
3138 op: BinaryOpKind::Modulo, left, right: divisor,
3139 });
3140 let zero = self.ctx.alloc_imperative_expr(Expr::Literal(crate::ast::Literal::Number(0)));
3141 return Ok(self.ctx.alloc_imperative_expr(Expr::BinaryOp {
3142 op: BinaryOpKind::Eq, left: rem, right: zero,
3143 }));
3144 }
3145 self.current = saved_pos;
3146 return Ok(left);
3147 }
3148 if self.check_word("between") {
3150 self.advance(); let lo = self.parse_xor_expr()?;
3152 if self.check_word("and") || self.check(&TokenType::And) {
3153 self.advance(); let hi = self.parse_xor_expr()?;
3155 let lower = self.ctx.alloc_imperative_expr(Expr::BinaryOp {
3156 op: BinaryOpKind::LtEq, left: lo, right: left,
3157 });
3158 let upper = self.ctx.alloc_imperative_expr(Expr::BinaryOp {
3159 op: BinaryOpKind::LtEq, left, right: hi,
3160 });
3161 return Ok(self.ctx.alloc_imperative_expr(Expr::BinaryOp {
3162 op: BinaryOpKind::And, left: lower, right: upper,
3163 }));
3164 }
3165 self.current = saved_pos;
3166 return Ok(left);
3167 }
3168
3169 if self.check_word("greater") {
3170 self.advance(); if self.check_word("than") || self.check_preposition_is("than") {
3172 self.advance(); Some(BinaryOpKind::Gt)
3174 } else {
3175 self.current = saved_pos;
3176 None
3177 }
3178 } else if self.check_word("less") {
3179 self.advance(); if self.check_word("than") || self.check_preposition_is("than") {
3181 self.advance(); Some(BinaryOpKind::Lt)
3183 } else {
3184 self.current = saved_pos;
3185 None
3186 }
3187 } else if self.check_word("at") {
3188 self.advance(); if self.check_word("least") {
3190 self.advance(); Some(BinaryOpKind::GtEq)
3192 } else if self.check_word("most") {
3193 self.advance(); Some(BinaryOpKind::LtEq)
3195 } else {
3196 self.current = saved_pos;
3197 None
3198 }
3199 } else if self.check_word("before") {
3200 self.advance(); Some(BinaryOpKind::Lt)
3203 } else if self.check_word("after") {
3204 self.advance(); Some(BinaryOpKind::Gt)
3207 } else if self.check_word("not") || self.check(&TokenType::Not) {
3208 self.advance(); Some(BinaryOpKind::NotEq)
3211 } else if self.check_word("equal") {
3212 self.advance(); if self.check_preposition_is("to") {
3215 self.advance(); Some(BinaryOpKind::Eq)
3217 } else {
3218 self.current = saved_pos;
3219 None
3220 }
3221 } else if self.check_word("approximately") {
3222 self.advance(); if self.check_word("equal") {
3227 self.advance(); if self.check_preposition_is("to") {
3229 self.advance(); }
3231 }
3232 Some(BinaryOpKind::ApproxEq)
3233 } else if matches!(self.peek().kind, TokenType::Number(_))
3234 || (self.check(&TokenType::Minus)
3235 && self.tokens.get(self.current + 1)
3236 .is_some_and(|t| matches!(t.kind, TokenType::Number(_))))
3237 {
3238 Some(BinaryOpKind::Eq)
3244 } else {
3245 self.current = saved_pos;
3246 None
3247 }
3248 } else if self.check(&TokenType::Lt) {
3249 self.advance();
3250 Some(BinaryOpKind::Lt)
3251 } else if self.check(&TokenType::Gt) {
3252 self.advance();
3253 Some(BinaryOpKind::Gt)
3254 } else if self.check(&TokenType::LtEq) {
3255 self.advance();
3256 Some(BinaryOpKind::LtEq)
3257 } else if self.check(&TokenType::GtEq) {
3258 self.advance();
3259 Some(BinaryOpKind::GtEq)
3260 } else if self.check(&TokenType::EqEq) || self.check(&TokenType::Assign) {
3261 self.advance();
3262 Some(BinaryOpKind::Eq)
3263 } else if self.check(&TokenType::NotEq) {
3264 self.advance();
3265 Some(BinaryOpKind::NotEq)
3266 } else {
3267 None
3268 };
3269
3270 if let Some(op) = op {
3271 let right = self.parse_xor_expr()?;
3272 let first = self.ctx.alloc_imperative_expr(Expr::BinaryOp { op, left, right });
3273 if let Some(op2) = self.try_symbolic_comparison_op() {
3277 let hi = self.parse_xor_expr()?;
3278 let second = self.ctx.alloc_imperative_expr(Expr::BinaryOp {
3279 op: op2, left: right, right: hi,
3280 });
3281 return Ok(self.ctx.alloc_imperative_expr(Expr::BinaryOp {
3282 op: BinaryOpKind::And, left: first, right: second,
3283 }));
3284 }
3285 Ok(first)
3286 } else {
3287 Ok(left)
3288 }
3289 }
3290
3291 fn try_symbolic_comparison_op(&mut self) -> Option<BinaryOpKind> {
3295 let op = if self.check(&TokenType::LtEq) {
3296 BinaryOpKind::LtEq
3297 } else if self.check(&TokenType::GtEq) {
3298 BinaryOpKind::GtEq
3299 } else if self.check(&TokenType::Lt) {
3300 BinaryOpKind::Lt
3301 } else if self.check(&TokenType::Gt) {
3302 BinaryOpKind::Gt
3303 } else if self.check(&TokenType::EqEq) {
3304 BinaryOpKind::Eq
3305 } else if self.check(&TokenType::NotEq) {
3306 BinaryOpKind::NotEq
3307 } else {
3308 return None;
3309 };
3310 self.advance();
3311 Some(op)
3312 }
3313
3314 fn parse_let_statement(&mut self) -> ParseResult<Stmt<'a>> {
3315 self.advance(); let mutable = if self.check_mutable_keyword() {
3319 self.advance();
3320 true
3321 } else {
3322 false
3323 };
3324
3325 let var = self.expect_identifier()?;
3327
3328 let ty = if self.check(&TokenType::Colon) {
3330 self.advance(); let type_expr = self.parse_type_expression()?;
3332 Some(self.ctx.alloc_type_expr(type_expr))
3333 } else {
3334 None
3335 };
3336
3337 if !self.check(&TokenType::Be) && !self.check(&TokenType::Assign) {
3339 return Err(ParseError {
3340 kind: ParseErrorKind::ExpectedKeyword { keyword: "be or =".to_string() },
3341 span: self.current_span(),
3342 });
3343 }
3344 self.advance(); if self.check_word("mounted") {
3348 self.advance(); if !self.check(&TokenType::At) && !self.check_preposition_is("at") {
3350 return Err(ParseError {
3351 kind: ParseErrorKind::ExpectedKeyword { keyword: "at".to_string() },
3352 span: self.current_span(),
3353 });
3354 }
3355 self.advance(); let path = self.parse_imperative_expr()?;
3357 return Ok(Stmt::Mount { var, path });
3358 }
3359
3360 if self.check_article() {
3362 let saved_pos = self.current;
3363 self.advance(); if let TokenType::Noun(sym) | TokenType::ProperName(sym) = self.peek().kind {
3367 let word = self.interner.resolve(sym).to_lowercase();
3368 if word == "peeragent" {
3369 self.advance(); if self.check(&TokenType::At) || self.check_preposition_is("at") {
3373 self.advance(); let address = self.parse_imperative_expr()?;
3377
3378 return Ok(Stmt::LetPeerAgent { var, address });
3379 }
3380 }
3381 }
3382 self.current = saved_pos;
3384 }
3385
3386 if self.check_article() {
3390 let saved_pos = self.current;
3391 self.advance(); if self.check(&TokenType::New) {
3393 self.advance(); }
3395
3396 if self.check(&TokenType::Pipe) {
3397 self.advance(); if !self.check_word("of") {
3401 return Err(ParseError {
3402 kind: ParseErrorKind::ExpectedKeyword { keyword: "of".to_string() },
3403 span: self.current_span(),
3404 });
3405 }
3406 self.advance(); let element_type = self.expect_identifier()?;
3410
3411 return Ok(Stmt::CreatePipe { var, element_type, capacity: None });
3414 }
3415 self.current = saved_pos;
3417 }
3418
3419 if self.check(&TokenType::Launch) {
3421 self.advance(); if !self.check_article() {
3425 return Err(ParseError {
3426 kind: ParseErrorKind::ExpectedKeyword { keyword: "a".to_string() },
3427 span: self.current_span(),
3428 });
3429 }
3430 self.advance();
3431
3432 if !self.check(&TokenType::Task) {
3434 return Err(ParseError {
3435 kind: ParseErrorKind::ExpectedKeyword { keyword: "task".to_string() },
3436 span: self.current_span(),
3437 });
3438 }
3439 self.advance();
3440
3441 if !self.check(&TokenType::To) && !self.check_word("to") {
3443 return Err(ParseError {
3444 kind: ParseErrorKind::ExpectedKeyword { keyword: "to".to_string() },
3445 span: self.current_span(),
3446 });
3447 }
3448 self.advance();
3449
3450 let function = self.expect_identifier()?;
3452
3453 let args = if self.check_word("with") {
3455 self.advance();
3456 self.parse_call_arguments()?
3457 } else {
3458 vec![]
3459 };
3460
3461 return Ok(Stmt::LaunchTaskWithHandle { handle: var, function, args });
3462 }
3463
3464 let value = self.parse_imperative_expr()?;
3466
3467 if let Some(declared_ty) = &ty {
3469 if let Some(inferred) = self.infer_literal_type(value) {
3470 if !self.check_type_compatibility(declared_ty, inferred) {
3471 let expected = match declared_ty {
3472 TypeExpr::Primitive(sym) | TypeExpr::Named(sym) => {
3473 self.interner.resolve(*sym).to_string()
3474 }
3475 _ => "unknown".to_string(),
3476 };
3477 return Err(ParseError {
3478 kind: ParseErrorKind::TypeMismatch {
3479 expected,
3480 found: inferred.to_string(),
3481 },
3482 span: self.current_span(),
3483 });
3484 }
3485 }
3486 }
3487
3488 let value = if self.check_word("with") {
3490 let saved = self.current;
3491 self.advance(); if self.check_word("capacity") {
3493 self.advance(); let cap_expr = self.parse_imperative_expr()?;
3495 self.ctx.alloc_imperative_expr(Expr::WithCapacity { value, capacity: cap_expr })
3496 } else {
3497 self.current = saved; value
3499 }
3500 } else {
3501 value
3502 };
3503
3504 self.world_state.drs.introduce_referent(var, var, crate::drs::Gender::Unknown, crate::drs::Number::Singular);
3506
3507 self.user_bound.insert(var);
3508 Ok(Stmt::Let { var, ty, value, mutable })
3509 }
3510
3511 fn check_mutable_keyword(&self) -> bool {
3512 if matches!(self.peek().kind, TokenType::Mut) {
3514 return true;
3515 }
3516 if let TokenType::Noun(sym) | TokenType::Adjective(sym) = self.peek().kind {
3518 let word = self.interner.resolve(sym).to_lowercase();
3519 word == "mutable" || word == "mut"
3520 } else {
3521 false
3522 }
3523 }
3524
3525 fn infer_literal_type(&self, expr: &Expr<'_>) -> Option<&'static str> {
3527 match expr {
3528 Expr::Literal(lit) => match lit {
3529 crate::ast::Literal::Number(_) => Some("Int"),
3530 crate::ast::Literal::Float(_) => Some("Real"),
3531 crate::ast::Literal::Text(_) => Some("Text"),
3532 crate::ast::Literal::Boolean(_) => Some("Bool"),
3533 crate::ast::Literal::Nothing => Some("Unit"),
3534 crate::ast::Literal::Char(_) => Some("Char"),
3535 crate::ast::Literal::Duration(_) => Some("Duration"),
3536 crate::ast::Literal::Date(_) => Some("Date"),
3537 crate::ast::Literal::Moment(_) => Some("Moment"),
3538 crate::ast::Literal::Span { .. } => Some("Span"),
3539 crate::ast::Literal::Time(_) => Some("Time"),
3540 },
3541 _ => None, }
3543 }
3544
3545 fn check_type_compatibility(&self, declared: &TypeExpr<'_>, inferred: &str) -> bool {
3547 match declared {
3548 TypeExpr::Primitive(sym) | TypeExpr::Named(sym) => {
3549 let declared_name = self.interner.resolve(*sym);
3550 declared_name.eq_ignore_ascii_case(inferred)
3553 || (declared_name.eq_ignore_ascii_case("Nat") && inferred == "Int")
3554 || (declared_name.eq_ignore_ascii_case("Byte") && inferred == "Int")
3555 || (declared_name.eq_ignore_ascii_case("Rational") && inferred == "Int")
3556 }
3557 _ => true, }
3559 }
3560
3561 fn peek_compound_assignment(&self) -> bool {
3572 let is_identifier = matches!(
3573 self.peek().kind,
3574 TokenType::Noun(_) | TokenType::ProperName(_) | TokenType::Identifier
3575 | TokenType::Adjective(_) | TokenType::Verb { .. }
3576 | TokenType::Particle(_) | TokenType::Ambiguous { .. }
3577 | TokenType::Pronoun { .. }
3578 );
3579 if !is_identifier {
3580 return false;
3581 }
3582 let mut offset = 1;
3583 while self.current + offset < self.tokens.len() {
3584 match &self.tokens[self.current + offset].kind {
3585 TokenType::PlusEq
3586 | TokenType::MinusEq
3587 | TokenType::StarEq
3588 | TokenType::SlashEq
3589 | TokenType::PercentEq => return true,
3590 TokenType::Period | TokenType::Newline | TokenType::EOF => return false,
3591 _ => offset += 1,
3592 }
3593 }
3594 false
3595 }
3596
3597 fn parse_compound_assignment(&mut self) -> ParseResult<Stmt<'a>> {
3601 use crate::ast::Expr;
3602 let target = self.parse_imperative_expr()?;
3603 let op = match self.peek().kind {
3604 TokenType::PlusEq => BinaryOpKind::Add,
3605 TokenType::MinusEq => BinaryOpKind::Subtract,
3606 TokenType::StarEq => BinaryOpKind::Multiply,
3607 TokenType::SlashEq => BinaryOpKind::Divide,
3608 TokenType::PercentEq => BinaryOpKind::Modulo,
3609 _ => {
3610 return Err(ParseError {
3611 kind: ParseErrorKind::ExpectedKeyword { keyword: "+= -= *= /= %=".to_string() },
3612 span: self.current_span(),
3613 });
3614 }
3615 };
3616 self.advance(); let rhs = self.parse_imperative_expr()?;
3618 let combined = self.ctx.alloc_imperative_expr(Expr::BinaryOp { op, left: target, right: rhs });
3619 match target {
3622 Expr::Identifier(sym) => Ok(Stmt::Set { target: *sym, value: combined }),
3623 Expr::FieldAccess { object, field } => {
3624 Ok(Stmt::SetField { object, field: *field, value: combined })
3625 }
3626 Expr::Index { collection, index } => {
3627 Ok(self.desugar_place_set_index(collection, index, combined))
3628 }
3629 _ => Err(ParseError {
3630 kind: ParseErrorKind::ExpectedIdentifier,
3631 span: self.current_span(),
3632 }),
3633 }
3634 }
3635
3636 fn peek_equals_assignment(&self) -> bool {
3637 let is_identifier = matches!(
3641 self.peek().kind,
3642 TokenType::Noun(_) | TokenType::ProperName(_) | TokenType::Identifier
3643 | TokenType::Adjective(_) | TokenType::Verb { .. }
3644 | TokenType::Particle(_) | TokenType::Ambiguous { .. }
3645 | TokenType::Pronoun { .. }
3646 );
3647 if !is_identifier {
3648 return false;
3649 }
3650
3651 if self.current + 1 >= self.tokens.len() {
3653 return false;
3654 }
3655
3656 let next = &self.tokens[self.current + 1].kind;
3657
3658 if matches!(next, TokenType::Assign) {
3660 return true;
3661 }
3662
3663 if matches!(next, TokenType::Colon) {
3666 let mut offset = 2;
3667 while self.current + offset < self.tokens.len() {
3668 let tok = &self.tokens[self.current + offset].kind;
3669 if matches!(tok, TokenType::Assign) {
3670 return true;
3671 }
3672 if matches!(tok, TokenType::Period | TokenType::Newline | TokenType::EOF) {
3673 return false;
3674 }
3675 offset += 1;
3676 }
3677 }
3678
3679 false
3680 }
3681
3682 fn parse_equals_assignment(&mut self, explicit_mutable: bool) -> ParseResult<Stmt<'a>> {
3684 if explicit_mutable {
3686 self.advance(); }
3688
3689 let var = self.expect_identifier()?;
3691
3692 let ty = if self.check(&TokenType::Colon) {
3694 self.advance(); let type_expr = self.parse_type_expression()?;
3696 Some(self.ctx.alloc_type_expr(type_expr))
3697 } else {
3698 None
3699 };
3700
3701 if !self.check(&TokenType::Assign) {
3703 return Err(ParseError {
3704 kind: ParseErrorKind::ExpectedKeyword { keyword: "=".to_string() },
3705 span: self.current_span(),
3706 });
3707 }
3708 self.advance(); let value = self.parse_imperative_expr()?;
3712
3713 let value = if self.check_word("with") {
3715 let saved = self.current;
3716 self.advance(); if self.check_word("capacity") {
3718 self.advance(); let cap_expr = self.parse_imperative_expr()?;
3720 self.ctx.alloc_imperative_expr(Expr::WithCapacity { value, capacity: cap_expr })
3721 } else {
3722 self.current = saved; value
3724 }
3725 } else {
3726 value
3727 };
3728
3729 if !explicit_mutable && ty.is_none() && self.user_bound.contains(&var) {
3735 return Ok(Stmt::Set { target: var, value });
3736 }
3737
3738 self.world_state.drs.introduce_referent(var, var, crate::drs::Gender::Unknown, crate::drs::Number::Singular);
3740
3741 self.user_bound.insert(var);
3742 Ok(Stmt::Let { var, ty, value, mutable: explicit_mutable })
3743 }
3744
3745 fn parse_set_statement(&mut self) -> ParseResult<Stmt<'a>> {
3746 use crate::ast::Expr;
3747 self.advance(); let target_expr = self.parse_imperative_expr()?;
3751
3752 let target_expr = if self.check(&TokenType::At) {
3754 self.advance(); let key = self.parse_imperative_expr()?;
3756 self.ctx.alloc_imperative_expr(Expr::Index { collection: target_expr, index: key })
3757 } else {
3758 target_expr
3759 };
3760
3761 let is_to = self.check(&TokenType::To) || matches!(
3763 &self.peek().kind,
3764 TokenType::Preposition(sym) if self.interner.resolve(*sym) == "to"
3765 );
3766 if !is_to {
3767 return Err(ParseError {
3768 kind: ParseErrorKind::ExpectedKeyword { keyword: "to".to_string() },
3769 span: self.current_span(),
3770 });
3771 }
3772 self.advance(); let value = self.parse_imperative_expr()?;
3776
3777 match target_expr {
3780 Expr::FieldAccess { object, field } => {
3781 Ok(Stmt::SetField { object: *object, field: *field, value })
3782 }
3783 Expr::Identifier(target) => {
3784 Ok(Stmt::Set { target: *target, value })
3785 }
3786 Expr::Index { collection, index } => {
3787 Ok(self.desugar_place_set_index(*collection, *index, value))
3788 }
3789 _ => Err(ParseError {
3790 kind: ParseErrorKind::ExpectedIdentifier,
3791 span: self.current_span(),
3792 })
3793 }
3794 }
3795
3796 fn parse_return_statement(&mut self) -> ParseResult<Stmt<'a>> {
3797 self.advance(); if self.check(&TokenType::Period) || self.is_at_end() {
3801 return Ok(Stmt::Return { value: None });
3802 }
3803
3804 let value = self.parse_condition()?;
3808 if self.check(&TokenType::If) {
3810 self.advance(); let cond = self.parse_condition()?;
3812 let ret = Stmt::Return { value: Some(value) };
3813 let then_block = self.ctx.stmts.expect("imperative arenas not initialized")
3814 .alloc_slice(std::iter::once(ret));
3815 return Ok(Stmt::If { cond, then_block, else_block: None });
3816 }
3817 Ok(Stmt::Return { value: Some(value) })
3818 }
3819
3820 fn parse_break_statement(&mut self) -> ParseResult<Stmt<'a>> {
3821 self.advance(); Ok(Stmt::Break)
3823 }
3824
3825 fn parse_assert_statement(&mut self) -> ParseResult<Stmt<'a>> {
3826 self.advance(); if self.check(&TokenType::That) || matches!(self.peek().kind, TokenType::Article(Definiteness::Distal)) {
3830 self.advance();
3831 }
3832
3833 let condition = self.parse_condition()?;
3836
3837 Ok(Stmt::RuntimeAssert { condition, hard: false })
3838 }
3839
3840 fn parse_require_statement(&mut self) -> ParseResult<Stmt<'a>> {
3844 self.advance(); if self.check(&TokenType::That) || matches!(self.peek().kind, TokenType::Article(Definiteness::Distal)) {
3848 self.advance();
3849 }
3850
3851 let condition = self.parse_condition()?;
3852 Ok(Stmt::RuntimeAssert { condition, hard: true })
3853 }
3854
3855 fn parse_trust_statement(&mut self) -> ParseResult<Stmt<'a>> {
3858 self.advance(); if self.check(&TokenType::That) || matches!(self.peek().kind, TokenType::Article(Definiteness::Distal)) {
3862 self.advance();
3863 }
3864
3865 let saved_mode = self.mode;
3867 self.mode = ParserMode::Declarative;
3868
3869 let proposition = self.parse_prefix()?;
3873
3874 self.mode = saved_mode;
3876
3877 if !self.check(&TokenType::Because) {
3879 return Err(ParseError {
3880 kind: ParseErrorKind::UnexpectedToken {
3881 expected: TokenType::Because,
3882 found: self.peek().kind.clone(),
3883 },
3884 span: self.current_span(),
3885 });
3886 }
3887 self.advance(); let justification = match &self.peek().kind {
3891 TokenType::StringLiteral(sym) => {
3892 let s = *sym;
3893 self.advance();
3894 s
3895 }
3896 _ => {
3897 return Err(ParseError {
3898 kind: ParseErrorKind::UnexpectedToken {
3899 expected: TokenType::StringLiteral(self.interner.intern("")),
3900 found: self.peek().kind.clone(),
3901 },
3902 span: self.current_span(),
3903 });
3904 }
3905 };
3906
3907 Ok(Stmt::Trust { proposition, justification })
3908 }
3909
3910 fn parse_check_statement(&mut self) -> ParseResult<Stmt<'a>> {
3914 let start_span = self.current_span();
3915 self.advance(); if self.check(&TokenType::That) {
3919 self.advance();
3920 }
3921
3922 if matches!(self.peek().kind, TokenType::Article(_)) {
3924 self.advance();
3925 }
3926
3927 let subject = match &self.peek().kind {
3929 TokenType::Noun(sym) | TokenType::Adjective(sym) | TokenType::ProperName(sym) => {
3930 let s = *sym;
3931 self.advance();
3932 s
3933 }
3934 _ => {
3935 let tok = self.peek();
3937 let s = tok.lexeme;
3938 self.advance();
3939 s
3940 }
3941 };
3942
3943 let is_capability;
3945 let predicate;
3946 let object;
3947
3948 if self.check(&TokenType::Is) || self.check(&TokenType::Are) {
3949 is_capability = false;
3951 self.advance(); predicate = match &self.peek().kind {
3955 TokenType::Noun(sym) | TokenType::Adjective(sym) | TokenType::ProperName(sym) => {
3956 let s = *sym;
3957 self.advance();
3958 s
3959 }
3960 _ => {
3961 let tok = self.peek();
3962 let s = tok.lexeme;
3963 self.advance();
3964 s
3965 }
3966 };
3967 object = None;
3968 } else if self.check(&TokenType::Can) {
3969 is_capability = true;
3971 self.advance(); predicate = match &self.peek().kind {
3975 TokenType::Verb { lemma, .. } => {
3976 let s = *lemma;
3977 self.advance();
3978 s
3979 }
3980 TokenType::Noun(sym) | TokenType::Adjective(sym) | TokenType::ProperName(sym) => {
3981 let s = *sym;
3982 self.advance();
3983 s
3984 }
3985 _ => {
3986 let tok = self.peek();
3987 let s = tok.lexeme;
3988 self.advance();
3989 s
3990 }
3991 };
3992
3993 if matches!(self.peek().kind, TokenType::Article(_)) {
3995 self.advance();
3996 }
3997
3998 let obj = match &self.peek().kind {
4000 TokenType::Noun(sym) | TokenType::Adjective(sym) | TokenType::ProperName(sym) => {
4001 let s = *sym;
4002 self.advance();
4003 s
4004 }
4005 _ => {
4006 let tok = self.peek();
4007 let s = tok.lexeme;
4008 self.advance();
4009 s
4010 }
4011 };
4012 object = Some(obj);
4013 } else {
4014 return Err(ParseError {
4015 kind: ParseErrorKind::ExpectedKeyword { keyword: "is/can".to_string() },
4016 span: self.current_span(),
4017 });
4018 }
4019
4020 let source_text = if is_capability {
4022 let obj_name = self.interner.resolve(object.unwrap());
4023 let pred_name = self.interner.resolve(predicate);
4024 let subj_name = self.interner.resolve(subject);
4025 format!("{} can {} the {}", subj_name, pred_name, obj_name)
4026 } else {
4027 let pred_name = self.interner.resolve(predicate);
4028 let subj_name = self.interner.resolve(subject);
4029 format!("{} is {}", subj_name, pred_name)
4030 };
4031
4032 Ok(Stmt::Check {
4033 subject,
4034 predicate,
4035 is_capability,
4036 object,
4037 source_text,
4038 span: start_span,
4039 })
4040 }
4041
4042 fn read_word_string(&mut self) -> String {
4044 let s = self.interner.resolve(self.peek().lexeme).to_string();
4045 self.advance();
4046 s
4047 }
4048
4049 fn expect_keyword(&mut self, word: &str) -> ParseResult<()> {
4051 if self.check_word(word) {
4052 self.advance();
4053 Ok(())
4054 } else {
4055 Err(ParseError {
4056 kind: ParseErrorKind::Custom(format!("expected `{}` here", word)),
4057 span: self.current_span(),
4058 })
4059 }
4060 }
4061
4062 fn read_int_literal(&mut self) -> ParseResult<i64> {
4064 if let TokenType::Number(sym) = &self.peek().kind {
4065 let sym = *sym;
4066 self.advance();
4067 self.interner.resolve(sym).parse::<i64>().map_err(|_| ParseError {
4068 kind: ParseErrorKind::Custom("expected an integer bound".to_string()),
4069 span: self.current_span(),
4070 })
4071 } else {
4072 Err(ParseError {
4073 kind: ParseErrorKind::Custom("expected an integer bound".to_string()),
4074 span: self.current_span(),
4075 })
4076 }
4077 }
4078
4079 fn parse_accept_contract(&mut self) -> ParseResult<()> {
4083 self.advance(); self.expect_keyword("computed")?;
4085 let name = self.read_word_string();
4086 self.expect_keyword("where")?;
4087 let _param = self.read_word_string(); self.expect_keyword("is")?;
4089 if self.check_word("a") || self.check_word("an") {
4090 self.advance();
4091 }
4092 self.expect_keyword("Int")?;
4093 self.expect_keyword("from")?;
4094 let lo = self.read_int_literal()?;
4095 if self.check(&TokenType::To) || self.check_word("to") {
4097 self.advance();
4098 } else {
4099 return Err(ParseError {
4100 kind: ParseErrorKind::Custom("expected `to` between the contract bounds".to_string()),
4101 span: self.current_span(),
4102 });
4103 }
4104 let hi = self.read_int_literal()?;
4105 if self.check(&TokenType::Period) {
4106 self.advance(); }
4108 self.contracts.insert(name, (lo, hi));
4109 Ok(())
4110 }
4111
4112 fn parse_run_under_contract(&mut self) -> ParseResult<Stmt<'a>> {
4116 self.advance(); let f_expr = self.parse_imperative_expr()?;
4118 self.expect_keyword("on")?;
4119 let arg_expr = self.parse_imperative_expr()?;
4120 self.expect_keyword("under")?;
4121 let name = self.read_word_string();
4122 let (lo, hi) = *self.contracts.get(&name).ok_or_else(|| ParseError {
4123 kind: ParseErrorKind::Custom(format!(
4124 "unknown acceptance contract `{name}` — declare it with `Accept computed {name} where …`"
4125 )),
4126 span: self.current_span(),
4127 })?;
4128 self.expect_keyword("into")?;
4129 let var = self.peek().lexeme;
4130 self.advance();
4131 let lo_e = self.ctx.alloc_imperative_expr(Expr::Literal(crate::ast::Literal::Number(lo)));
4132 let hi_e = self.ctx.alloc_imperative_expr(Expr::Literal(crate::ast::Literal::Number(hi)));
4133 let run_sym = self.interner.intern("run_accepted");
4134 let call = self
4135 .ctx
4136 .alloc_imperative_expr(Expr::Call { function: run_sym, args: vec![f_expr, arg_expr, lo_e, hi_e] });
4137 Ok(Stmt::Let { var, ty: None, value: call, mutable: false })
4138 }
4139
4140 fn parse_listen_statement(&mut self) -> ParseResult<Stmt<'a>> {
4143 self.advance(); if !self.check_preposition_is("on") {
4147 return Err(ParseError {
4148 kind: ParseErrorKind::ExpectedKeyword { keyword: "on".to_string() },
4149 span: self.current_span(),
4150 });
4151 }
4152 self.advance(); let address = self.parse_imperative_expr()?;
4156
4157 let secure = self.parse_secure_clause()?;
4158 Ok(Stmt::Listen { address, secure })
4159 }
4160
4161 fn parse_connect_statement(&mut self) -> ParseResult<Stmt<'a>> {
4164 self.advance(); if !self.check(&TokenType::To) && !self.check_preposition_is("to") {
4168 return Err(ParseError {
4169 kind: ParseErrorKind::ExpectedKeyword { keyword: "to".to_string() },
4170 span: self.current_span(),
4171 });
4172 }
4173 self.advance(); let address = self.parse_imperative_expr()?;
4177
4178 let secure = self.parse_secure_clause()?;
4179 Ok(Stmt::ConnectTo { address, secure })
4180 }
4181
4182 fn parse_secure_clause(&mut self) -> ParseResult<Option<crate::ast::SecurePad<'a>>> {
4186 if !(self.check_word("with") && self.peek_word_at(1, "pad")) {
4188 return Ok(None);
4189 }
4190 self.advance(); self.advance(); let pad = self.parse_imperative_expr()?;
4193 if !self.check_word("as") {
4194 return Err(ParseError {
4195 kind: ParseErrorKind::ExpectedKeyword { keyword: "as".to_string() },
4196 span: self.current_span(),
4197 });
4198 }
4199 self.advance(); let role = if self.check_word("initiator") {
4201 self.advance();
4202 crate::ast::SecureRole::Initiator
4203 } else if self.check_word("responder") {
4204 self.advance();
4205 crate::ast::SecureRole::Responder
4206 } else {
4207 return Err(ParseError {
4208 kind: ParseErrorKind::ExpectedKeyword { keyword: "initiator or responder".to_string() },
4209 span: self.current_span(),
4210 });
4211 };
4212 Ok(Some(crate::ast::SecurePad { pad, role }))
4213 }
4214
4215 fn parse_sleep_statement(&mut self) -> ParseResult<Stmt<'a>> {
4218 self.advance(); let milliseconds = self.parse_imperative_expr()?;
4222
4223 Ok(Stmt::Sleep { milliseconds })
4224 }
4225
4226 fn parse_sync_statement(&mut self) -> ParseResult<Stmt<'a>> {
4229 self.advance(); let var = match &self.tokens[self.current].kind {
4234 TokenType::ProperName(sym) | TokenType::Noun(sym) | TokenType::Adjective(sym) => {
4235 let s = *sym;
4236 self.advance();
4237 s
4238 }
4239 TokenType::Verb { .. } | TokenType::Ambiguous { .. } => {
4240 let s = self.tokens[self.current].lexeme;
4241 self.advance();
4242 s
4243 }
4244 _ => {
4245 return Err(ParseError {
4246 kind: ParseErrorKind::ExpectedKeyword { keyword: "variable name".to_string() },
4247 span: self.current_span(),
4248 });
4249 }
4250 };
4251
4252 if !self.check_preposition_is("on") {
4254 return Err(ParseError {
4255 kind: ParseErrorKind::ExpectedKeyword { keyword: "on".to_string() },
4256 span: self.current_span(),
4257 });
4258 }
4259 self.advance(); let topic = self.parse_imperative_expr()?;
4263
4264 Ok(Stmt::Sync { var, topic })
4265 }
4266
4267 fn parse_mount_statement(&mut self) -> ParseResult<Stmt<'a>> {
4271 self.advance(); let var = match &self.tokens[self.current].kind {
4276 TokenType::ProperName(sym) | TokenType::Noun(sym) | TokenType::Adjective(sym) => {
4277 let s = *sym;
4278 self.advance();
4279 s
4280 }
4281 TokenType::Verb { .. } | TokenType::Ambiguous { .. } => {
4282 let s = self.tokens[self.current].lexeme;
4283 self.advance();
4284 s
4285 }
4286 _ => {
4287 return Err(ParseError {
4288 kind: ParseErrorKind::ExpectedKeyword { keyword: "variable name".to_string() },
4289 span: self.current_span(),
4290 });
4291 }
4292 };
4293
4294 if !self.check(&TokenType::At) {
4296 return Err(ParseError {
4297 kind: ParseErrorKind::ExpectedKeyword { keyword: "at".to_string() },
4298 span: self.current_span(),
4299 });
4300 }
4301 self.advance(); let path = self.parse_imperative_expr()?;
4305
4306 Ok(Stmt::Mount { var, path })
4307 }
4308
4309 fn lookahead_contains_into(&self) -> bool {
4315 for i in self.current..std::cmp::min(self.current + 5, self.tokens.len()) {
4316 if matches!(self.tokens[i].kind, TokenType::Into) {
4317 return true;
4318 }
4319 }
4320 false
4321 }
4322
4323 fn lookahead_is_first_of(&self) -> bool {
4325 self.current + 3 < self.tokens.len()
4327 && matches!(self.tokens.get(self.current + 1), Some(t) if matches!(t.kind, TokenType::Article(_)))
4328 && self.tokens.get(self.current + 2)
4329 .map(|t| self.interner.resolve(t.lexeme).to_lowercase() == "first")
4330 .unwrap_or(false)
4331 }
4332
4333 fn parse_launch_statement(&mut self) -> ParseResult<Stmt<'a>> {
4336 self.advance(); if !self.check_article() {
4340 return Err(ParseError {
4341 kind: ParseErrorKind::ExpectedKeyword { keyword: "a".to_string() },
4342 span: self.current_span(),
4343 });
4344 }
4345 self.advance();
4346
4347 if !self.check(&TokenType::Task) {
4349 return Err(ParseError {
4350 kind: ParseErrorKind::ExpectedKeyword { keyword: "task".to_string() },
4351 span: self.current_span(),
4352 });
4353 }
4354 self.advance();
4355
4356 if !self.check(&TokenType::To) && !self.check_preposition_is("to") {
4358 return Err(ParseError {
4359 kind: ParseErrorKind::ExpectedKeyword { keyword: "to".to_string() },
4360 span: self.current_span(),
4361 });
4362 }
4363 self.advance();
4364
4365 let function = match &self.tokens[self.current].kind {
4368 TokenType::ProperName(sym) | TokenType::Noun(sym) | TokenType::Adjective(sym) => {
4369 let s = *sym;
4370 self.advance();
4371 s
4372 }
4373 TokenType::Verb { .. } | TokenType::Ambiguous { .. } => {
4374 let s = self.tokens[self.current].lexeme;
4375 self.advance();
4376 s
4377 }
4378 _ => {
4379 return Err(ParseError {
4380 kind: ParseErrorKind::ExpectedKeyword { keyword: "function name".to_string() },
4381 span: self.current_span(),
4382 });
4383 }
4384 };
4385
4386 let args = if self.check(&TokenType::LParen) {
4388 self.parse_call_arguments()?
4389 } else if self.check_word("with") {
4390 self.advance(); let mut args = Vec::new();
4392 let arg = self.parse_imperative_expr()?;
4393 args.push(arg);
4394 while self.check(&TokenType::And) {
4396 self.advance();
4397 let arg = self.parse_imperative_expr()?;
4398 args.push(arg);
4399 }
4400 args
4401 } else {
4402 Vec::new()
4403 };
4404
4405 Ok(Stmt::LaunchTask { function, args })
4406 }
4407
4408 fn parse_send_pipe_statement(&mut self) -> ParseResult<Stmt<'a>> {
4411 self.advance(); let value = self.parse_imperative_expr()?;
4415
4416 if !self.check(&TokenType::Into) {
4418 return Err(ParseError {
4419 kind: ParseErrorKind::ExpectedKeyword { keyword: "into".to_string() },
4420 span: self.current_span(),
4421 });
4422 }
4423 self.advance();
4424
4425 let pipe = self.parse_imperative_expr()?;
4427
4428 Ok(Stmt::SendPipe { value, pipe })
4429 }
4430
4431 fn parse_receive_pipe_statement(&mut self) -> ParseResult<Stmt<'a>> {
4434 self.advance(); let var = self.expect_identifier()?;
4438
4439 if !self.check(&TokenType::From) && !self.check_preposition_is("from") {
4441 return Err(ParseError {
4442 kind: ParseErrorKind::ExpectedKeyword { keyword: "from".to_string() },
4443 span: self.current_span(),
4444 });
4445 }
4446 self.advance();
4447
4448 let pipe = self.parse_imperative_expr()?;
4450
4451 Ok(Stmt::ReceivePipe { var, pipe })
4452 }
4453
4454 fn parse_try_statement(&mut self) -> ParseResult<Stmt<'a>> {
4457 self.advance(); if !self.check(&TokenType::To) && !self.check_preposition_is("to") {
4461 return Err(ParseError {
4462 kind: ParseErrorKind::ExpectedKeyword { keyword: "to".to_string() },
4463 span: self.current_span(),
4464 });
4465 }
4466 self.advance();
4467
4468 if self.check(&TokenType::Send) {
4470 self.advance(); let value = self.parse_imperative_expr()?;
4472
4473 if !self.check(&TokenType::Into) {
4474 return Err(ParseError {
4475 kind: ParseErrorKind::ExpectedKeyword { keyword: "into".to_string() },
4476 span: self.current_span(),
4477 });
4478 }
4479 self.advance();
4480
4481 let pipe = self.parse_imperative_expr()?;
4482 Ok(Stmt::TrySendPipe { value, pipe, result: None })
4483 } else if self.check(&TokenType::Receive) {
4484 self.advance(); let var = self.expect_identifier()?;
4487
4488 if !self.check(&TokenType::From) && !self.check_preposition_is("from") {
4489 return Err(ParseError {
4490 kind: ParseErrorKind::ExpectedKeyword { keyword: "from".to_string() },
4491 span: self.current_span(),
4492 });
4493 }
4494 self.advance();
4495
4496 let pipe = self.parse_imperative_expr()?;
4497 Ok(Stmt::TryReceivePipe { var, pipe })
4498 } else {
4499 Err(ParseError {
4500 kind: ParseErrorKind::ExpectedKeyword { keyword: "send or receive".to_string() },
4501 span: self.current_span(),
4502 })
4503 }
4504 }
4505
4506 fn parse_escape_body(&mut self) -> ParseResult<(crate::intern::Symbol, crate::intern::Symbol, crate::token::Span)> {
4509 let start_span = self.current_span();
4510 self.advance(); if !self.check(&TokenType::To) && !self.check_preposition_is("to") {
4514 return Err(ParseError {
4515 kind: ParseErrorKind::Custom(
4516 "Expected 'to' after 'Escape'. Syntax: Escape to Rust:".to_string()
4517 ),
4518 span: self.current_span(),
4519 });
4520 }
4521 self.advance(); let language = match &self.peek().kind {
4525 TokenType::ProperName(sym) => {
4526 let s = *sym;
4527 self.advance();
4528 s
4529 }
4530 TokenType::Noun(sym) | TokenType::Adjective(sym) => {
4531 let s = *sym;
4532 self.advance();
4533 s
4534 }
4535 _ => {
4536 return Err(ParseError {
4537 kind: ParseErrorKind::Custom(
4538 "Expected language name after 'Escape to'. Currently only 'Rust' is supported.".to_string()
4539 ),
4540 span: self.current_span(),
4541 });
4542 }
4543 };
4544
4545 if !language.is(self.interner, "Rust") {
4547 let lang_str = self.interner.resolve(language);
4548 return Err(ParseError {
4549 kind: ParseErrorKind::Custom(
4550 format!("Unsupported escape target '{}'. Only 'Rust' is supported.", lang_str)
4551 ),
4552 span: self.current_span(),
4553 });
4554 }
4555
4556 if !self.check(&TokenType::Colon) {
4558 return Err(ParseError {
4559 kind: ParseErrorKind::Custom(
4560 "Expected ':' after 'Escape to Rust'. Syntax: Escape to Rust:".to_string()
4561 ),
4562 span: self.current_span(),
4563 });
4564 }
4565 self.advance(); if !self.check(&TokenType::Indent) {
4569 return Err(ParseError {
4570 kind: ParseErrorKind::Custom(
4571 "Expected indented block after 'Escape to Rust:'.".to_string()
4572 ),
4573 span: self.current_span(),
4574 });
4575 }
4576 self.advance(); let code = match &self.peek().kind {
4580 TokenType::EscapeBlock(sym) => {
4581 let s = *sym;
4582 self.advance();
4583 s
4584 }
4585 _ => {
4586 return Err(ParseError {
4587 kind: ParseErrorKind::Custom(
4588 "Escape block body is empty or malformed.".to_string()
4589 ),
4590 span: self.current_span(),
4591 });
4592 }
4593 };
4594
4595 if self.check(&TokenType::Dedent) {
4597 self.advance();
4598 }
4599
4600 let end_span = self.previous().span;
4601 Ok((language, code, crate::token::Span::new(start_span.start, end_span.end)))
4602 }
4603
4604 fn parse_escape_statement(&mut self) -> ParseResult<Stmt<'a>> {
4606 let (language, code, span) = self.parse_escape_body()?;
4607 Ok(Stmt::Escape { language, code, span })
4608 }
4609
4610 fn parse_escape_expr(&mut self) -> ParseResult<&'a Expr<'a>> {
4613 let (language, code, _span) = self.parse_escape_body()?;
4614 Ok(self.ctx.alloc_imperative_expr(Expr::Escape { language, code }))
4615 }
4616
4617 fn parse_requires_block(&mut self) -> ParseResult<Vec<Stmt<'a>>> {
4620 let mut deps = Vec::new();
4621
4622 loop {
4623 if self.is_at_end() {
4625 break;
4626 }
4627 if matches!(self.peek().kind, TokenType::BlockHeader { .. }) {
4628 break;
4629 }
4630
4631 if self.check(&TokenType::Indent)
4633 || self.check(&TokenType::Dedent)
4634 || self.check(&TokenType::Newline)
4635 {
4636 self.advance();
4637 continue;
4638 }
4639
4640 if matches!(self.peek().kind, TokenType::Article(_)) {
4642 let dep = self.parse_require_line()?;
4643 deps.push(dep);
4644 continue;
4645 }
4646
4647 self.advance();
4649 }
4650
4651 Ok(deps)
4652 }
4653
4654 fn parse_require_line(&mut self) -> ParseResult<Stmt<'a>> {
4657 let start_span = self.current_span();
4658
4659 if !matches!(self.peek().kind, TokenType::Article(_)) {
4661 return Err(crate::error::ParseError {
4662 kind: crate::error::ParseErrorKind::Custom(
4663 "Expected 'The' to begin a dependency declaration.".to_string(),
4664 ),
4665 span: self.current_span(),
4666 });
4667 }
4668 self.advance(); let crate_name = if let TokenType::StringLiteral(sym) = self.peek().kind {
4672 let s = sym;
4673 self.advance();
4674 s
4675 } else {
4676 return Err(crate::error::ParseError {
4677 kind: crate::error::ParseErrorKind::Custom(
4678 "Expected a string literal for the crate name, e.g. \"serde\".".to_string(),
4679 ),
4680 span: self.current_span(),
4681 });
4682 };
4683
4684 if !self.check_word("crate") {
4686 return Err(crate::error::ParseError {
4687 kind: crate::error::ParseErrorKind::Custom(
4688 "Expected the word 'crate' after the crate name.".to_string(),
4689 ),
4690 span: self.current_span(),
4691 });
4692 }
4693 self.advance(); if !self.check_word("version") {
4697 return Err(crate::error::ParseError {
4698 kind: crate::error::ParseErrorKind::Custom(
4699 "Expected 'version' after 'crate'.".to_string(),
4700 ),
4701 span: self.current_span(),
4702 });
4703 }
4704 self.advance(); let version = if let TokenType::StringLiteral(sym) = self.peek().kind {
4708 let s = sym;
4709 self.advance();
4710 s
4711 } else {
4712 return Err(crate::error::ParseError {
4713 kind: crate::error::ParseErrorKind::Custom(
4714 "Expected a string literal for the version, e.g. \"1.0\".".to_string(),
4715 ),
4716 span: self.current_span(),
4717 });
4718 };
4719
4720 let mut features = Vec::new();
4722 if self.check_preposition_is("with") {
4723 self.advance(); if !self.check_word("features") {
4727 return Err(crate::error::ParseError {
4728 kind: crate::error::ParseErrorKind::Custom(
4729 "Expected 'features' after 'with'.".to_string(),
4730 ),
4731 span: self.current_span(),
4732 });
4733 }
4734 self.advance(); if let TokenType::StringLiteral(sym) = self.peek().kind {
4738 features.push(sym);
4739 self.advance();
4740 } else {
4741 return Err(crate::error::ParseError {
4742 kind: crate::error::ParseErrorKind::Custom(
4743 "Expected a string literal for a feature name.".to_string(),
4744 ),
4745 span: self.current_span(),
4746 });
4747 }
4748
4749 while self.check(&TokenType::And) {
4751 self.advance(); if let TokenType::StringLiteral(sym) = self.peek().kind {
4753 features.push(sym);
4754 self.advance();
4755 } else {
4756 return Err(crate::error::ParseError {
4757 kind: crate::error::ParseErrorKind::Custom(
4758 "Expected a string literal for a feature name after 'and'.".to_string(),
4759 ),
4760 span: self.current_span(),
4761 });
4762 }
4763 }
4764 }
4765
4766 if self.check(&TokenType::For) {
4768 self.advance(); while !self.check(&TokenType::Period) && !self.check(&TokenType::EOF)
4770 && !self.check(&TokenType::Newline)
4771 && !matches!(self.peek().kind, TokenType::BlockHeader { .. })
4772 {
4773 self.advance();
4774 }
4775 }
4776
4777 if self.check(&TokenType::Period) {
4779 self.advance();
4780 }
4781
4782 let end_span = self.previous().span;
4783
4784 Ok(Stmt::Require {
4785 crate_name,
4786 version,
4787 features,
4788 span: crate::token::Span::new(start_span.start, end_span.end),
4789 })
4790 }
4791
4792 fn parse_stop_statement(&mut self) -> ParseResult<Stmt<'a>> {
4795 self.advance(); let handle = self.parse_imperative_expr()?;
4798
4799 Ok(Stmt::StopTask { handle })
4800 }
4801
4802 fn parse_select_statement(&mut self) -> ParseResult<Stmt<'a>> {
4810 use crate::ast::stmt::SelectBranch;
4811
4812 self.advance(); if !self.check_article() {
4816 return Err(ParseError {
4817 kind: ParseErrorKind::ExpectedKeyword { keyword: "the".to_string() },
4818 span: self.current_span(),
4819 });
4820 }
4821 self.advance();
4822
4823 if !self.check_word("first") {
4825 return Err(ParseError {
4826 kind: ParseErrorKind::ExpectedKeyword { keyword: "first".to_string() },
4827 span: self.current_span(),
4828 });
4829 }
4830 self.advance();
4831
4832 if !self.check_preposition_is("of") {
4834 return Err(ParseError {
4835 kind: ParseErrorKind::ExpectedKeyword { keyword: "of".to_string() },
4836 span: self.current_span(),
4837 });
4838 }
4839 self.advance();
4840
4841 if !self.check(&TokenType::Colon) {
4843 return Err(ParseError {
4844 kind: ParseErrorKind::ExpectedKeyword { keyword: ":".to_string() },
4845 span: self.current_span(),
4846 });
4847 }
4848 self.advance();
4849
4850 if !self.check(&TokenType::Indent) {
4852 return Err(ParseError {
4853 kind: ParseErrorKind::ExpectedStatement,
4854 span: self.current_span(),
4855 });
4856 }
4857 self.advance();
4858
4859 let mut branches = Vec::new();
4861 while !self.check(&TokenType::Dedent) && !self.is_at_end() {
4862 let branch = self.parse_select_branch()?;
4863 branches.push(branch);
4864 }
4865
4866 if self.check(&TokenType::Dedent) {
4868 self.advance();
4869 }
4870
4871 Ok(Stmt::Select { branches })
4872 }
4873
4874 fn parse_select_branch(&mut self) -> ParseResult<crate::ast::stmt::SelectBranch<'a>> {
4876 use crate::ast::stmt::SelectBranch;
4877
4878 if self.check(&TokenType::Receive) {
4879 self.advance(); let var = match &self.tokens[self.current].kind {
4882 TokenType::ProperName(sym) | TokenType::Noun(sym) | TokenType::Adjective(sym) => {
4883 let s = *sym;
4884 self.advance();
4885 s
4886 }
4887 _ => {
4888 return Err(ParseError {
4889 kind: ParseErrorKind::ExpectedKeyword { keyword: "variable name".to_string() },
4890 span: self.current_span(),
4891 });
4892 }
4893 };
4894
4895 if !self.check(&TokenType::From) && !self.check_preposition_is("from") {
4896 return Err(ParseError {
4897 kind: ParseErrorKind::ExpectedKeyword { keyword: "from".to_string() },
4898 span: self.current_span(),
4899 });
4900 }
4901 self.advance();
4902
4903 let pipe = self.parse_imperative_expr()?;
4904
4905 if !self.check(&TokenType::Colon) {
4907 return Err(ParseError {
4908 kind: ParseErrorKind::ExpectedKeyword { keyword: ":".to_string() },
4909 span: self.current_span(),
4910 });
4911 }
4912 self.advance();
4913
4914 let body = self.parse_indented_block()?;
4916
4917 Ok(SelectBranch::Receive { var, pipe, body })
4918 } else if self.check_word("after") {
4919 self.advance(); let milliseconds = self.parse_imperative_expr()?;
4922
4923 if self.check_word("seconds") || self.check_word("milliseconds") {
4925 self.advance();
4926 }
4927
4928 if !self.check(&TokenType::Colon) {
4930 return Err(ParseError {
4931 kind: ParseErrorKind::ExpectedKeyword { keyword: ":".to_string() },
4932 span: self.current_span(),
4933 });
4934 }
4935 self.advance();
4936
4937 let body = self.parse_indented_block()?;
4939
4940 Ok(SelectBranch::Timeout { milliseconds, body })
4941 } else {
4942 Err(ParseError {
4943 kind: ParseErrorKind::ExpectedKeyword { keyword: "Receive or After".to_string() },
4944 span: self.current_span(),
4945 })
4946 }
4947 }
4948
4949 fn parse_indented_block(&mut self) -> ParseResult<crate::ast::stmt::Block<'a>> {
4953 self.enter_recursion()?;
4954 let result = self.parse_indented_block_inner();
4955 self.leave_recursion();
4956 result
4957 }
4958
4959 fn parse_indented_block_inner(&mut self) -> ParseResult<crate::ast::stmt::Block<'a>> {
4960 if !self.check(&TokenType::Indent) {
4962 return Err(ParseError {
4963 kind: ParseErrorKind::ExpectedStatement,
4964 span: self.current_span(),
4965 });
4966 }
4967 self.advance();
4968
4969 let mut stmts = Vec::new();
4970 while !self.check(&TokenType::Dedent) && !self.is_at_end() {
4971 let stmt = self.parse_statement()?;
4972 stmts.push(stmt);
4973 if self.check(&TokenType::Period) {
4974 self.advance();
4975 }
4976 }
4977
4978 if self.check(&TokenType::Dedent) {
4980 self.advance();
4981 }
4982
4983 let block = self.ctx.stmts.expect("imperative arenas not initialized")
4984 .alloc_slice(stmts.into_iter());
4985
4986 Ok(block)
4987 }
4988
4989 fn parse_give_statement(&mut self) -> ParseResult<Stmt<'a>> {
4990 self.advance(); let object = self.parse_imperative_expr()?;
4994
4995 if !self.check_to_preposition() {
4997 return Err(ParseError {
4998 kind: ParseErrorKind::ExpectedKeyword { keyword: "to".to_string() },
4999 span: self.current_span(),
5000 });
5001 }
5002 self.advance(); let recipient = self.parse_imperative_expr()?;
5006
5007 if let Expr::Identifier(sym) = object {
5009 self.world_state.set_ownership_by_var(*sym, crate::drs::OwnershipState::Moved);
5010 }
5011
5012 Ok(Stmt::Give { object, recipient })
5013 }
5014
5015 fn parse_show_statement(&mut self) -> ParseResult<Stmt<'a>> {
5016 self.advance(); let object = self.parse_condition()?;
5021
5022 let recipient = if self.check_to_preposition() {
5026 self.advance(); if self.check_article() {
5031 self.advance(); }
5033 if self.check(&TokenType::Console) {
5034 self.advance(); let show_sym = self.interner.intern("show");
5036 self.ctx.alloc_imperative_expr(Expr::Identifier(show_sym))
5037 } else {
5038 self.parse_imperative_expr()?
5040 }
5041 } else {
5042 let show_sym = self.interner.intern("show");
5044 self.ctx.alloc_imperative_expr(Expr::Identifier(show_sym))
5045 };
5046
5047 if let Expr::Identifier(sym) = object {
5049 self.world_state.set_ownership_by_var(*sym, crate::drs::OwnershipState::Borrowed);
5050 }
5051
5052 Ok(Stmt::Show { object, recipient })
5053 }
5054
5055 fn parse_push_statement(&mut self) -> ParseResult<Stmt<'a>> {
5058 self.advance(); let mut values = vec![self.parse_imperative_expr()?];
5063 while self.check(&TokenType::Comma) {
5064 self.advance(); values.push(self.parse_imperative_expr()?);
5066 }
5067
5068 if !self.check(&TokenType::To) && !self.check_preposition_is("to") {
5070 return Err(ParseError {
5071 kind: ParseErrorKind::ExpectedKeyword { keyword: "to".to_string() },
5072 span: self.current_span(),
5073 });
5074 }
5075 self.advance(); let collection = self.parse_imperative_expr()?;
5079
5080 if values.len() == 1 {
5081 Ok(self.desugar_place_push(values[0], collection))
5082 } else {
5083 let mut pushes = Vec::with_capacity(values.len());
5084 for value in values {
5085 pushes.push(self.desugar_place_push(value, collection));
5086 }
5087 let body = self.ctx.stmts.expect("imperative arenas not initialized")
5088 .alloc_slice(pushes.into_iter());
5089 Ok(Stmt::Splice { body })
5090 }
5091 }
5092
5093 fn parse_pop_statement(&mut self) -> ParseResult<Stmt<'a>> {
5096 self.advance(); if !self.check(&TokenType::From) && !self.check_preposition_is("from") {
5100 return Err(ParseError {
5101 kind: ParseErrorKind::ExpectedKeyword { keyword: "from".to_string() },
5102 span: self.current_span(),
5103 });
5104 }
5105 self.advance(); let collection = self.parse_imperative_expr()?;
5109
5110 let into = if self.check(&TokenType::Into) || self.check_preposition_is("into") {
5112 self.advance(); if let TokenType::Noun(sym) | TokenType::ProperName(sym) = &self.peek().kind {
5116 let sym = *sym;
5117 self.advance();
5118 Some(sym)
5119 } else if let Some(token) = self.tokens.get(self.current) {
5120 let sym = token.lexeme;
5122 self.advance();
5123 Some(sym)
5124 } else {
5125 return Err(ParseError {
5126 kind: ParseErrorKind::ExpectedIdentifier,
5127 span: self.current_span(),
5128 });
5129 }
5130 } else {
5131 None
5132 };
5133
5134 Ok(Stmt::Pop { collection, into })
5135 }
5136
5137 fn parse_add_statement(&mut self) -> ParseResult<Stmt<'a>> {
5140 self.advance(); let value = self.parse_imperative_expr()?;
5144
5145 if !self.check_preposition_is("to") && !self.check(&TokenType::To) {
5147 return Err(ParseError {
5148 kind: ParseErrorKind::ExpectedKeyword { keyword: "to".to_string() },
5149 span: self.current_span(),
5150 });
5151 }
5152 self.advance(); let collection = self.parse_imperative_expr()?;
5156
5157 Ok(Stmt::Add { value, collection })
5158 }
5159
5160 fn parse_remove_statement(&mut self) -> ParseResult<Stmt<'a>> {
5163 self.advance(); let value = self.parse_imperative_expr()?;
5167
5168 if !self.check(&TokenType::From) && !self.check_preposition_is("from") {
5170 return Err(ParseError {
5171 kind: ParseErrorKind::ExpectedKeyword { keyword: "from".to_string() },
5172 span: self.current_span(),
5173 });
5174 }
5175 self.advance(); let collection = self.parse_imperative_expr()?;
5179
5180 Ok(Stmt::Remove { value, collection })
5181 }
5182
5183 fn parse_read_statement(&mut self) -> ParseResult<Stmt<'a>> {
5187 self.advance(); let var = self.expect_identifier()?;
5191
5192 if !self.check(&TokenType::From) && !self.check_preposition_is("from") {
5194 return Err(ParseError {
5195 kind: ParseErrorKind::ExpectedKeyword { keyword: "from".to_string() },
5196 span: self.current_span(),
5197 });
5198 }
5199 self.advance(); if self.check_article() {
5203 self.advance();
5204 }
5205
5206 let source = if self.check(&TokenType::Console) {
5208 self.advance(); ReadSource::Console
5210 } else if self.check(&TokenType::File) {
5211 self.advance(); let path = self.parse_imperative_expr()?;
5213 ReadSource::File(path)
5214 } else {
5215 return Err(ParseError {
5216 kind: ParseErrorKind::ExpectedKeyword { keyword: "console or file".to_string() },
5217 span: self.current_span(),
5218 });
5219 };
5220
5221 Ok(Stmt::ReadFrom { var, source })
5222 }
5223
5224 fn parse_write_statement(&mut self) -> ParseResult<Stmt<'a>> {
5227 self.advance(); let content = self.parse_imperative_expr()?;
5231
5232 if !self.check(&TokenType::To) && !self.check_preposition_is("to") {
5234 return Err(ParseError {
5235 kind: ParseErrorKind::ExpectedKeyword { keyword: "to".to_string() },
5236 span: self.current_span(),
5237 });
5238 }
5239 self.advance(); if !self.check(&TokenType::File) {
5243 return Err(ParseError {
5244 kind: ParseErrorKind::ExpectedKeyword { keyword: "file".to_string() },
5245 span: self.current_span(),
5246 });
5247 }
5248 self.advance(); let path = self.parse_imperative_expr()?;
5252
5253 Ok(Stmt::WriteFile { content, path })
5254 }
5255
5256 fn parse_zone_statement(&mut self) -> ParseResult<Stmt<'a>> {
5262 self.advance(); if self.check_article() {
5266 self.advance();
5267 }
5268
5269 if self.check(&TokenType::New) {
5271 self.advance();
5272 }
5273
5274 if !self.check(&TokenType::Zone) {
5276 return Err(ParseError {
5277 kind: ParseErrorKind::ExpectedKeyword { keyword: "zone".to_string() },
5278 span: self.current_span(),
5279 });
5280 }
5281 self.advance(); if !self.check(&TokenType::Called) {
5285 return Err(ParseError {
5286 kind: ParseErrorKind::ExpectedKeyword { keyword: "called".to_string() },
5287 span: self.current_span(),
5288 });
5289 }
5290 self.advance(); let name = match &self.peek().kind {
5294 TokenType::StringLiteral(sym) => {
5295 let s = *sym;
5296 self.advance();
5297 s
5298 }
5299 TokenType::ProperName(sym) | TokenType::Noun(sym) | TokenType::Adjective(sym) => {
5300 let s = *sym;
5301 self.advance();
5302 s
5303 }
5304 _ => {
5305 let token = self.peek().clone();
5307 self.advance();
5308 token.lexeme
5309 }
5310 };
5311
5312 let mut capacity = None;
5313 let mut source_file = None;
5314
5315 if self.check(&TokenType::Mapped) {
5317 self.advance(); if !self.check(&TokenType::From) && !self.check_preposition_is("from") {
5321 return Err(ParseError {
5322 kind: ParseErrorKind::ExpectedKeyword { keyword: "from".to_string() },
5323 span: self.current_span(),
5324 });
5325 }
5326 self.advance(); if let TokenType::StringLiteral(path) = &self.peek().kind {
5331 let p = *path;
5332 self.advance();
5333 source_file = Some(crate::ast::stmt::ZoneSource::Literal(p));
5334 } else {
5335 let var = self.expect_identifier()?;
5336 source_file = Some(crate::ast::stmt::ZoneSource::Variable(var));
5337 }
5338 }
5339 else if self.check_of_preposition() {
5341 self.advance(); if !self.check(&TokenType::Size) {
5345 return Err(ParseError {
5346 kind: ParseErrorKind::ExpectedKeyword { keyword: "size".to_string() },
5347 span: self.current_span(),
5348 });
5349 }
5350 self.advance(); let size_value = match &self.peek().kind {
5354 TokenType::Number(sym) => {
5355 let num_str = self.interner.resolve(*sym).to_string();
5356 let val = self.parse_i64_numeral(&num_str)? as usize;
5357 self.advance();
5358 val
5359 }
5360 TokenType::Cardinal(n) => {
5361 let val = *n as usize;
5362 self.advance();
5363 val
5364 }
5365 _ => {
5366 return Err(ParseError {
5367 kind: ParseErrorKind::ExpectedNumber,
5368 span: self.current_span(),
5369 });
5370 }
5371 };
5372
5373 let unit_multiplier = self.parse_size_unit()?;
5375 capacity = Some(size_value * unit_multiplier);
5376 }
5377
5378 if !self.check(&TokenType::Colon) {
5380 return Err(ParseError {
5381 kind: ParseErrorKind::ExpectedKeyword { keyword: ":".to_string() },
5382 span: self.current_span(),
5383 });
5384 }
5385 self.advance(); if !self.check(&TokenType::Indent) {
5389 return Err(ParseError {
5390 kind: ParseErrorKind::ExpectedStatement,
5391 span: self.current_span(),
5392 });
5393 }
5394 self.advance(); let mut body_stmts = Vec::new();
5398 while !self.check(&TokenType::Dedent) && !self.is_at_end() {
5399 let stmt = self.parse_statement()?;
5400 body_stmts.push(stmt);
5401 if self.check(&TokenType::Period) {
5402 self.advance();
5403 }
5404 }
5405
5406 if self.check(&TokenType::Dedent) {
5408 self.advance();
5409 }
5410
5411 let body = self.ctx.stmts.expect("imperative arenas not initialized")
5412 .alloc_slice(body_stmts.into_iter());
5413
5414 Ok(Stmt::Zone { name, capacity, source_file, body })
5415 }
5416
5417 fn parse_size_unit(&mut self) -> ParseResult<usize> {
5419 let token = self.peek().clone();
5420 let unit_str = self.interner.resolve(token.lexeme).to_uppercase();
5421 self.advance();
5422
5423 match unit_str.as_str() {
5424 "B" | "BYTES" | "BYTE" => Ok(1),
5425 "KB" | "KILOBYTE" | "KILOBYTES" => Ok(1024),
5426 "MB" | "MEGABYTE" | "MEGABYTES" => Ok(1024 * 1024),
5427 "GB" | "GIGABYTE" | "GIGABYTES" => Ok(1024 * 1024 * 1024),
5428 _ => Err(ParseError {
5429 kind: ParseErrorKind::ExpectedKeyword {
5430 keyword: "size unit (B, KB, MB, GB)".to_string(),
5431 },
5432 span: token.span,
5433 }),
5434 }
5435 }
5436
5437 fn parse_concurrent_block(&mut self) -> ParseResult<Stmt<'a>> {
5446 self.advance(); if !self.check(&TokenType::All) {
5450 return Err(ParseError {
5451 kind: ParseErrorKind::ExpectedKeyword { keyword: "all".to_string() },
5452 span: self.current_span(),
5453 });
5454 }
5455 self.advance(); if !self.check_of_preposition() {
5459 return Err(ParseError {
5460 kind: ParseErrorKind::ExpectedKeyword { keyword: "of".to_string() },
5461 span: self.current_span(),
5462 });
5463 }
5464 self.advance(); if !self.check_article() {
5468 return Err(ParseError {
5469 kind: ParseErrorKind::ExpectedKeyword { keyword: "the".to_string() },
5470 span: self.current_span(),
5471 });
5472 }
5473 self.advance(); if !self.check(&TokenType::Following) {
5477 return Err(ParseError {
5478 kind: ParseErrorKind::ExpectedKeyword { keyword: "following".to_string() },
5479 span: self.current_span(),
5480 });
5481 }
5482 self.advance(); if !self.check(&TokenType::Colon) {
5486 return Err(ParseError {
5487 kind: ParseErrorKind::ExpectedKeyword { keyword: ":".to_string() },
5488 span: self.current_span(),
5489 });
5490 }
5491 self.advance(); if !self.check(&TokenType::Indent) {
5495 return Err(ParseError {
5496 kind: ParseErrorKind::ExpectedStatement,
5497 span: self.current_span(),
5498 });
5499 }
5500 self.advance(); let mut task_stmts = Vec::new();
5504 while !self.check(&TokenType::Dedent) && !self.is_at_end() {
5505 let stmt = self.parse_statement()?;
5506 task_stmts.push(stmt);
5507 if self.check(&TokenType::Period) {
5508 self.advance();
5509 }
5510 }
5511
5512 if self.check(&TokenType::Dedent) {
5514 self.advance();
5515 }
5516
5517 let tasks = self.ctx.stmts.expect("imperative arenas not initialized")
5518 .alloc_slice(task_stmts.into_iter());
5519
5520 Ok(Stmt::Concurrent { tasks })
5521 }
5522
5523 fn parse_parallel_block(&mut self) -> ParseResult<Stmt<'a>> {
5532 self.advance(); if !self.check(&TokenType::Colon) {
5536 return Err(ParseError {
5537 kind: ParseErrorKind::ExpectedKeyword { keyword: ":".to_string() },
5538 span: self.current_span(),
5539 });
5540 }
5541 self.advance(); if !self.check(&TokenType::Indent) {
5545 return Err(ParseError {
5546 kind: ParseErrorKind::ExpectedStatement,
5547 span: self.current_span(),
5548 });
5549 }
5550 self.advance(); let mut task_stmts = Vec::new();
5554 while !self.check(&TokenType::Dedent) && !self.is_at_end() {
5555 let stmt = self.parse_statement()?;
5556 task_stmts.push(stmt);
5557 if self.check(&TokenType::Period) {
5558 self.advance();
5559 }
5560 }
5561
5562 if self.check(&TokenType::Dedent) {
5564 self.advance();
5565 }
5566
5567 let tasks = self.ctx.stmts.expect("imperative arenas not initialized")
5568 .alloc_slice(task_stmts.into_iter());
5569
5570 Ok(Stmt::Parallel { tasks })
5571 }
5572
5573 fn parse_inspect_statement(&mut self) -> ParseResult<Stmt<'a>> {
5580 self.advance(); let target = self.parse_imperative_expr()?;
5584
5585 if !self.check(&TokenType::Colon) {
5587 return Err(ParseError {
5588 kind: ParseErrorKind::ExpectedKeyword { keyword: ":".to_string() },
5589 span: self.current_span(),
5590 });
5591 }
5592 self.advance(); if !self.check(&TokenType::Indent) {
5596 return Err(ParseError {
5597 kind: ParseErrorKind::ExpectedStatement,
5598 span: self.current_span(),
5599 });
5600 }
5601 self.advance(); let mut arms = Vec::new();
5604 let mut has_otherwise = false;
5605
5606 while !self.check(&TokenType::Dedent) && !self.is_at_end() {
5608 if self.check(&TokenType::Otherwise) {
5609 self.advance(); if !self.check(&TokenType::Colon) {
5613 return Err(ParseError {
5614 kind: ParseErrorKind::ExpectedKeyword { keyword: ":".to_string() },
5615 span: self.current_span(),
5616 });
5617 }
5618 self.advance(); let body_stmts = if self.check(&TokenType::Indent) {
5622 self.advance(); let mut stmts = Vec::new();
5624 while !self.check(&TokenType::Dedent) && !self.is_at_end() {
5625 let stmt = self.parse_statement()?;
5626 stmts.push(stmt);
5627 if self.check(&TokenType::Period) {
5628 self.advance();
5629 }
5630 }
5631 if self.check(&TokenType::Dedent) {
5632 self.advance();
5633 }
5634 stmts
5635 } else {
5636 let stmt = self.parse_statement()?;
5638 if self.check(&TokenType::Period) {
5639 self.advance();
5640 }
5641 vec![stmt]
5642 };
5643
5644 let body = self.ctx.stmts.expect("imperative arenas not initialized")
5645 .alloc_slice(body_stmts.into_iter());
5646
5647 arms.push(MatchArm { enum_name: None, variant: None, bindings: vec![], body });
5648 has_otherwise = true;
5649 break;
5650 }
5651
5652 if self.check(&TokenType::If) {
5653 let arm = self.parse_match_arm()?;
5655 arms.push(arm);
5656 } else if self.check(&TokenType::When) || self.check_word("When") {
5657 let arm = self.parse_when_arm()?;
5659 arms.push(arm);
5660 } else if self.check(&TokenType::Newline) {
5661 self.advance();
5663 } else {
5664 self.advance();
5666 }
5667 }
5668
5669 if self.check(&TokenType::Dedent) {
5671 self.advance();
5672 }
5673
5674 Ok(Stmt::Inspect { target, arms, has_otherwise })
5675 }
5676
5677 fn parse_match_arm(&mut self) -> ParseResult<MatchArm<'a>> {
5679 self.advance(); if !self.check_word("it") {
5683 return Err(ParseError {
5684 kind: ParseErrorKind::ExpectedKeyword { keyword: "it".to_string() },
5685 span: self.current_span(),
5686 });
5687 }
5688 self.advance(); if !self.check(&TokenType::Is) {
5692 return Err(ParseError {
5693 kind: ParseErrorKind::ExpectedKeyword { keyword: "is".to_string() },
5694 span: self.current_span(),
5695 });
5696 }
5697 self.advance(); if self.check_article() {
5701 self.advance();
5702 }
5703
5704 let variant = self.expect_identifier()?;
5706
5707 let enum_name = self.find_variant(variant);
5709
5710 let bindings = if self.check(&TokenType::LParen) {
5712 self.parse_pattern_bindings()?
5713 } else {
5714 vec![]
5715 };
5716
5717 if !self.check(&TokenType::Colon) {
5719 return Err(ParseError {
5720 kind: ParseErrorKind::ExpectedKeyword { keyword: ":".to_string() },
5721 span: self.current_span(),
5722 });
5723 }
5724 self.advance(); if !self.check(&TokenType::Indent) {
5728 return Err(ParseError {
5729 kind: ParseErrorKind::ExpectedStatement,
5730 span: self.current_span(),
5731 });
5732 }
5733 self.advance(); let mut body_stmts = Vec::new();
5737 while !self.check(&TokenType::Dedent) && !self.is_at_end() {
5738 let stmt = self.parse_statement()?;
5739 body_stmts.push(stmt);
5740 if self.check(&TokenType::Period) {
5741 self.advance();
5742 }
5743 }
5744
5745 if self.check(&TokenType::Dedent) {
5747 self.advance();
5748 }
5749
5750 let body = self.ctx.stmts.expect("imperative arenas not initialized")
5751 .alloc_slice(body_stmts.into_iter());
5752
5753 Ok(MatchArm { enum_name, variant: Some(variant), bindings, body })
5754 }
5755
5756 fn parse_when_arm(&mut self) -> ParseResult<MatchArm<'a>> {
5758 self.advance(); let variant = self.expect_identifier()?;
5762
5763 let (enum_name, variant_fields) = self.type_registry
5765 .as_ref()
5766 .and_then(|r| r.find_variant(variant).map(|(enum_name, vdef)| {
5767 let fields: Vec<_> = vdef.fields.iter().map(|f| f.name).collect();
5768 (Some(enum_name), fields)
5769 }))
5770 .unwrap_or((None, vec![]));
5771
5772 let bindings = if self.check(&TokenType::LParen) {
5774 let raw_bindings = self.parse_when_bindings()?;
5775 raw_bindings.into_iter().enumerate().map(|(i, binding)| {
5777 let field = variant_fields.get(i).copied().unwrap_or(binding);
5778 (field, binding)
5779 }).collect()
5780 } else {
5781 vec![]
5782 };
5783
5784 if !self.check(&TokenType::Colon) {
5786 return Err(ParseError {
5787 kind: ParseErrorKind::ExpectedKeyword { keyword: ":".to_string() },
5788 span: self.current_span(),
5789 });
5790 }
5791 self.advance(); let body_stmts = if self.check(&TokenType::Indent) {
5795 self.advance(); let mut stmts = Vec::new();
5797 while !self.check(&TokenType::Dedent) && !self.is_at_end() {
5798 let stmt = self.parse_statement()?;
5799 stmts.push(stmt);
5800 if self.check(&TokenType::Period) {
5801 self.advance();
5802 }
5803 }
5804 if self.check(&TokenType::Dedent) {
5805 self.advance();
5806 }
5807 stmts
5808 } else {
5809 let stmt = self.parse_statement()?;
5811 if self.check(&TokenType::Period) {
5812 self.advance();
5813 }
5814 vec![stmt]
5815 };
5816
5817 let body = self.ctx.stmts.expect("imperative arenas not initialized")
5818 .alloc_slice(body_stmts.into_iter());
5819
5820 Ok(MatchArm { enum_name, variant: Some(variant), bindings, body })
5821 }
5822
5823 fn parse_when_bindings(&mut self) -> ParseResult<Vec<Symbol>> {
5825 self.advance(); let mut bindings = Vec::new();
5827
5828 loop {
5829 let binding = self.expect_identifier()?;
5830 bindings.push(binding);
5831
5832 if !self.check(&TokenType::Comma) {
5833 break;
5834 }
5835 self.advance(); }
5837
5838 if !self.check(&TokenType::RParen) {
5839 return Err(ParseError {
5840 kind: ParseErrorKind::ExpectedKeyword { keyword: ")".to_string() },
5841 span: self.current_span(),
5842 });
5843 }
5844 self.advance(); Ok(bindings)
5847 }
5848
5849 fn parse_pattern_bindings(&mut self) -> ParseResult<Vec<(Symbol, Symbol)>> {
5851 self.advance(); let mut bindings = Vec::new();
5853
5854 loop {
5855 let field = self.expect_identifier()?;
5856 let binding = if self.check(&TokenType::Colon) {
5857 self.advance(); self.expect_identifier()?
5859 } else {
5860 field };
5862 bindings.push((field, binding));
5863
5864 if !self.check(&TokenType::Comma) {
5865 break;
5866 }
5867 self.advance(); }
5869
5870 if !self.check(&TokenType::RParen) {
5871 return Err(ParseError {
5872 kind: ParseErrorKind::ExpectedKeyword { keyword: ")".to_string() },
5873 span: self.current_span(),
5874 });
5875 }
5876 self.advance(); Ok(bindings)
5879 }
5880
5881 fn parse_constructor_fields(&mut self) -> ParseResult<Vec<(Symbol, &'a Expr<'a>)>> {
5885 use crate::ast::Expr;
5886 let mut fields = Vec::new();
5887
5888 self.advance();
5890
5891 loop {
5892 let field_name = self.expect_identifier()?;
5894
5895 let value = self.parse_comparison()?;
5898
5899 fields.push((field_name, value));
5900
5901 if self.check(&TokenType::And) {
5903 self.advance(); continue;
5905 }
5906 break;
5907 }
5908
5909 Ok(fields)
5910 }
5911
5912 fn parse_variant_constructor_fields(&mut self) -> ParseResult<Vec<(Symbol, &'a Expr<'a>)>> {
5914 self.parse_constructor_fields()
5915 }
5916
5917 fn parse_struct_init_fields(&mut self) -> ParseResult<Vec<(Symbol, &'a Expr<'a>)>> {
5919 self.parse_constructor_fields()
5920 }
5921
5922 fn parse_generic_type_args(&mut self, type_name: Symbol) -> ParseResult<Vec<TypeExpr<'a>>> {
5926 if !self.is_generic_type(type_name) {
5928 return Ok(vec![]);
5929 }
5930
5931 if !self.check_preposition_is("of") {
5933 return Ok(vec![]); }
5935 self.advance(); let mut type_args = Vec::new();
5938 loop {
5939 let type_arg = self.parse_type_expression()?;
5941 type_args.push(type_arg);
5942
5943 if self.check(&TokenType::And) || self.check_to_preposition() {
5945 self.advance(); continue;
5947 }
5948 break;
5949 }
5950
5951 Ok(type_args)
5952 }
5953
5954 fn skip_type_def_content(&mut self) {
5958 while !self.is_at_end() {
5959 if matches!(
5961 self.tokens.get(self.current),
5962 Some(Token { kind: TokenType::BlockHeader { .. }, .. })
5963 ) {
5964 break;
5965 }
5966 self.advance();
5967 }
5968 }
5969
5970 fn parse_theorem_block(&mut self) -> ParseResult<Stmt<'a>> {
5978 use crate::ast::theorem::{TheoremBlock, ProofStrategy};
5979
5980 self.skip_whitespace_tokens();
5982
5983 if self.check(&TokenType::Colon) {
5988 self.advance();
5989 }
5990
5991 self.skip_whitespace_tokens();
5993
5994 let name = if let Some(token) = self.tokens.get(self.current) {
5996 match &token.kind {
5997 TokenType::Noun(_)
5998 | TokenType::ProperName(_)
5999 | TokenType::Verb { .. }
6000 | TokenType::Adjective(_) => {
6001 let name = self.interner.resolve(token.lexeme).to_string();
6002 self.advance();
6003 name
6004 }
6005 _ => {
6006 let lexeme = self.interner.resolve(token.lexeme);
6008 if !lexeme.is_empty() && lexeme.chars().next().map(|c| c.is_alphanumeric()).unwrap_or(false) {
6009 let name = lexeme.to_string();
6010 self.advance();
6011 name
6012 } else {
6013 "Anonymous".to_string()
6014 }
6015 }
6016 }
6017 } else {
6018 "Anonymous".to_string()
6019 };
6020
6021 self.skip_whitespace_tokens();
6022
6023 if self.check(&TokenType::Period) {
6025 self.advance();
6026 }
6027
6028 self.skip_whitespace_tokens();
6029
6030 let mut premises = Vec::new();
6033 let mut premise_names: Vec<Option<String>> = Vec::new();
6034 while self.check(&TokenType::Given) {
6035 self.advance(); self.skip_whitespace_tokens();
6038
6039 let mut this_name: Option<String> = None;
6042 if self.check(&TokenType::LParen) {
6043 self.advance();
6044 self.skip_whitespace_tokens();
6045 if let Some(token) = self.tokens.get(self.current) {
6046 if !matches!(token.kind, TokenType::RParen) {
6047 this_name = Some(self.interner.resolve(token.lexeme).to_string());
6048 self.advance();
6049 }
6050 }
6051 self.skip_whitespace_tokens();
6052 if self.check(&TokenType::RParen) {
6053 self.advance();
6054 }
6055 self.skip_whitespace_tokens();
6056 }
6057 premise_names.push(this_name);
6058
6059 if self.check(&TokenType::Colon) {
6061 self.advance();
6062 }
6063
6064 self.skip_whitespace_tokens();
6065
6066 let scalar_trigger = self.pragmatic
6070 && matches!(
6071 self.peek().kind,
6072 TokenType::Some | TokenType::Most | TokenType::Many
6073 );
6074 let mut premise_expr = match self.try_parse_optative()? {
6079 Some(opt) => opt,
6080 None => self.parse_sentence()?,
6081 };
6082 if scalar_trigger {
6083 if let Some(strengthened) = self.scalar_implicature(premise_expr) {
6084 premise_expr = strengthened;
6085 }
6086 }
6087 premises.push(premise_expr);
6088
6089 self.world_state.end_sentence();
6092
6093 if self.check(&TokenType::Period) || self.check(&TokenType::Exclamation) {
6096 self.advance();
6097 }
6098
6099 self.skip_whitespace_tokens();
6100 }
6101
6102 let goal = if self.check(&TokenType::Prove) {
6104 self.advance(); if self.check(&TokenType::Colon) {
6107 self.advance();
6108 }
6109
6110 self.skip_whitespace_tokens();
6111
6112 let goal_expr = match self.try_parse_optative()? {
6115 Some(opt) => opt,
6116 None => self.parse_sentence()?,
6117 };
6118
6119 if self.check(&TokenType::Period) || self.check(&TokenType::Exclamation) {
6120 self.advance();
6121 }
6122
6123 goal_expr
6124 } else {
6125 return Err(ParseError {
6126 kind: ParseErrorKind::ExpectedKeyword { keyword: "Prove".to_string() },
6127 span: self.current_span(),
6128 });
6129 };
6130
6131 self.skip_whitespace_tokens();
6132
6133 let at_proof = self
6137 .check(&TokenType::BlockHeader { block_type: crate::token::BlockType::Proof })
6138 || self.tokens.get(self.current).is_some_and(|t| {
6139 self.interner.resolve(t.lexeme).eq_ignore_ascii_case("proof")
6140 });
6141 let strategy = if at_proof {
6142 self.advance();
6143 self.skip_whitespace_tokens();
6144
6145 if self.check(&TokenType::Colon) {
6146 self.advance();
6147 }
6148
6149 self.skip_whitespace_tokens();
6150
6151 if self.check(&TokenType::Auto) {
6152 self.advance();
6153 ProofStrategy::Auto
6154 } else {
6155 let mut parts: Vec<String> = Vec::new();
6161 while !self.is_at_end()
6162 && !matches!(self.tokens[self.current].kind, TokenType::BlockHeader { .. })
6163 && !self.check(&TokenType::Dedent)
6164 {
6165 let lexeme = self.tokens[self.current].lexeme;
6166 parts.push(self.interner.resolve(lexeme).to_string());
6167 self.advance();
6168 }
6169 let script = parts.join(" ");
6170 if script.trim().is_empty() {
6171 ProofStrategy::Auto
6172 } else {
6173 ProofStrategy::Script(script)
6174 }
6175 }
6176 } else {
6177 ProofStrategy::Auto
6179 };
6180
6181 if self.check(&TokenType::Period) {
6183 self.advance();
6184 }
6185
6186 let theorem = TheoremBlock {
6187 name,
6188 premises,
6189 premise_names,
6190 goal,
6191 strategy,
6192 };
6193
6194 Ok(Stmt::Theorem(theorem))
6195 }
6196
6197 fn parse_define_block(&mut self) -> ParseResult<Stmt<'a>> {
6204 use crate::ast::definition::DefinitionBlock;
6205
6206 self.skip_whitespace_tokens();
6207
6208 if self.check(&TokenType::Colon) {
6211 self.advance();
6212 self.skip_whitespace_tokens();
6213 if let Some(token) = self.tokens.get(self.current) {
6214 if matches!(
6215 token.kind,
6216 TokenType::Noun(_)
6217 | TokenType::ProperName(_)
6218 | TokenType::Adjective(_)
6219 | TokenType::Verb { .. }
6220 ) {
6221 self.advance();
6222 }
6223 }
6224 if self.check(&TokenType::Period) {
6225 self.advance();
6226 }
6227 }
6228
6229 self.skip_whitespace_tokens();
6230
6231 let sentence = self.parse_sentence()?;
6233 if self.check(&TokenType::Period) || self.check(&TokenType::Exclamation) {
6234 self.advance();
6235 }
6236
6237 let (definiendum, definiens) = match sentence {
6239 LogicExpr::BinaryOp { left, op: TokenType::Iff, right } => (*left, *right),
6240 _ => {
6241 return Err(ParseError {
6242 kind: ParseErrorKind::Custom(
6243 "a `## Define` body must be a biconditional: \
6244 `<subject> is <predicate> if and only if <definiens>`"
6245 .to_string(),
6246 ),
6247 span: self.current_span(),
6248 });
6249 }
6250 };
6251
6252 let (name, params) = match definiendum {
6255 LogicExpr::Predicate { name, args, .. } => {
6256 let pname = self.interner.resolve(*name).to_string();
6257 let params: Vec<Symbol> = args
6258 .iter()
6259 .filter_map(|t| match t {
6260 Term::Constant(s) | Term::Variable(s) => Some(*s),
6261 _ => None,
6262 })
6263 .collect();
6264 (pname, params)
6265 }
6266 _ => {
6267 return Err(ParseError {
6268 kind: ParseErrorKind::Custom(
6269 "the left side of a `## Define` biconditional must be a \
6270 predicate applied to its parameters (e.g. `x is a bachelor`)"
6271 .to_string(),
6272 ),
6273 span: self.current_span(),
6274 });
6275 }
6276 };
6277
6278 Ok(Stmt::Definition(DefinitionBlock {
6279 name,
6280 params,
6281 definiendum,
6282 definiens,
6283 }))
6284 }
6285
6286 fn parse_axiom_block(&mut self) -> ParseResult<Stmt<'a>> {
6292 use crate::ast::axiom::AxiomBlock;
6293 self.skip_whitespace_tokens();
6294 let name = self.read_block_name();
6295 self.skip_whitespace_tokens();
6296 if self.check(&TokenType::Colon) {
6297 self.advance();
6298 }
6299 let formula = self.collect_block_text();
6300 Ok(Stmt::Axiom(AxiomBlock { name, formula }))
6301 }
6302
6303 fn parse_theory_block(&mut self) -> ParseResult<Stmt<'a>> {
6307 use crate::ast::axiom::TheoryBlock;
6308 self.skip_whitespace_tokens();
6309 let name = self.read_block_name();
6310 self.skip_whitespace_tokens();
6311 if self.check(&TokenType::Colon) {
6312 self.advance();
6313 }
6314 let body = self.collect_block_text();
6315 Ok(Stmt::Theory(TheoryBlock { name, body }))
6316 }
6317
6318 fn read_block_name(&mut self) -> String {
6321 if let Some(token) = self.tokens.get(self.current) {
6322 if matches!(
6323 token.kind,
6324 TokenType::Noun(_)
6325 | TokenType::ProperName(_)
6326 | TokenType::Adjective(_)
6327 | TokenType::Verb { .. }
6328 ) {
6329 let name = self.interner.resolve(token.lexeme).to_string();
6330 self.advance();
6331 return name;
6332 }
6333 }
6334 "Anonymous".to_string()
6335 }
6336
6337 fn collect_block_text(&mut self) -> String {
6343 let mut parts: Vec<String> = Vec::new();
6344 while !self.is_at_end()
6345 && !matches!(self.tokens[self.current].kind, TokenType::BlockHeader { .. })
6346 {
6347 match &self.tokens[self.current].kind {
6348 TokenType::Newline | TokenType::Indent | TokenType::Dedent => {}
6349 _ => {
6350 let lexeme = self.tokens[self.current].lexeme;
6351 parts.push(self.interner.resolve(lexeme).to_string());
6352 }
6353 }
6354 self.advance();
6355 }
6356 parts.join(" ")
6357 }
6358
6359 fn skip_whitespace_tokens(&mut self) {
6361 while self.check(&TokenType::Newline) || self.check(&TokenType::Indent) || self.check(&TokenType::Dedent) {
6362 self.advance();
6363 }
6364 }
6365
6366 fn insert_ensures_before_returns(
6373 &self,
6374 stmts: &[Stmt<'a>],
6375 checks: &[&'a Expr<'a>],
6376 ) -> Vec<Stmt<'a>> {
6377 let mut out: Vec<Stmt<'a>> = Vec::new();
6378 for s in stmts {
6379 if matches!(s, Stmt::Return { .. }) {
6380 for &c in checks {
6381 out.push(Stmt::RuntimeAssert { condition: c, hard: true });
6382 }
6383 out.push(s.clone());
6384 continue;
6385 }
6386 let mut c = s.clone();
6389 match &mut c {
6390 Stmt::If { then_block, else_block, .. } => {
6391 *then_block = self.alloc_block(self.insert_ensures_before_returns(then_block, checks));
6392 if let Some(eb) = else_block {
6393 *eb = self.alloc_block(self.insert_ensures_before_returns(eb, checks));
6394 }
6395 }
6396 Stmt::While { body, .. }
6397 | Stmt::Repeat { body, .. }
6398 | Stmt::Zone { body, .. } => {
6399 *body = self.alloc_block(self.insert_ensures_before_returns(body, checks));
6400 }
6401 Stmt::Inspect { arms, .. } => {
6402 for arm in arms.iter_mut() {
6403 arm.body = self.alloc_block(self.insert_ensures_before_returns(arm.body, checks));
6404 }
6405 }
6406 Stmt::Select { branches } => {
6407 for br in branches.iter_mut() {
6410 match br {
6411 crate::ast::stmt::SelectBranch::Receive { body, .. }
6412 | crate::ast::stmt::SelectBranch::Timeout { body, .. } => {
6413 *body = self.alloc_block(self.insert_ensures_before_returns(body, checks));
6414 }
6415 }
6416 }
6417 }
6418 _ => {}
6421 }
6422 out.push(c);
6423 }
6424 out
6425 }
6426
6427 fn alloc_block(&self, stmts: Vec<Stmt<'a>>) -> &'a [Stmt<'a>] {
6429 self.ctx.stmts.expect("imperative arenas not initialized").alloc_slice(stmts.into_iter())
6430 }
6431
6432 fn parse_function_def(&mut self) -> ParseResult<Stmt<'a>> {
6437 self.parse_function_def_with_flags(OptimizationConfig::all_on())
6438 }
6439
6440 fn parse_function_def_with_flags(&mut self, opt_flags: OptimizationConfig) -> ParseResult<Stmt<'a>> {
6442 if self.check(&TokenType::To) || self.check_preposition_is("to") {
6444 self.advance();
6445 }
6446
6447 let mut is_native = if self.check(&TokenType::Native) {
6449 self.advance(); true
6451 } else {
6452 false
6453 };
6454
6455 let name = self.expect_identifier()?;
6457
6458 let mut parsed_generics: Vec<Symbol> = Vec::new();
6460 if self.check_preposition_is("of") {
6461 self.advance(); loop {
6463 if !self.check(&TokenType::LBracket) {
6464 return Err(ParseError {
6465 kind: ParseErrorKind::Custom("Expected '[TypeParam]' after 'of' in generic function".to_string()),
6466 span: self.current_span(),
6467 });
6468 }
6469 self.advance(); let type_param = self.expect_identifier()?;
6471 parsed_generics.push(type_param);
6472 if !self.check(&TokenType::RBracket) {
6473 return Err(ParseError {
6474 kind: ParseErrorKind::Custom("Expected ']' after type parameter name".to_string()),
6475 span: self.current_span(),
6476 });
6477 }
6478 self.advance(); if self.check_word("and") {
6480 self.advance(); } else {
6482 break;
6483 }
6484 }
6485 }
6486
6487 let mut params = Vec::new();
6489 while self.check(&TokenType::LParen) {
6490 self.advance(); if self.check(&TokenType::RParen) {
6494 self.advance(); break;
6496 }
6497
6498 loop {
6500 let param_name = self.expect_identifier()?;
6501
6502 if !self.check(&TokenType::Colon) {
6504 return Err(ParseError {
6505 kind: ParseErrorKind::ExpectedKeyword { keyword: ":".to_string() },
6506 span: self.current_span(),
6507 });
6508 }
6509 self.advance(); let param_is_mutable = self.check_mutable_keyword();
6515 if param_is_mutable {
6516 self.advance(); }
6518
6519 let param_type_expr = self.parse_type_expression()?;
6521 let param_type_inner = self.ctx.alloc_type_expr(param_type_expr);
6522 let param_type = if param_is_mutable {
6523 self.ctx.alloc_type_expr(TypeExpr::Mutable { inner: param_type_inner })
6524 } else {
6525 param_type_inner
6526 };
6527
6528 params.push((param_name, param_type));
6529
6530 if self.check(&TokenType::Comma) {
6532 self.advance(); continue;
6534 }
6535 break;
6536 }
6537
6538 if !self.check(&TokenType::RParen) {
6540 return Err(ParseError {
6541 kind: ParseErrorKind::ExpectedKeyword { keyword: ")".to_string() },
6542 span: self.current_span(),
6543 });
6544 }
6545 self.advance(); if self.check_word("and") || self.check_preposition() || self.check(&TokenType::From) {
6550 self.advance();
6551 }
6552 }
6553
6554 let return_type = if self.check(&TokenType::Arrow) {
6556 self.advance(); let ret_type_expr = self.parse_type_expression()?;
6558 Some(self.ctx.alloc_type_expr(ret_type_expr))
6559 } else {
6560 None
6561 };
6562
6563 let mut native_path: Option<Symbol> = None;
6565 let mut is_exported = false;
6566 let mut export_target: Option<Symbol> = None;
6567
6568 if self.check_word("is") {
6569 self.advance(); if self.check(&TokenType::Native) {
6571 self.advance(); is_native = true;
6574 if let TokenType::StringLiteral(sym) = self.peek().kind {
6575 native_path = Some(sym);
6576 self.advance(); } else {
6578 return Err(ParseError {
6579 kind: ParseErrorKind::Custom(
6580 "Expected a string literal for native function path (e.g., is native \"reqwest::blocking::get\")".to_string()
6581 ),
6582 span: self.current_span(),
6583 });
6584 }
6585 } else if self.check_word("exported") {
6586 self.advance(); is_exported = true;
6589 if self.check_word("for") {
6590 self.advance(); let target_sym = if self.check(&TokenType::Native) {
6593 self.advance();
6594 self.interner.intern("native")
6595 } else {
6596 self.expect_identifier()?
6597 };
6598 let target_str = self.interner.resolve(target_sym);
6599 if !target_str.eq_ignore_ascii_case("c")
6600 && !target_str.eq_ignore_ascii_case("wasm")
6601 && !target_str.eq_ignore_ascii_case("native")
6602 {
6603 return Err(ParseError {
6604 kind: ParseErrorKind::Custom(
6605 format!("Unsupported export target \"{}\". Supported targets are \"c\", \"wasm\", and \"native\".", target_str)
6606 ),
6607 span: self.current_span(),
6608 });
6609 }
6610 export_target = Some(target_sym);
6611 }
6612 }
6613 }
6614
6615 if is_native {
6617 if self.check(&TokenType::Period) {
6619 self.advance();
6620 }
6621 if self.check(&TokenType::Newline) {
6622 self.advance();
6623 }
6624
6625 let empty_body = self.ctx.stmts.expect("imperative arenas not initialized")
6627 .alloc_slice(std::iter::empty());
6628
6629 return Ok(Stmt::FunctionDef {
6630 name,
6631 generics: parsed_generics,
6632 params,
6633 body: empty_body,
6634 return_type,
6635 is_native: true,
6636 native_path,
6637 is_exported: false,
6638 export_target: None,
6639 opt_flags,
6640 });
6641 }
6642
6643 if !self.check(&TokenType::Colon) {
6645 return Err(ParseError {
6646 kind: ParseErrorKind::ExpectedKeyword { keyword: ":".to_string() },
6647 span: self.current_span(),
6648 });
6649 }
6650 self.advance(); if !self.check(&TokenType::Indent) {
6654 return Err(ParseError {
6655 kind: ParseErrorKind::ExpectedStatement,
6656 span: self.current_span(),
6657 });
6658 }
6659 self.advance(); let saved_user_bound = std::mem::take(&mut self.user_bound);
6667 for (param_name, _) in ¶ms {
6668 self.user_bound.insert(*param_name);
6669 }
6670
6671 let mut body_stmts = Vec::new();
6673 let mut requires_checks: Vec<&'a Expr<'a>> = Vec::new();
6678 let mut ensures_checks: Vec<&'a Expr<'a>> = Vec::new();
6679 while !self.check(&TokenType::Dedent) && !self.is_at_end() {
6680 if self.check(&TokenType::Newline) {
6682 self.advance();
6683 continue;
6684 }
6685 if matches!(self.peek().kind, TokenType::BlockHeader { .. }) {
6687 break;
6688 }
6689 if self.check(&TokenType::Requires) {
6690 self.advance(); requires_checks.push(self.parse_condition()?);
6692 if self.check(&TokenType::Period) { self.advance(); }
6693 continue;
6694 }
6695 if self.check(&TokenType::Ensures) {
6696 self.advance(); ensures_checks.push(self.parse_condition()?);
6698 if self.check(&TokenType::Period) { self.advance(); }
6699 continue;
6700 }
6701 let stmt = self.parse_statement()?;
6702 body_stmts.push(stmt);
6703 if self.check(&TokenType::Period) {
6704 self.advance();
6705 }
6706 }
6707
6708 if self.check(&TokenType::Dedent) {
6710 self.advance();
6711 }
6712
6713 self.user_bound = saved_user_bound;
6715
6716 if !ensures_checks.is_empty() {
6719 body_stmts = self.insert_ensures_before_returns(&body_stmts, &ensures_checks);
6720 if !matches!(body_stmts.last(), Some(Stmt::Return { .. })) {
6721 for &c in &ensures_checks {
6722 body_stmts.push(Stmt::RuntimeAssert { condition: c, hard: true });
6723 }
6724 }
6725 }
6726 if !requires_checks.is_empty() {
6728 let mut prefixed: Vec<Stmt<'a>> = requires_checks
6729 .iter()
6730 .map(|&c| Stmt::RuntimeAssert { condition: c, hard: true })
6731 .collect();
6732 prefixed.extend(body_stmts);
6733 body_stmts = prefixed;
6734 }
6735
6736 let body = self.ctx.stmts.expect("imperative arenas not initialized")
6738 .alloc_slice(body_stmts.into_iter());
6739
6740 Ok(Stmt::FunctionDef {
6741 name,
6742 generics: parsed_generics,
6743 params,
6744 body,
6745 return_type,
6746 is_native: false,
6747 native_path: None,
6748 is_exported,
6749 export_target,
6750 opt_flags,
6751 })
6752 }
6753
6754 fn parse_primary_expr(&mut self) -> ParseResult<&'a Expr<'a>> {
6760 self.enter_recursion()?;
6761 let result = self.parse_primary_expr_inner();
6762 self.leave_recursion();
6763 result
6764 }
6765
6766 fn parse_primary_expr_inner(&mut self) -> ParseResult<&'a Expr<'a>> {
6767 use crate::ast::{Expr, Literal};
6768
6769 if self.check_word("the") && self.peek_word_at(2, "of") {
6774 let op = if self.peek_word_at(1, "sum") {
6775 Some(BinaryOpKind::Add)
6776 } else if self.peek_word_at(1, "product") {
6777 Some(BinaryOpKind::Multiply)
6778 } else if self.peek_word_at(1, "difference") {
6779 Some(BinaryOpKind::Subtract)
6780 } else if self.peek_word_at(1, "quotient") {
6781 Some(BinaryOpKind::Divide)
6782 } else if self.peek_word_at(1, "remainder") {
6783 Some(BinaryOpKind::Modulo)
6784 } else {
6785 None
6786 };
6787 if let Some(op) = op {
6788 self.advance(); self.advance(); self.advance(); let a = self.parse_additive_expr()?;
6792 if self.check(&TokenType::And) || self.check_word("and") {
6793 self.advance(); } else {
6795 return Err(ParseError {
6796 kind: ParseErrorKind::ExpectedKeyword { keyword: "and".to_string() },
6797 span: self.current_span(),
6798 });
6799 }
6800 let b = self.parse_additive_expr()?;
6801 return Ok(self.ctx.alloc_imperative_expr(Expr::BinaryOp { op, left: a, right: b }));
6802 }
6803 }
6804
6805 if matches!(self.peek().kind, TokenType::Identifier | TokenType::Noun(_))
6810 && self.interner.resolve(self.peek().lexeme).eq_ignore_ascii_case("timestamp")
6811 {
6812 let str_sym = match self.tokens.get(self.current + 1).map(|t| &t.kind) {
6813 Some(TokenType::StringLiteral(s)) => Some(*s),
6814 _ => None,
6815 };
6816 if let Some(s) = str_sym {
6817 self.advance(); self.advance(); let text = self.ctx.alloc_imperative_expr(Expr::Literal(Literal::Text(s)));
6820 let func = self.interner.intern("parse_timestamp");
6821 return Ok(self.ctx.alloc_imperative_expr(Expr::Call { function: func, args: vec![text] }));
6822 }
6823 }
6824
6825 if matches!(self.peek().kind, TokenType::Identifier | TokenType::Noun(_))
6829 && self.interner.resolve(self.peek().lexeme).eq_ignore_ascii_case("uuid")
6830 {
6831 let str_sym = match self.tokens.get(self.current + 1).map(|t| &t.kind) {
6832 Some(TokenType::StringLiteral(s)) => Some(*s),
6833 _ => None,
6834 };
6835 if let Some(s) = str_sym {
6836 self.advance(); self.advance(); let text = self.ctx.alloc_imperative_expr(Expr::Literal(Literal::Text(s)));
6839 let func = self.interner.intern("uuid");
6840 return Ok(self.ctx.alloc_imperative_expr(Expr::Call { function: func, args: vec![text] }));
6841 }
6842 }
6843
6844 let token = self.peek().clone();
6845 match &token.kind {
6846 TokenType::New => {
6850 self.advance(); let base_type_name = self.expect_identifier()?;
6852
6853 let type_name = if self.check(&TokenType::From) {
6855 self.advance(); let module_name = self.expect_identifier()?;
6857 let module_str = self.interner.resolve(module_name);
6858 let base_str = self.interner.resolve(base_type_name);
6859 let qualified = format!("{}::{}", module_str, base_str);
6860 self.interner.intern(&qualified)
6861 } else {
6862 base_type_name
6863 };
6864
6865 if let Some(enum_name) = self.find_variant(type_name) {
6867 let fields = if self.check_word("with") {
6869 self.parse_variant_constructor_fields()?
6870 } else {
6871 vec![]
6872 };
6873 let base = self.ctx.alloc_imperative_expr(Expr::NewVariant {
6874 enum_name,
6875 variant: type_name,
6876 fields,
6877 });
6878 return self.parse_field_access_chain(base);
6879 }
6880
6881 let type_args = self.parse_generic_type_args(type_name)?;
6883
6884 let init_fields = if self.check_word("with") && !self.peek_word_at(1, "capacity") {
6887 self.parse_struct_init_fields()?
6888 } else {
6889 vec![]
6890 };
6891
6892 let base = self.ctx.alloc_imperative_expr(Expr::New { type_name, type_args, init_fields });
6893 return self.parse_field_access_chain(base);
6894 }
6895
6896 TokenType::Article(_) => {
6900 let comp_lex = self.tokens.get(self.current + 1).map(|t| t.lexeme);
6904 let of_lex = self.tokens.get(self.current + 2).map(|t| t.lexeme);
6905 if let (Some(cl), Some(ol)) = (comp_lex, of_lex) {
6906 let extractor = match self.interner.resolve(cl).to_ascii_lowercase().as_str() {
6907 "year" => Some("year_of"),
6908 "month" => Some("month_of"),
6909 "day" => Some("day_of"),
6910 "weekday" => Some("weekday_of"),
6911 "hour" => Some("hour_of"),
6912 "minute" => Some("minute_of"),
6913 "second" => Some("second_of"),
6914 "date" => Some("date_of"),
6915 "time" => Some("time_of"),
6916 "week" => Some("week_of"),
6917 "quarter" => Some("quarter_of"),
6918 _ => None,
6919 };
6920 if let Some(extractor) = extractor {
6921 if self.interner.resolve(ol).eq_ignore_ascii_case("of") {
6922 self.advance(); self.advance(); self.advance(); let mut operand = self.parse_primary_expr()?;
6926 if self.check(&TokenType::In) || self.check_preposition_is("in") {
6931 let zone_sym = match self.tokens.get(self.current + 1).map(|t| &t.kind) {
6932 Some(TokenType::StringLiteral(z)) => Some(*z),
6933 _ => None,
6934 };
6935 if let Some(z) = zone_sym {
6936 self.advance(); self.advance(); let zone = self
6939 .ctx
6940 .alloc_imperative_expr(Expr::Literal(crate::ast::Literal::Text(z)));
6941 let local = self.interner.intern("local_instant");
6942 operand = self.ctx.alloc_imperative_expr(Expr::Call {
6943 function: local,
6944 args: vec![operand, zone],
6945 });
6946 }
6947 }
6948 let func = self.interner.intern(extractor);
6949 return Ok(self
6950 .ctx
6951 .alloc_imperative_expr(Expr::Call { function: func, args: vec![operand] }));
6952 }
6953 }
6954 let unit_lexeme = self.interner.resolve(cl).to_ascii_lowercase();
6958 let per_unit: Option<i64> = match unit_lexeme.as_str() {
6959 "second" | "seconds" => Some(1),
6960 "minute" | "minutes" => Some(60),
6961 "hour" | "hours" => Some(3600),
6962 "day" | "days" => Some(86400),
6963 "week" | "weeks" => Some(604800),
6964 _ => None,
6965 };
6966 let cal_func: Option<&str> = match unit_lexeme.as_str() {
6967 "month" | "months" => Some("months_between"),
6968 "year" | "years" => Some("years_between"),
6969 _ => None,
6970 };
6971 if (per_unit.is_some() || cal_func.is_some())
6972 && self.interner.resolve(ol).eq_ignore_ascii_case("between")
6973 {
6974 self.advance(); self.advance(); self.advance(); let a = self.parse_primary_expr()?;
6978 if !(self.check(&TokenType::And) || self.check_word("and")) {
6979 return Err(ParseError {
6980 kind: ParseErrorKind::ExpectedKeyword { keyword: "and".to_string() },
6981 span: self.current_span(),
6982 });
6983 }
6984 self.advance(); let b = self.parse_primary_expr()?;
6986 if let Some(cal) = cal_func {
6987 let func = self.interner.intern(cal);
6988 return Ok(self
6989 .ctx
6990 .alloc_imperative_expr(Expr::Call { function: func, args: vec![a, b] }));
6991 }
6992 let per_unit = per_unit.unwrap();
6993 let func = self.interner.intern("seconds_between");
6994 let secs = self.ctx.alloc_imperative_expr(Expr::Call { function: func, args: vec![a, b] });
6995 return Ok(if per_unit == 1 {
6996 secs
6997 } else {
6998 let d = self.ctx.alloc_imperative_expr(Expr::Literal(Literal::Number(per_unit)));
6999 self.ctx.alloc_imperative_expr(Expr::BinaryOp {
7000 op: BinaryOpKind::Divide,
7001 left: secs,
7002 right: d,
7003 })
7004 });
7005 }
7006 }
7007 if let Some(next) = self.tokens.get(self.current + 1) {
7010 if matches!(next.kind, TokenType::Manifest) {
7011 self.advance(); return self.parse_primary_expr();
7014 }
7015 if matches!(next.kind, TokenType::Chunk) {
7016 self.advance(); return self.parse_primary_expr();
7019 }
7020 if matches!(next.kind, TokenType::Length) {
7021 self.advance(); return self.parse_primary_expr();
7023 }
7024 }
7025 if let Some(next) = self.tokens.get(self.current + 1) {
7027 if matches!(next.kind, TokenType::New) {
7028 self.advance(); self.advance(); let base_type_name = self.expect_identifier()?;
7031
7032 let type_name = if self.check(&TokenType::From) {
7034 self.advance(); let module_name = self.expect_identifier()?;
7036 let module_str = self.interner.resolve(module_name);
7037 let base_str = self.interner.resolve(base_type_name);
7038 let qualified = format!("{}::{}", module_str, base_str);
7039 self.interner.intern(&qualified)
7040 } else {
7041 base_type_name
7042 };
7043
7044 if let Some(enum_name) = self.find_variant(type_name) {
7046 let fields = if self.check_word("with") {
7048 self.parse_variant_constructor_fields()?
7049 } else {
7050 vec![]
7051 };
7052 let base = self.ctx.alloc_imperative_expr(Expr::NewVariant {
7053 enum_name,
7054 variant: type_name,
7055 fields,
7056 });
7057 return self.parse_field_access_chain(base);
7058 }
7059
7060 let type_args = self.parse_generic_type_args(type_name)?;
7062
7063 let init_fields = if self.check_word("with") && !self.peek_word_at(1, "capacity") {
7066 self.parse_struct_init_fields()?
7067 } else {
7068 vec![]
7069 };
7070
7071 let base = self.ctx.alloc_imperative_expr(Expr::New { type_name, type_args, init_fields });
7072 return self.parse_field_access_chain(base);
7073 }
7074 }
7075 let sym = token.lexeme;
7077 self.advance();
7078 let base = self.ctx.alloc_imperative_expr(Expr::Identifier(sym));
7079 return self.parse_field_access_chain(base);
7080 }
7081
7082 TokenType::Item => {
7084 self.advance(); let index = if let TokenType::Number(sym) = &self.peek().kind {
7088 let sym = *sym;
7090 self.advance();
7091 self.parse_index_numeral(sym)?
7092 } else if self.check(&TokenType::Minus)
7093 && matches!(
7094 self.tokens.get(self.current + 1).map(|t| &t.kind),
7095 Some(TokenType::Number(_))
7096 )
7097 {
7098 self.advance(); let TokenType::Number(sym) = self.peek().kind else { unreachable!() };
7102 self.advance();
7103 let num_str = self.interner.resolve(sym).to_string();
7104 let n = self.parse_i64_numeral_signed(&num_str, true).map_err(|_| ParseError {
7105 kind: ParseErrorKind::ExpectedKeyword {
7106 keyword: format!("a numeric index (got '{}')", num_str),
7107 },
7108 span: self.current_span(),
7109 })?;
7110 self.ctx
7111 .alloc_imperative_expr(Expr::Literal(crate::ast::Literal::Number(n)))
7112 } else if self.check(&TokenType::LParen) {
7113 self.advance(); let first = self.parse_imperative_expr()?;
7117 let inner = if self.check(&TokenType::Comma) {
7118 let mut items = vec![first];
7119 while self.check(&TokenType::Comma) {
7120 self.advance(); items.push(self.parse_imperative_expr()?);
7122 }
7123 self.ctx.alloc_imperative_expr(Expr::Tuple(items))
7124 } else {
7125 first
7126 };
7127 if !self.check(&TokenType::RParen) {
7128 return Err(ParseError {
7129 kind: ParseErrorKind::ExpectedKeyword { keyword: ")".to_string() },
7130 span: self.current_span(),
7131 });
7132 }
7133 self.advance(); inner
7135 } else if let TokenType::StringLiteral(sym) = self.peek().kind {
7136 let sym = sym;
7138 self.advance();
7139 self.ctx.alloc_imperative_expr(Expr::Literal(crate::ast::Literal::Text(sym)))
7140 } else if self.check(&TokenType::LBracket) {
7141 return Err(ParseError {
7146 kind: ParseErrorKind::Custom(
7147 "A List cannot be a map key: keys must be immutable, and a live \
7148 List can change after insertion — the map would lose the entry. \
7149 Which fixed value identifies this entry? Use an Int or Text key, \
7150 or a tuple like ('a', 1) for a compound key."
7151 .to_string(),
7152 ),
7153 span: self.peek().span,
7154 });
7155 } else if !self.check_preposition_is("of") {
7156 let word = self.interner.resolve(self.peek().lexeme);
7158 if word == "true" {
7159 self.advance();
7160 self.ctx.alloc_imperative_expr(Expr::Literal(crate::ast::Literal::Boolean(true)))
7161 } else if word == "false" {
7162 self.advance();
7163 self.ctx.alloc_imperative_expr(Expr::Literal(crate::ast::Literal::Boolean(false)))
7164 } else {
7165 let sym = self.peek().lexeme;
7167 self.advance();
7168 self.ctx.alloc_imperative_expr(Expr::Identifier(sym))
7169 }
7170 } else {
7171 return Err(ParseError {
7172 kind: ParseErrorKind::ExpectedExpression,
7173 span: self.current_span(),
7174 });
7175 };
7176
7177 if !self.check_preposition_is("of") {
7179 return Err(ParseError {
7180 kind: ParseErrorKind::ExpectedKeyword { keyword: "of".to_string() },
7181 span: self.current_span(),
7182 });
7183 }
7184 self.advance(); let collection = self.parse_primary_expr()?;
7189
7190 Ok(self.ctx.alloc_imperative_expr(Expr::Index {
7191 collection,
7192 index,
7193 }))
7194 }
7195
7196 TokenType::Items => {
7199 let is_slice_syntax = if let Some(next) = self.tokens.get(self.current + 1) {
7203 matches!(next.kind, TokenType::Number(_) | TokenType::LParen)
7204 } else {
7205 false
7206 };
7207
7208 if !is_slice_syntax {
7209 let sym = token.lexeme;
7211 self.advance();
7212 let base = self.ctx.alloc_imperative_expr(Expr::Identifier(sym));
7213 return self.parse_field_access_chain(base);
7214 }
7215
7216 self.advance(); let start = if let TokenType::Number(sym) = &self.peek().kind {
7220 let sym = *sym;
7222 self.advance();
7223 self.parse_index_numeral(sym)?
7224 } else if self.check(&TokenType::LParen) {
7225 self.advance(); let inner = self.parse_imperative_expr()?;
7228 if !self.check(&TokenType::RParen) {
7229 return Err(ParseError {
7230 kind: ParseErrorKind::ExpectedKeyword { keyword: ")".to_string() },
7231 span: self.current_span(),
7232 });
7233 }
7234 self.advance(); inner
7236 } else if self.check(&TokenType::Length) {
7237 self.advance(); if self.check_preposition_is("of") {
7240 self.advance(); let target = self.parse_primary_expr()?;
7242 self.ctx.alloc_imperative_expr(Expr::Length { collection: target })
7243 } else {
7244 let sym = self.tokens[self.current - 1].lexeme;
7246 self.ctx.alloc_imperative_expr(Expr::Identifier(sym))
7247 }
7248 } else if !self.check_preposition_is("through") {
7249 let sym = self.peek().lexeme;
7251 self.advance();
7252 self.ctx.alloc_imperative_expr(Expr::Identifier(sym))
7253 } else {
7254 return Err(ParseError {
7255 kind: ParseErrorKind::ExpectedExpression,
7256 span: self.current_span(),
7257 });
7258 };
7259
7260 if !self.check_preposition_is("through") {
7262 return Err(ParseError {
7263 kind: ParseErrorKind::ExpectedKeyword { keyword: "through".to_string() },
7264 span: self.current_span(),
7265 });
7266 }
7267 self.advance(); let end = if let TokenType::Number(sym) = &self.peek().kind {
7271 let sym = *sym;
7273 self.advance();
7274 self.parse_index_numeral(sym)?
7275 } else if self.check(&TokenType::LParen) {
7276 self.advance(); let inner = self.parse_imperative_expr()?;
7279 if !self.check(&TokenType::RParen) {
7280 return Err(ParseError {
7281 kind: ParseErrorKind::ExpectedKeyword { keyword: ")".to_string() },
7282 span: self.current_span(),
7283 });
7284 }
7285 self.advance(); inner
7287 } else if self.check(&TokenType::Length) {
7288 self.advance(); if self.check_preposition_is("of") {
7291 self.advance(); let target = self.parse_primary_expr()?;
7293 self.ctx.alloc_imperative_expr(Expr::Length { collection: target })
7294 } else {
7295 let sym = self.tokens[self.current - 1].lexeme;
7297 self.ctx.alloc_imperative_expr(Expr::Identifier(sym))
7298 }
7299 } else if !self.check_preposition_is("of") {
7300 let sym = self.peek().lexeme;
7302 self.advance();
7303 self.ctx.alloc_imperative_expr(Expr::Identifier(sym))
7304 } else {
7305 return Err(ParseError {
7306 kind: ParseErrorKind::ExpectedExpression,
7307 span: self.current_span(),
7308 });
7309 };
7310
7311 let collection = if self.check_preposition_is("of") {
7314 self.advance(); self.parse_imperative_expr()?
7316 } else {
7317 let items_sym = self.interner.intern("items");
7320 self.ctx.alloc_imperative_expr(Expr::Identifier(items_sym))
7321 };
7322
7323 Ok(self.ctx.alloc_imperative_expr(Expr::Slice {
7324 collection,
7325 start,
7326 end,
7327 }))
7328 }
7329
7330 TokenType::LBracket => {
7332 self.advance(); let mut items = Vec::new();
7335 if !self.check(&TokenType::RBracket) {
7336 loop {
7337 items.push(self.parse_imperative_expr()?);
7338 if !self.check(&TokenType::Comma) {
7339 break;
7340 }
7341 self.advance(); if self.check(&TokenType::RBracket) {
7344 break;
7345 }
7346 }
7347 }
7348
7349 if !self.check(&TokenType::RBracket) {
7350 return Err(ParseError {
7351 kind: ParseErrorKind::ExpectedKeyword { keyword: "]".to_string() },
7352 span: self.current_span(),
7353 });
7354 }
7355 self.advance(); if items.is_empty() && self.check_word("of") {
7359 self.advance(); let type_name = self.expect_identifier()?;
7361 let seq_sym = self.interner.intern("Seq");
7363 return Ok(self.ctx.alloc_imperative_expr(Expr::New {
7364 type_name: seq_sym,
7365 type_args: vec![TypeExpr::Named(type_name)],
7366 init_fields: vec![],
7367 }));
7368 }
7369
7370 Ok(self.ctx.alloc_imperative_expr(Expr::List(items)))
7371 }
7372
7373 TokenType::LBrace => {
7380 self.advance(); if self.check(&TokenType::RBrace) {
7383 self.advance(); if !self.check_word("of") {
7385 return Err(ParseError {
7386 kind: ParseErrorKind::ExpectedKeyword {
7387 keyword: "of — an empty {} needs its element type: `{} of Int` (set) or `{} of Text to Int` (map)".to_string(),
7388 },
7389 span: self.current_span(),
7390 });
7391 }
7392 self.advance(); let first_ty = self.expect_identifier()?;
7394 if self.check(&TokenType::To) || self.check_preposition_is("to") {
7395 self.advance(); let val_ty = self.expect_identifier()?;
7397 let map_sym = self.interner.intern("Map");
7398 return Ok(self.ctx.alloc_imperative_expr(Expr::New {
7399 type_name: map_sym,
7400 type_args: vec![TypeExpr::Named(first_ty), TypeExpr::Named(val_ty)],
7401 init_fields: vec![],
7402 }));
7403 }
7404 let set_sym = self.interner.intern("Set");
7405 return Ok(self.ctx.alloc_imperative_expr(Expr::New {
7406 type_name: set_sym,
7407 type_args: vec![TypeExpr::Named(first_ty)],
7408 init_fields: vec![],
7409 }));
7410 }
7411
7412 let first = self.parse_imperative_expr()?;
7413 if self.check(&TokenType::Colon) {
7414 self.advance(); let mut args = vec![first, self.parse_imperative_expr()?];
7418 while self.check(&TokenType::Comma) {
7419 self.advance(); if self.check(&TokenType::RBrace) {
7422 break;
7423 }
7424 args.push(self.parse_imperative_expr()?);
7425 if !self.check(&TokenType::Colon) {
7426 return Err(ParseError {
7427 kind: ParseErrorKind::ExpectedKeyword { keyword: ":".to_string() },
7428 span: self.current_span(),
7429 });
7430 }
7431 self.advance(); args.push(self.parse_imperative_expr()?);
7433 }
7434 if !self.check(&TokenType::RBrace) {
7435 return Err(ParseError {
7436 kind: ParseErrorKind::ExpectedKeyword { keyword: "}".to_string() },
7437 span: self.current_span(),
7438 });
7439 }
7440 self.advance(); let map_of = self.interner.intern("mapOf");
7442 return Ok(self.ctx.alloc_imperative_expr(Expr::Call { function: map_of, args }));
7443 }
7444
7445 let mut args = vec![first];
7447 while self.check(&TokenType::Comma) {
7448 self.advance(); if self.check(&TokenType::RBrace) {
7451 break;
7452 }
7453 args.push(self.parse_imperative_expr()?);
7454 }
7455 if !self.check(&TokenType::RBrace) {
7456 return Err(ParseError {
7457 kind: ParseErrorKind::ExpectedKeyword { keyword: "}".to_string() },
7458 span: self.current_span(),
7459 });
7460 }
7461 self.advance(); let set_of = self.interner.intern("setOf");
7463 Ok(self.ctx.alloc_imperative_expr(Expr::Call { function: set_of, args }))
7464 }
7465
7466 TokenType::MoneyLiteral { amount, currency } => {
7470 let amount = *amount;
7471 let currency = *currency;
7472 let num_str = self.interner.resolve(amount).to_string();
7473 self.advance();
7474 let num_expr = if num_str.contains('.') {
7475 let text = self.ctx.alloc_imperative_expr(Expr::Literal(Literal::Text(amount)));
7476 let dec = self.interner.intern("decimal");
7477 self.ctx.alloc_imperative_expr(Expr::Call { function: dec, args: vec![text] })
7478 } else {
7479 let num = self.parse_i64_numeral(&num_str)?;
7480 self.ctx.alloc_imperative_expr(Expr::Literal(Literal::Number(num)))
7481 };
7482 let code_expr = self.ctx.alloc_imperative_expr(Expr::Literal(Literal::Text(currency)));
7483 let func = self.interner.intern("money");
7484 return Ok(self
7485 .ctx
7486 .alloc_imperative_expr(Expr::Call { function: func, args: vec![num_expr, code_expr] }));
7487 }
7488
7489 TokenType::Number(sym) => {
7490 let num_str = self.interner.resolve(*sym).to_string();
7491 self.advance();
7492
7493 if let TokenType::CalendarUnit(unit) = self.peek().kind {
7495 return self.parse_span_literal_from_num(&num_str);
7496 }
7497
7498 if matches!(
7504 self.peek().kind,
7505 TokenType::Identifier | TokenType::Noun(_) | TokenType::Adjective(_)
7506 ) {
7507 let unit_lexeme = self.peek().lexeme;
7508 let is_unit =
7509 logicaffeine_base::quantity::units::by_name(self.interner.resolve(unit_lexeme)).is_some();
7510 if is_unit {
7511 self.advance(); let num_expr = if num_str.contains('.') || num_str.contains('e') || num_str.contains('E') {
7513 let text = self.ctx.alloc_imperative_expr(Expr::Literal(Literal::Text(*sym)));
7514 let dec = self.interner.intern("decimal");
7515 self.ctx.alloc_imperative_expr(Expr::Call { function: dec, args: vec![text] })
7516 } else {
7517 let num = self.parse_i64_numeral(&num_str)?;
7518 self.ctx.alloc_imperative_expr(Expr::Literal(Literal::Number(num)))
7519 };
7520 let unit_expr = self.ctx.alloc_imperative_expr(Expr::Literal(Literal::Text(unit_lexeme)));
7521 let func = self.interner.intern("quantity");
7522 return Ok(self
7523 .ctx
7524 .alloc_imperative_expr(Expr::Call { function: func, args: vec![num_expr, unit_expr] }));
7525 }
7526 }
7527
7528 if matches!(
7533 self.peek().kind,
7534 TokenType::Identifier
7535 | TokenType::Noun(_)
7536 | TokenType::ProperName(_)
7537 | TokenType::Adjective(_)
7538 ) {
7539 let code_lexeme = self.peek().lexeme;
7540 if logicaffeine_base::money::currency::by_code(self.interner.resolve(code_lexeme)).is_some() {
7541 self.advance(); let num_expr = if num_str.contains('.') || num_str.contains('e') || num_str.contains('E') {
7543 let text = self.ctx.alloc_imperative_expr(Expr::Literal(Literal::Text(*sym)));
7544 let dec = self.interner.intern("decimal");
7545 self.ctx.alloc_imperative_expr(Expr::Call { function: dec, args: vec![text] })
7546 } else {
7547 let num = self.parse_i64_numeral(&num_str)?;
7548 self.ctx.alloc_imperative_expr(Expr::Literal(Literal::Number(num)))
7549 };
7550 let code_expr = self.ctx.alloc_imperative_expr(Expr::Literal(Literal::Text(code_lexeme)));
7551 let func = self.interner.intern("money");
7552 return Ok(self
7553 .ctx
7554 .alloc_imperative_expr(Expr::Call { function: func, args: vec![num_expr, code_expr] }));
7555 }
7556 }
7557
7558 if Self::is_radix_numeral(&num_str) {
7562 let num = self.parse_i64_numeral(&num_str)?;
7563 Ok(self.ctx.alloc_imperative_expr(Expr::Literal(Literal::Number(num))))
7564 } else if num_str.contains('.') || num_str.contains('e') || num_str.contains('E') {
7565 let num = num_str.replace('_', "").parse::<f64>().map_err(|_| ParseError {
7566 kind: ParseErrorKind::ExpectedKeyword {
7567 keyword: format!("a Float literal (got `{}`)", num_str),
7568 },
7569 span: self.current_span(),
7570 })?;
7571 Ok(self.ctx.alloc_imperative_expr(Expr::Literal(Literal::Float(num))))
7572 } else {
7573 let num = self.parse_i64_numeral(&num_str)?;
7574 Ok(self.ctx.alloc_imperative_expr(Expr::Literal(Literal::Number(num))))
7575 }
7576 }
7577
7578 TokenType::StringLiteral(sym) => {
7580 self.advance();
7581 Ok(self.ctx.alloc_imperative_expr(Expr::Literal(Literal::Text(*sym))))
7582 }
7583
7584 TokenType::InterpolatedString(sym) => {
7586 let raw = self.interner.resolve(*sym).to_string();
7587 self.advance();
7588 let parts = self.parse_interpolation_parts(&raw)?;
7589 Ok(self.ctx.alloc_imperative_expr(Expr::InterpolatedString(parts)))
7590 }
7591
7592 TokenType::CharLiteral(sym) => {
7594 let char_str = self.interner.resolve(*sym);
7595 let ch = char_str.chars().next().unwrap_or('\0');
7596 self.advance();
7597 Ok(self.ctx.alloc_imperative_expr(Expr::Literal(Literal::Char(ch))))
7598 }
7599
7600 TokenType::DurationLiteral { nanos, .. } => {
7602 let nanos = *nanos;
7603 self.advance();
7604 Ok(self.ctx.alloc_imperative_expr(Expr::Literal(Literal::Duration(nanos))))
7605 }
7606
7607 TokenType::DateLiteral { days } => {
7610 let days = *days;
7611 self.advance();
7612
7613 if self.check(&TokenType::At) {
7615 self.advance(); if let TokenType::TimeLiteral { nanos_from_midnight } = self.peek().kind {
7619 let time_nanos = nanos_from_midnight;
7620 self.advance(); let moment_nanos = (days as i64) * 86_400_000_000_000 + time_nanos;
7624 return Ok(self.ctx.alloc_imperative_expr(Expr::Literal(Literal::Moment(moment_nanos))));
7625 } else {
7626 return Err(ParseError {
7627 kind: ParseErrorKind::ExpectedExpression,
7628 span: self.current_span(),
7629 });
7630 }
7631 }
7632
7633 Ok(self.ctx.alloc_imperative_expr(Expr::Literal(Literal::Date(days))))
7634 }
7635
7636 TokenType::TimeLiteral { nanos_from_midnight } => {
7638 let nanos = *nanos_from_midnight;
7639 self.advance();
7640 Ok(self.ctx.alloc_imperative_expr(Expr::Literal(Literal::Time(nanos))))
7641 }
7642
7643 TokenType::Nothing => {
7645 self.advance();
7646 Ok(self.ctx.alloc_imperative_expr(Expr::Literal(Literal::Nothing)))
7647 }
7648
7649 TokenType::Some => {
7651 self.advance(); let value = self.parse_imperative_expr()?;
7653 Ok(self.ctx.alloc_imperative_expr(Expr::OptionSome { value }))
7654 }
7655
7656 TokenType::Length => {
7658 let func_name = self.peek().lexeme;
7659
7660 if self.tokens.get(self.current + 1)
7662 .map(|t| matches!(t.kind, TokenType::LParen))
7663 .unwrap_or(false)
7664 {
7665 self.advance(); return self.parse_call_expr(func_name);
7667 }
7668
7669 self.advance(); if !self.check_preposition_is("of") {
7673 return Err(ParseError {
7674 kind: ParseErrorKind::ExpectedKeyword { keyword: "of".to_string() },
7675 span: self.current_span(),
7676 });
7677 }
7678 self.advance(); let collection = self.parse_primary_expr()?;
7683 Ok(self.ctx.alloc_imperative_expr(Expr::Length { collection }))
7684 }
7685
7686 TokenType::Copy => {
7688 let func_name = self.peek().lexeme;
7689
7690 if self.tokens.get(self.current + 1)
7692 .map(|t| matches!(t.kind, TokenType::LParen))
7693 .unwrap_or(false)
7694 {
7695 self.advance(); return self.parse_call_expr(func_name);
7697 }
7698
7699 self.advance(); if !self.check_preposition_is("of") {
7703 return Err(ParseError {
7704 kind: ParseErrorKind::ExpectedKeyword { keyword: "of".to_string() },
7705 span: self.current_span(),
7706 });
7707 }
7708 self.advance(); let expr = self.parse_imperative_expr()?;
7711 Ok(self.ctx.alloc_imperative_expr(Expr::Copy { expr }))
7712 }
7713
7714 TokenType::Manifest => {
7716 self.advance(); if !self.check_preposition_is("of") {
7720 return Err(ParseError {
7721 kind: ParseErrorKind::ExpectedKeyword { keyword: "of".to_string() },
7722 span: self.current_span(),
7723 });
7724 }
7725 self.advance(); let zone = self.parse_imperative_expr()?;
7728 Ok(self.ctx.alloc_imperative_expr(Expr::ManifestOf { zone }))
7729 }
7730
7731 TokenType::Chunk => {
7733 self.advance(); if !self.check(&TokenType::At) {
7737 return Err(ParseError {
7738 kind: ParseErrorKind::ExpectedKeyword { keyword: "at".to_string() },
7739 span: self.current_span(),
7740 });
7741 }
7742 self.advance(); let index = self.parse_xor_expr()?;
7751
7752 if !self.check_preposition_is("in") && !self.check(&TokenType::In) {
7754 return Err(ParseError {
7755 kind: ParseErrorKind::ExpectedKeyword { keyword: "in".to_string() },
7756 span: self.current_span(),
7757 });
7758 }
7759 self.advance(); let zone = self.parse_imperative_expr()?;
7762 Ok(self.ctx.alloc_imperative_expr(Expr::ChunkAt { index, zone }))
7763 }
7764
7765 TokenType::Verb { lemma, .. } => {
7769 let word = self.interner.resolve(*lemma).to_lowercase();
7770 if word == "empty" {
7771 self.advance();
7772 return Ok(self.ctx.alloc_imperative_expr(Expr::Literal(Literal::Nothing)));
7773 }
7774 let sym = token.lexeme;
7776 self.advance();
7777 if self.check(&TokenType::LParen) {
7778 return self.parse_call_expr(sym);
7779 }
7780 self.verify_identifier_access(sym)?;
7782 let base = self.ctx.alloc_imperative_expr(Expr::Identifier(sym));
7783 self.parse_field_access_chain(base)
7784 }
7785
7786 TokenType::TemporalAdverb(_) | TokenType::ScopalAdverb(_) | TokenType::Adverb(_) => {
7788 let sym = token.lexeme;
7789 self.advance();
7790 if self.check(&TokenType::LParen) {
7791 return self.parse_call_expr(sym);
7792 }
7793 self.verify_identifier_access(sym)?;
7795 let base = self.ctx.alloc_imperative_expr(Expr::Identifier(sym));
7796 self.parse_field_access_chain(base)
7797 }
7798
7799 TokenType::Read | TokenType::Write | TokenType::File | TokenType::Console |
7802 TokenType::Add | TokenType::Remove => {
7803 let sym = token.lexeme;
7804 self.advance();
7805 if self.check(&TokenType::LParen) {
7806 return self.parse_call_expr(sym);
7807 }
7808 self.verify_identifier_access(sym)?;
7810 let base = self.ctx.alloc_imperative_expr(Expr::Identifier(sym));
7811 self.parse_field_access_chain(base)
7812 }
7813
7814 TokenType::Noun(sym) | TokenType::ProperName(sym) | TokenType::Adjective(sym) => {
7817 let sym = *sym;
7818 let word = self.interner.resolve(sym);
7819
7820 if word == "true" {
7822 self.advance();
7823 return Ok(self.ctx.alloc_imperative_expr(Expr::Literal(Literal::Boolean(true))));
7824 }
7825 if word == "false" {
7826 self.advance();
7827 return Ok(self.ctx.alloc_imperative_expr(Expr::Literal(Literal::Boolean(false))));
7828 }
7829 if word == "infinity" && !self.user_bound.contains(&sym) {
7832 self.advance();
7833 return Ok(self.ctx.alloc_imperative_expr(Expr::Literal(Literal::Float(f64::INFINITY))));
7834 }
7835 if word == "nan" && !self.user_bound.contains(&sym) {
7836 self.advance();
7837 return Ok(self.ctx.alloc_imperative_expr(Expr::Literal(Literal::Float(f64::NAN))));
7838 }
7839
7840 if word == "empty" {
7842 self.advance();
7843 return Ok(self.ctx.alloc_imperative_expr(Expr::Literal(Literal::Nothing)));
7844 }
7845
7846 if word == "none" {
7848 self.advance();
7849 return Ok(self.ctx.alloc_imperative_expr(Expr::OptionNone));
7850 }
7851
7852 self.advance();
7854
7855 if self.check(&TokenType::LParen) {
7857 return self.parse_call_expr(sym);
7858 }
7859
7860 if let Some(enum_name) = self.find_variant(sym) {
7862 let fields = if self.check_word("with") {
7863 self.parse_variant_constructor_fields()?
7864 } else {
7865 vec![]
7866 };
7867 let base = self.ctx.alloc_imperative_expr(Expr::NewVariant {
7868 enum_name,
7869 variant: sym,
7870 fields,
7871 });
7872 return self.parse_field_access_chain(base);
7873 }
7874
7875 self.verify_identifier_access(sym)?;
7877 let base = self.ctx.alloc_imperative_expr(Expr::Identifier(sym));
7878 self.parse_field_access_chain(base)
7880 }
7881
7882 TokenType::Pronoun { .. } => {
7884 let sym = token.lexeme;
7885 self.advance();
7886 let base = self.ctx.alloc_imperative_expr(Expr::Identifier(sym));
7887 self.parse_field_access_chain(base)
7889 }
7890
7891 TokenType::Merge | TokenType::Increase => {
7893 let sym = token.lexeme;
7894 self.advance();
7895
7896 if self.check(&TokenType::LParen) {
7898 return self.parse_call_expr(sym);
7899 }
7900
7901 let base = self.ctx.alloc_imperative_expr(Expr::Identifier(sym));
7902 self.parse_field_access_chain(base)
7903 }
7904
7905 TokenType::Escape => {
7909 if self.tokens.get(self.current + 1).map_or(false, |t|
7910 matches!(t.kind, TokenType::To) || {
7911 if let TokenType::Preposition(sym) = t.kind {
7912 sym.is(self.interner, "to")
7913 } else {
7914 false
7915 }
7916 }
7917 ) {
7918 return self.parse_escape_expr();
7919 }
7920 let sym = token.lexeme;
7922 self.advance();
7923 if self.check(&TokenType::LParen) {
7924 return self.parse_call_expr(sym);
7925 }
7926 self.verify_identifier_access(sym)?;
7927 let base = self.ctx.alloc_imperative_expr(Expr::Identifier(sym));
7928 self.parse_field_access_chain(base)
7929 }
7930
7931 TokenType::Values | TokenType::Both | TokenType::Either | TokenType::Combined | TokenType::Followed | TokenType::Shared | TokenType::Particle(_) | TokenType::Preposition(_) | TokenType::All => { let sym = token.lexeme;
7944 self.advance();
7945
7946 if self.check(&TokenType::LParen) {
7948 return self.parse_call_expr(sym);
7949 }
7950
7951 self.verify_identifier_access(sym)?;
7952 let base = self.ctx.alloc_imperative_expr(Expr::Identifier(sym));
7953 self.parse_field_access_chain(base)
7954 }
7955
7956 TokenType::Ambiguous { primary, alternatives } => {
7958 let sym = token.lexeme;
7961
7962 let is_identifier_token = match &**primary {
7964 TokenType::Noun(_) | TokenType::Adjective(_) | TokenType::ProperName(_) |
7965 TokenType::Verb { .. } => true,
7966 _ => alternatives.iter().any(|t| matches!(t,
7967 TokenType::Noun(_) | TokenType::Adjective(_) | TokenType::ProperName(_) |
7968 TokenType::Verb { .. }
7969 ))
7970 };
7971
7972 if is_identifier_token {
7973 self.advance();
7974
7975 if self.check(&TokenType::LParen) {
7977 return self.parse_call_expr(sym);
7978 }
7979
7980 self.verify_identifier_access(sym)?;
7981 let base = self.ctx.alloc_imperative_expr(Expr::Identifier(sym));
7982 self.parse_field_access_chain(base)
7984 } else {
7985 Err(ParseError {
7986 kind: ParseErrorKind::ExpectedExpression,
7987 span: self.current_span(),
7988 })
7989 }
7990 }
7991
7992 TokenType::LParen => {
7994 if let Some(closure) = self.try_parse(|p| p.parse_closure_expr()) {
7997 return Ok(closure);
7998 }
7999
8000 self.advance(); let first = self.parse_imperative_expr()?;
8003
8004 if self.check(&TokenType::Comma) {
8006 let mut items = vec![first];
8008 while self.check(&TokenType::Comma) {
8009 self.advance(); items.push(self.parse_imperative_expr()?);
8011 }
8012
8013 if !self.check(&TokenType::RParen) {
8014 return Err(ParseError {
8015 kind: ParseErrorKind::ExpectedKeyword { keyword: ")".to_string() },
8016 span: self.current_span(),
8017 });
8018 }
8019 self.advance(); let base = self.ctx.alloc_imperative_expr(Expr::Tuple(items));
8022 self.parse_field_access_chain(base)
8023 } else {
8024 if !self.check(&TokenType::RParen) {
8026 return Err(ParseError {
8027 kind: ParseErrorKind::ExpectedKeyword { keyword: ")".to_string() },
8028 span: self.current_span(),
8029 });
8030 }
8031 self.advance(); self.parse_field_access_chain(first)
8035 }
8036 }
8037
8038 TokenType::Call => {
8040 self.advance(); let function = match &self.peek().kind {
8042 TokenType::Noun(sym) | TokenType::Adjective(sym) => {
8043 let s = *sym;
8044 self.advance();
8045 s
8046 }
8047 TokenType::Verb { .. } | TokenType::Ambiguous { .. } => {
8048 let s = self.peek().lexeme;
8049 self.advance();
8050 s
8051 }
8052 _ => {
8053 return Err(ParseError {
8054 kind: ParseErrorKind::ExpectedIdentifier,
8055 span: self.current_span(),
8056 });
8057 }
8058 };
8059 let args = if self.check_preposition_is("with") {
8060 self.advance(); self.parse_call_arguments()?
8062 } else {
8063 Vec::new()
8064 };
8065 Ok(self.ctx.alloc_imperative_expr(Expr::Call { function, args }))
8066 }
8067
8068 _ => {
8069 Err(ParseError {
8070 kind: ParseErrorKind::ExpectedExpression,
8071 span: self.current_span(),
8072 })
8073 }
8074 }
8075 }
8076
8077 fn parse_closure_expr(&mut self) -> ParseResult<&'a Expr<'a>> {
8080 use crate::ast::stmt::ClosureBody;
8081
8082 if !self.check(&TokenType::LParen) {
8084 return Err(ParseError {
8085 kind: ParseErrorKind::ExpectedExpression,
8086 span: self.current_span(),
8087 });
8088 }
8089 self.advance(); let mut params = Vec::new();
8093 if !self.check(&TokenType::RParen) {
8094 let name = self.expect_identifier()?;
8096 if !self.check(&TokenType::Colon) {
8097 return Err(ParseError {
8098 kind: ParseErrorKind::ExpectedKeyword { keyword: ":".to_string() },
8099 span: self.current_span(),
8100 });
8101 }
8102 self.advance(); let ty = self.parse_type_expression()?;
8104 let ty_ref = self.ctx.alloc_type_expr(ty);
8105 params.push((name, ty_ref));
8106
8107 while self.check(&TokenType::Comma) {
8109 self.advance(); let name = self.expect_identifier()?;
8111 if !self.check(&TokenType::Colon) {
8112 return Err(ParseError {
8113 kind: ParseErrorKind::ExpectedKeyword { keyword: ":".to_string() },
8114 span: self.current_span(),
8115 });
8116 }
8117 self.advance(); let ty = self.parse_type_expression()?;
8119 let ty_ref = self.ctx.alloc_type_expr(ty);
8120 params.push((name, ty_ref));
8121 }
8122 }
8123
8124 if !self.check(&TokenType::RParen) {
8126 return Err(ParseError {
8127 kind: ParseErrorKind::ExpectedKeyword { keyword: ")".to_string() },
8128 span: self.current_span(),
8129 });
8130 }
8131 self.advance(); if !self.check(&TokenType::Arrow) {
8135 return Err(ParseError {
8136 kind: ParseErrorKind::ExpectedKeyword { keyword: "->".to_string() },
8137 span: self.current_span(),
8138 });
8139 }
8140 self.advance(); let body = if self.check(&TokenType::Colon) {
8144 self.advance(); if !self.check(&TokenType::Indent) {
8147 return Err(ParseError {
8148 kind: ParseErrorKind::ExpectedStatement,
8149 span: self.current_span(),
8150 });
8151 }
8152 self.advance(); let mut block_stmts = Vec::new();
8155 while !self.check(&TokenType::Dedent) && !self.is_at_end() {
8156 let stmt = self.parse_statement()?;
8157 block_stmts.push(stmt);
8158 if self.check(&TokenType::Period) {
8159 self.advance();
8160 }
8161 }
8162 if self.check(&TokenType::Dedent) {
8163 self.advance(); }
8165
8166 let block = self.ctx.stmts.expect("imperative arenas not initialized")
8167 .alloc_slice(block_stmts.into_iter());
8168 ClosureBody::Block(block)
8169 } else {
8170 let expr = self.parse_condition()?;
8172 ClosureBody::Expression(expr)
8173 };
8174
8175 Ok(self.ctx.alloc_imperative_expr(Expr::Closure {
8176 params,
8177 body,
8178 return_type: None,
8179 }))
8180 }
8181
8182 fn parse_imperative_expr(&mut self) -> ParseResult<&'a Expr<'a>> {
8186 self.parse_condition()
8187 }
8188
8189 fn parse_xor_expr(&mut self) -> ParseResult<&'a Expr<'a>> {
8193 let mut left = self.parse_bitxor_expr()?;
8194
8195 while self.check(&TokenType::VBar) {
8196 self.advance(); let right = self.parse_bitxor_expr()?;
8198 left = self.ctx.alloc_imperative_expr(Expr::BinaryOp {
8199 op: BinaryOpKind::BitOr,
8200 left,
8201 right,
8202 });
8203 }
8204
8205 Ok(left)
8206 }
8207
8208 fn parse_bitxor_expr(&mut self) -> ParseResult<&'a Expr<'a>> {
8210 let mut left = self.parse_bitand_expr()?;
8211
8212 while self.check(&TokenType::Xor) || self.check(&TokenType::Caret) {
8213 self.advance(); let right = self.parse_bitand_expr()?;
8215 left = self.ctx.alloc_imperative_expr(Expr::BinaryOp {
8216 op: BinaryOpKind::BitXor,
8217 left,
8218 right,
8219 });
8220 }
8221
8222 Ok(left)
8223 }
8224
8225 fn parse_bitand_expr(&mut self) -> ParseResult<&'a Expr<'a>> {
8227 let mut left = self.parse_additive_expr()?;
8228
8229 while self.check(&TokenType::Amp) {
8230 self.advance(); let right = self.parse_additive_expr()?;
8232 left = self.ctx.alloc_imperative_expr(Expr::BinaryOp {
8233 op: BinaryOpKind::BitAnd,
8234 left,
8235 right,
8236 });
8237 }
8238
8239 Ok(left)
8240 }
8241
8242 fn parse_additive_expr(&mut self) -> ParseResult<&'a Expr<'a>> {
8244 let mut left = self.parse_shift_expr()?;
8245
8246 loop {
8247 match &self.peek().kind {
8248 TokenType::Plus => {
8249 self.advance();
8250 let right = self.parse_shift_expr()?;
8251 left = self.ctx.alloc_imperative_expr(Expr::BinaryOp {
8252 op: BinaryOpKind::Add,
8253 left,
8254 right,
8255 });
8256 }
8257 TokenType::Minus => {
8258 self.advance();
8259 let right = self.parse_shift_expr()?;
8260 left = self.ctx.alloc_imperative_expr(Expr::BinaryOp {
8261 op: BinaryOpKind::Subtract,
8262 left,
8263 right,
8264 });
8265 }
8266 TokenType::Combined => {
8268 self.advance(); if !self.check_preposition_is("with") {
8271 return Err(ParseError {
8272 kind: ParseErrorKind::ExpectedKeyword { keyword: "with".to_string() },
8273 span: self.current_span(),
8274 });
8275 }
8276 self.advance(); let right = self.parse_shift_expr()?;
8278 left = self.ctx.alloc_imperative_expr(Expr::BinaryOp {
8279 op: BinaryOpKind::Concat,
8280 left,
8281 right,
8282 });
8283 }
8284 TokenType::Followed => {
8286 self.advance(); if !self.check_preposition_is("by") {
8288 return Err(ParseError {
8289 kind: ParseErrorKind::ExpectedKeyword { keyword: "by".to_string() },
8290 span: self.current_span(),
8291 });
8292 }
8293 self.advance(); let right = self.parse_shift_expr()?;
8295 left = self.ctx.alloc_imperative_expr(Expr::BinaryOp {
8296 op: BinaryOpKind::SeqConcat,
8297 left,
8298 right,
8299 });
8300 }
8301 TokenType::Union => {
8303 self.advance(); let right = self.parse_shift_expr()?;
8305 left = self.ctx.alloc_imperative_expr(Expr::Union {
8306 left,
8307 right,
8308 });
8309 }
8310 TokenType::Intersection => {
8311 self.advance(); let right = self.parse_shift_expr()?;
8313 left = self.ctx.alloc_imperative_expr(Expr::Intersection {
8314 left,
8315 right,
8316 });
8317 }
8318 TokenType::Contains => {
8320 self.advance(); let value = self.parse_shift_expr()?;
8322 left = self.ctx.alloc_imperative_expr(Expr::Contains {
8323 collection: left,
8324 value,
8325 });
8326 }
8327 _ if self.check_word("without") => {
8331 self.advance(); let right = self.parse_shift_expr()?;
8333 left = self.ctx.alloc_imperative_expr(Expr::BinaryOp {
8334 op: BinaryOpKind::Subtract,
8335 left,
8336 right,
8337 });
8338 }
8339 _ if self.check_word("copies") && self.peek_word_at(1, "of") => {
8344 self.advance(); self.advance(); let element = self.parse_shift_expr()?;
8347 let repeat_sym = self.interner.intern("repeatSeq");
8348 left = self.ctx.alloc_imperative_expr(Expr::Call {
8349 function: repeat_sym,
8350 args: vec![element, left],
8351 });
8352 }
8353 _ if self.check_op_word("plus") => {
8356 self.advance(); let right = self.parse_shift_expr()?;
8358 left = self.ctx.alloc_imperative_expr(Expr::BinaryOp { op: BinaryOpKind::Add, left, right });
8359 }
8360 _ if self.check_op_word("minus") => {
8361 self.advance(); let right = self.parse_shift_expr()?;
8363 left = self.ctx.alloc_imperative_expr(Expr::BinaryOp { op: BinaryOpKind::Subtract, left, right });
8364 }
8365 _ => break,
8366 }
8367 }
8368
8369 Ok(left)
8370 }
8371
8372 fn parse_shift_expr(&mut self) -> ParseResult<&'a Expr<'a>> {
8375 let mut left = self.parse_multiplicative_expr()?;
8376
8377 loop {
8378 if !self.check(&TokenType::Shifted) {
8379 break;
8380 }
8381 self.advance(); let is_left = self.check_word("left");
8384 if is_left {
8385 self.advance(); } else if self.check_word("right") {
8387 self.advance(); } else {
8389 return Err(ParseError {
8390 kind: ParseErrorKind::ExpectedKeyword { keyword: "left or right".to_string() },
8391 span: self.current_span(),
8392 });
8393 }
8394
8395 if !self.check_preposition_is("by") && !self.check_word("by") {
8397 return Err(ParseError {
8398 kind: ParseErrorKind::ExpectedKeyword { keyword: "by".to_string() },
8399 span: self.current_span(),
8400 });
8401 }
8402 self.advance(); let right = self.parse_multiplicative_expr()?;
8405 let op = if is_left { BinaryOpKind::Shl } else { BinaryOpKind::Shr };
8406 left = self.ctx.alloc_imperative_expr(Expr::BinaryOp { op, left, right });
8407 }
8408
8409 Ok(left)
8410 }
8411
8412 fn parse_unary_expr(&mut self) -> ParseResult<&'a Expr<'a>> {
8414 use crate::ast::{Expr, Literal};
8415
8416 if self.check(&TokenType::Tilde) {
8417 self.advance(); let operand = self.parse_unary_expr()?;
8419 let neg_one = self.ctx.alloc_imperative_expr(Expr::Literal(Literal::Number(-1)));
8422 return Ok(self.ctx.alloc_imperative_expr(Expr::BinaryOp {
8423 op: BinaryOpKind::BitXor,
8424 left: operand,
8425 right: neg_one,
8426 }));
8427 }
8428 if self.check(&TokenType::Minus) {
8429 if let Some(TokenType::Number(sym)) =
8434 self.tokens.get(self.current + 1).map(|t| t.kind.clone())
8435 {
8436 self.advance(); self.advance(); let num_str = self.interner.resolve(sym).to_string();
8439 if !Self::is_radix_numeral(&num_str)
8440 && (num_str.contains('.') || num_str.contains('e') || num_str.contains('E'))
8441 {
8442 let f = num_str.replace('_', "").parse::<f64>().map_err(|_| ParseError {
8443 kind: ParseErrorKind::ExpectedKeyword {
8444 keyword: format!("a Float literal (got `-{}`)", num_str),
8445 },
8446 span: self.current_span(),
8447 })?;
8448 return Ok(self.ctx.alloc_imperative_expr(Expr::Literal(Literal::Float(-f))));
8449 }
8450 let n = self.parse_i64_numeral_signed(&num_str, true)?;
8451 return Ok(self.ctx.alloc_imperative_expr(Expr::Literal(Literal::Number(n))));
8452 }
8453 if self
8454 .tokens
8455 .get(self.current + 1)
8456 .is_some_and(|t| self.interner.resolve(t.lexeme) == "infinity"
8457 && !self.user_bound.contains(&t.lexeme))
8458 {
8459 self.advance(); self.advance(); return Ok(self
8462 .ctx
8463 .alloc_imperative_expr(Expr::Literal(Literal::Float(f64::NEG_INFINITY))));
8464 }
8465 self.advance(); let operand = self.parse_unary_expr()?; return Ok(self.ctx.alloc_imperative_expr(Expr::BinaryOp {
8469 op: BinaryOpKind::Subtract,
8470 left: self.ctx.alloc_imperative_expr(Expr::Literal(Literal::Number(0))),
8471 right: operand,
8472 }));
8473 }
8474 self.parse_primary_expr()
8475 }
8476
8477 fn parse_power_expr(&mut self) -> ParseResult<&'a Expr<'a>> {
8482 let base = self.parse_unary_expr()?;
8483 let symbolic = self.check(&TokenType::StarStar);
8485 let spoken = (self.check_to_preposition() || self.check_word("to"))
8486 && self.peek_word_at(1, "the")
8487 && self.peek_word_at(2, "power")
8488 && self.peek_word_at(3, "of");
8489 if symbolic || spoken {
8490 if symbolic {
8491 self.advance(); } else {
8493 self.advance(); self.advance(); self.advance(); self.advance(); }
8498 let exp = self.parse_power_expr()?;
8499 return Ok(self.ctx.alloc_imperative_expr(Expr::BinaryOp {
8500 op: BinaryOpKind::Pow,
8501 left: base,
8502 right: exp,
8503 }));
8504 }
8505 Ok(base)
8506 }
8507
8508 fn parse_multiplicative_expr(&mut self) -> ParseResult<&'a Expr<'a>> {
8509 let mut left = self.parse_power_expr()?;
8510
8511 loop {
8512 let op = match &self.peek().kind {
8513 TokenType::Star => {
8514 self.advance();
8515 BinaryOpKind::Multiply
8516 }
8517 TokenType::Slash => {
8518 self.advance();
8519 BinaryOpKind::Divide
8520 }
8521 TokenType::SlashSlash => {
8522 self.advance();
8523 BinaryOpKind::FloorDivide
8524 }
8525 TokenType::Percent => {
8526 self.advance();
8527 BinaryOpKind::Modulo
8528 }
8529 _ if self.check_op_word("times") => {
8533 self.advance(); BinaryOpKind::Multiply
8535 }
8536 _ if self.check_op_word("divided") && self.peek_word_at(1, "by") => {
8537 self.advance(); self.advance(); BinaryOpKind::Divide
8540 }
8541 _ if self.check_op_word("modulo") || self.check_op_word("mod") => {
8542 self.advance(); BinaryOpKind::Modulo
8544 }
8545 _ => break,
8546 };
8547 let right = self.parse_power_expr()?;
8548 left = self.ctx.alloc_imperative_expr(Expr::BinaryOp {
8549 op,
8550 left,
8551 right,
8552 });
8553 }
8554
8555 Ok(left)
8556 }
8557
8558 fn try_parse_binary_op(&mut self) -> Option<BinaryOpKind> {
8560 match &self.peek().kind {
8561 TokenType::Plus => {
8562 self.advance();
8563 Some(BinaryOpKind::Add)
8564 }
8565 TokenType::Minus => {
8566 self.advance();
8567 Some(BinaryOpKind::Subtract)
8568 }
8569 TokenType::Star => {
8570 self.advance();
8571 Some(BinaryOpKind::Multiply)
8572 }
8573 TokenType::Slash => {
8574 self.advance();
8575 Some(BinaryOpKind::Divide)
8576 }
8577 _ => None,
8578 }
8579 }
8580
8581 fn parse_interpolation_parts(&mut self, raw: &str) -> ParseResult<Vec<crate::ast::stmt::StringPart<'a>>> {
8588 use crate::ast::stmt::StringPart;
8589
8590 let mut parts = Vec::new();
8591 let chars: Vec<char> = raw.chars().collect();
8592 let mut i = 0;
8593 let mut literal_buf = String::new();
8594
8595 while i < chars.len() {
8596 match chars[i] {
8597 '{' if i + 1 < chars.len() && chars[i + 1] == '{' => {
8598 literal_buf.push('{');
8600 i += 2;
8601 }
8602 '{' => {
8603 if !literal_buf.is_empty() {
8605 let sym = self.interner.intern(&literal_buf);
8606 parts.push(StringPart::Literal(sym));
8607 literal_buf.clear();
8608 }
8609
8610 let start = i + 1;
8612 let mut depth = 1;
8613 let mut j = start;
8614 while j < chars.len() && depth > 0 {
8615 if chars[j] == '{' { depth += 1; }
8616 if chars[j] == '}' { depth -= 1; }
8617 if depth > 0 { j += 1; }
8618 }
8619 if depth != 0 {
8620 return Err(ParseError {
8621 kind: crate::error::ParseErrorKind::Custom(
8622 "Unclosed interpolation brace in string".to_string()
8623 ),
8624 span: self.current_span(),
8625 });
8626 }
8627
8628 let hole_content: String = chars[start..j].iter().collect();
8629
8630 let (hole_after_debug, is_debug) = {
8635 if let Some(eq_pos) = hole_content.rfind('=') {
8636 let before_eq = hole_content[..eq_pos].trim();
8637 let is_double_eq = eq_pos > 0 && hole_content.as_bytes().get(eq_pos - 1) == Some(&b'=');
8640 let is_preceded_by_comparison = eq_pos > 0 && matches!(hole_content.as_bytes().get(eq_pos - 1), Some(b'!' | b'<' | b'>'));
8641 if !is_double_eq && !is_preceded_by_comparison
8642 && !before_eq.is_empty()
8643 && before_eq.chars().all(|c| c.is_alphanumeric() || c == '_')
8644 {
8645 (hole_content[..eq_pos].to_string() + &hole_content[eq_pos + 1..], true)
8646 } else {
8647 (hole_content.clone(), false)
8648 }
8649 } else {
8650 (hole_content.clone(), false)
8651 }
8652 };
8653
8654 let (expr_str, format_spec) = if let Some(colon_pos) = hole_after_debug.rfind(':') {
8656 let before = &hole_after_debug[..colon_pos];
8657 let after = &hole_after_debug[colon_pos + 1..];
8658 if !after.is_empty() && (after.starts_with('.') || after.starts_with('<') || after.starts_with('>') || after.starts_with('^') || after == "$" || after.chars().next().map_or(false, |c| c.is_ascii_digit())) {
8661 let valid = if after == "$" {
8663 true
8664 } else if after.starts_with('.') {
8665 after[1..].parse::<usize>().is_ok()
8666 } else if after.starts_with('<') || after.starts_with('>') || after.starts_with('^') {
8667 after[1..].parse::<usize>().is_ok()
8668 } else {
8669 after.parse::<usize>().is_ok()
8670 };
8671 if !valid {
8672 return Err(ParseError {
8673 kind: crate::error::ParseErrorKind::Custom(
8674 format!("Invalid format specifier `{}` in interpolation hole", after)
8675 ),
8676 span: self.current_span(),
8677 });
8678 }
8679 (before.to_string(), Some(after.to_string()))
8680 } else {
8681 (hole_after_debug.clone(), None)
8682 }
8683 } else {
8684 (hole_after_debug.clone(), None)
8685 };
8686
8687 let expr_source = expr_str.trim().to_string();
8689 if expr_source.is_empty() {
8690 return Err(ParseError {
8691 kind: crate::error::ParseErrorKind::Custom(
8692 "Empty interpolation hole in string".to_string()
8693 ),
8694 span: self.current_span(),
8695 });
8696 }
8697
8698 let sub_expr = {
8701 let mut sub_lexer = crate::lexer::Lexer::new(&expr_source, self.interner);
8702 let sub_tokens = sub_lexer.tokenize();
8703
8704 let saved_tokens = std::mem::replace(&mut self.tokens, sub_tokens);
8706 let saved_current = self.current;
8707 self.current = 0;
8708
8709 let result = self.parse_primary_or_binary_expr();
8710
8711 self.tokens = saved_tokens;
8713 self.current = saved_current;
8714
8715 result?
8716 };
8717
8718 let format_sym = format_spec.map(|s| self.interner.intern(&s));
8719 parts.push(StringPart::Expr {
8720 value: sub_expr,
8721 format_spec: format_sym,
8722 debug: is_debug,
8723 });
8724
8725 i = j + 1; }
8727 '}' if i + 1 < chars.len() && chars[i + 1] == '}' => {
8728 literal_buf.push('}');
8730 i += 2;
8731 }
8732 _ => {
8733 literal_buf.push(chars[i]);
8734 i += 1;
8735 }
8736 }
8737 }
8738
8739 if !literal_buf.is_empty() {
8741 let sym = self.interner.intern(&literal_buf);
8742 parts.push(StringPart::Literal(sym));
8743 }
8744
8745 Ok(parts)
8746 }
8747
8748 fn parse_primary_or_binary_expr(&mut self) -> ParseResult<&'a Expr<'a>> {
8750 self.parse_imperative_expr()
8751 }
8752
8753 fn parse_span_literal_from_num(&mut self, first_num_str: &str) -> ParseResult<&'a Expr<'a>> {
8754 use crate::ast::Literal;
8755 use crate::token::CalendarUnit;
8756
8757 let first_num = self.parse_i64_numeral(first_num_str)?;
8758
8759 let unit = match self.peek().kind {
8761 TokenType::CalendarUnit(u) => u,
8762 _ => {
8763 return Err(ParseError {
8764 kind: ParseErrorKind::ExpectedKeyword { keyword: "calendar unit (day, week, month, year)".to_string() },
8765 span: self.current_span(),
8766 });
8767 }
8768 };
8769 self.advance(); let mut total_months: i64 = 0;
8777 let mut total_days: i64 = 0;
8778 let mut total_nanos: i64 = 0;
8779 let mut saw_calendar = false;
8780 let mut saw_clock = false;
8781
8782 fn apply(
8783 unit: CalendarUnit,
8784 n: i64,
8785 months: &mut i64,
8786 days: &mut i64,
8787 nanos: &mut i64,
8788 cal: &mut bool,
8789 clk: &mut bool,
8790 ) {
8791 match unit {
8792 CalendarUnit::Day => {
8793 *days += n;
8794 *cal = true;
8795 }
8796 CalendarUnit::Week => {
8797 *days += n * 7;
8798 *cal = true;
8799 }
8800 CalendarUnit::Month => {
8801 *months += n;
8802 *cal = true;
8803 }
8804 CalendarUnit::Year => {
8805 *months += n * 12;
8806 *cal = true;
8807 }
8808 CalendarUnit::Hour => {
8809 *nanos += n * 3_600_000_000_000;
8810 *clk = true;
8811 }
8812 CalendarUnit::Minute => {
8813 *nanos += n * 60_000_000_000;
8814 *clk = true;
8815 }
8816 CalendarUnit::Second => {
8817 *nanos += n * 1_000_000_000;
8818 *clk = true;
8819 }
8820 }
8821 }
8822 apply(
8823 unit, first_num, &mut total_months, &mut total_days, &mut total_nanos,
8824 &mut saw_calendar, &mut saw_clock,
8825 );
8826
8827 while self.check(&TokenType::And) {
8829 self.advance(); let next_num = match &self.peek().kind {
8833 TokenType::Number(sym) => {
8834 let num_str = self.interner.resolve(*sym).to_string();
8835 self.advance();
8836 self.parse_i64_numeral(&num_str)?
8837 }
8838 _ => break, };
8840
8841 let next_unit = match self.peek().kind {
8843 TokenType::CalendarUnit(u) => {
8844 self.advance();
8845 u
8846 }
8847 _ => break, };
8849
8850 apply(
8851 next_unit, next_num, &mut total_months, &mut total_days, &mut total_nanos,
8852 &mut saw_calendar, &mut saw_clock,
8853 );
8854 }
8855
8856 if saw_clock && !saw_calendar {
8857 Ok(self.ctx.alloc_imperative_expr(Expr::Literal(Literal::Duration(total_nanos))))
8858 } else {
8859 Ok(self.ctx.alloc_imperative_expr(Expr::Literal(Literal::Span {
8860 months: total_months as i32,
8861 days: total_days as i32,
8862 })))
8863 }
8864 }
8865
8866 fn parse_call_expr(&mut self, function: Symbol) -> ParseResult<&'a Expr<'a>> {
8868 use crate::ast::Expr;
8869
8870 self.advance(); let mut args = Vec::new();
8873 if !self.check(&TokenType::RParen) {
8874 loop {
8875 args.push(self.parse_imperative_expr()?);
8876 if !self.check(&TokenType::Comma) {
8877 break;
8878 }
8879 self.advance(); }
8881 }
8882
8883 if !self.check(&TokenType::RParen) {
8884 return Err(ParseError {
8885 kind: ParseErrorKind::ExpectedKeyword { keyword: ")".to_string() },
8886 span: self.current_span(),
8887 });
8888 }
8889 self.advance(); Ok(self.ctx.alloc_imperative_expr(Expr::Call { function, args }))
8892 }
8893
8894 fn parse_field_access_chain(&mut self, base: &'a Expr<'a>) -> ParseResult<&'a Expr<'a>> {
8897 use crate::ast::Expr;
8898
8899 let mut result = base;
8900
8901 loop {
8903 if self.check(&TokenType::Dot) {
8904 self.advance(); let name = self.expect_identifier()?;
8910 if self.check(&TokenType::LParen) {
8911 self.advance(); let mut args = vec![result]; if !self.check(&TokenType::RParen) {
8914 loop {
8915 args.push(self.parse_imperative_expr()?);
8916 if !self.check(&TokenType::Comma) {
8917 break;
8918 }
8919 self.advance(); }
8921 }
8922 if !self.check(&TokenType::RParen) {
8923 return Err(ParseError {
8924 kind: ParseErrorKind::ExpectedKeyword { keyword: ")".to_string() },
8925 span: self.current_span(),
8926 });
8927 }
8928 self.advance(); result = self.ctx.alloc_imperative_expr(Expr::Call { function: name, args });
8930 } else {
8931 result = self.ctx.alloc_imperative_expr(Expr::FieldAccess {
8932 object: result,
8933 field: name,
8934 });
8935 }
8936 } else if self.check(&TokenType::Possessive) {
8937 self.advance(); let field = self.expect_identifier()?;
8940 result = self.ctx.alloc_imperative_expr(Expr::FieldAccess {
8941 object: result,
8942 field,
8943 });
8944 } else if self.check(&TokenType::LBracket) {
8945 self.advance(); let index = self.parse_imperative_expr()?;
8948
8949 if !self.check(&TokenType::RBracket) {
8950 return Err(ParseError {
8951 kind: ParseErrorKind::ExpectedKeyword { keyword: "]".to_string() },
8952 span: self.current_span(),
8953 });
8954 }
8955 self.advance(); result = self.ctx.alloc_imperative_expr(Expr::Index {
8958 collection: result,
8959 index,
8960 });
8961 } else {
8962 break;
8963 }
8964 }
8965
8966 Ok(result)
8967 }
8968
8969 fn verify_identifier_access(&self, sym: Symbol) -> ParseResult<()> {
8972 if self.mode != ParserMode::Imperative {
8973 return Ok(());
8974 }
8975
8976 if let Some(crate::drs::OwnershipState::Moved) = self.world_state.get_ownership_by_var(sym) {
8978 return Err(ParseError {
8979 kind: ParseErrorKind::UseAfterMove {
8980 name: self.interner.resolve(sym).to_string()
8981 },
8982 span: self.current_span(),
8983 });
8984 }
8985
8986 Ok(())
8987 }
8988
8989 fn expect_identifier(&mut self) -> ParseResult<Symbol> {
8990 let token = self.peek().clone();
8991 match &token.kind {
8992 TokenType::Noun(sym) | TokenType::ProperName(sym) | TokenType::Adjective(sym) => {
8994 self.advance();
8995 Ok(*sym)
8996 }
8997 TokenType::Verb { .. } => {
9000 let sym = token.lexeme;
9001 self.advance();
9002 Ok(sym)
9003 }
9004 TokenType::Article(_) => {
9006 let sym = token.lexeme;
9007 self.advance();
9008 Ok(sym)
9009 }
9010 TokenType::Pronoun { .. } | TokenType::Items | TokenType::Values | TokenType::Item | TokenType::Nothing | TokenType::TemporalAdverb(_) |
9018 TokenType::ScopalAdverb(_) |
9019 TokenType::Adverb(_) |
9020 TokenType::Read |
9022 TokenType::Write |
9023 TokenType::File |
9024 TokenType::Console |
9025 TokenType::Merge |
9027 TokenType::Increase |
9028 TokenType::Decrease |
9029 TokenType::Sleep |
9032 TokenType::Tally |
9034 TokenType::SharedSet |
9035 TokenType::SharedSequence |
9036 TokenType::CollaborativeSequence |
9037 TokenType::Add |
9040 TokenType::Remove |
9041 TokenType::First |
9042 TokenType::Both | TokenType::Either | TokenType::Combined | TokenType::Followed | TokenType::Shared | TokenType::All | TokenType::CalendarUnit(_) |
9051 TokenType::Focus(_) |
9053 TokenType::Particle(_) |
9055 TokenType::Preposition(_) |
9057 TokenType::Escape => {
9059 let sym = token.lexeme;
9061 self.advance();
9062 Ok(sym)
9063 }
9064 TokenType::Ambiguous { .. } => {
9065 let sym = token.lexeme;
9068 self.advance();
9069 Ok(sym)
9070 }
9071 _ => Err(ParseError {
9072 kind: ParseErrorKind::ExpectedIdentifier,
9073 span: self.current_span(),
9074 }),
9075 }
9076 }
9077
9078 fn consume_content_word_for_relative(&mut self) -> ParseResult<Symbol> {
9079 let t = self.advance().clone();
9080 match t.kind {
9081 TokenType::Noun(s) | TokenType::Adjective(s) => Ok(s),
9082 TokenType::ProperName(s) => Ok(s),
9083 TokenType::Verb { lemma, .. } => Ok(lemma),
9084 other => Err(ParseError {
9085 kind: ParseErrorKind::ExpectedContentWord { found: other },
9086 span: self.current_span(),
9087 }),
9088 }
9089 }
9090
9091 fn check_modal(&self) -> bool {
9092 matches!(
9093 self.peek().kind,
9094 TokenType::Must
9095 | TokenType::Shall
9096 | TokenType::Should
9097 | TokenType::Can
9098 | TokenType::May
9099 | TokenType::Cannot
9100 | TokenType::Could
9101 | TokenType::Would
9102 | TokenType::Might
9103 )
9104 }
9105
9106 fn possessive_np_head_follows(&self) -> bool {
9110 let mut i = self.current + 1;
9111 while let Some(token) = self.tokens.get(i) {
9112 match &token.kind {
9113 TokenType::Adjective(_) => i += 1,
9114 TokenType::Noun(_) => return true,
9115 TokenType::Ambiguous { primary, alternatives } => {
9118 return matches!(**primary, TokenType::Noun(_))
9119 || alternatives.iter().any(|t| matches!(t, TokenType::Noun(_)));
9120 }
9121 _ => return false,
9122 }
9123 }
9124 false
9125 }
9126
9127 fn check_pronoun(&self) -> bool {
9128 match &self.peek().kind {
9129 TokenType::Pronoun { case, .. } => {
9130 if matches!(case, Case::Possessive) {
9131 if self.noun_priority_mode {
9134 return false;
9135 }
9136 if self.possessive_np_head_follows() {
9142 return false;
9143 }
9144 }
9145 true
9146 }
9147 TokenType::Ambiguous { primary, alternatives } => {
9148 let has_possessive = matches!(**primary, TokenType::Pronoun { case: Case::Possessive, .. })
9149 || alternatives.iter().any(|t| matches!(t, TokenType::Pronoun { case: Case::Possessive, .. }));
9150 if self.noun_priority_mode && has_possessive {
9152 return false;
9153 }
9154 if has_possessive && self.possessive_np_head_follows() {
9158 return false;
9159 }
9160 matches!(**primary, TokenType::Pronoun { .. })
9161 || alternatives.iter().any(|t| matches!(t, TokenType::Pronoun { .. }))
9162 }
9163 _ => false,
9164 }
9165 }
9166
9167 fn peek_heads_reduced_relative_participle(&self) -> bool {
9174 let idx = if matches!(
9175 self.peek().kind,
9176 TokenType::Adverb(_) | TokenType::TemporalAdverb(_)
9177 ) && self
9178 .tokens
9179 .get(self.current + 1)
9180 .map_or(false, |t| self.kind_is_verb(&t.kind))
9181 {
9182 self.current + 1
9183 } else {
9184 self.current
9185 };
9186 let Some(t) = self.tokens.get(idx) else {
9187 return false;
9188 };
9189 if !self.kind_is_verb(&t.kind) {
9190 return false;
9191 }
9192 if let TokenType::Verb { lemma, .. } = &t.kind {
9195 return !matches!(
9196 self.interner.resolve(*lemma).to_lowercase().as_str(),
9197 "have" | "be" | "do"
9198 );
9199 }
9200 true
9201 }
9202
9203 fn has_comma_before_clause_end(&self) -> bool {
9208 for i in self.current..self.tokens.len() {
9209 match &self.tokens[i].kind {
9210 TokenType::Period | TokenType::EOF => return false,
9211 TokenType::Comma => return true,
9212 _ => {}
9213 }
9214 }
9215 false
9216 }
9217
9218 fn try_consume_reduced_relative(
9233 &mut self,
9234 term: Term<'a>,
9235 ) -> ParseResult<Option<&'a LogicExpr<'a>>> {
9236 if !self.peek_heads_reduced_relative_participle() {
9237 return Ok(None);
9238 }
9239 let mut preds: Vec<&'a LogicExpr<'a>> = Vec::new();
9240 if matches!(
9242 self.peek().kind,
9243 TokenType::Adverb(_) | TokenType::TemporalAdverb(_)
9244 ) {
9245 let adv = match self.peek().kind {
9246 TokenType::Adverb(s) | TokenType::TemporalAdverb(s) => s,
9247 _ => unreachable!(),
9248 };
9249 self.advance();
9250 preds.push(self.ctx.exprs.alloc(LogicExpr::Predicate {
9251 name: adv,
9252 args: self.ctx.terms.alloc_slice([term]),
9253 world: None,
9254 }));
9255 }
9256 let (red_verb, _t, _a, _c) = self.consume_verb_with_metadata();
9257 preds.push(self.ctx.exprs.alloc(LogicExpr::Predicate {
9258 name: red_verb,
9259 args: self.ctx.terms.alloc_slice([term]),
9260 world: None,
9261 }));
9262 loop {
9266 let prep = if self.check_preposition() {
9267 match self.advance().kind {
9268 TokenType::Preposition(s) => s,
9269 _ => break,
9270 }
9271 } else if self.check(&TokenType::To)
9272 && matches!(
9273 self.tokens.get(self.current + 1).map(|t| &t.kind),
9274 Some(TokenType::Article(_))
9275 | Some(TokenType::Noun(_))
9276 | Some(TokenType::ProperName(_))
9277 )
9278 {
9279 self.advance();
9280 self.interner.intern("To")
9281 } else {
9282 break;
9283 };
9284 if self.check_number() {
9285 let m = self.parse_measure_phrase()?;
9286 preds.push(self.ctx.exprs.alloc(LogicExpr::Predicate {
9287 name: prep,
9288 args: self.ctx.terms.alloc_slice([term, *m]),
9289 world: None,
9290 }));
9291 } else if self.check_article() || self.check_content_word() {
9292 let obj = self.parse_noun_phrase(true)?;
9293 preds.push(self.ctx.exprs.alloc(LogicExpr::Predicate {
9294 name: prep,
9295 args: self.ctx.terms.alloc_slice([term, Term::Constant(obj.noun)]),
9296 world: None,
9297 }));
9298 } else {
9299 break;
9300 }
9301 }
9302 let mut result = preds[0];
9303 for p in &preds[1..] {
9304 result = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
9305 left: result,
9306 op: TokenType::And,
9307 right: p,
9308 });
9309 }
9310 Ok(Some(result))
9311 }
9312
9313 fn parse_list_member_np(
9326 &mut self,
9327 np: &crate::ast::NounPhrase<'a>,
9328 bare_definite_distinct: bool,
9329 ) -> ParseResult<(Term<'a>, Option<Symbol>, Option<&'a LogicExpr<'a>>)> {
9330 let has_rel = self.check(&TokenType::Who)
9331 || self.check(&TokenType::That)
9332 || self.check(&TokenType::Where)
9333 || self.check(&TokenType::Whose);
9334 let is_desc = has_rel
9335 || (bare_definite_distinct && np.definiteness.is_some())
9336 || !np.adjectives.is_empty()
9337 || np.possessor.is_some()
9338 || !np.pps.is_empty();
9339 if is_desc {
9340 let var = self.next_var_name();
9341 let term = Term::Variable(var);
9342 let mut r = self.nominal_predication(term, np);
9343 if let Some(poss) = np.possessor {
9344 let possesses = self.interner.intern("Possesses");
9345 let pr = self.ctx.exprs.alloc(LogicExpr::Predicate {
9346 name: possesses,
9347 args: self.ctx.terms.alloc_slice([Term::Constant(poss.noun), term]),
9348 world: None,
9349 });
9350 r = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
9351 left: r,
9352 op: TokenType::And,
9353 right: pr,
9354 });
9355 }
9356 for pp in np.pps {
9357 let pp_sub = self.substitute_pp_self_term(pp, term);
9358 r = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
9359 left: r,
9360 op: TokenType::And,
9361 right: pp_sub,
9362 });
9363 }
9364 if let Some(rc) = self.try_attach_relative(term)? {
9366 r = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
9367 left: r,
9368 op: TokenType::And,
9369 right: rc,
9370 });
9371 }
9372 if let Some(rr) = self.try_consume_reduced_relative(term)? {
9376 r = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
9377 left: r,
9378 op: TokenType::And,
9379 right: rr,
9380 });
9381 }
9382 Ok((term, Some(var), Some(r)))
9383 } else {
9384 Ok((Term::Constant(np.noun), None, None))
9385 }
9386 }
9387
9388 fn finish_enumerated_identity(
9394 &mut self,
9395 subject: &crate::ast::NounPhrase<'a>,
9396 is_negated: bool,
9397 first: (Term<'a>, Option<Symbol>, Option<&'a LogicExpr<'a>>),
9398 ) -> ParseResult<&'a LogicExpr<'a>> {
9399 let mut members: Vec<Term<'a>> = Vec::new();
9400 let mut member_vars: Vec<Symbol> = Vec::new();
9401 let mut member_restrictors: Vec<&'a LogicExpr<'a>> = Vec::new();
9402 let (t0, v0, r0) = first;
9403 members.push(t0);
9404 if let Some(v) = v0 {
9405 member_vars.push(v);
9406 }
9407 if let Some(r) = r0 {
9408 member_restrictors.push(r);
9409 }
9410 while self.check(&TokenType::Comma) || self.check(&TokenType::And) {
9411 while self.check(&TokenType::Comma) || self.check(&TokenType::And) {
9413 self.advance();
9414 }
9415 if !(self.check_article() || self.check_content_word()) {
9416 break;
9417 }
9418 let item = self.parse_noun_phrase(true)?;
9419 let (t, v, r) = self.parse_list_member_np(&item, false)?;
9420 members.push(t);
9421 if let Some(vv) = v {
9422 member_vars.push(vv);
9423 }
9424 if let Some(rr) = r {
9425 member_restrictors.push(rr);
9426 }
9427 }
9428 let group = Term::Group(self.ctx.terms.alloc_slice(members));
9429 let identity: &'a LogicExpr<'a> = self.ctx.exprs.alloc(LogicExpr::Identity {
9430 left: self.ctx.terms.alloc(Term::Constant(subject.noun)),
9431 right: self.ctx.terms.alloc(group),
9432 });
9433 let mut result = if is_negated {
9434 &*self.ctx.exprs.alloc(LogicExpr::UnaryOp {
9435 op: TokenType::Not,
9436 operand: identity,
9437 })
9438 } else {
9439 identity
9440 };
9441 for rc in member_restrictors {
9442 result = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
9443 left: result,
9444 op: TokenType::And,
9445 right: rc,
9446 });
9447 }
9448 for v in member_vars.into_iter().rev() {
9449 result = self.ctx.exprs.alloc(LogicExpr::Quantifier {
9450 kind: QuantifierKind::Existential,
9451 variable: v,
9452 body: result,
9453 island_id: self.current_island,
9454 });
9455 }
9456 self.wrap_with_definiteness_full(subject, result)
9457 }
9458
9459 fn try_parse_list_subject(
9465 &mut self,
9466 first: &crate::ast::NounPhrase<'a>,
9467 ) -> ParseResult<Option<&'a LogicExpr<'a>>> {
9468 let cp = self.checkpoint();
9469 let mut member_terms: Vec<Term<'a>> = Vec::new();
9476 let mut member_vars: Vec<Symbol> = Vec::new();
9477 let mut member_restrictors: Vec<&'a LogicExpr<'a>> = Vec::new();
9478 macro_rules! add_member {
9479 ($np:expr) => {{
9480 let np = $np;
9481 match self.parse_list_member_np(&np, true) {
9482 Ok((term, var, restrictor)) => {
9483 member_terms.push(term);
9484 if let Some(v) = var {
9485 member_vars.push(v);
9486 }
9487 if let Some(r) = restrictor {
9488 member_restrictors.push(r);
9489 }
9490 }
9491 Err(_) => {
9492 self.restore(cp);
9493 return Ok(None);
9494 }
9495 }
9496 }};
9497 }
9498 add_member!(*first);
9499 if !self.check(&TokenType::Comma) && !self.check(&TokenType::And) {
9506 self.restore(cp);
9507 return Ok(None);
9508 }
9509 let mut saw_and = false;
9510 loop {
9511 let mut advanced = false;
9512 if self.check(&TokenType::Comma) {
9513 self.advance();
9514 advanced = true;
9515 }
9516 if self.check(&TokenType::And) {
9517 self.advance();
9518 saw_and = true;
9519 advanced = true;
9520 }
9521 if !advanced {
9522 break;
9523 }
9524 if !(self.check_article() || self.check_content_word()) {
9525 break;
9526 }
9527 let np = match self.parse_noun_phrase(true) {
9528 Ok(np) => np,
9529 Err(_) => {
9530 self.restore(cp);
9531 return Ok(None);
9532 }
9533 };
9534 add_member!(np);
9535 }
9536
9537 if !saw_and || member_terms.len() < 2 {
9544 self.restore(cp);
9545 return Ok(None);
9546 }
9547
9548 let copula_past = self.check(&TokenType::Were);
9549 if !(self.check(&TokenType::Are)
9550 || self.check(&TokenType::Were)
9551 || self.check(&TokenType::Is))
9552 {
9553 self.restore(cp);
9554 return Ok(None);
9555 }
9556 self.advance(); if self.check(&TokenType::All) {
9559 self.advance();
9560 }
9561
9562 if matches!(self.peek().kind, TokenType::Cardinal(_))
9566 && self
9567 .tokens
9568 .get(self.current + 1)
9569 .map(|t| self.interner.resolve(t.lexeme).eq_ignore_ascii_case("different"))
9570 .unwrap_or(false)
9571 {
9572 self.advance();
9573 }
9574
9575 let mut conjuncts: Vec<&'a LogicExpr<'a>> = member_restrictors;
9579
9580 let is_different = self
9581 .interner
9582 .resolve(self.peek().lexeme)
9583 .eq_ignore_ascii_case("different");
9584 if is_different {
9585 self.advance(); if self.check_content_word() {
9588 let type_noun = self.consume_content_word()?;
9589 for t in &member_terms {
9590 conjuncts.push(self.ctx.exprs.alloc(LogicExpr::Predicate {
9591 name: type_noun,
9592 args: self.ctx.terms.alloc_slice([*t]),
9593 world: None,
9594 }));
9595 if let Term::Constant(item) = t {
9602 self.drs.register_item_category(*item, type_noun);
9603 }
9604 }
9605 }
9606 for i in 0..member_terms.len() {
9609 for j in (i + 1)..member_terms.len() {
9610 let id = self.ctx.exprs.alloc(LogicExpr::Identity {
9611 left: self.ctx.terms.alloc(member_terms[i]),
9612 right: self.ctx.terms.alloc(member_terms[j]),
9613 });
9614 conjuncts.push(self.ctx.exprs.alloc(LogicExpr::UnaryOp {
9615 op: TokenType::Not,
9616 operand: id,
9617 }));
9618 }
9619 }
9620 } else if self.check_article() || self.check_content_word() {
9621 let pred_np = self.parse_noun_phrase(true)?;
9623 for t in &member_terms {
9624 conjuncts.push(self.ctx.exprs.alloc(LogicExpr::Predicate {
9625 name: pred_np.noun,
9626 args: self.ctx.terms.alloc_slice([*t]),
9627 world: None,
9628 }));
9629 }
9630 } else {
9631 self.restore(cp);
9632 return Ok(None);
9633 }
9634
9635 if conjuncts.is_empty() {
9636 self.restore(cp);
9637 return Ok(None);
9638 }
9639 let mut result = conjuncts[0];
9640 for c in &conjuncts[1..] {
9641 result = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
9642 left: result,
9643 op: TokenType::And,
9644 right: c,
9645 });
9646 }
9647 if copula_past {
9648 result = self.ctx.exprs.alloc(LogicExpr::Temporal {
9649 operator: TemporalOperator::Past,
9650 body: result,
9651 });
9652 }
9653 for &var in member_vars.iter().rev() {
9656 result = self.ctx.exprs.alloc(LogicExpr::Quantifier {
9657 kind: QuantifierKind::Existential,
9658 variable: var,
9659 body: result,
9660 island_id: self.current_island,
9661 });
9662 }
9663 Ok(Some(result))
9664 }
9665
9666 fn parse_atom(&mut self) -> ParseResult<&'a LogicExpr<'a>> {
9667 self.pending_subject_restriction = None;
9671
9672 if self.check_focus() {
9674 return self.parse_focus();
9675 }
9676
9677 if self.check_measure() {
9679 return self.parse_measure();
9680 }
9681
9682 if let TokenType::Verb {
9687 lemma,
9688 aspect: Aspect::Progressive,
9689 time: Time::None,
9690 ..
9691 } = self.peek().kind
9692 {
9693 let noun_next = matches!(
9694 self.tokens.get(self.current + 1).map(|t| t.kind.clone()),
9695 Some(TokenType::Noun(_))
9696 );
9697 let finite_after = matches!(
9698 self.tokens.get(self.current + 2).map(|t| t.kind.clone()),
9699 Some(
9700 TokenType::Can
9701 | TokenType::Could
9702 | TokenType::May
9703 | TokenType::Must
9704 | TokenType::Should
9705 | TokenType::Would
9706 | TokenType::Is
9707 | TokenType::Are
9708 )
9709 );
9710 if noun_next && finite_after {
9711 self.advance(); let noun_sym = match self.advance().kind {
9713 TokenType::Noun(n) => n,
9714 _ => unreachable!("guarded by noun_next"),
9715 };
9716
9717 let event_var = self.get_event_var();
9718 let activity = self.ctx.exprs.alloc(LogicExpr::NeoEvent(Box::new(NeoEventData {
9719 event_var,
9720 verb: lemma,
9721 roles: self
9722 .ctx
9723 .roles
9724 .alloc_slice(vec![(ThematicRole::Theme, Term::Constant(noun_sym))]),
9725 modifiers: self.ctx.syms.alloc_slice(vec![]),
9726 suppress_existential: false,
9727 world: None,
9728 })));
9729
9730 let modal_tok = if matches!(
9731 self.peek().kind,
9732 TokenType::Can
9733 | TokenType::Could
9734 | TokenType::May
9735 | TokenType::Must
9736 | TokenType::Should
9737 | TokenType::Would
9738 ) {
9739 Some(self.advance().kind.clone())
9740 } else {
9741 None
9742 };
9743 if matches!(self.peek().kind, TokenType::Is | TokenType::Are | TokenType::Be) {
9745 self.advance();
9746 } else if matches!(self.peek().kind, TokenType::Verb { .. })
9747 && self
9748 .interner
9749 .resolve(self.peek().lexeme)
9750 .eq_ignore_ascii_case("be")
9751 {
9752 self.advance();
9753 }
9754
9755 if let TokenType::Adjective(adj) = self.peek().kind {
9756 self.advance();
9757 let pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
9758 name: adj,
9759 args: self.ctx.terms.alloc_slice([Term::Proposition(activity)]),
9760 world: None,
9761 });
9762 let result = match modal_tok {
9763 Some(tok) => {
9764 let force = match tok {
9765 TokenType::Must => 1.0,
9766 TokenType::Should | TokenType::Would => 0.6,
9767 TokenType::Could => 0.4,
9768 _ => 0.5,
9769 };
9770 &*self.ctx.exprs.alloc(LogicExpr::Modal {
9771 vector: crate::ast::ModalVector::new(
9772 crate::ast::ModalDomain::Alethic,
9773 force,
9774 crate::ast::ModalFlavor::Root,
9775 ),
9776 operand: pred,
9777 })
9778 }
9779 None => pred,
9780 };
9781 return Ok(result);
9782 }
9783 return Err(ParseError {
9784 kind: ParseErrorKind::ExpectedContentWord {
9785 found: self.peek().kind.clone(),
9786 },
9787 span: self.current_span(),
9788 });
9789 }
9790 }
9791
9792 if self.check_quantifier() {
9793 self.advance();
9794 return self.parse_quantified();
9795 }
9796
9797 if self.check_npi_quantifier() {
9798 return self.parse_npi_quantified();
9799 }
9800
9801 if self.check_temporal_npi() {
9802 return self.parse_temporal_npi();
9803 }
9804
9805 if self.match_token(&[TokenType::LParen]) {
9806 let expr = self.parse_sentence()?;
9807 self.consume(TokenType::RParen)?;
9808 return Ok(expr);
9809 }
9810
9811 if self.check_pronoun() {
9813 let token = self.advance().clone();
9814 let (gender, number) = match &token.kind {
9815 TokenType::Pronoun { gender, number, .. } => (*gender, *number),
9816 TokenType::Ambiguous { primary, alternatives } => {
9817 if let TokenType::Pronoun { gender, number, .. } = **primary {
9818 (gender, number)
9819 } else {
9820 alternatives.iter().find_map(|t| {
9821 if let TokenType::Pronoun { gender, number, .. } = t {
9822 Some((*gender, *number))
9823 } else {
9824 None
9825 }
9826 }).unwrap_or((Gender::Unknown, Number::Singular))
9827 }
9828 }
9829 _ => (Gender::Unknown, Number::Singular),
9830 };
9831
9832 let token_text = self.interner.resolve(token.lexeme);
9833
9834 if token_text.eq_ignore_ascii_case("it") && self.check_verb() {
9837 if let TokenType::Verb { lemma, time, .. } = &self.peek().kind {
9838 let lemma_str = self.interner.resolve(*lemma);
9839 if Lexer::is_weather_verb(lemma_str) {
9840 let verb = *lemma;
9841 let verb_time = *time;
9842 self.advance(); let event_var = self.get_event_var();
9845 let suppress_existential = self.drs.in_conditional_antecedent();
9846 if suppress_existential {
9847 let event_class = self.interner.intern("Event");
9848 self.drs.introduce_referent(event_var, event_class, Gender::Neuter, Number::Singular);
9849 }
9850 let neo_event = self.ctx.exprs.alloc(LogicExpr::NeoEvent(Box::new(NeoEventData {
9851 event_var,
9852 verb,
9853 roles: self.ctx.roles.alloc_slice(vec![]), modifiers: self.ctx.syms.alloc_slice(vec![]),
9855 suppress_existential,
9856 world: None,
9857 })));
9858
9859 return Ok(match verb_time {
9860 Time::Past => self.ctx.exprs.alloc(LogicExpr::Temporal {
9861 operator: TemporalOperator::Past,
9862 body: neo_event,
9863 }),
9864 Time::Future => self.ctx.exprs.alloc(LogicExpr::Temporal {
9865 operator: TemporalOperator::Future,
9866 body: neo_event,
9867 }),
9868 _ => neo_event,
9869 });
9870 }
9871 }
9872 }
9873
9874 let resolved = if token_text.eq_ignore_ascii_case("i") {
9876 ResolvedPronoun::Constant(self.interner.intern("Speaker"))
9877 } else if token_text.eq_ignore_ascii_case("you") {
9878 ResolvedPronoun::Constant(self.interner.intern("Addressee"))
9879 } else {
9880 self.resolve_pronoun(gender, number)?
9882 };
9883
9884 if self
9886 .interner
9887 .resolve(self.peek().lexeme)
9888 .eq_ignore_ascii_case("hereby")
9889 {
9890 self.advance();
9891 }
9892
9893 if self.check_performative() {
9895 if let TokenType::Performative(act) = self.advance().kind.clone() {
9896 let sym = match resolved {
9897 ResolvedPronoun::Variable(s) | ResolvedPronoun::Constant(s) => s,
9898 };
9899
9900 if self.check(&TokenType::To) {
9904 self.advance(); if !self.is_at_end() && !self.check(&TokenType::Period) {
9907 let lexeme =
9912 self.interner.resolve(self.peek().lexeme).to_string();
9913 let verb_name = lexeme
9914 .chars()
9915 .next()
9916 .map(|c| c.to_uppercase().collect::<String>() + &lexeme[1..])
9917 .unwrap_or(lexeme);
9918 let infinitive_verb = self.interner.intern(&verb_name);
9919 self.advance(); let content = self.performative_predicate(infinitive_verb, sym);
9921 return Ok(self.ctx.exprs.alloc(LogicExpr::SpeechAct {
9922 performer: sym,
9923 act_type: act,
9924 content,
9925 }));
9926 }
9927 }
9928
9929 if self.check(&TokenType::That) {
9931 self.advance();
9932 let content = self.parse_sentence()?;
9933 return Ok(self.ctx.exprs.alloc(LogicExpr::SpeechAct {
9934 performer: sym,
9935 act_type: act,
9936 content,
9937 }));
9938 }
9939
9940 let at_end = self.check(&TokenType::Period) || self.is_at_end();
9946 let lone_object_then_end = matches!(
9947 self.peek().kind,
9948 TokenType::Pronoun { .. } | TokenType::ProperName(_)
9949 ) && self.current + 1 < self.tokens.len()
9950 && matches!(
9951 self.tokens[self.current + 1].kind,
9952 TokenType::Period | TokenType::EOF
9953 );
9954 if at_end || lone_object_then_end {
9955 let content = self.performative_predicate(act, sym);
9956 return Ok(self.ctx.exprs.alloc(LogicExpr::SpeechAct {
9957 performer: sym,
9958 act_type: act,
9959 content,
9960 }));
9961 }
9962
9963 let content = self.parse_sentence()?;
9966 return Ok(self.ctx.exprs.alloc(LogicExpr::SpeechAct {
9967 performer: sym,
9968 act_type: act,
9969 content,
9970 }));
9971 }
9972 }
9973
9974 return match resolved {
9977 ResolvedPronoun::Variable(sym) => self.parse_predicate_with_subject_as_var(sym),
9978 ResolvedPronoun::Constant(sym) => self.parse_predicate_with_subject(sym),
9979 };
9980 }
9981
9982 let _had_both = self.match_token(&[TokenType::Both]);
9985
9986 let mut subject = self.parse_noun_phrase(true)?;
9987
9988 if self.check(&TokenType::All)
9993 || self.check(&TokenType::Both)
9994 || self.interner.resolve(self.peek().lexeme).eq_ignore_ascii_case("each")
9995 {
9996 self.advance();
9997 self.collective_mode = false; self.distributive_marker = true;
9999 }
10000
10001 if subject.definiteness == Some(Definiteness::Indefinite)
10007 || subject.definiteness == Some(Definiteness::Distal) {
10008 let gender = Self::infer_noun_gender(self.interner.resolve(subject.noun));
10009 let number = if Self::is_plural_noun(self.interner.resolve(subject.noun)) {
10010 Number::Plural
10011 } else {
10012 Number::Singular
10013 };
10014 self.drs.introduce_referent(subject.noun, subject.noun, gender, number);
10016 }
10017
10018 if self.check(&TokenType::And) {
10020 match self.try_parse_plural_subject(&subject) {
10021 Ok(Some(result)) => return Ok(result),
10022 Ok(None) => {} Err(e) => return Err(e), }
10025 }
10026
10027 if self.check_scopal_adverb() {
10029 return self.parse_scopal_adverb(&subject);
10030 }
10031
10032 if self.check(&TokenType::Comma)
10036 && matches!(
10037 self.tokens.get(self.current + 1).map(|t| &t.kind),
10038 Some(TokenType::Who) | Some(TokenType::That)
10039 )
10040 {
10041 self.advance(); self.advance(); let rc = self.parse_relative_clause(subject.noun)?;
10045 if self.check(&TokenType::Comma) {
10046 self.advance(); }
10048 let main = self.parse_predicate_with_subject(subject.noun)?;
10050 let conj = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
10051 left: main,
10052 op: TokenType::And,
10053 right: rc,
10054 });
10055 return self.wrap_with_definiteness_full(&subject, conj);
10056 }
10057
10058 if self.check(&TokenType::Comma)
10065 || self.check(&TokenType::Who)
10066 || self.check(&TokenType::That)
10067 || self.check(&TokenType::And)
10074 || (self.peek_heads_reduced_relative_participle() && self.has_comma_before_clause_end())
10081 {
10082 if let Some(result) = self.try_parse_list_subject(&subject)? {
10083 return Ok(result);
10084 }
10085 }
10086
10087 if self.check(&TokenType::Comma) {
10089 let saved_pos = self.current;
10090 self.advance(); if self.check_pronoun() {
10094 let topic_attempt = self.try_parse(|p| {
10095 let token = p.peek().clone();
10096 let pronoun_features = match &token.kind {
10097 TokenType::Pronoun { gender, number, .. } => Some((*gender, *number)),
10098 TokenType::Ambiguous { primary, alternatives } => {
10099 if let TokenType::Pronoun { gender, number, .. } = **primary {
10100 Some((gender, number))
10101 } else {
10102 alternatives.iter().find_map(|t| {
10103 if let TokenType::Pronoun { gender, number, .. } = t {
10104 Some((*gender, *number))
10105 } else {
10106 None
10107 }
10108 })
10109 }
10110 }
10111 _ => None,
10112 };
10113
10114 if let Some((gender, number)) = pronoun_features {
10115 p.advance(); let resolved = p.resolve_pronoun(gender, number)?;
10117 let resolved_term = match resolved {
10118 ResolvedPronoun::Variable(s) => Term::Variable(s),
10119 ResolvedPronoun::Constant(s) => Term::Constant(s),
10120 };
10121
10122 if p.check_verb() {
10123 let verb = p.consume_verb();
10124 let predicate = p.ctx.exprs.alloc(LogicExpr::Predicate {
10125 name: verb,
10126 args: p.ctx.terms.alloc_slice([
10127 resolved_term,
10128 Term::Constant(subject.noun),
10129 ]),
10130 world: None,
10131 });
10132 p.wrap_with_definiteness_full(&subject, predicate)
10133 } else {
10134 Err(ParseError {
10135 kind: ParseErrorKind::ExpectedVerb { found: p.peek().kind.clone() },
10136 span: p.current_span(),
10137 })
10138 }
10139 } else {
10140 Err(ParseError {
10141 kind: ParseErrorKind::ExpectedContentWord { found: token.kind },
10142 span: p.current_span(),
10143 })
10144 }
10145 });
10146
10147 if let Some(result) = topic_attempt {
10148 return Ok(result);
10149 }
10150 }
10151
10152 if self.check_content_word() {
10154 let topic_attempt = self.try_parse(|p| {
10155 let real_subject = p.parse_noun_phrase(true)?;
10156 if p.check_verb() {
10157 let verb = p.consume_verb();
10158 let predicate = p.ctx.exprs.alloc(LogicExpr::Predicate {
10159 name: verb,
10160 args: p.ctx.terms.alloc_slice([
10161 Term::Constant(real_subject.noun),
10162 Term::Constant(subject.noun),
10163 ]),
10164 world: None,
10165 });
10166 p.wrap_with_definiteness_full(&subject, predicate)
10167 } else {
10168 Err(ParseError {
10169 kind: ParseErrorKind::ExpectedVerb { found: p.peek().kind.clone() },
10170 span: p.current_span(),
10171 })
10172 }
10173 });
10174
10175 if let Some(result) = topic_attempt {
10176 return Ok(result);
10177 }
10178 }
10179
10180 self.current = saved_pos;
10182 }
10183
10184 let mut relative_clause: Option<(Symbol, &'a LogicExpr<'a>)> = None;
10186 if self.check(&TokenType::That) || self.check(&TokenType::Who) {
10187 self.advance();
10188 let var_name = self.next_var_name();
10189 let rel_pred = self.parse_relative_clause(var_name)?;
10190 relative_clause = Some((var_name, rel_pred));
10191 } else if self.check(&TokenType::Where) {
10192 let var_name = self.next_var_name();
10199 let rel_pred = self.parse_where_relative(var_name)?;
10200 relative_clause = Some((var_name, rel_pred));
10201 } else if matches!(self.peek().kind, TokenType::Article(_)) && self.is_contact_clause_pattern() {
10202 let var_name = self.next_var_name();
10205 let rel_pred = self.parse_relative_clause(var_name)?;
10206 relative_clause = Some((var_name, rel_pred));
10207 }
10208
10209 if let Some((var_name, rel_clause)) = relative_clause {
10211 if self.check_presup_trigger()
10216 && !self.is_followed_by_np_object()
10217 && self.is_followed_by_gerund()
10218 {
10219 let presup_kind = self.consume_presup_trigger();
10220 let main_pred =
10221 self.parse_presupposition_for_term(Term::Variable(var_name), presup_kind, false)?;
10222 let type_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
10223 name: subject.noun,
10224 args: self.ctx.terms.alloc_slice([Term::Variable(var_name)]),
10225 world: None,
10226 });
10227 let inner = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
10228 left: type_pred,
10229 op: TokenType::And,
10230 right: rel_clause,
10231 });
10232 let body = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
10233 left: inner,
10234 op: TokenType::And,
10235 right: main_pred,
10236 });
10237 return Ok(self.ctx.exprs.alloc(LogicExpr::Quantifier {
10238 kind: QuantifierKind::Existential,
10239 variable: var_name,
10240 body,
10241 island_id: self.current_island,
10242 }));
10243 }
10244 if self.check_verb() {
10245 let (verb, verb_time, _, _) = self.consume_verb_with_metadata();
10246 let var_term = Term::Variable(var_name);
10247
10248 let main_pred = if self.at_clause_boundary() {
10252 let event_var = self.get_event_var();
10253 let suppress_existential = self.drs.in_conditional_antecedent();
10254 let mut modifiers = vec![];
10255 if verb_time == Time::Past {
10256 modifiers.push(self.interner.intern("Past"));
10257 }
10258 &*self.ctx.exprs.alloc(LogicExpr::NeoEvent(Box::new(NeoEventData {
10259 event_var,
10260 verb,
10261 roles: self.ctx.roles.alloc_slice(vec![
10262 (ThematicRole::Agent, var_term),
10263 ]),
10264 modifiers: self.ctx.syms.alloc_slice(modifiers),
10265 suppress_existential,
10266 world: None,
10267 })))
10268 } else {
10269 self.current -= 1; self.parse_predicate_with_subject_as_var(var_name)?
10271 };
10272
10273 let type_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
10274 name: subject.noun,
10275 args: self.ctx.terms.alloc_slice([Term::Variable(var_name)]),
10276 world: None,
10277 });
10278
10279 let inner = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
10280 left: type_pred,
10281 op: TokenType::And,
10282 right: rel_clause,
10283 });
10284
10285 let body = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
10286 left: inner,
10287 op: TokenType::And,
10288 right: main_pred,
10289 });
10290
10291 return Ok(self.ctx.exprs.alloc(LogicExpr::Quantifier {
10292 kind: QuantifierKind::Existential,
10293 variable: var_name,
10294 body,
10295 island_id: self.current_island,
10296 }));
10297 }
10298
10299 if self.is_at_end() || self.check(&TokenType::Period) || self.check(&TokenType::Comma) {
10302 let type_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
10303 name: subject.noun,
10304 args: self.ctx.terms.alloc_slice([Term::Variable(var_name)]),
10305 world: None,
10306 });
10307
10308 let body = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
10309 left: type_pred,
10310 op: TokenType::And,
10311 right: rel_clause,
10312 });
10313
10314 let uniqueness_body = if subject.definiteness == Some(Definiteness::Definite) {
10316 let y_var = self.next_var_name();
10317 let type_pred_y = self.ctx.exprs.alloc(LogicExpr::Predicate {
10318 name: subject.noun,
10319 args: self.ctx.terms.alloc_slice([Term::Variable(y_var)]),
10320 world: None,
10321 });
10322 let identity = self.ctx.exprs.alloc(LogicExpr::Identity {
10323 left: self.ctx.terms.alloc(Term::Variable(y_var)),
10324 right: self.ctx.terms.alloc(Term::Variable(var_name)),
10325 });
10326 let uniqueness_cond = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
10327 left: type_pred_y,
10328 op: TokenType::Implies,
10329 right: identity,
10330 });
10331 let uniqueness = self.ctx.exprs.alloc(LogicExpr::Quantifier {
10332 kind: QuantifierKind::Universal,
10333 variable: y_var,
10334 body: uniqueness_cond,
10335 island_id: self.current_island,
10336 });
10337 self.ctx.exprs.alloc(LogicExpr::BinaryOp {
10338 left: body,
10339 op: TokenType::And,
10340 right: uniqueness,
10341 })
10342 } else {
10343 body
10344 };
10345
10346 return Ok(self.ctx.exprs.alloc(LogicExpr::Quantifier {
10347 kind: QuantifierKind::Existential,
10348 variable: var_name,
10349 body: uniqueness_body,
10350 island_id: self.current_island,
10351 }));
10352 }
10353
10354 relative_clause = Some((var_name, rel_clause));
10356 }
10357
10358 if self.check(&TokenType::Identity) {
10360 self.advance();
10361 let right = self.consume_content_word()?;
10362 return Ok(self.ctx.exprs.alloc(LogicExpr::Identity {
10363 left: self.ctx.terms.alloc(Term::Constant(subject.noun)),
10364 right: self.ctx.terms.alloc(Term::Constant(right)),
10365 }));
10366 }
10367
10368 if self.check_modal() {
10369 if let Some((var_name, rel_clause)) = relative_clause {
10370 let modal_pred = self.parse_aspect_chain_with_term(Term::Variable(var_name))?;
10371
10372 let type_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
10373 name: subject.noun,
10374 args: self.ctx.terms.alloc_slice([Term::Variable(var_name)]),
10375 world: None,
10376 });
10377
10378 let inner = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
10379 left: type_pred,
10380 op: TokenType::And,
10381 right: rel_clause,
10382 });
10383
10384 let body = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
10385 left: inner,
10386 op: TokenType::And,
10387 right: modal_pred,
10388 });
10389
10390 return Ok(self.ctx.exprs.alloc(LogicExpr::Quantifier {
10391 kind: QuantifierKind::Existential,
10392 variable: var_name,
10393 body,
10394 island_id: self.current_island,
10395 }));
10396 }
10397
10398 let modal_pred = self.parse_aspect_chain(subject.noun)?;
10399 return self.wrap_with_definiteness_full(&subject, modal_pred);
10400 }
10401
10402 let leading_adverb = if matches!(
10421 self.peek().kind,
10422 TokenType::Adverb(_) | TokenType::TemporalAdverb(_)
10423 ) && self
10424 .tokens
10425 .get(self.current + 1)
10426 .map_or(false, |t| self.kind_is_verb(&t.kind))
10427 {
10428 match self.peek().kind {
10429 TokenType::Adverb(s) | TokenType::TemporalAdverb(s) => Some(s),
10430 _ => None,
10431 }
10432 } else {
10433 None
10434 };
10435 let head_verb_idx = if leading_adverb.is_some() {
10436 self.current + 1
10437 } else {
10438 self.current
10439 };
10440 let head_verb_is_aux = if let Some(TokenType::Verb { lemma, .. }) =
10441 self.tokens.get(head_verb_idx).map(|t| &t.kind)
10442 {
10443 matches!(
10444 self.interner.resolve(*lemma).to_lowercase().as_str(),
10445 "have" | "be" | "do"
10446 )
10447 } else {
10448 false
10449 };
10450 let heads_reduced_rel = self
10451 .tokens
10452 .get(head_verb_idx)
10453 .map_or(false, |t| self.kind_is_verb(&t.kind));
10454 if subject.definiteness.is_some()
10455 && heads_reduced_rel
10456 && self.pending_time.is_none()
10457 && !head_verb_is_aux
10458 {
10459 if let Some(restrs) = self.try_parse(|p| {
10460 let placeholder = p.interner.intern("_PP_SELF_");
10461 let mut preds: Vec<&'a LogicExpr<'a>> = Vec::new();
10462 if let Some(adv) = leading_adverb {
10463 p.advance();
10464 preds.push(p.ctx.exprs.alloc(LogicExpr::Predicate {
10465 name: adv,
10466 args: p.ctx.terms.alloc_slice([Term::Variable(placeholder)]),
10467 world: None,
10468 }));
10469 }
10470 let (red_verb, _t, _a, _c) = p.consume_verb_with_metadata();
10471 preds.push(p.ctx.exprs.alloc(LogicExpr::Predicate {
10472 name: red_verb,
10473 args: p.ctx.terms.alloc_slice([Term::Variable(placeholder)]),
10474 world: None,
10475 }));
10476 loop {
10479 let prep = if p.check_preposition() {
10480 match p.advance().kind {
10481 TokenType::Preposition(s) => s,
10482 _ => break,
10483 }
10484 } else if p.check(&TokenType::To)
10485 && matches!(
10486 p.tokens.get(p.current + 1).map(|t| &t.kind),
10487 Some(TokenType::Article(_))
10488 | Some(TokenType::Noun(_))
10489 | Some(TokenType::ProperName(_))
10490 )
10491 {
10492 p.advance(); p.interner.intern("To")
10494 } else {
10495 break;
10496 };
10497 if p.check_number() {
10498 let m = p.parse_measure_phrase()?;
10499 preds.push(p.ctx.exprs.alloc(LogicExpr::Predicate {
10500 name: prep,
10501 args: p.ctx.terms.alloc_slice([Term::Variable(placeholder), *m]),
10502 world: None,
10503 }));
10504 } else if p.check_article() || p.check_content_word() {
10505 let obj = p.parse_noun_phrase(true)?;
10506 preds.push(p.ctx.exprs.alloc(LogicExpr::Predicate {
10507 name: prep,
10508 args: p
10509 .ctx
10510 .terms
10511 .alloc_slice([Term::Variable(placeholder), Term::Constant(obj.noun)]),
10512 world: None,
10513 }));
10514 } else {
10515 break;
10516 }
10517 }
10518 let matrix_finite_verb = matches!(
10529 p.peek().kind,
10530 TokenType::Verb { aspect, .. } if !matches!(aspect, Aspect::Progressive)
10531 );
10532 if !(p.check(&TokenType::Is)
10533 || p.check(&TokenType::Are)
10534 || p.check(&TokenType::Was)
10535 || p.check(&TokenType::Were)
10536 || p.check(&TokenType::Does)
10537 || p.check(&TokenType::Do)
10538 || p.check(&TokenType::Had)
10539 || matrix_finite_verb)
10540 {
10541 return Err(ParseError {
10542 kind: ParseErrorKind::ExpectedCopula,
10543 span: p.current_span(),
10544 });
10545 }
10546 Ok(preds)
10547 }) {
10548 let mut pps: Vec<&'a LogicExpr<'a>> = subject.pps.to_vec();
10549 pps.extend(restrs);
10550 subject = crate::ast::NounPhrase {
10551 pps: self.ctx.pps.alloc_slice(pps),
10552 ..subject
10553 };
10554 }
10555 }
10556
10557 if (self.check(&TokenType::Are) || self.check(&TokenType::Is))
10561 && subject.definiteness.is_none()
10562 && subject.possessor.is_none()
10563 {
10564 let noun_str = self.interner.resolve(subject.noun);
10565 let lower = noun_str.to_lowercase();
10566 let is_known_plural = Self::is_plural_noun(noun_str)
10567 && (crate::lexicon::is_common_noun(&lower)
10568 || matches!(
10569 crate::lexicon::analyze_word(&lower),
10570 Some(crate::lexicon::WordAnalysis::Noun(_))
10571 ));
10572 let nominal_or_adj_follows = matches!(
10573 self.tokens.get(self.current + 1).map(|t| &t.kind),
10574 Some(TokenType::Noun(_))
10575 | Some(TokenType::Adjective(_))
10576 | Some(TokenType::Article(_))
10577 );
10578 if is_known_plural && nominal_or_adj_follows {
10579 self.advance(); let negated = self.check(&TokenType::Not);
10581 if negated {
10582 self.advance();
10583 }
10584 if self.check_article() {
10585 self.advance();
10586 }
10587 let var_name = self.next_var_name();
10588 let type_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
10589 name: subject.noun,
10590 args: self.ctx.terms.alloc_slice([Term::Variable(var_name)]),
10591 world: None,
10592 });
10593 let pred_name = match self.peek().kind {
10594 TokenType::Noun(s) | TokenType::Adjective(s) => {
10595 self.advance();
10596 s
10597 }
10598 _ => self.consume_content_word()?,
10599 };
10600 let mut nucleus: &'a LogicExpr<'a> =
10601 self.ctx.exprs.alloc(LogicExpr::Predicate {
10602 name: pred_name,
10603 args: self.ctx.terms.alloc_slice([Term::Variable(var_name)]),
10604 world: None,
10605 });
10606 if negated {
10607 nucleus = self.ctx.exprs.alloc(LogicExpr::UnaryOp {
10608 op: TokenType::Not,
10609 operand: nucleus,
10610 });
10611 }
10612 let body = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
10613 left: type_pred,
10614 op: TokenType::Implies,
10615 right: nucleus,
10616 });
10617 return Ok(self.ctx.exprs.alloc(LogicExpr::Quantifier {
10618 kind: QuantifierKind::Generic,
10619 variable: var_name,
10620 body,
10621 island_id: self.current_island,
10622 }));
10623 }
10624 }
10625
10626 if let Some((rc_var, rc_pred)) = relative_clause {
10632 if self.check(&TokenType::Is) || self.check(&TokenType::Are)
10633 || self.check(&TokenType::Was) || self.check(&TokenType::Were)
10634 {
10635 let restr =
10636 self.substitute_variable_with_constant(rc_pred, rc_var, subject.noun)?;
10637 self.pending_subject_restriction = Some((subject.noun, restr));
10638 }
10639 }
10640
10641 if self.check(&TokenType::Is) || self.check(&TokenType::Are)
10642 || self.check(&TokenType::Was) || self.check(&TokenType::Were)
10643 {
10644 let copula_time = if self.check(&TokenType::Was) || self.check(&TokenType::Were) {
10645 Time::Past
10646 } else {
10647 Time::Present
10648 };
10649 self.advance();
10650
10651 let is_negated = self.check(&TokenType::Not);
10653 if is_negated {
10654 self.advance(); }
10656
10657 let mut copula_temporal = None;
10659 if !is_negated {
10660 if self.check(&TokenType::Never) {
10661 self.advance();
10662 copula_temporal = Some(CopulaTemporal::Never);
10663 } else if let TokenType::Adverb(sym) | TokenType::ScopalAdverb(sym) | TokenType::TemporalAdverb(sym) = &self.peek().kind {
10664 let resolved = self.interner.resolve(*sym).to_string();
10665 if resolved == "Always" || resolved == "always" {
10666 self.advance();
10667 copula_temporal = Some(CopulaTemporal::Always);
10668 } else if resolved == "Eventually" || resolved == "eventually" {
10669 self.advance();
10670 copula_temporal = Some(CopulaTemporal::Eventually);
10671 }
10672 }
10673 }
10674
10675 if matches!(self.peek().kind, TokenType::Cardinal(1)) {
10679 let of_follows = matches!(
10680 self.tokens.get(self.current + 1).map(|t| &t.kind),
10681 Some(TokenType::Preposition(p)) if self.interner.resolve(*p).eq_ignore_ascii_case("of")
10682 );
10683 let article_then_noun = matches!(
10684 self.tokens.get(self.current + 2).map(|t| &t.kind),
10685 Some(TokenType::Article(_))
10686 ) && matches!(
10687 self.tokens.get(self.current + 3).map(|t| &t.kind),
10688 Some(TokenType::Noun(_))
10689 );
10690 if of_follows && article_then_noun {
10691 self.advance(); self.advance(); self.advance(); let noun_sym = match self.advance().kind {
10695 TokenType::Noun(s) => s,
10696 _ => unreachable!("guarded by article_then_noun"),
10697 };
10698 let noun_str = self.interner.resolve(noun_sym).to_string();
10699 let singular = Self::singularize_noun(&noun_str);
10700 let name_sym = self.interner.intern(&singular);
10701 let mut result: &'a LogicExpr<'a> =
10702 self.ctx.exprs.alloc(LogicExpr::Predicate {
10703 name: name_sym,
10704 args: self.ctx.terms.alloc_slice([Term::Constant(subject.noun)]),
10705 world: None,
10706 });
10707 if is_negated {
10708 result = self.ctx.exprs.alloc(LogicExpr::UnaryOp {
10709 op: TokenType::Not,
10710 operand: result,
10711 });
10712 }
10713 return self.wrap_with_definiteness_full(&subject, result);
10714 }
10715 }
10716
10717 if matches!(
10724 self.tokens.get(self.current + 1).map(|t| &t.kind),
10725 Some(TokenType::Comparative(_))
10726 ) && lexicon::is_degree_adverb(
10727 &self.interner.resolve(self.peek().lexeme).to_lowercase(),
10728 ) {
10729 self.advance(); }
10731
10732 if self.check_number() {
10735 let measure = self.parse_measure_phrase()?;
10736
10737 if self.check_comparative() {
10739 return self.parse_comparative(&subject, copula_time, Some(measure));
10740 }
10741
10742 if self.check_content_word() {
10744 let adj = self.consume_content_word()?;
10745 let result = self.ctx.exprs.alloc(LogicExpr::Predicate {
10746 name: adj,
10747 args: self.ctx.terms.alloc_slice([
10748 Term::Constant(subject.noun),
10749 *measure,
10750 ]),
10751 world: None,
10752 });
10753 return self.wrap_with_definiteness_full(&subject, result);
10754 }
10755
10756 if self.check(&TokenType::Period) || self.is_at_end() {
10759 if self.mode == ParserMode::Imperative {
10761 let variable = self.interner.resolve(subject.noun).to_string();
10762 let value = if let Term::Value { kind, .. } = measure {
10763 format!("{:?}", kind)
10764 } else {
10765 "value".to_string()
10766 };
10767 return Err(ParseError {
10768 kind: ParseErrorKind::IsValueEquality { variable, value },
10769 span: self.current_span(),
10770 });
10771 }
10772 let result = self.ctx.exprs.alloc(LogicExpr::Identity {
10773 left: self.ctx.terms.alloc(Term::Constant(subject.noun)),
10774 right: measure,
10775 });
10776 return self.wrap_with_definiteness_full(&subject, result);
10777 }
10778 }
10779
10780 if self.interner.resolve(self.peek().lexeme).eq_ignore_ascii_case("as") {
10782 return self.parse_equative(&subject);
10783 }
10784
10785 if self.check_comparative() {
10787 return self.parse_comparative(&subject, copula_time, None);
10788 }
10789
10790 if self.check(&TokenType::Period) || self.is_at_end() {
10792 let var = self.next_var_name();
10793 let body = self.ctx.exprs.alloc(LogicExpr::Identity {
10794 left: self.ctx.terms.alloc(Term::Variable(var)),
10795 right: self.ctx.terms.alloc(Term::Constant(subject.noun)),
10796 });
10797 return Ok(self.ctx.exprs.alloc(LogicExpr::Quantifier {
10798 kind: QuantifierKind::Existential,
10799 variable: var,
10800 body,
10801 island_id: self.current_island,
10802 }));
10803 }
10804
10805 if self.check(&TokenType::Article(Definiteness::Definite)) {
10807 let saved_pos = self.current;
10808 self.advance();
10809 if self.check_superlative() {
10810 return self.parse_superlative(&subject);
10811 }
10812 self.current = saved_pos;
10813 }
10814
10815 if self.check_article() {
10817 let saved_ctx = self.nominal_np_context;
10821 self.nominal_np_context = true;
10822 let predicate_np_result = self.parse_noun_phrase(true);
10823 self.nominal_np_context = saved_ctx;
10824 let predicate_np = predicate_np_result?;
10825 let predicate_noun = predicate_np.noun;
10826
10827 if self.check(&TokenType::Who) || self.check(&TokenType::That) {
10838 let rel_cp = self.checkpoint();
10839 if let Ok(first) = self.parse_list_member_np(&predicate_np, false) {
10840 if self.check(&TokenType::Comma) {
10841 return self.finish_enumerated_identity(&subject, is_negated, first);
10842 }
10843 }
10844 self.restore(rel_cp);
10845 }
10846 if self.check(&TokenType::Comma) {
10847 let first = self.parse_list_member_np(&predicate_np, false)?;
10848 return self.finish_enumerated_identity(&subject, is_negated, first);
10849 }
10850
10851 if self.event_reading_mode {
10854 let noun_str = self.interner.resolve(predicate_noun);
10855 if let Some(base_verb) = lexicon::lookup_agentive_noun(noun_str) {
10856 let event_adj = predicate_np.adjectives.iter().find(|adj| {
10858 lexicon::is_event_modifier_adjective(self.interner.resolve(**adj))
10859 });
10860
10861 if let Some(&adj_sym) = event_adj {
10862 let verb_sym = self.interner.intern(base_verb);
10864 let event_var = self.get_event_var();
10865
10866 let verb_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
10867 name: verb_sym,
10868 args: self.ctx.terms.alloc_slice([Term::Variable(event_var)]),
10869 world: None,
10870 });
10871
10872 let agent_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
10873 name: self.interner.intern("Agent"),
10874 args: self.ctx.terms.alloc_slice([
10875 Term::Variable(event_var),
10876 Term::Constant(subject.noun),
10877 ]),
10878 world: None,
10879 });
10880
10881 let adj_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
10882 name: adj_sym,
10883 args: self.ctx.terms.alloc_slice([Term::Variable(event_var)]),
10884 world: None,
10885 });
10886
10887 let verb_agent = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
10889 left: verb_pred,
10890 op: TokenType::And,
10891 right: agent_pred,
10892 });
10893
10894 let body = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
10896 left: verb_agent,
10897 op: TokenType::And,
10898 right: adj_pred,
10899 });
10900
10901 let event_reading = self.ctx.exprs.alloc(LogicExpr::Quantifier {
10903 kind: QuantifierKind::Existential,
10904 variable: event_var,
10905 body,
10906 island_id: self.current_island,
10907 });
10908
10909 return self.wrap_with_definiteness_full(&subject, event_reading);
10910 }
10911 }
10912 }
10913
10914 let subject_sort = lexicon::lookup_sort(self.interner.resolve(subject.noun));
10915 let predicate_sort = lexicon::lookup_sort(self.interner.resolve(predicate_noun));
10916
10917 if let (Some(s_sort), Some(p_sort)) = (subject_sort, predicate_sort) {
10918 if !s_sort.is_compatible_with(p_sort) && !p_sort.is_compatible_with(s_sort) {
10919 let metaphor: &'a LogicExpr<'a> = self.ctx.exprs.alloc(LogicExpr::Metaphor {
10920 tenor: self.ctx.terms.alloc(Term::Constant(subject.noun)),
10921 vehicle: self.ctx.terms.alloc(Term::Constant(predicate_noun)),
10922 });
10923 let metaphor = if is_negated {
10924 &*self.ctx.exprs.alloc(LogicExpr::UnaryOp {
10925 op: TokenType::Not,
10926 operand: metaphor,
10927 })
10928 } else {
10929 metaphor
10930 };
10931 return self.wrap_with_definiteness_full(&subject, metaphor);
10932 }
10933 }
10934
10935 let mut predicates: Vec<&'a LogicExpr<'a>> = Vec::new();
10938
10939 for &adj_sym in predicate_np.adjectives {
10941 let adj_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
10942 name: adj_sym,
10943 args: self.ctx.terms.alloc_slice([Term::Constant(subject.noun)]),
10944 world: None,
10945 });
10946 predicates.push(adj_pred);
10947 }
10948
10949 let noun_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
10951 name: predicate_noun,
10952 args: self.ctx.terms.alloc_slice([Term::Constant(subject.noun)]),
10953 world: None,
10954 });
10955 predicates.push(noun_pred);
10956
10957 if let Some(possessor) = predicate_np.possessor {
10964 let poss_pred =
10965 self.possessor_predication(possessor, Term::Constant(subject.noun));
10966 predicates.push(poss_pred);
10967 }
10968
10969 for pp in predicate_np.pps {
10977 let pp_sub = self.substitute_pp_self_term(pp, Term::Constant(subject.noun));
10978 predicates.push(pp_sub);
10979 }
10980
10981 let mut result = if predicates.len() == 1 {
10983 predicates[0]
10984 } else {
10985 let mut combined = predicates[0];
10986 for pred in &predicates[1..] {
10987 combined = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
10988 left: combined,
10989 op: TokenType::And,
10990 right: *pred,
10991 });
10992 }
10993 combined
10994 };
10995
10996 let mut result = result;
11003 if let Some(rc) = self.try_attach_relative(Term::Constant(subject.noun))? {
11004 result = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
11005 left: result,
11006 op: TokenType::And,
11007 right: rc,
11008 });
11009 }
11010
11011 loop {
11017 if !self.check(&TokenType::And) {
11018 break;
11019 }
11020 let save = self.current;
11021 self.advance(); let next_is_boundary = matches!(
11027 self.tokens.get(self.current + 1).map(|t| &t.kind),
11028 Some(TokenType::Period) | Some(TokenType::Comma) | Some(TokenType::And)
11029 | Some(TokenType::EOF) | Some(TokenType::Exclamation) | None
11030 );
11031 let conjunct: Option<&'a LogicExpr<'a>> = match self.peek().kind {
11032 TokenType::Adjective(a) | TokenType::NonIntersectiveAdjective(a) => {
11033 self.advance();
11034 Some(self.ctx.exprs.alloc(LogicExpr::Predicate {
11035 name: a,
11036 args: self.ctx.terms.alloc_slice([Term::Constant(subject.noun)]),
11037 world: None,
11038 }))
11039 }
11040 TokenType::Noun(a) if next_is_boundary => {
11041 self.advance();
11042 Some(self.ctx.exprs.alloc(LogicExpr::Predicate {
11043 name: a,
11044 args: self.ctx.terms.alloc_slice([Term::Constant(subject.noun)]),
11045 world: None,
11046 }))
11047 }
11048 _ if self.check_article() => match self.parse_noun_phrase(true) {
11049 Ok(np) => {
11050 Some(self.nominal_predication(Term::Constant(subject.noun), &np))
11051 }
11052 Err(_) => None,
11053 },
11054 _ => None,
11055 };
11056 match conjunct {
11057 Some(c) => {
11058 result = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
11059 left: result,
11060 op: TokenType::And,
11061 right: c,
11062 });
11063 }
11064 None => {
11065 self.current = save;
11066 break;
11067 }
11068 }
11069 }
11070
11071 let result = if is_negated {
11073 &*self.ctx.exprs.alloc(LogicExpr::UnaryOp {
11074 op: TokenType::Not,
11075 operand: result,
11076 })
11077 } else {
11078 result
11079 };
11080
11081 return self.wrap_with_definiteness_full(&subject, result);
11087 }
11088
11089 let prefer_adjective = if let TokenType::Ambiguous { primary, alternatives } = &self.peek().kind {
11092 let is_simple_verb = if let TokenType::Verb { aspect, .. } = **primary {
11093 aspect == Aspect::Simple
11094 } else {
11095 false
11096 };
11097 let has_adj_alt = alternatives.iter().any(|t| matches!(t, TokenType::Adjective(_)));
11098 is_simple_verb && has_adj_alt
11099 } else {
11100 false
11101 };
11102
11103 if !prefer_adjective && self.check_verb() {
11104 let (verb, _verb_time, verb_aspect, verb_class) = self.consume_verb_with_metadata();
11105
11106 if verb_class.is_stative() && verb_aspect == Aspect::Progressive {
11108 return Err(ParseError {
11109 kind: ParseErrorKind::StativeProgressiveConflict,
11110 span: self.current_span(),
11111 });
11112 }
11113
11114 let mut goal_args: Vec<Term<'a>> = Vec::new();
11117 while self.check_to_preposition() {
11118 self.advance(); let goal = self.parse_noun_phrase(true)?;
11120 goal_args.push(self.noun_phrase_to_term(&goal));
11121 }
11122
11123 if self.check_by_preposition() {
11125 self.advance(); let agent = self.parse_noun_phrase(true)?;
11127
11128 let (agent_term, agent_restr) = self.possessor_entity(&agent);
11133 let mut args = vec![agent_term, self.noun_phrase_to_term(&subject)];
11134 args.extend(goal_args);
11135
11136 let predicate = self.ctx.exprs.alloc(LogicExpr::Predicate {
11137 name: verb,
11138 args: self.ctx.terms.alloc_slice(args),
11139 world: None,
11140 });
11141 let predicate = self.wrap_in_possessor_entity(agent_restr, predicate);
11142
11143 let with_time = if copula_time == Time::Past {
11144 self.ctx.exprs.alloc(LogicExpr::Temporal {
11145 operator: TemporalOperator::Past,
11146 body: predicate,
11147 })
11148 } else {
11149 predicate
11150 };
11151
11152 return self.wrap_with_definiteness_full(&subject, with_time);
11153 }
11154
11155 let subject_is_common_noun = {
11166 let n = self.interner.resolve(subject.noun);
11167 lexicon::lookup_noun_db(n).is_some()
11168 || (n.ends_with('s')
11169 && lexicon::lookup_noun_db(&n[..n.len() - 1]).is_some())
11170 };
11171 if copula_time == Time::Past && verb_aspect == Aspect::Simple
11172 && subject.definiteness != Some(Definiteness::Definite)
11173 && subject_is_common_noun {
11174 let var_name = self.next_var_name();
11176 let predicate = self.ctx.exprs.alloc(LogicExpr::Predicate {
11177 name: verb,
11178 args: self.ctx.terms.alloc_slice([
11179 Term::Variable(var_name),
11180 Term::Constant(subject.noun),
11181 ]),
11182 world: None,
11183 });
11184
11185 let type_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
11186 name: subject.noun,
11187 args: self.ctx.terms.alloc_slice([Term::Variable(var_name)]),
11188 world: None,
11189 });
11190
11191 let temporal = self.ctx.exprs.alloc(LogicExpr::Temporal {
11192 operator: TemporalOperator::Past,
11193 body: predicate,
11194 });
11195
11196 let body = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
11197 left: type_pred,
11198 op: TokenType::And,
11199 right: temporal,
11200 });
11201
11202 let result = self.ctx.exprs.alloc(LogicExpr::Quantifier {
11203 kind: QuantifierKind::Existential,
11204 variable: var_name,
11205 body,
11206 island_id: self.current_island,
11207 });
11208
11209 if is_negated {
11211 return Ok(self.ctx.exprs.alloc(LogicExpr::UnaryOp {
11212 op: TokenType::Not,
11213 operand: result,
11214 }));
11215 }
11216 return Ok(result);
11217 }
11218
11219 let verb_str = self.interner.resolve(verb).to_lowercase();
11222 let subject_term = if lexicon::is_intensional_predicate(&verb_str) {
11223 Term::Intension(subject.noun)
11224 } else {
11225 Term::Constant(subject.noun)
11226 };
11227
11228 let mut predicate: &'a LogicExpr<'a> = self.ctx.exprs.alloc(LogicExpr::Predicate {
11229 name: verb,
11230 args: self.ctx.terms.alloc_slice([subject_term]),
11231 world: None,
11232 });
11233
11234 if verb_aspect == Aspect::Progressive
11240 && !self.check_preposition()
11241 && (self.check_article() || self.check_number() || self.check_content_word())
11242 {
11243 let obj_term = if self.check_number() {
11244 *self.parse_measure_phrase()?
11245 } else {
11246 let obj_np = self.parse_noun_phrase(false)?;
11247 self.noun_phrase_to_term(&obj_np)
11248 };
11249 predicate = self.ctx.exprs.alloc(LogicExpr::Predicate {
11250 name: verb,
11251 args: self.ctx.terms.alloc_slice([subject_term, obj_term]),
11252 world: None,
11253 });
11254 }
11255
11256 while self.check_preposition() {
11261 let prep = match self.advance().kind {
11262 TokenType::Preposition(s) => s,
11263 _ => break,
11264 };
11265 let pp = if self.check_number() {
11266 let m = self.parse_measure_phrase()?;
11267 self.ctx.exprs.alloc(LogicExpr::Predicate {
11268 name: prep,
11269 args: self.ctx.terms.alloc_slice([subject_term, *m]),
11270 world: None,
11271 })
11272 } else if self.check_content_word()
11273 || matches!(self.peek().kind, TokenType::Article(_))
11274 {
11275 let obj = self.parse_noun_phrase(true)?;
11276 self.ctx.exprs.alloc(LogicExpr::Predicate {
11277 name: prep,
11278 args: self.ctx.terms.alloc_slice([subject_term, Term::Constant(obj.noun)]),
11279 world: None,
11280 })
11281 } else {
11282 break;
11283 };
11284 predicate = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
11285 left: predicate,
11286 op: TokenType::And,
11287 right: pp,
11288 });
11289 }
11290
11291 if let Some(constraint) = self.parse_temporal_offset_constraint(subject_term)? {
11296 predicate = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
11297 left: predicate,
11298 op: TokenType::And,
11299 right: constraint,
11300 });
11301 }
11302 else if let Some(constraint) = self.parse_bare_temporal_constraint(subject_term)? {
11306 predicate = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
11307 left: predicate,
11308 op: TokenType::And,
11309 right: constraint,
11310 });
11311 }
11312
11313 let adverbs = self.collect_adverbs();
11316 let predicate = if adverbs.is_empty() {
11317 predicate
11318 } else {
11319 self.ctx.exprs.alloc(LogicExpr::Event {
11320 predicate,
11321 adverbs: self.ctx.syms.alloc_slice(adverbs),
11322 })
11323 };
11324
11325 let with_aspect = if verb_aspect == Aspect::Progressive {
11326 let operator = if verb_class == VerbClass::Semelfactive {
11328 AspectOperator::Iterative
11329 } else {
11330 AspectOperator::Progressive
11331 };
11332 self.ctx.exprs.alloc(LogicExpr::Aspectual {
11333 operator,
11334 body: predicate,
11335 })
11336 } else {
11337 predicate
11338 };
11339
11340 let with_time = if copula_time == Time::Past {
11341 self.ctx.exprs.alloc(LogicExpr::Temporal {
11342 operator: TemporalOperator::Past,
11343 body: with_aspect,
11344 })
11345 } else {
11346 with_aspect
11347 };
11348
11349 let final_expr = if is_negated {
11350 self.ctx.exprs.alloc(LogicExpr::UnaryOp {
11351 op: TokenType::Not,
11352 operand: with_time,
11353 })
11354 } else {
11355 with_time
11356 };
11357
11358 if subject.definiteness == Some(Definiteness::Definite)
11365 && subject.adjectives.is_empty()
11366 && subject.pps.is_empty()
11367 && subject.possessor.is_none()
11368 {
11369 return Ok(final_expr);
11370 }
11371
11372 return self.wrap_with_definiteness_full(&subject, final_expr);
11373 }
11374
11375 if let Some((var_name, rel_clause)) = relative_clause {
11380 let var_term = Term::Variable(var_name);
11381
11382 let main_pred: &'a LogicExpr<'a> = if self.check(&TokenType::Either) {
11383 self.advance();
11384 let np1 = self.parse_noun_phrase(true)?;
11385 let p1 = self.nominal_predication_with_pps(var_term, &np1);
11386 let p1 = self.conjoin_trailing_relative(p1, var_term)?;
11387 if self.check(&TokenType::Or) {
11388 self.advance();
11389 let np2 = self.parse_noun_phrase(true)?;
11390 let p2 = self.nominal_predication_with_pps(var_term, &np2);
11391 let p2 = self.conjoin_trailing_relative(p2, var_term)?;
11392 self.ctx.exprs.alloc(LogicExpr::BinaryOp {
11393 left: p1,
11394 op: TokenType::Or,
11395 right: p2,
11396 })
11397 } else {
11398 p1
11399 }
11400 } else if matches!(self.peek().kind, TokenType::ProperName(_))
11401 && matches!(
11402 self.tokens.get(self.current + 1).map(|t| &t.kind),
11403 Some(TokenType::Possessive)
11404 )
11405 {
11406 let np = self.parse_noun_phrase(true)?;
11408 self.nominal_predication_with_pps(var_term, &np)
11409 } else if let TokenType::ProperName(pname) = self.peek().kind {
11410 self.advance();
11411 self.ctx.exprs.alloc(LogicExpr::Identity {
11412 left: self.ctx.terms.alloc(var_term),
11413 right: self.ctx.terms.alloc(Term::Constant(pname)),
11414 })
11415 } else if self.check_article() {
11416 let np = self.parse_noun_phrase(true)?;
11417 let pred = self.nominal_predication_with_pps(var_term, &np);
11418 self.conjoin_trailing_relative(pred, var_term)?
11419 } else if self.check_preposition() && !self.check_by_preposition() {
11420 let prep_sym = match self.advance().kind {
11424 TokenType::Preposition(s) => s,
11425 _ => unreachable!("guarded by check_preposition()"),
11426 };
11427 if self.check_number() {
11428 let measure = self.parse_measure_phrase()?;
11429 self.ctx.exprs.alloc(LogicExpr::Predicate {
11430 name: prep_sym,
11431 args: self.ctx.terms.alloc_slice([var_term, *measure]),
11432 world: None,
11433 })
11434 } else {
11435 let obj = self.parse_noun_phrase(true)?;
11436 self.ctx.exprs.alloc(LogicExpr::Predicate {
11437 name: prep_sym,
11438 args: self.ctx.terms.alloc_slice([var_term, Term::Constant(obj.noun)]),
11439 world: None,
11440 })
11441 }
11442 } else {
11443 let pred_word = self.consume_content_word()?;
11444 self.ctx.exprs.alloc(LogicExpr::Predicate {
11445 name: pred_word,
11446 args: self.ctx.terms.alloc_slice([var_term]),
11447 world: None,
11448 })
11449 };
11450 let main_pred = if is_negated {
11451 &*self.ctx.exprs.alloc(LogicExpr::UnaryOp {
11452 op: TokenType::Not,
11453 operand: main_pred,
11454 })
11455 } else {
11456 main_pred
11457 };
11458
11459 let type_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
11460 name: subject.noun,
11461 args: self.ctx.terms.alloc_slice([Term::Variable(var_name)]),
11462 world: None,
11463 });
11464
11465 let inner = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
11466 left: type_pred,
11467 op: TokenType::And,
11468 right: rel_clause,
11469 });
11470
11471 let body = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
11472 left: inner,
11473 op: TokenType::And,
11474 right: main_pred,
11475 });
11476
11477 return Ok(self.ctx.exprs.alloc(LogicExpr::Quantifier {
11478 kind: QuantifierKind::Existential,
11479 variable: var_name,
11480 body,
11481 island_id: self.current_island,
11482 }));
11483 }
11484
11485 if let TokenType::ProperName(predicate_name) = self.peek().kind {
11493 let next_is_possessive = matches!(
11494 self.tokens.get(self.current + 1).map(|t| &t.kind),
11495 Some(TokenType::Possessive)
11496 );
11497 let elided = matches!(
11498 self.tokens.get(self.current + 2).map(|t| &t.kind),
11499 Some(TokenType::Period)
11500 | Some(TokenType::EOF)
11501 | Some(TokenType::Comma)
11502 | Some(TokenType::And)
11503 | Some(TokenType::Or)
11504 | None
11505 );
11506 if next_is_possessive && elided {
11507 self.advance(); self.advance(); let poss = self.ctx.exprs.alloc(LogicExpr::Predicate {
11510 name: self.interner.intern("Possesses"),
11511 args: self.ctx.terms.alloc_slice([
11512 Term::Constant(predicate_name),
11513 Term::Constant(subject.noun),
11514 ]),
11515 world: None,
11516 });
11517 let result = if is_negated {
11518 self.ctx.exprs.alloc(LogicExpr::UnaryOp {
11519 op: TokenType::Not,
11520 operand: poss,
11521 })
11522 } else {
11523 poss
11524 };
11525 return self.wrap_with_definiteness_full(&subject, result);
11526 }
11527 }
11528
11529 if matches!(self.peek().kind, TokenType::ProperName(_))
11533 && matches!(
11534 self.tokens.get(self.current + 1).map(|t| &t.kind),
11535 Some(TokenType::Possessive)
11536 )
11537 {
11538 let np = self.parse_noun_phrase(true)?;
11539 let pred = self.nominal_predication_with_pps(Term::Constant(subject.noun), &np);
11540 let result = if is_negated {
11541 self.ctx.exprs.alloc(LogicExpr::UnaryOp {
11542 op: TokenType::Not,
11543 operand: pred,
11544 })
11545 } else {
11546 pred
11547 };
11548 return self.wrap_with_definiteness_full(&subject, result);
11549 }
11550
11551 if let TokenType::ProperName(predicate_name) = self.peek().kind {
11554 self.advance(); let predicate_name = self.absorb_multiword_proper_name(predicate_name);
11559
11560 if self.check(&TokenType::Comma) {
11567 let mut members: Vec<Term<'a>> = vec![Term::Constant(predicate_name)];
11568 let mut member_rels: Vec<&'a LogicExpr<'a>> = Vec::new();
11569 while self.check(&TokenType::Comma) || self.check(&TokenType::And) {
11570 while self.check(&TokenType::Comma) || self.check(&TokenType::And) {
11571 self.advance();
11572 }
11573 if let TokenType::ProperName(pn) = self.peek().kind {
11574 self.advance();
11575 let pn = self.absorb_multiword_proper_name(pn);
11576 members.push(Term::Constant(pn));
11577 } else if self.check_article() || self.check_content_word() {
11578 let item = self.parse_noun_phrase(true)?;
11579 members.push(Term::Constant(item.noun));
11580 if let Some(rc) = self.try_attach_relative(Term::Constant(item.noun))? {
11581 member_rels.push(rc);
11582 }
11583 } else {
11584 break;
11585 }
11586 }
11587 let group = Term::Group(self.ctx.terms.alloc_slice(members));
11588 let identity: &'a LogicExpr<'a> = self.ctx.exprs.alloc(LogicExpr::Identity {
11589 left: self.ctx.terms.alloc(Term::Constant(subject.noun)),
11590 right: self.ctx.terms.alloc(group),
11591 });
11592 let mut result = if is_negated {
11593 &*self.ctx.exprs.alloc(LogicExpr::UnaryOp {
11594 op: TokenType::Not,
11595 operand: identity,
11596 })
11597 } else {
11598 identity
11599 };
11600 for rc in member_rels {
11601 result = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
11602 left: result,
11603 op: TokenType::And,
11604 right: rc,
11605 });
11606 }
11607 return self.wrap_with_definiteness_full(&subject, result);
11608 }
11609
11610 let identity = self.ctx.exprs.alloc(LogicExpr::Identity {
11611 left: self.ctx.terms.alloc(Term::Constant(subject.noun)),
11612 right: self.ctx.terms.alloc(Term::Constant(predicate_name)),
11613 });
11614 let result = if is_negated {
11615 self.ctx.exprs.alloc(LogicExpr::UnaryOp {
11616 op: TokenType::Not,
11617 operand: identity,
11618 })
11619 } else {
11620 identity
11621 };
11622 return self.wrap_with_definiteness_full(&subject, result);
11623 }
11624
11625 if self.check(&TokenType::Either) {
11628 self.advance(); let parse_disjunct = |p: &mut Self| -> ParseResult<&'a LogicExpr<'a>> {
11633 let saved_ctx = p.nominal_np_context;
11636 p.nominal_np_context = true;
11637 let np_result = p.parse_noun_phrase(true);
11638 p.nominal_np_context = saved_ctx;
11639 let np = np_result?;
11640 let mut pred: &'a LogicExpr<'a> =
11646 p.nominal_predication_with_pps(Term::Constant(subject.noun), &np);
11647 if let Some(rel) = p.try_attach_relative(Term::Constant(subject.noun))? {
11648 pred = p.ctx.exprs.alloc(LogicExpr::BinaryOp {
11649 left: pred,
11650 op: TokenType::And,
11651 right: rel,
11652 });
11653 }
11654 if let Some(rr) = p.try_consume_reduced_relative(Term::Constant(subject.noun))? {
11658 pred = p.ctx.exprs.alloc(LogicExpr::BinaryOp {
11659 left: pred,
11660 op: TokenType::And,
11661 right: rr,
11662 });
11663 }
11664 Ok(pred)
11665 };
11666 let pred1 = parse_disjunct(self)?;
11667 if self.check(&TokenType::Or) {
11668 self.advance(); let pred2 = parse_disjunct(self)?;
11670 let disj = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
11671 left: pred1,
11672 op: TokenType::Or,
11673 right: pred2,
11674 });
11675 let with_time = if copula_time == Time::Past {
11676 self.ctx.exprs.alloc(LogicExpr::Temporal {
11677 operator: TemporalOperator::Past,
11678 body: disj,
11679 })
11680 } else {
11681 disj
11682 };
11683 let result = if is_negated {
11684 self.ctx.exprs.alloc(LogicExpr::UnaryOp {
11685 op: TokenType::Not,
11686 operand: with_time,
11687 })
11688 } else {
11689 with_time
11690 };
11691 return self.wrap_with_definiteness_full(&subject, result);
11694 }
11695 }
11696
11697 if self.check_preposition() && !self.check_by_preposition() {
11700 let prep_token = self.advance().clone();
11701 let prep_sym = match prep_token.kind {
11702 TokenType::Preposition(s) => s,
11703 _ => unreachable!("guarded by check_preposition()"),
11704 };
11705 let base = if self.check_number() {
11709 let m = self.parse_measure_phrase()?;
11710 self.ctx.exprs.alloc(LogicExpr::Predicate {
11711 name: prep_sym,
11712 args: self.ctx.terms.alloc_slice([Term::Constant(subject.noun), *m]),
11713 world: None,
11714 })
11715 } else {
11716 let saved_ctx = self.nominal_np_context;
11720 self.nominal_np_context = true;
11721 let pp_obj_result = self.parse_noun_phrase(true);
11722 self.nominal_np_context = saved_ctx;
11723 let pp_obj = pp_obj_result?;
11724 let pred: &'a LogicExpr<'a> = self.ctx.exprs.alloc(LogicExpr::Predicate {
11725 name: prep_sym,
11726 args: self.ctx.terms.alloc_slice([
11727 Term::Constant(subject.noun),
11728 Term::Constant(pp_obj.noun),
11729 ]),
11730 world: None,
11731 });
11732 self.attach_pp_object_modifiers(pred, &pp_obj)
11736 };
11737 let mut base: &'a LogicExpr<'a> = base;
11742 while self.check(&TokenType::Or) {
11743 let cp = self.checkpoint();
11744 self.advance(); let disj_prep = if self.check_preposition() && !self.check_by_preposition() {
11746 match self.advance().kind {
11747 TokenType::Preposition(s) => s,
11748 _ => prep_sym,
11749 }
11750 } else {
11751 prep_sym
11752 };
11753 if !(self.check_content_word()
11754 || self.check_number()
11755 || matches!(self.peek().kind, TokenType::Article(_)))
11756 {
11757 self.restore(cp);
11758 break;
11759 }
11760 let saved_ctx = self.nominal_np_context;
11761 self.nominal_np_context = true;
11762 let disj_obj_res = self.parse_noun_phrase(true);
11763 self.nominal_np_context = saved_ctx;
11764 let disj_obj = disj_obj_res?;
11765 let disj_pred: &'a LogicExpr<'a> = self.ctx.exprs.alloc(LogicExpr::Predicate {
11766 name: disj_prep,
11767 args: self
11768 .ctx
11769 .terms
11770 .alloc_slice([Term::Constant(subject.noun), Term::Constant(disj_obj.noun)]),
11771 world: None,
11772 });
11773 let disj_pred = self.attach_pp_object_modifiers(disj_pred, &disj_obj);
11774 base = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
11775 left: base,
11776 op: TokenType::Or,
11777 right: disj_pred,
11778 });
11779 }
11780 let with_time = if copula_time == Time::Past {
11781 self.ctx.exprs.alloc(LogicExpr::Temporal {
11782 operator: TemporalOperator::Past,
11783 body: base,
11784 })
11785 } else {
11786 base
11787 };
11788 let result = if is_negated {
11789 self.ctx.exprs.alloc(LogicExpr::UnaryOp {
11790 op: TokenType::Not,
11791 operand: with_time,
11792 })
11793 } else {
11794 with_time
11795 };
11796 return self.wrap_with_definiteness_full(&subject, result);
11799 }
11800
11801 if let Some(base) =
11805 self.copula_temporal_adverb_complement(Term::Constant(subject.noun))?
11806 {
11807 let with_time = if copula_time == Time::Past {
11808 self.ctx.exprs.alloc(LogicExpr::Temporal {
11809 operator: TemporalOperator::Past,
11810 body: base,
11811 })
11812 } else {
11813 base
11814 };
11815 let result = if is_negated {
11816 self.ctx.exprs.alloc(LogicExpr::UnaryOp {
11817 op: TokenType::Not,
11818 operand: with_time,
11819 })
11820 } else {
11821 with_time
11822 };
11823 return self.wrap_with_definiteness_full(&subject, result);
11824 }
11825
11826 let predicate_name = self.consume_content_word()?;
11829
11830 {
11836 let mut coord_adjs: Vec<Symbol> = vec![predicate_name];
11837 while self.check(&TokenType::And) {
11838 let cp = self.checkpoint();
11839 self.advance(); if let TokenType::Adjective(a) = self.peek().kind {
11841 if matches!(
11846 self.tokens.get(self.current + 1).map(|t| &t.kind),
11847 Some(TokenType::Is) | Some(TokenType::Are)
11848 | Some(TokenType::Was) | Some(TokenType::Were)
11849 | Some(TokenType::Verb { .. })
11850 ) {
11851 self.restore(cp);
11852 break;
11853 }
11854 self.advance();
11855 coord_adjs.push(a);
11856 } else {
11857 self.restore(cp); break;
11859 }
11860 }
11861 if coord_adjs.len() > 1 {
11862 let mut conj: &'a LogicExpr<'a> = self.ctx.exprs.alloc(LogicExpr::Predicate {
11863 name: coord_adjs[0],
11864 args: self.ctx.terms.alloc_slice([Term::Constant(subject.noun)]),
11865 world: None,
11866 });
11867 for &a in &coord_adjs[1..] {
11868 let p = self.ctx.exprs.alloc(LogicExpr::Predicate {
11869 name: a,
11870 args: self.ctx.terms.alloc_slice([Term::Constant(subject.noun)]),
11871 world: None,
11872 });
11873 conj = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
11874 left: conj,
11875 op: TokenType::And,
11876 right: p,
11877 });
11878 }
11879 let conj = if is_negated {
11880 self.ctx.exprs.alloc(LogicExpr::UnaryOp { op: TokenType::Not, operand: conj })
11881 } else {
11882 conj
11883 };
11884 let conj = if copula_time == Time::Past {
11885 self.ctx.exprs.alloc(LogicExpr::Temporal {
11886 operator: TemporalOperator::Past,
11887 body: conj,
11888 })
11889 } else {
11890 conj
11891 };
11892 return self.wrap_with_definiteness_full(&subject, conj);
11893 }
11894 }
11895
11896 if self.check_number() {
11902 let measure = self.parse_measure_phrase()?;
11903 let pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
11904 name: predicate_name,
11905 args: self.ctx.terms.alloc_slice([Term::Constant(subject.noun), *measure]),
11906 world: None,
11907 });
11908 let pred = if is_negated {
11909 self.ctx.exprs.alloc(LogicExpr::UnaryOp { op: TokenType::Not, operand: pred })
11910 } else {
11911 pred
11912 };
11913 let pred = if copula_time == Time::Past {
11914 self.ctx.exprs.alloc(LogicExpr::Temporal {
11915 operator: TemporalOperator::Past,
11916 body: pred,
11917 })
11918 } else {
11919 pred
11920 };
11921 return self.wrap_with_definiteness_full(&subject, pred);
11922 }
11923
11924 let subject_sort = lexicon::lookup_sort(self.interner.resolve(subject.noun));
11926 let predicate_str = self.interner.resolve(predicate_name);
11927
11928 if let Some(s_sort) = subject_sort {
11930 if !crate::ontology::check_sort_compatibility(predicate_str, s_sort) {
11931 let metaphor = self.ctx.exprs.alloc(LogicExpr::Metaphor {
11932 tenor: self.ctx.terms.alloc(Term::Constant(subject.noun)),
11933 vehicle: self.ctx.terms.alloc(Term::Constant(predicate_name)),
11934 });
11935 return self.wrap_with_definiteness_full(&subject, metaphor);
11936 }
11937 }
11938
11939 let predicate_sort = lexicon::lookup_sort(predicate_str);
11941 if let (Some(s_sort), Some(p_sort)) = (subject_sort, predicate_sort) {
11942 if s_sort != p_sort && !s_sort.is_compatible_with(p_sort) && !p_sort.is_compatible_with(s_sort) {
11943 let metaphor = self.ctx.exprs.alloc(LogicExpr::Metaphor {
11944 tenor: self.ctx.terms.alloc(Term::Constant(subject.noun)),
11945 vehicle: self.ctx.terms.alloc(Term::Constant(predicate_name)),
11946 });
11947 return self.wrap_with_definiteness_full(&subject, metaphor);
11948 }
11949 }
11950
11951 let predicate = if self.pragmatic
11955 && crate::lexicon::is_gradable_adjective(
11956 &self.interner.resolve(predicate_name).to_lowercase(),
11957 ) {
11958 let d = self.next_var_name();
11959 let theta = self.interner.intern("θ_C");
11960 let adj_d = self.ctx.exprs.alloc(LogicExpr::Predicate {
11961 name: predicate_name,
11962 args: self
11963 .ctx
11964 .terms
11965 .alloc_slice([Term::Constant(subject.noun), Term::Variable(d)]),
11966 world: None,
11967 });
11968 let exceeds = self.ctx.exprs.alloc(LogicExpr::Predicate {
11969 name: self.interner.intern(">"),
11970 args: self
11971 .ctx
11972 .terms
11973 .alloc_slice([Term::Variable(d), Term::Constant(theta)]),
11974 world: None,
11975 });
11976 let mut body = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
11977 left: adj_d,
11978 op: TokenType::And,
11979 right: exceeds,
11980 });
11981 if crate::lexicon::is_vague_adjective(
11984 &self.interner.resolve(predicate_name).to_lowercase(),
11985 ) {
11986 let borderline = self.ctx.exprs.alloc(LogicExpr::Predicate {
11987 name: self.interner.intern("Borderline"),
11988 args: self.ctx.terms.alloc_slice([Term::Constant(theta)]),
11989 world: None,
11990 });
11991 body = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
11992 left: body,
11993 op: TokenType::And,
11994 right: borderline,
11995 });
11996 }
11997 self.ctx.exprs.alloc(LogicExpr::Quantifier {
11998 kind: QuantifierKind::Existential,
11999 variable: d,
12000 body,
12001 island_id: self.current_island,
12002 })
12003 } else {
12004 self.ctx.exprs.alloc(LogicExpr::Predicate {
12005 name: predicate_name,
12006 args: self.ctx.terms.alloc_slice([Term::Constant(subject.noun)]),
12007 world: None,
12008 })
12009 };
12010
12011 let result = if is_negated {
12013 self.ctx.exprs.alloc(LogicExpr::UnaryOp {
12014 op: TokenType::Not,
12015 operand: predicate,
12016 })
12017 } else {
12018 predicate
12019 };
12020
12021 let result = match copula_temporal {
12023 Some(CopulaTemporal::Always) => {
12024 self.ctx.exprs.alloc(LogicExpr::Temporal {
12025 operator: TemporalOperator::Always,
12026 body: result,
12027 })
12028 }
12029 Some(CopulaTemporal::Never) => {
12030 let negated = self.ctx.exprs.alloc(LogicExpr::UnaryOp {
12031 op: TokenType::Not,
12032 operand: predicate,
12033 });
12034 self.ctx.exprs.alloc(LogicExpr::Temporal {
12035 operator: TemporalOperator::Always,
12036 body: negated,
12037 })
12038 }
12039 Some(CopulaTemporal::Eventually) => {
12040 self.ctx.exprs.alloc(LogicExpr::Temporal {
12041 operator: TemporalOperator::Eventually,
12042 body: result,
12043 })
12044 }
12045 None => result,
12046 };
12047
12048 return self.wrap_with_definiteness_full(&subject, result);
12052 }
12053
12054 if self.check_auxiliary_as_main_verb() {
12060 let subject_term = self.noun_phrase_to_term(&subject);
12061 let result = self.parse_do_as_main_verb(subject_term)?;
12062 return self.wrap_with_definiteness_full(&subject, result);
12063 }
12064
12065 if self.check_auxiliary() && self.is_true_auxiliary_usage() {
12069 let aux_time = if let TokenType::Auxiliary(time) = self.advance().kind {
12070 time
12071 } else {
12072 Time::None
12073 };
12074 self.pending_time = Some(aux_time);
12075
12076 if self.match_token(&[TokenType::Not]) {
12078 self.negative_depth += 1;
12079
12080 if self.check(&TokenType::Ever) {
12082 self.advance();
12083 }
12084
12085 if self.check_presup_trigger()
12089 && !self.is_followed_by_np_object()
12090 && self.is_followed_by_gerund()
12091 {
12092 let presup_kind = self.consume_presup_trigger();
12093 self.negative_depth -= 1; return self.parse_presupposition(&subject, presup_kind, true);
12095 }
12096
12097 if let TokenType::Performative(_) = self.peek().kind {
12101 let lemma = self
12102 .interner
12103 .intern(&self.interner.resolve(self.peek().lexeme).to_lowercase());
12104 self.tokens[self.current].kind = TokenType::Verb {
12105 lemma,
12106 time: Time::None,
12107 aspect: Aspect::Simple,
12108 class: crate::lexicon::VerbClass::Activity,
12109 };
12110 }
12111 if self.check_verb() || self.check(&TokenType::Do) {
12113 let (verb, verb_time, verb_aspect, verb_class) =
12114 if self.check(&TokenType::Do) {
12115 self.advance(); (
12117 self.interner.intern("Do"),
12118 Time::None,
12119 Aspect::Simple,
12120 crate::lexicon::VerbClass::Activity,
12121 )
12122 } else {
12123 self.consume_verb_with_metadata()
12124 };
12125 let subject_term = self.noun_phrase_to_term(&subject);
12126
12127 if self.check_npi_object() {
12129 let npi_token = self.advance().kind.clone();
12130 let obj_var = self.next_var_name();
12131
12132 let restriction_name = match npi_token {
12133 TokenType::Anything => "Thing",
12134 TokenType::Anyone => "Person",
12135 _ => "Thing",
12136 };
12137
12138 let restriction_sym = self.interner.intern(restriction_name);
12139 let obj_restriction = self.ctx.exprs.alloc(LogicExpr::Predicate {
12140 name: restriction_sym,
12141 args: self.ctx.terms.alloc_slice([Term::Variable(obj_var)]),
12142 world: None,
12143 });
12144
12145 let verb_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
12146 name: verb,
12147 args: self.ctx.terms.alloc_slice([subject_term.clone(), Term::Variable(obj_var)]),
12148 world: None,
12149 });
12150
12151 let body = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
12152 left: obj_restriction,
12153 op: TokenType::And,
12154 right: verb_pred,
12155 });
12156
12157 let quantified = self.ctx.exprs.alloc(LogicExpr::Quantifier {
12158 kind: QuantifierKind::Existential,
12159 variable: obj_var,
12160 body,
12161 island_id: self.current_island,
12162 });
12163
12164 let effective_time = self.pending_time.take().unwrap_or(Time::None);
12165 let with_time = match effective_time {
12166 Time::Past => self.ctx.exprs.alloc(LogicExpr::Temporal {
12167 operator: TemporalOperator::Past,
12168 body: quantified,
12169 }),
12170 Time::Future => self.ctx.exprs.alloc(LogicExpr::Temporal {
12171 operator: TemporalOperator::Future,
12172 body: quantified,
12173 }),
12174 _ => quantified,
12175 };
12176
12177 self.negative_depth -= 1;
12178 return Ok(self.ctx.exprs.alloc(LogicExpr::UnaryOp {
12179 op: TokenType::Not,
12180 operand: with_time,
12181 }));
12182 }
12183
12184 if self.check_quantifier() {
12186 let quantifier_token = self.advance().kind.clone();
12187 let object_np = self.parse_noun_phrase(false)?;
12188 let obj_var = self.next_var_name();
12189
12190 let obj_restriction = self.ctx.exprs.alloc(LogicExpr::Predicate {
12191 name: object_np.noun,
12192 args: self.ctx.terms.alloc_slice([Term::Variable(obj_var)]),
12193 world: None,
12194 });
12195
12196 let verb_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
12197 name: verb,
12198 args: self.ctx.terms.alloc_slice([subject_term.clone(), Term::Variable(obj_var)]),
12199 world: None,
12200 });
12201
12202 let (kind, body) = match quantifier_token {
12203 TokenType::Any => {
12204 if self.is_negative_context() {
12205 (
12206 QuantifierKind::Existential,
12207 self.ctx.exprs.alloc(LogicExpr::BinaryOp {
12208 left: obj_restriction,
12209 op: TokenType::And,
12210 right: verb_pred,
12211 }),
12212 )
12213 } else {
12214 (
12215 QuantifierKind::Universal,
12216 self.ctx.exprs.alloc(LogicExpr::BinaryOp {
12217 left: obj_restriction,
12218 op: TokenType::Implies,
12219 right: verb_pred,
12220 }),
12221 )
12222 }
12223 }
12224 TokenType::Some => (
12225 QuantifierKind::Existential,
12226 self.ctx.exprs.alloc(LogicExpr::BinaryOp {
12227 left: obj_restriction,
12228 op: TokenType::And,
12229 right: verb_pred,
12230 }),
12231 ),
12232 TokenType::All => (
12233 QuantifierKind::Universal,
12234 self.ctx.exprs.alloc(LogicExpr::BinaryOp {
12235 left: obj_restriction,
12236 op: TokenType::Implies,
12237 right: verb_pred,
12238 }),
12239 ),
12240 _ => (
12241 QuantifierKind::Existential,
12242 self.ctx.exprs.alloc(LogicExpr::BinaryOp {
12243 left: obj_restriction,
12244 op: TokenType::And,
12245 right: verb_pred,
12246 }),
12247 ),
12248 };
12249
12250 let quantified = self.ctx.exprs.alloc(LogicExpr::Quantifier {
12251 kind,
12252 variable: obj_var,
12253 body,
12254 island_id: self.current_island,
12255 });
12256
12257 let effective_time = self.pending_time.take().unwrap_or(Time::None);
12258 let with_time = match effective_time {
12259 Time::Past => self.ctx.exprs.alloc(LogicExpr::Temporal {
12260 operator: TemporalOperator::Past,
12261 body: quantified,
12262 }),
12263 Time::Future => self.ctx.exprs.alloc(LogicExpr::Temporal {
12264 operator: TemporalOperator::Future,
12265 body: quantified,
12266 }),
12267 _ => quantified,
12268 };
12269
12270 self.negative_depth -= 1;
12271 return Ok(self.ctx.exprs.alloc(LogicExpr::UnaryOp {
12272 op: TokenType::Not,
12273 operand: with_time,
12274 }));
12275 }
12276
12277 if self.check_pronoun() {
12283 let pronoun_token = self.advance();
12284 let pronoun_sym = pronoun_token.lexeme;
12285 let roles = vec![
12286 (ThematicRole::Agent, subject_term.clone()),
12287 (ThematicRole::Theme, Term::Constant(pronoun_sym)),
12288 ];
12289 let effective_time = self.pending_time.take().unwrap_or(Time::None);
12290 let mut modifiers: Vec<Symbol> = vec![];
12291 match effective_time {
12292 Time::Past => modifiers.push(self.interner.intern("Past")),
12293 Time::Future => modifiers.push(self.interner.intern("Future")),
12294 _ => {}
12295 }
12296 let event_var = self.get_event_var();
12297 let suppress_existential = self.drs.in_conditional_antecedent();
12298 let neo_event = self.ctx.exprs.alloc(LogicExpr::NeoEvent(Box::new(
12299 NeoEventData {
12300 event_var,
12301 verb,
12302 roles: self.ctx.roles.alloc_slice(roles),
12303 modifiers: self.ctx.syms.alloc_slice(modifiers),
12304 suppress_existential,
12305 world: None,
12306 },
12307 )));
12308 self.negative_depth -= 1;
12309 return Ok(self.ctx.exprs.alloc(LogicExpr::UnaryOp {
12310 op: TokenType::Not,
12311 operand: neo_event,
12312 }));
12313 }
12314
12315 let vp = self.build_verb_vp(
12322 subject.noun,
12323 subject_term,
12324 false,
12325 verb,
12326 verb_time,
12327 verb_aspect,
12328 verb_class,
12329 )?;
12330
12331 self.negative_depth -= 1;
12332 return Ok(self.ctx.exprs.alloc(LogicExpr::UnaryOp {
12333 op: TokenType::Not,
12334 operand: vp,
12335 }));
12336 }
12337
12338 self.negative_depth -= 1;
12339 }
12340 }
12342
12343 if self.check_presup_trigger() && !self.is_followed_by_np_object() && self.is_followed_by_gerund() {
12349 let presup_kind = self.consume_presup_trigger();
12350 return self.parse_presupposition(&subject, presup_kind, false);
12351 }
12352
12353 let noun_str = self.interner.resolve(subject.noun);
12355 let is_known_plural = {
12358 let lower = noun_str.to_lowercase();
12359 Self::is_plural_noun(noun_str)
12360 && (crate::lexicon::is_common_noun(&lower)
12361 || matches!(
12362 crate::lexicon::analyze_word(&lower),
12363 Some(crate::lexicon::WordAnalysis::Noun(_))
12364 ))
12365 };
12366 let generic_do_not = matches!(self.peek().kind, TokenType::Does | TokenType::Do)
12370 && matches!(
12371 self.tokens.get(self.current + 1).map(|t| &t.kind),
12372 Some(TokenType::Not)
12373 );
12374 let is_bare_plural = subject.definiteness.is_none()
12375 && subject.possessor.is_none()
12376 && is_known_plural
12377 && (self.check_verb() || generic_do_not);
12378
12379 if is_bare_plural && generic_do_not {
12380 self.advance(); self.advance(); let var_name = self.next_var_name();
12386 let (verb, _t, _a, _) = self.consume_verb_with_metadata();
12387 let type_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
12388 name: subject.noun,
12389 args: self.ctx.terms.alloc_slice([Term::Variable(var_name)]),
12390 world: None,
12391 });
12392 let event_var = self.get_event_var();
12393 let verb_pred = self.ctx.exprs.alloc(LogicExpr::NeoEvent(Box::new(NeoEventData {
12394 event_var,
12395 verb,
12396 roles: self
12397 .ctx
12398 .roles
12399 .alloc_slice(vec![(ThematicRole::Agent, Term::Variable(var_name))]),
12400 modifiers: self.ctx.syms.alloc_slice(vec![]),
12401 suppress_existential: false,
12402 world: None,
12403 })));
12404 let negated = self.ctx.exprs.alloc(LogicExpr::UnaryOp {
12405 op: TokenType::Not,
12406 operand: verb_pred,
12407 });
12408 let body = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
12409 left: type_pred,
12410 op: TokenType::Implies,
12411 right: negated,
12412 });
12413 return Ok(self.ctx.exprs.alloc(LogicExpr::Quantifier {
12414 kind: QuantifierKind::Generic,
12415 variable: var_name,
12416 body,
12417 island_id: self.current_island,
12418 }));
12419 }
12420
12421 if is_bare_plural {
12422 let var_name = self.next_var_name();
12423 let (verb, verb_time, verb_aspect, _) = self.consume_verb_with_metadata();
12424
12425 let type_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
12426 name: subject.noun,
12427 args: self.ctx.terms.alloc_slice([Term::Variable(var_name)]),
12428 world: None,
12429 });
12430
12431 let mut roles = vec![(ThematicRole::Agent, Term::Variable(var_name))];
12435 if self.check_content_word() {
12436 let object = self.parse_noun_phrase(false)?;
12437 roles.push((ThematicRole::Theme, self.noun_phrase_to_term(&object)));
12438 }
12439
12440 let manner_adverbs = self.collect_adverbs();
12444
12445 let event_var = self.get_event_var();
12446 let verb_pred = self.ctx.exprs.alloc(LogicExpr::NeoEvent(Box::new(NeoEventData {
12447 event_var,
12448 verb,
12449 roles: self.ctx.roles.alloc_slice(roles),
12450 modifiers: self.ctx.syms.alloc_slice(manner_adverbs),
12451 suppress_existential: false,
12452 world: None,
12453 })));
12454
12455 let effective_time = self.pending_time.take().unwrap_or(verb_time);
12456 let with_time = match effective_time {
12457 Time::Past => self.ctx.exprs.alloc(LogicExpr::Temporal {
12458 operator: TemporalOperator::Past,
12459 body: verb_pred,
12460 }),
12461 Time::Future => self.ctx.exprs.alloc(LogicExpr::Temporal {
12462 operator: TemporalOperator::Future,
12463 body: verb_pred,
12464 }),
12465 _ => verb_pred,
12466 };
12467
12468 let with_aspect = if verb_aspect == Aspect::Progressive {
12469 self.ctx.exprs.alloc(LogicExpr::Aspectual {
12470 operator: AspectOperator::Progressive,
12471 body: with_time,
12472 })
12473 } else {
12474 with_time
12475 };
12476
12477 let body = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
12478 left: type_pred,
12479 op: TokenType::Implies,
12480 right: with_aspect,
12481 });
12482
12483 return Ok(self.ctx.exprs.alloc(LogicExpr::Quantifier {
12484 kind: QuantifierKind::Generic,
12485 variable: var_name,
12486 body,
12487 island_id: self.current_island,
12488 }));
12489 }
12490
12491 if self.check(&TokenType::Does) || self.check(&TokenType::Do) {
12493 self.advance(); let is_negated = self.match_token(&[TokenType::Not]);
12495
12496 if self.check_presup_trigger()
12499 && !self.is_followed_by_np_object()
12500 && self.is_followed_by_gerund()
12501 {
12502 let presup_kind = self.consume_presup_trigger();
12503 return self.parse_presupposition(&subject, presup_kind, is_negated);
12504 }
12505
12506 if self.check_verb() {
12507 let (verb, verb_time, verb_aspect, verb_class) =
12508 self.consume_verb_with_metadata();
12509 let verb_lemma = self.interner.resolve(verb).to_lowercase();
12510
12511 if self.check_wh_word() {
12513 let wh_token = self.advance().kind.clone();
12514 let is_who = matches!(wh_token, TokenType::Who);
12515 let is_what = matches!(wh_token, TokenType::What);
12516
12517 let is_sluicing = self.is_at_end() ||
12518 self.check(&TokenType::Period) ||
12519 self.check(&TokenType::Comma);
12520
12521 if is_sluicing {
12522 if let Some(template) = self.last_event_template.clone() {
12523 let wh_var = self.next_var_name();
12524 let subject_term = self.noun_phrase_to_term(&subject);
12525
12526 let roles: Vec<_> = if is_who {
12527 std::iter::once((ThematicRole::Agent, Term::Variable(wh_var)))
12528 .chain(template.non_agent_roles.iter().cloned())
12529 .collect()
12530 } else if is_what {
12531 vec![
12532 (ThematicRole::Agent, subject_term.clone()),
12533 (ThematicRole::Theme, Term::Variable(wh_var)),
12534 ]
12535 } else {
12536 std::iter::once((ThematicRole::Agent, Term::Variable(wh_var)))
12537 .chain(template.non_agent_roles.iter().cloned())
12538 .collect()
12539 };
12540
12541 let event_var = self.get_event_var();
12542 let suppress_existential = self.drs.in_conditional_antecedent();
12543 if suppress_existential {
12544 let event_class = self.interner.intern("Event");
12545 self.drs.introduce_referent(event_var, event_class, Gender::Neuter, Number::Singular);
12546 }
12547 let reconstructed = self.ctx.exprs.alloc(LogicExpr::NeoEvent(Box::new(NeoEventData {
12548 event_var,
12549 verb: template.verb,
12550 roles: self.ctx.roles.alloc_slice(roles),
12551 modifiers: self.ctx.syms.alloc_slice(template.modifiers.clone()),
12552 suppress_existential,
12553 world: None,
12554 })));
12555
12556 let question = self.ctx.exprs.alloc(LogicExpr::Question {
12557 wh_variable: wh_var,
12558 body: reconstructed,
12559 });
12560
12561 let know_event_var = self.get_event_var();
12562 let suppress_existential2 = self.drs.in_conditional_antecedent();
12563 if suppress_existential2 {
12564 let event_class = self.interner.intern("Event");
12565 self.drs.introduce_referent(know_event_var, event_class, Gender::Neuter, Number::Singular);
12566 }
12567 let know_event = self.ctx.exprs.alloc(LogicExpr::NeoEvent(Box::new(NeoEventData {
12568 event_var: know_event_var,
12569 verb,
12570 roles: self.ctx.roles.alloc_slice(vec![
12571 (ThematicRole::Agent, subject_term),
12572 (ThematicRole::Theme, Term::Proposition(question)),
12573 ]),
12574 modifiers: self.ctx.syms.alloc_slice(vec![]),
12575 suppress_existential: suppress_existential2,
12576 world: None,
12577 })));
12578
12579 let result = if is_negated {
12580 self.ctx.exprs.alloc(LogicExpr::UnaryOp {
12581 op: TokenType::Not,
12582 operand: know_event,
12583 })
12584 } else {
12585 know_event
12586 };
12587
12588 return self.wrap_with_definiteness_full(&subject, result);
12589 }
12590 }
12591 }
12592
12593 if verb_lemma == "exist" && is_negated {
12595 let var_name = self.next_var_name();
12597 let restriction = self.ctx.exprs.alloc(LogicExpr::Predicate {
12598 name: subject.noun,
12599 args: self.ctx.terms.alloc_slice([Term::Variable(var_name)]),
12600 world: None,
12601 });
12602 let exists = self.ctx.exprs.alloc(LogicExpr::Quantifier {
12603 kind: QuantifierKind::Existential,
12604 variable: var_name,
12605 body: restriction,
12606 island_id: self.current_island,
12607 });
12608 return Ok(self.ctx.exprs.alloc(LogicExpr::UnaryOp {
12609 op: TokenType::Not,
12610 operand: exists,
12611 }));
12612 }
12613
12614 let subject_term = self.noun_phrase_to_term(&subject);
12617 let modifiers: Vec<Symbol> = vec![];
12618
12619 if self.check(&TokenType::Reflexive) {
12621 self.advance();
12622 let roles = vec![
12623 (ThematicRole::Agent, subject_term.clone()),
12624 (ThematicRole::Theme, subject_term),
12625 ];
12626 let event_var = self.get_event_var();
12627 let suppress_existential = self.drs.in_conditional_antecedent();
12628 if suppress_existential {
12629 let event_class = self.interner.intern("Event");
12630 self.drs.introduce_referent(event_var, event_class, Gender::Neuter, Number::Singular);
12631 }
12632 let neo_event = self.ctx.exprs.alloc(LogicExpr::NeoEvent(Box::new(NeoEventData {
12633 event_var,
12634 verb,
12635 roles: self.ctx.roles.alloc_slice(roles),
12636 modifiers: self.ctx.syms.alloc_slice(modifiers),
12637 suppress_existential,
12638 world: None,
12639 })));
12640
12641 let result = if is_negated {
12642 self.ctx.exprs.alloc(LogicExpr::UnaryOp {
12643 op: TokenType::Not,
12644 operand: neo_event,
12645 })
12646 } else {
12647 neo_event
12648 };
12649 return self.wrap_with_definiteness_full(&subject, result);
12650 }
12651
12652 if self.check_npi_quantifier() || self.check_quantifier() || self.check_article() {
12654 let (obj_quantifier, was_definite_article) = if self.check_npi_quantifier() {
12655 let tok = self.advance().kind.clone();
12657 (Some(tok), false)
12658 } else if self.check_quantifier() {
12659 (Some(self.advance().kind.clone()), false)
12660 } else {
12661 let art = self.advance().kind.clone();
12662 if let TokenType::Article(def) = art {
12663 if def == Definiteness::Indefinite {
12664 (Some(TokenType::Some), false)
12665 } else {
12666 (None, true)
12667 }
12668 } else {
12669 (None, false)
12670 }
12671 };
12672
12673 let object_np = self.parse_noun_phrase(false)?;
12674 let obj_var = self.next_var_name();
12675
12676 let mut type_pred: &'a LogicExpr<'a> = self.ctx.exprs.alloc(LogicExpr::Predicate {
12677 name: object_np.noun,
12678 args: self.ctx.terms.alloc_slice([Term::Variable(obj_var)]),
12679 world: None,
12680 });
12681 for &adj in object_np.adjectives {
12685 let adj_pred = self.adjective_restriction(adj, obj_var, object_np.noun);
12686 type_pred = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
12687 left: type_pred,
12688 op: TokenType::And,
12689 right: adj_pred,
12690 });
12691 }
12692 for pp in object_np.pps {
12693 let pp_sub = self.substitute_pp_placeholder(pp, obj_var);
12694 type_pred = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
12695 left: type_pred,
12696 op: TokenType::And,
12697 right: pp_sub,
12698 });
12699 }
12700
12701 let obj_restriction = if self.check(&TokenType::That) || self.check(&TokenType::Who) {
12703 self.advance();
12704 let rel_clause = self.parse_relative_clause(obj_var)?;
12705 self.ctx.exprs.alloc(LogicExpr::BinaryOp {
12706 left: type_pred,
12707 op: TokenType::And,
12708 right: rel_clause,
12709 })
12710 } else {
12711 type_pred
12712 };
12713
12714 let event_var = self.get_event_var();
12715 let suppress_existential = self.drs.in_conditional_antecedent();
12716 if suppress_existential {
12717 let event_class = self.interner.intern("Event");
12718 self.drs.introduce_referent(event_var, event_class, Gender::Neuter, Number::Singular);
12719 }
12720
12721 let roles = vec![
12722 (ThematicRole::Agent, subject_term),
12723 (ThematicRole::Theme, Term::Variable(obj_var)),
12724 ];
12725
12726 let neo_event = self.ctx.exprs.alloc(LogicExpr::NeoEvent(Box::new(NeoEventData {
12727 event_var,
12728 verb,
12729 roles: self.ctx.roles.alloc_slice(roles),
12730 modifiers: self.ctx.syms.alloc_slice(modifiers),
12731 suppress_existential,
12732 world: None,
12733 })));
12734
12735 let quantifier_kind = match &obj_quantifier {
12739 Some(TokenType::Any) if is_negated => QuantifierKind::Existential,
12740 Some(TokenType::All) => QuantifierKind::Universal,
12741 Some(TokenType::No) => QuantifierKind::Universal,
12742 _ => QuantifierKind::Existential,
12743 };
12744
12745 let obj_body = match &obj_quantifier {
12746 Some(TokenType::All) => self.ctx.exprs.alloc(LogicExpr::BinaryOp {
12747 left: obj_restriction,
12748 op: TokenType::Implies,
12749 right: neo_event,
12750 }),
12751 Some(TokenType::No) => {
12752 let neg = self.ctx.exprs.alloc(LogicExpr::UnaryOp {
12753 op: TokenType::Not,
12754 operand: neo_event,
12755 });
12756 self.ctx.exprs.alloc(LogicExpr::BinaryOp {
12757 left: obj_restriction,
12758 op: TokenType::Implies,
12759 right: neg,
12760 })
12761 }
12762 _ => self.ctx.exprs.alloc(LogicExpr::BinaryOp {
12763 left: obj_restriction,
12764 op: TokenType::And,
12765 right: neo_event,
12766 }),
12767 };
12768
12769 let obj_quantified = self.ctx.exprs.alloc(LogicExpr::Quantifier {
12770 kind: quantifier_kind,
12771 variable: obj_var,
12772 body: obj_body,
12773 island_id: self.current_island,
12774 });
12775
12776 let result = if is_negated && matches!(obj_quantifier, Some(TokenType::Any)) {
12778 self.ctx.exprs.alloc(LogicExpr::UnaryOp {
12779 op: TokenType::Not,
12780 operand: obj_quantified,
12781 })
12782 } else if is_negated {
12783 self.ctx.exprs.alloc(LogicExpr::UnaryOp {
12785 op: TokenType::Not,
12786 operand: obj_quantified,
12787 })
12788 } else {
12789 obj_quantified
12790 };
12791
12792 return self.wrap_with_definiteness_full(&subject, result);
12793 }
12794
12795 if is_negated {
12802 self.negative_depth += 1;
12803 }
12804 let vp = self.build_verb_vp(
12805 subject.noun,
12806 subject_term,
12807 false,
12808 verb,
12809 verb_time,
12810 verb_aspect,
12811 verb_class,
12812 )?;
12813 if is_negated {
12814 self.negative_depth -= 1;
12815 }
12816 let result = if is_negated {
12820 self.ctx.exprs.alloc(LogicExpr::UnaryOp {
12821 op: TokenType::Not,
12822 operand: vp,
12823 })
12824 } else {
12825 vp
12826 };
12827 return Ok(result);
12828 }
12829 }
12830
12831 let is_perfect_aux = if self.check_verb() {
12837 let word = self.interner.resolve(self.peek().lexeme).to_lowercase();
12838 word == "has" || word == "have" || word == "had"
12839 } else {
12840 false
12841 };
12842 if subject.definiteness == Some(Definiteness::Definite) && self.check_verb() && self.pending_time.is_none() && !is_perfect_aux {
12843 let saved_pos = self.current;
12844
12845 if let Some(garden_path_result) = self.try_parse(|p| {
12847 let (modifier_verb, _modifier_time, _, _) = p.consume_verb_with_metadata();
12848
12849 let mut pp_mods: Vec<&'a LogicExpr<'a>> = Vec::new();
12851 while p.check_preposition() {
12852 let prep = if let TokenType::Preposition(prep) = p.advance().kind {
12853 prep
12854 } else {
12855 break;
12856 };
12857 if p.check_article() || p.check_content_word() {
12858 let pp_obj = p.parse_noun_phrase(false)?;
12859 let pp_pred = p.ctx.exprs.alloc(LogicExpr::Predicate {
12860 name: prep,
12861 args: p.ctx.terms.alloc_slice([Term::Variable(p.interner.intern("x")), Term::Constant(pp_obj.noun)]),
12862 world: None,
12863 });
12864 pp_mods.push(pp_pred);
12865 }
12866 }
12867
12868 if !p.check_verb() {
12870 return Err(ParseError {
12871 kind: ParseErrorKind::ExpectedVerb { found: p.peek().kind.clone() },
12872 span: p.current_span(),
12873 });
12874 }
12875
12876 let (main_verb, main_time, _, _) = p.consume_verb_with_metadata();
12877
12878 let main_complement = if let TokenType::Adjective(a) = p.peek().kind {
12881 p.advance();
12882 Some(a)
12883 } else {
12884 None
12885 };
12886
12887 if !p.at_clause_boundary() {
12890 return Err(ParseError {
12891 kind: ParseErrorKind::TrailingTokens {
12892 found: p.peek().kind.clone(),
12893 },
12894 span: p.current_span(),
12895 });
12896 }
12897
12898 let var = p.interner.intern("x");
12900
12901 let type_pred = p.ctx.exprs.alloc(LogicExpr::Predicate {
12903 name: subject.noun,
12904 args: p.ctx.terms.alloc_slice([Term::Variable(var)]),
12905 world: None,
12906 });
12907
12908 let mod_pred = p.ctx.exprs.alloc(LogicExpr::Predicate {
12910 name: modifier_verb,
12911 args: p.ctx.terms.alloc_slice([Term::Variable(var)]),
12912 world: None,
12913 });
12914
12915 let main_pred = p.ctx.exprs.alloc(LogicExpr::Predicate {
12917 name: main_verb,
12918 args: match main_complement {
12919 Some(adj) => p
12920 .ctx
12921 .terms
12922 .alloc_slice([Term::Variable(var), Term::Constant(adj)]),
12923 None => p.ctx.terms.alloc_slice([Term::Variable(var)]),
12924 },
12925 world: None,
12926 });
12927
12928 let mut body = p.ctx.exprs.alloc(LogicExpr::BinaryOp {
12930 left: type_pred,
12931 op: TokenType::And,
12932 right: mod_pred,
12933 });
12934
12935 for pp in pp_mods {
12937 body = p.ctx.exprs.alloc(LogicExpr::BinaryOp {
12938 left: body,
12939 op: TokenType::And,
12940 right: pp,
12941 });
12942 }
12943
12944 body = p.ctx.exprs.alloc(LogicExpr::BinaryOp {
12946 left: body,
12947 op: TokenType::And,
12948 right: main_pred,
12949 });
12950
12951 let with_time = match main_time {
12953 Time::Past => p.ctx.exprs.alloc(LogicExpr::Temporal {
12954 operator: TemporalOperator::Past,
12955 body,
12956 }),
12957 Time::Future => p.ctx.exprs.alloc(LogicExpr::Temporal {
12958 operator: TemporalOperator::Future,
12959 body,
12960 }),
12961 _ => body,
12962 };
12963
12964 Ok(p.ctx.exprs.alloc(LogicExpr::Quantifier {
12966 kind: QuantifierKind::Existential,
12967 variable: var,
12968 body: with_time,
12969 island_id: p.current_island,
12970 }))
12971 }) {
12972 return Ok(garden_path_result);
12973 }
12974
12975 self.current = saved_pos;
12977 }
12978
12979 if self.check_modal() {
12980 return self.parse_aspect_chain(subject.noun);
12981 }
12982
12983 if self.check_content_word() {
12985 let word = self.interner.resolve(self.peek().lexeme).to_lowercase();
12986 if word == "has" || word == "have" || word == "had" {
12987 let is_perfect_aspect = if self.current + 1 < self.tokens.len() {
12989 let next_token = &self.tokens[self.current + 1].kind;
12990 matches!(
12991 next_token,
12992 TokenType::Verb { .. } | TokenType::Not
12993 ) && !matches!(next_token, TokenType::Number(_))
12994 } else {
12995 false
12996 };
12997 if is_perfect_aspect {
12998 return self.parse_aspect_chain(subject.noun);
12999 }
13000 }
13002 }
13003
13004 if self.check(&TokenType::Had) {
13009 let next_is_participle = matches!(
13010 self.tokens.get(self.current + 1).map(|t| &t.kind),
13011 Some(TokenType::Verb { .. })
13012 );
13013 if next_is_participle {
13014 return self.parse_aspect_chain(subject.noun);
13015 }
13016 let have_lemma = self.interner.intern("Have");
13017 self.tokens[self.current].kind = TokenType::Verb {
13018 lemma: have_lemma,
13019 time: Time::Past,
13020 aspect: Aspect::Simple,
13021 class: VerbClass::State,
13022 };
13023 }
13025
13026 if self.check(&TokenType::Never) {
13028 self.advance();
13029 let verb = self.consume_verb();
13030 let subject_term = self.noun_phrase_to_term(&subject);
13031
13032 let mut object_quant: Option<(QuantifierKind, Symbol, Symbol)> = None;
13036 let mut object_term: Option<Term<'a>> = None;
13037 if let TokenType::Cardinal(n) = self.peek().kind {
13038 self.advance();
13039 let np = self.parse_noun_phrase(false)?;
13040 let var = self.next_var_name();
13041 object_quant = Some((QuantifierKind::Cardinal(n), var, np.noun));
13042 object_term = Some(Term::Variable(var));
13043 } else if matches!(self.peek().kind, TokenType::All | TokenType::Some) {
13044 let universal = matches!(self.advance().kind, TokenType::All);
13045 let np = self.parse_noun_phrase(false)?;
13046 let var = self.next_var_name();
13047 let kind = if universal {
13048 QuantifierKind::Universal
13049 } else {
13050 QuantifierKind::Existential
13051 };
13052 object_quant = Some((kind, var, np.noun));
13053 object_term = Some(Term::Variable(var));
13054 } else if self.check_content_word() || self.check_article() {
13055 let np = self.parse_noun_phrase(false)?;
13056 object_term = Some(self.noun_phrase_to_term(&np));
13057 }
13058
13059 if object_term.is_none() {
13060 let verb_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
13061 name: verb,
13062 args: self.ctx.terms.alloc_slice([subject_term]),
13063 world: None,
13064 });
13065 let result = self.ctx.exprs.alloc(LogicExpr::UnaryOp {
13066 op: TokenType::Not,
13067 operand: verb_pred,
13068 });
13069 return self.wrap_with_definiteness_full(&subject, result);
13070 }
13071
13072 let mut roles = vec![(crate::ast::ThematicRole::Agent, subject_term)];
13073 if let Some(t) = object_term {
13074 roles.push((crate::ast::ThematicRole::Theme, t));
13075 }
13076 let modifiers = self.collect_adverbs();
13077 let event_var = self.get_event_var();
13078 let suppress_existential = self.drs.in_conditional_antecedent();
13079 let event = self.ctx.exprs.alloc(LogicExpr::NeoEvent(Box::new(NeoEventData {
13080 event_var,
13081 verb,
13082 roles: self.ctx.roles.alloc_slice(roles),
13083 modifiers: self.ctx.syms.alloc_slice(modifiers),
13084 suppress_existential,
13085 world: None,
13086 })));
13087 let mut result = self.ctx.exprs.alloc(LogicExpr::UnaryOp {
13088 op: TokenType::Not,
13089 operand: event,
13090 });
13091 if let Some((kind, var, noun)) = object_quant {
13092 let restriction = self.ctx.exprs.alloc(LogicExpr::Predicate {
13093 name: noun,
13094 args: self.ctx.terms.alloc_slice([Term::Variable(var)]),
13095 world: None,
13096 });
13097 let connective = if matches!(kind, QuantifierKind::Universal) {
13098 TokenType::Implies
13099 } else {
13100 TokenType::And
13101 };
13102 let body = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
13103 left: restriction,
13104 op: connective,
13105 right: result,
13106 });
13107 result = self.ctx.exprs.alloc(LogicExpr::Quantifier {
13108 kind,
13109 variable: var,
13110 body,
13111 island_id: self.current_island,
13112 });
13113 }
13114 return self.wrap_with_definiteness_full(&subject, result);
13115 }
13116
13117 if let TokenType::Adverb(sym)
13123 | TokenType::ScopalAdverb(sym)
13124 | TokenType::TemporalAdverb(sym) = self.peek().kind
13125 {
13126 let w = self.interner.resolve(sym).to_lowercase();
13129 if crate::lexicon::is_quantificational_adverb(&w)
13130 && self.current + 1 < self.tokens.len()
13131 && matches!(self.tokens[self.current + 1].kind, TokenType::Verb { .. })
13132 {
13133 self.advance();
13134 }
13135 }
13136
13137 if self.check_verb() {
13138 let (mut verb, verb_time, verb_aspect, verb_class) = self.consume_verb_with_metadata();
13139
13140 let subject_sort = lexicon::lookup_sort(self.interner.resolve(subject.noun));
13142 let verb_str = self.interner.resolve(verb);
13143 if let Some(s_sort) = subject_sort {
13144 if !crate::ontology::check_sort_compatibility(verb_str, s_sort) {
13145 let metaphor = self.ctx.exprs.alloc(LogicExpr::Metaphor {
13146 tenor: self.ctx.terms.alloc(Term::Constant(subject.noun)),
13147 vehicle: self.ctx.terms.alloc(Term::Constant(verb)),
13148 });
13149 return self.wrap_with_definiteness_full(&subject, metaphor);
13150 }
13151 }
13152
13153 if let Some(cmp) =
13158 self.try_arithmetic_comparative(verb, Term::Constant(subject.noun), verb_time)?
13159 {
13160 return self.wrap_with_definiteness_full(&subject, cmp);
13161 }
13162
13163 if let Some(off) =
13165 self.try_temporal_offset(verb, Term::Constant(subject.noun), verb_time)?
13166 {
13167 return self.wrap_with_definiteness_full(&subject, off);
13168 }
13169
13170 if let Some(off) =
13172 self.try_positional_offset(verb, Term::Constant(subject.noun), verb_time)?
13173 {
13174 return self.wrap_with_definiteness_full(&subject, off);
13175 }
13176
13177 let is_raising =
13188 crate::lexicon::is_raising_verb(&self.interner.resolve(verb).to_lowercase());
13189 let next_is_to_be = self.check(&TokenType::To)
13190 && self.current + 1 < self.tokens.len()
13191 && matches!(self.tokens[self.current + 1].kind, TokenType::Be);
13192 let raising_with_complement = is_raising
13193 && (matches!(self.peek().kind, TokenType::Adjective(_))
13194 || next_is_to_be
13195 || (self.check_content_word() && !self.check(&TokenType::To)));
13196 if raising_with_complement {
13197 if self.check(&TokenType::To) {
13199 self.advance();
13200 if self.check(&TokenType::Be) {
13201 self.advance();
13202 }
13203 }
13204 let complement = if let TokenType::Adjective(adj) = self.peek().kind {
13205 self.advance();
13206 self.ctx.exprs.alloc(LogicExpr::Predicate {
13207 name: adj,
13208 args: self.ctx.terms.alloc_slice([Term::Constant(subject.noun)]),
13209 world: None,
13210 })
13211 } else if self.check_content_word() {
13212 self.parse_predicate_with_subject(subject.noun)?
13213 } else {
13214 self.ctx.exprs.alloc(LogicExpr::Atom(self.interner.intern("?")))
13215 };
13216 let evidential = self.ctx.exprs.alloc(LogicExpr::Modal {
13217 vector: crate::ast::ModalVector::new(
13218 crate::ast::ModalDomain::Alethic,
13219 1.0,
13220 crate::ast::ModalFlavor::Evidential,
13221 )
13222 .with_base(verb),
13223 operand: complement,
13224 });
13225 return self.wrap_with_definiteness_full(&subject, evidential);
13226 }
13227
13228 if crate::lexicon::is_perception_verb(&self.interner.resolve(verb).to_lowercase()) {
13235 let is_verb_capable = |kind: &TokenType| match kind {
13236 TokenType::Verb { .. } => true,
13237 TokenType::Ambiguous { primary, alternatives } => {
13238 matches!(**primary, TokenType::Verb { .. })
13239 || alternatives.iter().any(|t| matches!(t, TokenType::Verb { .. }))
13240 }
13241 _ => false,
13242 };
13243 let mut vp_idx = None;
13244 let mut i = self.current;
13245 while i < self.tokens.len() {
13246 if matches!(
13247 self.tokens[i].kind,
13248 TokenType::Period | TokenType::EOF | TokenType::Comma
13249 ) {
13250 break;
13251 }
13252 let lex = self.interner.resolve(self.tokens[i].lexeme).to_lowercase();
13255 if is_verb_capable(&self.tokens[i].kind)
13256 || crate::lexicon::lookup_verb_db(&lex).is_some()
13257 {
13258 vp_idx = Some(i);
13259 }
13260 i += 1;
13261 }
13262 if let Some(vp_i) = vp_idx {
13263 if vp_i > self.current {
13265 let subj_kind = self.tokens[vp_i - 1].kind.clone();
13266 let psubj = match subj_kind {
13267 TokenType::Noun(n) | TokenType::ProperName(n) => Some(n),
13268 TokenType::Article(_)
13270 | TokenType::Preposition(_)
13271 | TokenType::Period
13272 | TokenType::Comma => None,
13273 TokenType::Adjective(_)
13279 | TokenType::NonIntersectiveAdjective(_)
13280 | TokenType::Cardinal(_)
13281 | TokenType::Number(_)
13282 | TokenType::AtLeast(_)
13283 | TokenType::AtMost(_) => None,
13284 _ => {
13287 let lx = self
13288 .interner
13289 .resolve(self.tokens[vp_i - 1].lexeme)
13290 .to_lowercase();
13291 let cap = lx
13292 .chars()
13293 .next()
13294 .map(|c| c.to_uppercase().collect::<String>() + &lx[1..])
13295 .unwrap_or(lx);
13296 Some(self.interner.intern(&cap))
13297 }
13298 };
13299 if let Some(psubj) = psubj {
13300 let vlex = self.interner.resolve(self.tokens[vp_i].lexeme).to_lowercase();
13301 let vname = vlex
13302 .chars()
13303 .next()
13304 .map(|c| c.to_uppercase().collect::<String>() + &vlex[1..])
13305 .unwrap_or(vlex);
13306 let inner_verb = self.interner.intern(&vname);
13307 self.current = vp_i + 1; let perceived = self.ctx.exprs.alloc(LogicExpr::Predicate {
13309 name: inner_verb,
13310 args: self.ctx.terms.alloc_slice([Term::Constant(psubj)]),
13311 world: None,
13312 });
13313 let perceived_advs = self.collect_adverbs();
13316 let perceived = if perceived_advs.is_empty() {
13317 perceived
13318 } else {
13319 self.ctx.exprs.alloc(LogicExpr::Event {
13320 predicate: perceived,
13321 adverbs: self.ctx.syms.alloc_slice(perceived_advs),
13322 })
13323 };
13324 let event_var = self.get_event_var();
13325 let roles = vec![
13326 (ThematicRole::Agent, Term::Constant(subject.noun)),
13327 (ThematicRole::Theme, Term::Proposition(perceived)),
13328 ];
13329 let mut modifiers: Vec<Symbol> = Vec::new();
13330 match verb_time {
13331 Time::Past => modifiers.push(self.interner.intern("Past")),
13332 Time::Future => modifiers.push(self.interner.intern("Future")),
13333 _ => {}
13334 }
13335 let neo =
13336 self.ctx.exprs.alloc(LogicExpr::NeoEvent(Box::new(NeoEventData {
13337 event_var,
13338 verb,
13339 roles: self.ctx.roles.alloc_slice(roles),
13340 modifiers: self.ctx.syms.alloc_slice(modifiers),
13341 suppress_existential: false,
13342 world: None,
13343 })));
13344 return self.wrap_with_definiteness_full(&subject, neo);
13345 }
13346 }
13347 }
13348 }
13349
13350 if self.is_control_verb(verb)
13358 && (self.check_to()
13359 || lexicon::is_object_control_verb(
13360 &self.interner.resolve(verb).to_lowercase(),
13361 ))
13362 {
13363 return self.parse_control_structure(&subject, verb, verb_time);
13364 }
13365
13366 if let Some((var_name, rel_clause)) = relative_clause {
13368 let with_time = if self.at_clause_boundary() {
13372 let main_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
13373 name: verb,
13374 args: self.ctx.terms.alloc_slice([Term::Variable(var_name)]),
13375 world: None,
13376 });
13377
13378 let effective_time = self.pending_time.take().unwrap_or(verb_time);
13379 match effective_time {
13380 Time::Past => &*self.ctx.exprs.alloc(LogicExpr::Temporal {
13381 operator: TemporalOperator::Past,
13382 body: main_pred,
13383 }),
13384 Time::Future => &*self.ctx.exprs.alloc(LogicExpr::Temporal {
13385 operator: TemporalOperator::Future,
13386 body: main_pred,
13387 }),
13388 _ => main_pred,
13389 }
13390 } else {
13391 self.current -= 1; self.parse_predicate_with_subject_as_var(var_name)?
13393 };
13394
13395 let type_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
13397 name: subject.noun,
13398 args: self.ctx.terms.alloc_slice([Term::Variable(var_name)]),
13399 world: None,
13400 });
13401
13402 let inner = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
13403 left: type_pred,
13404 op: TokenType::And,
13405 right: rel_clause,
13406 });
13407
13408 let body = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
13409 left: inner,
13410 op: TokenType::And,
13411 right: with_time,
13412 });
13413
13414 return Ok(self.ctx.exprs.alloc(LogicExpr::Quantifier {
13415 kind: QuantifierKind::Existential,
13416 variable: var_name,
13417 body,
13418 island_id: self.current_island,
13419 }));
13420 }
13421
13422 let subject_term = self.noun_phrase_to_term(&subject);
13423 let mut args = vec![subject_term.clone()];
13424
13425 let unknown = self.interner.intern("?");
13426
13427 if self.check_wh_word() {
13429 let wh_token = self.advance().kind.clone();
13430
13431 let is_who = matches!(wh_token, TokenType::Who);
13433 let is_what = matches!(wh_token, TokenType::What);
13434
13435 let is_sluicing = self.is_at_end() ||
13437 self.check(&TokenType::Period) ||
13438 self.check(&TokenType::Comma);
13439
13440 if is_sluicing {
13441 if let Some(template) = self.last_event_template.clone() {
13443 let wh_var = self.next_var_name();
13444
13445 let roles: Vec<_> = if is_who {
13447 std::iter::once((ThematicRole::Agent, Term::Variable(wh_var)))
13449 .chain(template.non_agent_roles.iter().cloned())
13450 .collect()
13451 } else if is_what {
13452 vec![
13454 (ThematicRole::Agent, subject_term.clone()),
13455 (ThematicRole::Theme, Term::Variable(wh_var)),
13456 ]
13457 } else {
13458 std::iter::once((ThematicRole::Agent, Term::Variable(wh_var)))
13460 .chain(template.non_agent_roles.iter().cloned())
13461 .collect()
13462 };
13463
13464 let event_var = self.get_event_var();
13465 let suppress_existential = self.drs.in_conditional_antecedent();
13466 if suppress_existential {
13467 let event_class = self.interner.intern("Event");
13468 self.drs.introduce_referent(event_var, event_class, Gender::Neuter, Number::Singular);
13469 }
13470 let reconstructed = self.ctx.exprs.alloc(LogicExpr::NeoEvent(Box::new(NeoEventData {
13471 event_var,
13472 verb: template.verb,
13473 roles: self.ctx.roles.alloc_slice(roles),
13474 modifiers: self.ctx.syms.alloc_slice(template.modifiers.clone()),
13475 suppress_existential,
13476 world: None,
13477 })));
13478
13479 let question = self.ctx.exprs.alloc(LogicExpr::Question {
13480 wh_variable: wh_var,
13481 body: reconstructed,
13482 });
13483
13484 let know_event_var = self.get_event_var();
13486 let suppress_existential2 = self.drs.in_conditional_antecedent();
13487 if suppress_existential2 {
13488 let event_class = self.interner.intern("Event");
13489 self.drs.introduce_referent(know_event_var, event_class, Gender::Neuter, Number::Singular);
13490 }
13491 let know_event = self.ctx.exprs.alloc(LogicExpr::NeoEvent(Box::new(NeoEventData {
13492 event_var: know_event_var,
13493 verb,
13494 roles: self.ctx.roles.alloc_slice(vec![
13495 (ThematicRole::Agent, subject_term),
13496 (ThematicRole::Theme, Term::Proposition(question)),
13497 ]),
13498 modifiers: self.ctx.syms.alloc_slice(vec![]),
13499 suppress_existential: suppress_existential2,
13500 world: None,
13501 })));
13502
13503 return self.wrap_with_definiteness_full(&subject, know_event);
13504 }
13505 }
13506
13507 let embedded = self.parse_embedded_wh_clause()?;
13509 let question = self.ctx.exprs.alloc(LogicExpr::Question {
13510 wh_variable: self.interner.intern("x"),
13511 body: embedded,
13512 });
13513
13514 let know_event_var = self.get_event_var();
13516 let suppress_existential = self.drs.in_conditional_antecedent();
13517 if suppress_existential {
13518 let event_class = self.interner.intern("Event");
13519 self.drs.introduce_referent(know_event_var, event_class, Gender::Neuter, Number::Singular);
13520 }
13521 let know_event = self.ctx.exprs.alloc(LogicExpr::NeoEvent(Box::new(NeoEventData {
13522 event_var: know_event_var,
13523 verb,
13524 roles: self.ctx.roles.alloc_slice(vec![
13525 (ThematicRole::Agent, subject_term),
13526 (ThematicRole::Theme, Term::Proposition(question)),
13527 ]),
13528 modifiers: self.ctx.syms.alloc_slice(vec![]),
13529 suppress_existential,
13530 world: None,
13531 })));
13532
13533 return self.wrap_with_definiteness_full(&subject, know_event);
13534 }
13535
13536 if crate::lexicon::is_opaque_verb(&self.interner.resolve(verb).to_lowercase()) {
13543 let mut i = self.current;
13544 if i < self.tokens.len() && matches!(self.tokens[i].kind, TokenType::That) {
13545 i += 1;
13546 }
13547 let subj_ok = i < self.tokens.len()
13548 && matches!(
13549 self.tokens[i].kind,
13550 TokenType::ProperName(_) | TokenType::Pronoun { .. }
13551 );
13552 let verb_follows = subj_ok
13553 && i + 1 < self.tokens.len()
13554 && (matches!(
13555 self.tokens[i + 1].kind,
13556 TokenType::Verb { .. } | TokenType::Auxiliary(_)
13557 )
13558 || crate::lexicon::lookup_irregular_verb(
13562 &self
13563 .interner
13564 .resolve(self.tokens[i + 1].lexeme)
13565 .to_lowercase(),
13566 )
13567 .is_some());
13568 if verb_follows {
13569 if self.check(&TokenType::That) {
13570 self.advance();
13571 }
13572 let embedded_subject = match self.peek().kind {
13573 TokenType::ProperName(s) => {
13574 self.advance();
13575 s
13576 }
13577 TokenType::Pronoun { gender, number, .. } => {
13578 self.advance();
13579 match self.resolve_pronoun(gender, number)? {
13580 ResolvedPronoun::Variable(s) | ResolvedPronoun::Constant(s) => s,
13581 }
13582 }
13583 _ => unreachable!("guarded by subj_ok"),
13584 };
13585 let embedded_pred = self.parse_predicate_with_subject(embedded_subject)?;
13586 let subject_term_for_event = self.coerce_agent(&subject);
13587 let main_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
13588 name: verb,
13589 args: self.ctx.terms.alloc_slice([
13590 subject_term_for_event,
13591 Term::Proposition(embedded_pred),
13592 ]),
13593 world: None,
13594 });
13595 let effective_time = self.pending_time.take().unwrap_or(verb_time);
13596 let with_time = match effective_time {
13597 Time::Past => self.ctx.exprs.alloc(LogicExpr::Temporal {
13598 operator: TemporalOperator::Past,
13599 body: main_pred,
13600 }),
13601 Time::Future => self.ctx.exprs.alloc(LogicExpr::Temporal {
13602 operator: TemporalOperator::Future,
13603 body: main_pred,
13604 }),
13605 _ => main_pred,
13606 };
13607 return self.wrap_with_definiteness_full(&subject, with_time);
13608 }
13609 }
13610
13611 let mut object_term: Option<Term<'a>> = None;
13612 let mut object_adjectives: &[Symbol] = &[];
13617 let mut object_desc_pps: &[&'a LogicExpr<'a>] = &[];
13618 let mut secondary_adj: Option<Symbol> = None;
13622 let secondary_role = |verb_lemma: &str| -> ThematicRole {
13625 if crate::lexicon::is_resultative_verb(verb_lemma) {
13626 ThematicRole::Result
13627 } else {
13628 ThematicRole::Depictive
13629 }
13630 };
13631 let mut second_object_term: Option<Term<'a>> = None;
13632 let mut object_superlative: Option<(Symbol, Symbol)> = None; if self.check(&TokenType::Reflexive) {
13634 self.advance();
13635 let term = self.noun_phrase_to_term(&subject);
13636 object_term = Some(term.clone());
13637 args.push(term);
13638
13639 if let TokenType::Particle(particle_sym) = self.peek().kind {
13641 let verb_str = self.interner.resolve(verb).to_lowercase();
13642 let particle_str = self.interner.resolve(particle_sym).to_lowercase();
13643 if let Some((phrasal_lemma, _class)) = crate::lexicon::lookup_phrasal_verb(&verb_str, &particle_str) {
13644 self.advance();
13645 verb = self.interner.intern(phrasal_lemma);
13646 }
13647 }
13648 } else if self.check_pronoun() {
13649 let token = self.advance().clone();
13650 let pronoun_analysis = match &token.kind {
13654 TokenType::Pronoun { gender, number, .. } => Some((*gender, *number)),
13655 TokenType::Ambiguous { primary, .. } => match primary.as_ref() {
13656 TokenType::Pronoun { gender, number, .. } => Some((*gender, *number)),
13657 _ => None,
13658 },
13659 _ => None,
13660 };
13661 if let Some((gender, number)) = pronoun_analysis {
13662 let plex = self.interner.resolve(token.lexeme).to_lowercase();
13665 let deictic_role = match plex.as_str() {
13666 "you" | "yourself" => Some("Addressee"),
13667 "i" | "me" | "myself" => Some("Speaker"),
13668 _ => None,
13669 };
13670 if let Some(role) = deictic_role {
13671 let term = Term::Constant(self.interner.intern(role));
13672 object_term = Some(term.clone());
13673 args.push(term);
13674 } else {
13676 let resolved = self.resolve_pronoun(gender, number)?;
13677 let resolved_sym = match resolved {
13678 ResolvedPronoun::Variable(s) | ResolvedPronoun::Constant(s) => s,
13679 };
13680 let term = if resolved_sym == subject.noun {
13685 let deictic = match (gender, number) {
13686 (Gender::Male, Number::Singular) => "Him",
13687 (Gender::Female, Number::Singular) => "Her",
13688 (Gender::Neuter, Number::Singular) => "It",
13689 _ => "Them",
13690 };
13691 let sym = self.interner.intern(deictic);
13692 self.drs.introduce_referent_with_source(
13693 sym,
13694 sym,
13695 gender,
13696 number,
13697 crate::drs::ReferentSource::ProperName,
13698 );
13699 Term::Constant(sym)
13700 } else {
13701 match resolved {
13702 ResolvedPronoun::Variable(s) => Term::Variable(s),
13703 ResolvedPronoun::Constant(s) => Term::Constant(s),
13704 }
13705 };
13706 object_term = Some(term.clone());
13707 args.push(term);
13708
13709 if let TokenType::Particle(particle_sym) = self.peek().kind {
13711 let verb_str = self.interner.resolve(verb).to_lowercase();
13712 let particle_str = self.interner.resolve(particle_sym).to_lowercase();
13713 if let Some((phrasal_lemma, _class)) = crate::lexicon::lookup_phrasal_verb(&verb_str, &particle_str) {
13714 self.advance();
13715 verb = self.interner.intern(phrasal_lemma);
13716 }
13717 }
13718 } }
13720 } else if self.check(&TokenType::Either) {
13721 self.advance(); let np1 = self.parse_noun_phrase(true)?;
13724 if self.check(&TokenType::Or) {
13725 self.advance(); let np2 = self.parse_noun_phrase(true)?;
13727
13728 let effective_time = self.pending_time.take().unwrap_or(verb_time);
13729 let subject_term1 = self.coerce_agent(&subject);
13730 let subject_term2 = self.coerce_agent(&subject);
13731 let suppress_existential = self.drs.in_conditional_antecedent();
13732
13733 let past_sym = self.interner.intern("Past");
13734 let future_sym = self.interner.intern("Future");
13735 let mut mods1 = vec![];
13736 let mut mods2 = vec![];
13737 match effective_time {
13738 Time::Past => { mods1.push(past_sym); mods2.push(past_sym); }
13739 Time::Future => { mods1.push(future_sym); mods2.push(future_sym); }
13740 _ => {}
13741 }
13742
13743 let event_var1 = self.get_event_var();
13744 let event_var2 = self.get_event_var();
13745
13746 let neo1 = self.ctx.exprs.alloc(LogicExpr::NeoEvent(Box::new(NeoEventData {
13747 event_var: event_var1,
13748 verb,
13749 roles: self.ctx.roles.alloc_slice(vec![
13750 (ThematicRole::Agent, subject_term1),
13751 (ThematicRole::Theme, Term::Constant(np1.noun)),
13752 ]),
13753 modifiers: self.ctx.syms.alloc_slice(mods1),
13754 suppress_existential,
13755 world: None,
13756 })));
13757 let neo2 = self.ctx.exprs.alloc(LogicExpr::NeoEvent(Box::new(NeoEventData {
13758 event_var: event_var2,
13759 verb,
13760 roles: self.ctx.roles.alloc_slice(vec![
13761 (ThematicRole::Agent, subject_term2),
13762 (ThematicRole::Theme, Term::Constant(np2.noun)),
13763 ]),
13764 modifiers: self.ctx.syms.alloc_slice(mods2),
13765 suppress_existential,
13766 world: None,
13767 })));
13768
13769 let placeholder = self.interner.intern("_PP_SELF_");
13773 let possesses = self.interner.intern("Possesses");
13774 let mut augment = |p: &mut Self, neo: &'a LogicExpr<'a>, np: &crate::ast::NounPhrase<'a>| -> &'a LogicExpr<'a> {
13775 let obj = Term::Constant(np.noun);
13776 let mut e = neo;
13777 if let Some(possessor) = np.possessor {
13778 let poss = p.ctx.exprs.alloc(LogicExpr::Predicate {
13779 name: possesses,
13780 args: p
13781 .ctx
13782 .terms
13783 .alloc_slice([Term::Constant(possessor.noun), obj]),
13784 world: None,
13785 });
13786 e = p.ctx.exprs.alloc(LogicExpr::BinaryOp {
13787 left: e,
13788 op: TokenType::And,
13789 right: poss,
13790 });
13791 }
13792 for pp in np.pps {
13793 let pp_sub = match pp {
13794 LogicExpr::Predicate { name, args, world } => {
13795 let new_args: Vec<Term<'a>> = args
13796 .iter()
13797 .map(|a| match a {
13798 Term::Variable(v) if *v == placeholder => obj,
13799 other => *other,
13800 })
13801 .collect();
13802 p.ctx.exprs.alloc(LogicExpr::Predicate {
13803 name: *name,
13804 args: p.ctx.terms.alloc_slice(new_args),
13805 world: *world,
13806 })
13807 }
13808 other => *other,
13809 };
13810 e = p.ctx.exprs.alloc(LogicExpr::BinaryOp {
13811 left: e,
13812 op: TokenType::And,
13813 right: pp_sub,
13814 });
13815 }
13816 e
13817 };
13818 let neo1 = augment(self, neo1, &np1);
13819 let neo2 = augment(self, neo2, &np2);
13820 let disj = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
13821 left: neo1,
13822 op: TokenType::Or,
13823 right: neo2,
13824 });
13825 return self.wrap_with_definiteness_full(&subject, disj);
13826 }
13827 return Err(ParseError {
13828 kind: ParseErrorKind::UnexpectedToken {
13829 expected: TokenType::Or,
13830 found: self.peek().kind.clone(),
13831 },
13832 span: self.current_span(),
13833 });
13834 } else if self.counting_np_lookahead().is_some()
13835 || self.check_quantifier()
13836 || self.check_article()
13837 || self.check_possessive_pronoun()
13838 {
13839 let (obj_quantifier, was_definite_article) = if let Some(n) =
13841 self.counting_np_lookahead()
13842 {
13843 self.advance();
13850 (Some(TokenType::Cardinal(n)), false)
13851 } else if self.check_possessive_pronoun() {
13852 (None, true)
13855 } else if self.check_quantifier() {
13856 (Some(self.advance().kind.clone()), false)
13857 } else {
13858 let art = self.advance().kind.clone();
13859 if let TokenType::Article(def) = art {
13860 if def == Definiteness::Indefinite {
13861 (Some(TokenType::Some), false)
13862 } else {
13863 (None, true) }
13865 } else {
13866 (None, false)
13867 }
13868 };
13869
13870 self.nominal_np_context = true;
13873 let object_np_result = self.parse_noun_phrase(false);
13874 self.nominal_np_context = false;
13875 let object_np = object_np_result?;
13876
13877 if let Some(adj) = object_np.superlative {
13879 object_superlative = Some((adj, object_np.noun));
13880 }
13881
13882 if let TokenType::Adjective(a) = self.peek().kind {
13884 self.advance();
13885 secondary_adj = Some(a);
13886 }
13887
13888 if let TokenType::Particle(particle_sym) = self.peek().kind {
13890 let verb_str = self.interner.resolve(verb).to_lowercase();
13891 let particle_str = self.interner.resolve(particle_sym).to_lowercase();
13892 if let Some((phrasal_lemma, _class)) = crate::lexicon::lookup_phrasal_verb(&verb_str, &particle_str) {
13893 self.advance(); verb = self.interner.intern(phrasal_lemma);
13895 }
13896 }
13897
13898 if let Some(obj_q) = obj_quantifier {
13899 let verb_str = self.interner.resolve(verb).to_lowercase();
13903 let is_opaque = lexicon::lookup_verb_db(&verb_str)
13904 .map(|meta| meta.features.contains(&lexicon::Feature::Opaque))
13905 .unwrap_or(false);
13906
13907 if is_opaque && self.check_verb() {
13911 let emb_var = self.next_var_name();
13912 let emb_restriction = self.ctx.exprs.alloc(LogicExpr::Predicate {
13913 name: object_np.noun,
13914 args: self.ctx.terms.alloc_slice([Term::Variable(emb_var)]),
13915 world: None,
13916 });
13917 let emb_vp = self.parse_predicate_with_subject_as_var(emb_var)?;
13918 let (emb_kind, emb_op) = match obj_q {
13919 TokenType::All => (QuantifierKind::Universal, TokenType::Implies),
13920 _ => (QuantifierKind::Existential, TokenType::And),
13921 };
13922 let emb_body = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
13923 left: emb_restriction,
13924 op: emb_op,
13925 right: emb_vp,
13926 });
13927 let embedded = self.ctx.exprs.alloc(LogicExpr::Quantifier {
13928 kind: emb_kind,
13929 variable: emb_var,
13930 body: emb_body,
13931 island_id: self.current_island,
13932 });
13933 let subject_term_for_event = self.coerce_agent(&subject);
13934 let main_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
13935 name: verb,
13936 args: self.ctx.terms.alloc_slice([
13937 subject_term_for_event,
13938 Term::Proposition(embedded),
13939 ]),
13940 world: None,
13941 });
13942 let effective_time = self.pending_time.take().unwrap_or(verb_time);
13943 let with_time = match effective_time {
13944 Time::Past => self.ctx.exprs.alloc(LogicExpr::Temporal {
13945 operator: TemporalOperator::Past,
13946 body: main_pred,
13947 }),
13948 _ => main_pred,
13949 };
13950 return self.wrap_with_definiteness_full(&subject, with_time);
13951 }
13952
13953 if is_opaque && matches!(obj_q, TokenType::Some) {
13954 let intension_term = Term::Intension(object_np.noun);
13956
13957 let event_var = self.get_event_var();
13959 let mut modifiers = self.collect_adverbs();
13960 let effective_time = self.pending_time.take().unwrap_or(verb_time);
13961 match effective_time {
13962 Time::Past => modifiers.push(self.interner.intern("Past")),
13963 Time::Future => modifiers.push(self.interner.intern("Future")),
13964 _ => {}
13965 }
13966
13967 let subject_term_for_event = self.coerce_agent(&subject);
13968 let roles = vec![
13969 (ThematicRole::Agent, subject_term_for_event),
13970 (ThematicRole::Theme, intension_term),
13971 ];
13972
13973 let suppress_existential = self.drs.in_conditional_antecedent();
13974 if suppress_existential {
13975 let event_class = self.interner.intern("Event");
13976 self.drs.introduce_referent(event_var, event_class, Gender::Neuter, Number::Singular);
13977 }
13978 let neo_event = self.ctx.exprs.alloc(LogicExpr::NeoEvent(Box::new(NeoEventData {
13979 event_var,
13980 verb,
13981 roles: self.ctx.roles.alloc_slice(roles),
13982 modifiers: self.ctx.syms.alloc_slice(modifiers),
13983 suppress_existential,
13984 world: None,
13985 })));
13986
13987 return self.wrap_with_definiteness_full(&subject, neo_event);
13988 }
13989
13990 let obj_var = self.next_var_name();
13991
13992 let obj_gender = Self::infer_noun_gender(self.interner.resolve(object_np.noun));
13994 let obj_number = if Self::is_plural_noun(self.interner.resolve(object_np.noun)) {
13995 Number::Plural
13996 } else {
13997 Number::Singular
13998 };
13999 if object_np.definiteness == Some(Definiteness::Definite) {
14001 self.drs.introduce_referent_with_source(obj_var, object_np.noun, obj_gender, obj_number, ReferentSource::MainClause);
14002 } else {
14003 self.drs.introduce_referent(obj_var, object_np.noun, obj_gender, obj_number);
14004 }
14005
14006 let mut type_pred: &'a LogicExpr<'a> = self.ctx.exprs.alloc(LogicExpr::Predicate {
14007 name: object_np.noun,
14008 args: self.ctx.terms.alloc_slice([Term::Variable(obj_var)]),
14009 world: None,
14010 });
14011
14012 if crate::lexicon::is_mass_noun(&self.interner.resolve(object_np.noun).to_lowercase()) {
14017 let portion_sym = self.interner.intern("Portion");
14018 let portion_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
14019 name: portion_sym,
14020 args: self.ctx.terms.alloc_slice([Term::Variable(obj_var)]),
14021 world: None,
14022 });
14023 type_pred = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
14024 left: portion_pred,
14025 op: TokenType::And,
14026 right: type_pred,
14027 });
14028 }
14029
14030 for &adj in object_np.adjectives {
14034 let adj_pred = self.adjective_restriction(adj, obj_var, object_np.noun);
14035 type_pred = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
14036 left: type_pred,
14037 op: TokenType::And,
14038 right: adj_pred,
14039 });
14040 }
14041 for pp in object_np.pps {
14042 let pp_sub = self.substitute_pp_placeholder(pp, obj_var);
14043 type_pred = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
14044 left: type_pred,
14045 op: TokenType::And,
14046 right: pp_sub,
14047 });
14048 }
14049
14050 let obj_restriction = if self.check(&TokenType::That) || self.check(&TokenType::Who) {
14051 self.advance();
14052 let rel_clause = self.parse_relative_clause(obj_var)?;
14053 self.ctx.exprs.alloc(LogicExpr::BinaryOp {
14054 left: type_pred,
14055 op: TokenType::And,
14056 right: rel_clause,
14057 })
14058 } else {
14059 type_pred
14060 };
14061
14062 let mut recipient: Option<Term<'a>> = None;
14066 let mut control_infinitive: Option<Symbol> = None;
14067 if self.check_to_marker() {
14068 let after_to = self.tokens.get(self.current + 1).map(|t| t.kind.clone());
14069 match after_to {
14070 Some(TokenType::Verb { lemma, .. }) => {
14071 self.advance(); self.advance(); control_infinitive = Some(lemma);
14074 }
14075 Some(TokenType::Noun(word))
14076 if crate::lexicon::lookup_verb_db(
14077 &self.interner.resolve(word).to_lowercase(),
14078 )
14079 .is_some() =>
14080 {
14081 let lemma_str = crate::lexicon::lookup_verb_db(
14082 &self.interner.resolve(word).to_lowercase(),
14083 )
14084 .map(|m| m.lemma)
14085 .unwrap();
14086 self.advance(); self.advance(); control_infinitive = Some(self.interner.intern(lemma_str));
14089 }
14090 Some(kind)
14091 if Lexer::is_ditransitive_verb(&self.interner.resolve(verb))
14092 && matches!(
14093 kind,
14094 TokenType::ProperName(_)
14095 | TokenType::Noun(_)
14096 | TokenType::Article(_)
14097 ) =>
14098 {
14099 self.advance(); let r_np = self.parse_noun_phrase(false)?;
14101 recipient = Some(Term::Constant(r_np.noun));
14102 }
14103 _ => {}
14104 }
14105 }
14106
14107 let event_var = self.get_event_var();
14108 let mut modifiers = self.collect_adverbs();
14109 let effective_time = self.pending_time.take().unwrap_or(verb_time);
14110 match effective_time {
14111 Time::Past => modifiers.push(self.interner.intern("Past")),
14112 Time::Future => modifiers.push(self.interner.intern("Future")),
14113 _ => {}
14114 }
14115
14116 let subject_term_for_event = self.coerce_agent(&subject);
14117 let mut roles = vec![
14118 (ThematicRole::Agent, subject_term_for_event),
14119 (ThematicRole::Theme, Term::Variable(obj_var)),
14120 ];
14121 if let Some(r) = recipient {
14122 roles.push((ThematicRole::Recipient, r));
14123 }
14124
14125 if let Some(adj) = secondary_adj {
14127 let sec_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
14128 name: adj,
14129 args: self.ctx.terms.alloc_slice([Term::Variable(obj_var)]),
14130 world: None,
14131 });
14132 let role = secondary_role(&self.interner.resolve(verb).to_lowercase());
14133 roles.push((role, Term::Proposition(sec_pred)));
14134 }
14135
14136 let template_roles = vec![
14139 (ThematicRole::Agent, subject_term_for_event),
14140 (ThematicRole::Theme, Term::Constant(object_np.noun)),
14141 ];
14142 self.capture_event_template(verb, &template_roles, &modifiers);
14143
14144 let suppress_existential = self.drs.in_conditional_antecedent();
14145 if suppress_existential {
14146 let event_class = self.interner.intern("Event");
14147 self.drs.introduce_referent(event_var, event_class, Gender::Neuter, Number::Singular);
14148 }
14149 let neo_event = if let Some(inf) = control_infinitive {
14150 let inf_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
14151 name: inf,
14152 args: self.ctx.terms.alloc_slice([Term::Variable(obj_var)]),
14153 world: None,
14154 });
14155 let control = self.ctx.exprs.alloc(LogicExpr::Control {
14156 verb,
14157 subject: self.ctx.terms.alloc(subject_term_for_event),
14158 object: Some(&*self.ctx.terms.alloc(Term::Variable(obj_var))),
14159 infinitive: inf_pred,
14160 });
14161 match effective_time {
14162 Time::Past => &*self.ctx.exprs.alloc(LogicExpr::Temporal {
14163 operator: TemporalOperator::Past,
14164 body: control,
14165 }),
14166 Time::Future => &*self.ctx.exprs.alloc(LogicExpr::Temporal {
14167 operator: TemporalOperator::Future,
14168 body: control,
14169 }),
14170 _ => control,
14171 }
14172 } else {
14173 let plain = &*self.ctx.exprs.alloc(LogicExpr::NeoEvent(Box::new(NeoEventData {
14174 event_var,
14175 verb,
14176 roles: self.ctx.roles.alloc_slice(roles),
14177 modifiers: self.ctx.syms.alloc_slice(modifiers),
14178 suppress_existential,
14179 world: None,
14180 })));
14181 self.attach_trailing_event_pps(plain, event_var)?
14186 };
14187
14188 let obj_kind = match obj_q {
14189 TokenType::All => QuantifierKind::Universal,
14190 TokenType::Some => QuantifierKind::Existential,
14191 TokenType::No => QuantifierKind::Universal,
14192 TokenType::Most => QuantifierKind::Most,
14193 TokenType::Few => QuantifierKind::Few,
14194 TokenType::Many => QuantifierKind::Many,
14195 TokenType::Cardinal(n) => QuantifierKind::Cardinal(n),
14196 TokenType::AtLeast(n) => QuantifierKind::AtLeast(n),
14197 TokenType::AtMost(n) => QuantifierKind::AtMost(n),
14198 _ => QuantifierKind::Existential,
14199 };
14200
14201 let obj_body = match obj_q {
14202 TokenType::All => self.ctx.exprs.alloc(LogicExpr::BinaryOp {
14203 left: obj_restriction,
14204 op: TokenType::Implies,
14205 right: neo_event,
14206 }),
14207 TokenType::No => {
14208 let neg = self.ctx.exprs.alloc(LogicExpr::UnaryOp {
14209 op: TokenType::Not,
14210 operand: neo_event,
14211 });
14212 self.ctx.exprs.alloc(LogicExpr::BinaryOp {
14213 left: obj_restriction,
14214 op: TokenType::Implies,
14215 right: neg,
14216 })
14217 }
14218 _ => self.ctx.exprs.alloc(LogicExpr::BinaryOp {
14219 left: obj_restriction,
14220 op: TokenType::And,
14221 right: neo_event,
14222 }),
14223 };
14224
14225 let obj_quantified = self.ctx.exprs.alloc(LogicExpr::Quantifier {
14227 kind: obj_kind,
14228 variable: obj_var,
14229 body: obj_body,
14230 island_id: self.current_island,
14231 });
14232
14233 let obj_quantified = {
14240 let subj = self.coerce_agent(&subject);
14241 let temporal = match self.parse_temporal_offset_constraint(subj)? {
14248 Some(off) => Some(off),
14249 None => self.parse_bare_temporal_constraint(subj)?,
14250 };
14251 match temporal {
14252 Some(t) => self.ctx.exprs.alloc(LogicExpr::BinaryOp {
14253 left: obj_quantified,
14254 op: TokenType::And,
14255 right: t,
14256 }),
14257 None => obj_quantified,
14258 }
14259 };
14260 return self.wrap_with_definiteness_full(&subject, obj_quantified);
14262 } else {
14263 if was_definite_article {
14268 let obj_gender = Self::infer_noun_gender(self.interner.resolve(object_np.noun));
14269 let obj_number = if Self::is_plural_noun(self.interner.resolve(object_np.noun)) {
14270 Number::Plural
14271 } else {
14272 Number::Singular
14273 };
14274 self.drs.introduce_referent_with_source(object_np.noun, object_np.noun, obj_gender, obj_number, ReferentSource::MainClause);
14276 }
14277
14278 let term = self.noun_phrase_to_term(&object_np);
14279 object_term = Some(term.clone());
14280 object_adjectives = object_np.adjectives;
14281 object_desc_pps = object_np.pps;
14282 args.push(term);
14283
14284 let verb_str = self.interner.resolve(verb);
14291 if Lexer::is_ditransitive_verb(verb_str)
14292 && (self.check_content_word() || self.check_article())
14293 {
14294 let second_np = self.parse_noun_phrase(false)?;
14295 let second_term = Term::Constant(second_np.noun);
14296 second_object_term = Some(second_term);
14297 args.push(second_term);
14298 }
14299 }
14300 } else if self.check_focus() {
14301 let focus_kind = if let TokenType::Focus(k) = self.advance().kind {
14302 k
14303 } else {
14304 FocusKind::Only
14305 };
14306
14307 let event_var = self.get_event_var();
14308 let mut modifiers = self.collect_adverbs();
14309 let effective_time = self.pending_time.take().unwrap_or(verb_time);
14310 match effective_time {
14311 Time::Past => modifiers.push(self.interner.intern("Past")),
14312 Time::Future => modifiers.push(self.interner.intern("Future")),
14313 _ => {}
14314 }
14315
14316 let subject_term_for_event = self.coerce_agent(&subject);
14317
14318 if self.check_preposition() {
14319 let prep_token = self.advance().clone();
14320 let prep_name = if let TokenType::Preposition(sym) = prep_token.kind {
14321 sym
14322 } else {
14323 self.interner.intern("to")
14324 };
14325 let pp_obj = self.parse_noun_phrase(false)?;
14326 let pp_obj_term = Term::Constant(pp_obj.noun);
14327
14328 let roles = vec![(ThematicRole::Agent, subject_term_for_event)];
14329 let suppress_existential = self.drs.in_conditional_antecedent();
14330 if suppress_existential {
14331 let event_class = self.interner.intern("Event");
14332 self.drs.introduce_referent(event_var, event_class, Gender::Neuter, Number::Singular);
14333 }
14334 let neo_event = self.ctx.exprs.alloc(LogicExpr::NeoEvent(Box::new(NeoEventData {
14335 event_var,
14336 verb,
14337 roles: self.ctx.roles.alloc_slice(roles),
14338 modifiers: self.ctx.syms.alloc_slice(modifiers),
14339 suppress_existential,
14340 world: None,
14341 })));
14342
14343 let pp_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
14344 name: prep_name,
14345 args: self.ctx.terms.alloc_slice([Term::Variable(event_var), pp_obj_term]),
14346 world: None,
14347 });
14348
14349 let with_pp = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
14350 left: neo_event,
14351 op: TokenType::And,
14352 right: pp_pred,
14353 });
14354
14355 let focused_ref = self.ctx.terms.alloc(pp_obj_term);
14356 return Ok(self.ctx.exprs.alloc(LogicExpr::Focus {
14357 kind: focus_kind,
14358 focused: focused_ref,
14359 scope: with_pp,
14360 }));
14361 }
14362
14363 let focused_np = self.parse_noun_phrase(false)?;
14364 let focused_term = self.noun_phrase_to_term(&focused_np);
14365 args.push(focused_term.clone());
14366
14367 let roles = vec![
14368 (ThematicRole::Agent, subject_term_for_event),
14369 (ThematicRole::Theme, focused_term.clone()),
14370 ];
14371
14372 let suppress_existential = self.drs.in_conditional_antecedent();
14373 if suppress_existential {
14374 let event_class = self.interner.intern("Event");
14375 self.drs.introduce_referent(event_var, event_class, Gender::Neuter, Number::Singular);
14376 }
14377 let neo_event = self.ctx.exprs.alloc(LogicExpr::NeoEvent(Box::new(NeoEventData {
14378 event_var,
14379 verb,
14380 roles: self.ctx.roles.alloc_slice(roles),
14381 modifiers: self.ctx.syms.alloc_slice(modifiers),
14382 suppress_existential,
14383 world: None,
14384 })));
14385
14386 let focused_ref = self.ctx.terms.alloc(focused_term);
14387 return Ok(self.ctx.exprs.alloc(LogicExpr::Focus {
14388 kind: focus_kind,
14389 focused: focused_ref,
14390 scope: neo_event,
14391 }));
14392 } else if self.check_number() {
14393 let measure = self.parse_measure_phrase()?;
14395
14396 if self.check_content_word() && !self.check_article() {
14400 let noun_sym = self.consume_content_word()?;
14401 let count_term = *measure;
14403 object_term = Some(count_term.clone());
14404 args.push(count_term);
14405 second_object_term = Some(Term::Constant(noun_sym));
14406 args.push(Term::Constant(noun_sym));
14407 } else {
14408 object_term = Some(*measure);
14410 args.push(*measure);
14411 }
14412 } else if self.check_content_word() || self.check_article() {
14413 let object = self.parse_noun_phrase(false)?;
14414 if let Some(adj) = object.superlative {
14415 object_superlative = Some((adj, object.noun));
14416 }
14417
14418 let mut all_objects: Vec<Symbol> = vec![object.noun];
14420
14421 while self.check(&TokenType::And) {
14423 let saved = self.current;
14424 self.advance(); if self.check_content_word() || self.check_article() {
14426 let next_obj = match self.parse_noun_phrase(false) {
14427 Ok(np) => np,
14428 Err(_) => {
14429 self.current = saved;
14430 break;
14431 }
14432 };
14433 all_objects.push(next_obj.noun);
14434 } else {
14435 self.current = saved;
14436 break;
14437 }
14438 }
14439
14440 if self.check(&TokenType::Respectively) {
14442 let respectively_span = self.peek().span;
14443 if all_objects.len() > 1 {
14445 return Err(ParseError {
14446 kind: ParseErrorKind::RespectivelyLengthMismatch {
14447 subject_count: 1,
14448 object_count: all_objects.len(),
14449 },
14450 span: respectively_span,
14451 });
14452 }
14453 self.advance(); }
14456
14457 let term = self.noun_phrase_to_term(&object);
14459 object_term = Some(term.clone());
14460 args.push(term.clone());
14461
14462 if all_objects.len() > 1 {
14464 let obj_members: Vec<Term<'a>> = all_objects.iter()
14465 .map(|o| Term::Constant(*o))
14466 .collect();
14467 let obj_group = Term::Group(self.ctx.terms.alloc_slice(obj_members));
14468 args.pop();
14470 args.push(obj_group);
14471 }
14472
14473 if let TokenType::Particle(particle_sym) = self.peek().kind {
14475 let verb_str = self.interner.resolve(verb).to_lowercase();
14476 let particle_str = self.interner.resolve(particle_sym).to_lowercase();
14477 if let Some((phrasal_lemma, _class)) = crate::lexicon::lookup_phrasal_verb(&verb_str, &particle_str) {
14478 self.advance(); verb = self.interner.intern(phrasal_lemma);
14480 }
14481 }
14482
14483 if self.check_number() {
14485 let measure = self.parse_measure_phrase()?;
14486 second_object_term = Some(*measure);
14487 args.push(*measure);
14488 }
14489 else {
14491 let verb_str = self.interner.resolve(verb);
14492 if Lexer::is_ditransitive_verb(verb_str) && (self.check_content_word() || self.check_article()) {
14493 let second_np = self.parse_noun_phrase(false)?;
14494 let second_term = self.noun_phrase_to_term(&second_np);
14495 second_object_term = Some(second_term.clone());
14496 args.push(second_term);
14497 }
14498 }
14499 }
14500
14501 let mut pp_predicates: Vec<&'a LogicExpr<'a>> = Vec::new();
14502
14503 if matches!(object_term, Some(Term::Value { .. })) {
14508 let rate = self.check_preposition_is("per")
14509 || (matches!(
14510 self.peek().kind,
14511 TokenType::Article(Definiteness::Indefinite)
14512 ) && matches!(
14513 self.tokens.get(self.current + 1).map(|t| &t.kind),
14514 Some(TokenType::CalendarUnit(_)) | Some(TokenType::Noun(_))
14515 ));
14516 if rate {
14517 self.advance(); let unit_lexeme = self.peek().lexeme;
14519 self.advance(); let unit_cap = {
14521 let s = self.interner.resolve(unit_lexeme).to_string();
14522 let mut c = s.chars();
14523 match c.next() {
14524 Some(f) => f.to_uppercase().collect::<String>() + c.as_str(),
14525 None => s,
14526 }
14527 };
14528 let event_sym = self.get_event_var();
14529 pp_predicates.push(self.ctx.exprs.alloc(LogicExpr::Predicate {
14530 name: self.interner.intern("Per"),
14531 args: self.ctx.terms.alloc_slice([
14532 Term::Variable(event_sym),
14533 Term::Constant(self.interner.intern(&unit_cap)),
14534 ]),
14535 world: None,
14536 }));
14537 }
14538 }
14539
14540 while self.check_preposition() || self.check_to() {
14541 if self.check_preposition_is("within") && self.current + 1 < self.tokens.len()
14543 && matches!(self.tokens[self.current + 1].kind, TokenType::Cardinal(_) | TokenType::Number(_))
14544 {
14545 break;
14546 }
14547 let prep_token = self.advance().clone();
14548 let prep_name = if let TokenType::Preposition(sym) = prep_token.kind {
14549 sym
14550 } else if matches!(prep_token.kind, TokenType::To) {
14551 self.interner.intern("To")
14552 } else {
14553 continue;
14554 };
14555
14556 let pp_obj_term = if self.check(&TokenType::Reflexive) {
14557 self.advance();
14558 self.noun_phrase_to_term(&subject)
14559 } else if self.check_pronoun() {
14560 let token = self.advance().clone();
14561 if let TokenType::Pronoun { gender, number, .. } = token.kind {
14562 let resolved = self.resolve_pronoun(gender, number)?;
14563 match resolved {
14564 ResolvedPronoun::Variable(s) => Term::Variable(s),
14565 ResolvedPronoun::Constant(s) => Term::Constant(s),
14566 }
14567 } else {
14568 continue;
14569 }
14570 } else if self.check_content_word() || self.check_article() {
14571 let prep_obj = self.parse_noun_phrase(false)?;
14572 self.noun_phrase_to_term(&prep_obj)
14573 } else if self.check_number() {
14574 *self.parse_measure_phrase()?
14576 } else if self.at_clause_boundary()
14577 && crate::lexicon::is_particle(
14578 &self.interner.resolve(prep_name).to_lowercase(),
14579 )
14580 {
14581 let event_sym = self.get_event_var();
14585 pp_predicates.push(self.ctx.exprs.alloc(LogicExpr::Predicate {
14586 name: prep_name,
14587 args: self.ctx.terms.alloc_slice([Term::Variable(event_sym)]),
14588 world: None,
14589 }));
14590 continue;
14591 } else {
14592 self.current -= 1;
14596 break;
14597 };
14598
14599 if self.pp_attach_to_noun {
14600 if let Some(ref obj) = object_term {
14601 let pp_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
14603 name: prep_name,
14604 args: self.ctx.terms.alloc_slice([obj.clone(), pp_obj_term]),
14605 world: None,
14606 });
14607 pp_predicates.push(pp_pred);
14608 } else {
14609 args.push(pp_obj_term);
14610 }
14611 } else {
14612 let event_sym = self.get_event_var();
14614 let pp_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
14615 name: prep_name,
14616 args: self.ctx.terms.alloc_slice([Term::Variable(event_sym), pp_obj_term]),
14617 world: None,
14618 });
14619 pp_predicates.push(pp_pred);
14620 }
14621
14622 for adv in self.collect_adverbs() {
14626 let event_sym = self.get_event_var();
14627 pp_predicates.push(self.ctx.exprs.alloc(LogicExpr::Predicate {
14628 name: adv,
14629 args: self.ctx.terms.alloc_slice([Term::Variable(event_sym)]),
14630 world: None,
14631 }));
14632 }
14633 }
14634
14635 if self.check(&TokenType::That) || self.check(&TokenType::Who) {
14637 self.advance();
14638 let rel_var = self.next_var_name();
14639 let rel_pred = self.parse_relative_clause(rel_var)?;
14640 pp_predicates.push(rel_pred);
14641 }
14642
14643 {
14654 let subj = self.coerce_agent(&subject);
14655 let off = match self.parse_temporal_offset_constraint(subj)? {
14656 Some(o) => Some(o),
14657 None => self.parse_bare_temporal_constraint(subj)?,
14658 };
14659 if let Some(off) = off {
14660 pp_predicates.push(off);
14661 }
14662 }
14663
14664 let mut modifiers = self.collect_adverbs();
14666
14667 let effective_time = self.pending_time.take().unwrap_or(verb_time);
14669 match effective_time {
14670 Time::Past => modifiers.push(self.interner.intern("Past")),
14671 Time::Future => modifiers.push(self.interner.intern("Future")),
14672 _ => {}
14673 }
14674
14675 if verb_aspect == Aspect::Progressive {
14677 modifiers.push(self.interner.intern("Progressive"));
14678 } else if verb_aspect == Aspect::Perfect {
14679 modifiers.push(self.interner.intern("Perfect"));
14680 }
14681
14682 let mut roles: Vec<(ThematicRole, Term<'a>)> = Vec::new();
14684
14685 let verb_str_for_check = self.interner.resolve(verb).to_lowercase();
14687 let is_unaccusative = crate::lexicon::lookup_verb_db(&verb_str_for_check)
14688 .map(|meta| meta.features.contains(&crate::lexicon::Feature::Unaccusative))
14689 .unwrap_or(false);
14690
14691 let has_object = object_term.is_some() || second_object_term.is_some();
14693 let subject_role = if is_unaccusative && !has_object {
14694 ThematicRole::Theme
14695 } else {
14696 ThematicRole::Agent
14697 };
14698
14699 roles.push((subject_role, subject_term));
14700 if let Some(second_obj) = second_object_term {
14701 if let Some(first_obj) = object_term {
14703 roles.push((ThematicRole::Recipient, first_obj));
14704 }
14705 roles.push((ThematicRole::Theme, second_obj));
14706 } else if let Some(obj) = object_term {
14707 roles.push((ThematicRole::Theme, obj));
14709 }
14710
14711 if let (Some(adj), Some(obj)) = (secondary_adj, object_term) {
14714 let sec_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
14715 name: adj,
14716 args: self.ctx.terms.alloc_slice([obj]),
14717 world: None,
14718 });
14719 let role = secondary_role(&self.interner.resolve(verb).to_lowercase());
14720 roles.push((role, Term::Proposition(sec_pred)));
14721 }
14722
14723 let event_var = self.get_event_var();
14725
14726 self.capture_event_template(verb, &roles, &modifiers);
14728
14729 let suppress_existential = self.drs.in_conditional_antecedent();
14731 if suppress_existential {
14732 let event_class = self.interner.intern("Event");
14733 self.drs.introduce_referent(event_var, event_class, Gender::Neuter, Number::Singular);
14734 }
14735 let neo_event = self.ctx.exprs.alloc(LogicExpr::NeoEvent(Box::new(NeoEventData {
14736 event_var,
14737 verb,
14738 roles: self.ctx.roles.alloc_slice(roles),
14739 modifiers: self.ctx.syms.alloc_slice(modifiers),
14740 suppress_existential,
14741 world: None,
14742 })));
14743
14744 let with_pps = if pp_predicates.is_empty() {
14746 neo_event
14747 } else {
14748 let mut combined = neo_event;
14749 for pp in pp_predicates {
14750 combined = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
14751 left: combined,
14752 op: TokenType::And,
14753 right: pp,
14754 });
14755 }
14756 combined
14757 };
14758
14759 let with_pps = if let Some(obj_term) = object_term {
14763 let placeholder = self.interner.intern("_PP_SELF_");
14764 let mut combined = with_pps;
14765 for &adj in object_adjectives {
14766 let adj_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
14767 name: adj,
14768 args: self.ctx.terms.alloc_slice([obj_term]),
14769 world: None,
14770 });
14771 combined = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
14772 left: combined,
14773 op: TokenType::And,
14774 right: adj_pred,
14775 });
14776 }
14777 for pp in object_desc_pps {
14778 if let LogicExpr::Predicate { name, args, world } = pp {
14779 let new_args: Vec<Term<'a>> = args
14780 .iter()
14781 .map(|a| match a {
14782 Term::Variable(v) if *v == placeholder => obj_term,
14783 other => *other,
14784 })
14785 .collect();
14786 let sub = self.ctx.exprs.alloc(LogicExpr::Predicate {
14787 name: *name,
14788 args: self.ctx.terms.alloc_slice(new_args),
14789 world: *world,
14790 });
14791 combined = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
14792 left: combined,
14793 op: TokenType::And,
14794 right: sub,
14795 });
14796 }
14797 }
14798 combined
14799 } else {
14800 with_pps
14801 };
14802
14803 let with_aspect = if verb_aspect == Aspect::Progressive {
14805 if verb_class == crate::lexicon::VerbClass::Semelfactive {
14807 self.ctx.exprs.alloc(LogicExpr::Aspectual {
14808 operator: AspectOperator::Iterative,
14809 body: with_pps,
14810 })
14811 } else {
14812 self.ctx.exprs.alloc(LogicExpr::Aspectual {
14814 operator: AspectOperator::Progressive,
14815 body: with_pps,
14816 })
14817 }
14818 } else if verb_aspect == Aspect::Perfect {
14819 self.ctx.exprs.alloc(LogicExpr::Aspectual {
14820 operator: AspectOperator::Perfect,
14821 body: with_pps,
14822 })
14823 } else if effective_time == Time::Present && verb_aspect == Aspect::Simple {
14824 if !verb_class.is_stative() {
14826 self.ctx.exprs.alloc(LogicExpr::Aspectual {
14827 operator: AspectOperator::Habitual,
14828 body: with_pps,
14829 })
14830 } else {
14831 with_pps
14833 }
14834 } else {
14835 with_pps
14836 };
14837
14838 let with_adverbs = with_aspect;
14839
14840 let with_temporal = if self.check_temporal_adverb() {
14842 let anchor = if let TokenType::TemporalAdverb(adv) = self.advance().kind.clone() {
14843 adv
14844 } else {
14845 panic!("Expected temporal adverb");
14846 };
14847 self.ctx.exprs.alloc(LogicExpr::TemporalAnchor {
14848 anchor,
14849 body: with_adverbs,
14850 })
14851 } else {
14852 with_adverbs
14853 };
14854
14855 let wrapped = self.wrap_with_definiteness_full(&subject, with_temporal)?;
14856
14857 if let Some((adj, noun)) = object_superlative {
14859 let superlative_expr = self.ctx.exprs.alloc(LogicExpr::Superlative {
14860 adjective: adj,
14861 subject: self.ctx.terms.alloc(Term::Constant(noun)),
14862 domain: noun,
14863 });
14864 return Ok(self.ctx.exprs.alloc(LogicExpr::BinaryOp {
14865 left: wrapped,
14866 op: TokenType::And,
14867 right: superlative_expr,
14868 }));
14869 }
14870
14871 return Ok(wrapped);
14872 }
14873
14874 Ok(self.ctx.exprs.alloc(LogicExpr::Atom(subject.noun)))
14875 }
14876
14877 fn check_preposition(&self) -> bool {
14878 matches!(self.peek().kind, TokenType::Preposition(_))
14879 }
14880
14881 fn check_by_preposition(&self) -> bool {
14882 if let TokenType::Preposition(p) = self.peek().kind {
14883 p.is(self.interner, "by")
14884 } else {
14885 false
14886 }
14887 }
14888
14889 fn check_preposition_is(&self, word: &str) -> bool {
14890 if let TokenType::Preposition(p) = self.peek().kind {
14891 p.is(self.interner, word)
14892 } else {
14893 false
14894 }
14895 }
14896
14897 fn check_word(&self, word: &str) -> bool {
14899 let token = self.peek();
14900 if matches!(token.kind, TokenType::StringLiteral(_) | TokenType::CharLiteral(_)) {
14904 return false;
14905 }
14906 let lexeme = self.interner.resolve(token.lexeme);
14907 lexeme.eq_ignore_ascii_case(word)
14908 }
14909
14910 fn check_op_word(&self, word: &str) -> bool {
14915 self.check_word(word) && !self.user_bound.contains(&self.peek().lexeme)
14916 }
14917
14918 fn peek_word_at(&self, offset: usize, word: &str) -> bool {
14919 if self.current + offset >= self.tokens.len() {
14920 return false;
14921 }
14922 let token = &self.tokens[self.current + offset];
14923 if matches!(token.kind, TokenType::StringLiteral(_) | TokenType::CharLiteral(_)) {
14924 return false;
14925 }
14926 let lexeme = self.interner.resolve(token.lexeme);
14927 lexeme.eq_ignore_ascii_case(word)
14928 }
14929
14930 fn check_to_preposition(&self) -> bool {
14931 match self.peek().kind {
14932 TokenType::To => true,
14933 TokenType::Preposition(p) => p.is(self.interner, "to"),
14934 _ => false,
14935 }
14936 }
14937
14938 fn check_content_word(&self) -> bool {
14939 match &self.peek().kind {
14940 TokenType::Noun(_)
14941 | TokenType::Adjective(_)
14942 | TokenType::NonIntersectiveAdjective(_)
14943 | TokenType::Verb { .. }
14944 | TokenType::ProperName(_)
14945 | TokenType::Article(_)
14946 | TokenType::StringLiteral(_)
14948 | TokenType::May
14951 | TokenType::Number(_)
14954 | TokenType::Performative(_) => true,
14955 TokenType::Item | TokenType::Items if self.mode == ParserMode::Declarative => true,
14961 TokenType::CalendarUnit(_) if self.mode == ParserMode::Declarative => true,
14965 TokenType::Ambiguous { primary, alternatives } => {
14966 Self::is_content_word_type(primary)
14967 || alternatives.iter().any(Self::is_content_word_type)
14968 }
14969 _ => false,
14970 }
14971 }
14972
14973 fn is_content_word_type(t: &TokenType) -> bool {
14974 matches!(
14975 t,
14976 TokenType::Noun(_)
14977 | TokenType::Adjective(_)
14978 | TokenType::NonIntersectiveAdjective(_)
14979 | TokenType::Verb { .. }
14980 | TokenType::ProperName(_)
14981 | TokenType::Article(_)
14982 | TokenType::StringLiteral(_)
14983 | TokenType::Performative(_)
14984 )
14985 }
14986
14987 pub(super) fn try_wrap_bounded_delay(&mut self, expr: &'a LogicExpr<'a>) -> &'a LogicExpr<'a> {
14989 if !self.check_preposition_is("within") {
14990 return expr;
14991 }
14992 let has_number = if self.current + 1 < self.tokens.len() {
14993 matches!(self.tokens[self.current + 1].kind, TokenType::Cardinal(_) | TokenType::Number(_))
14994 } else {
14995 false
14996 };
14997 if !has_number {
14998 return expr;
14999 }
15000 self.advance(); let bound = match self.advance().kind {
15002 TokenType::Cardinal(n) => n,
15003 TokenType::Number(sym) => {
15004 let n_str = self.interner.resolve(sym);
15005 n_str.parse::<u32>().unwrap_or(1)
15006 }
15007 _ => 1,
15008 };
15009 if self.check_content_word() {
15011 let word = self.interner.resolve(self.peek().lexeme).to_lowercase();
15012 if word == "cycle" || word == "cycles" {
15013 self.advance();
15014 }
15015 }
15016 self.ctx.exprs.alloc(LogicExpr::Temporal {
15017 operator: TemporalOperator::BoundedEventually(bound),
15018 body: expr,
15019 })
15020 }
15021
15022 pub(super) fn pp_is_cycle_temporal(&self) -> bool {
15028 let prep = match &self.peek().kind {
15029 TokenType::Preposition(s) => self.interner.resolve(*s).to_lowercase(),
15030 _ => return false,
15031 };
15032 if !matches!(prep.as_str(), "in" | "within" | "after") {
15033 return false;
15034 }
15035 let mut i = self.current + 1;
15036 let end = (self.current + 5).min(self.tokens.len());
15037 while i < end {
15038 match &self.tokens[i].kind {
15039 TokenType::Period | TokenType::Comma | TokenType::EOF => return false,
15040 _ => {
15041 let w = self.interner.resolve(self.tokens[i].lexeme).to_lowercase();
15042 if matches!(w.as_str(), "cycle" | "cycles" | "tick" | "ticks") {
15043 return true;
15044 }
15045 }
15046 }
15047 i += 1;
15048 }
15049 false
15050 }
15051
15052 pub(super) fn try_wrap_next_cycle(&mut self, expr: &'a LogicExpr<'a>) -> &'a LogicExpr<'a> {
15055 let bare_next_cycle = self.interner.resolve(self.peek().lexeme).eq_ignore_ascii_case("next")
15057 && self
15058 .tokens
15059 .get(self.current + 1)
15060 .map(|t| self.interner.resolve(t.lexeme).eq_ignore_ascii_case("cycle"))
15061 .unwrap_or(false);
15062 if bare_next_cycle {
15063 self.advance(); self.advance(); return self.ctx.exprs.alloc(LogicExpr::Temporal {
15066 operator: TemporalOperator::Next,
15067 body: expr,
15068 });
15069 }
15070 if !self.check_preposition_is("in") {
15071 return expr;
15072 }
15073 let mut i = self.current + 1;
15075 if matches!(self.tokens.get(i).map(|t| &t.kind), Some(TokenType::Article(_))) {
15076 i += 1;
15077 }
15078 let next_matches = self
15079 .tokens
15080 .get(i)
15081 .map(|t| self.interner.resolve(t.lexeme).eq_ignore_ascii_case("next"))
15082 .unwrap_or(false);
15083 let cycle_matches = self
15084 .tokens
15085 .get(i + 1)
15086 .map(|t| self.interner.resolve(t.lexeme).eq_ignore_ascii_case("cycle"))
15087 .unwrap_or(false);
15088 if !next_matches || !cycle_matches {
15089 return expr;
15090 }
15091 while self.current <= i + 1 {
15092 self.advance();
15093 }
15094 self.ctx.exprs.alloc(LogicExpr::Temporal {
15095 operator: TemporalOperator::Next,
15096 body: expr,
15097 })
15098 }
15099
15100 fn check_verb(&self) -> bool {
15101 self.kind_is_verb(&self.peek().kind)
15102 }
15103
15104 fn kind_is_verb(&self, kind: &TokenType) -> bool {
15109 match kind {
15110 TokenType::Verb { .. } => true,
15111 TokenType::Ambiguous { primary, alternatives } => {
15112 if self.noun_priority_mode {
15113 return false;
15114 }
15115 matches!(**primary, TokenType::Verb { .. })
15116 || alternatives.iter().any(|t| matches!(t, TokenType::Verb { .. }))
15117 }
15118 _ => false,
15119 }
15120 }
15121
15122 fn check_adverb(&self) -> bool {
15123 matches!(self.peek().kind, TokenType::Adverb(_))
15124 }
15125
15126 fn check_performative(&self) -> bool {
15127 matches!(self.peek().kind, TokenType::Performative(_))
15128 }
15129
15130 fn try_performative_object(&mut self) -> Option<Term<'a>> {
15135 match self.peek().kind {
15136 TokenType::Pronoun { .. } => {
15137 let text = self.interner.resolve(self.peek().lexeme).to_lowercase();
15138 let sym = match text.as_str() {
15139 "you" => self.interner.intern("Addressee"),
15140 "me" | "myself" => self.interner.intern("Speaker"),
15141 other => {
15142 let cap = other
15143 .chars()
15144 .next()
15145 .map(|c| c.to_uppercase().collect::<String>() + &other[1..])
15146 .unwrap_or_default();
15147 self.interner.intern(&cap)
15148 }
15149 };
15150 self.advance();
15151 Some(Term::Constant(sym))
15152 }
15153 TokenType::ProperName(s) => {
15154 self.advance();
15155 Some(Term::Constant(s))
15156 }
15157 _ => None,
15158 }
15159 }
15160
15161 fn performative_predicate(&mut self, verb: Symbol, subject: Symbol) -> &'a LogicExpr<'a> {
15166 if let Some(obj) = self.try_performative_object() {
15167 self.ctx.exprs.alloc(LogicExpr::Predicate {
15168 name: verb,
15169 args: self.ctx.terms.alloc_slice([Term::Constant(subject), obj]),
15170 world: None,
15171 })
15172 } else {
15173 self.ctx.exprs.alloc(LogicExpr::Predicate {
15174 name: verb,
15175 args: self.ctx.terms.alloc_slice([Term::Constant(subject)]),
15176 world: None,
15177 })
15178 }
15179 }
15180
15181 fn collect_adverbs(&mut self) -> Vec<Symbol> {
15182 let mut adverbs = Vec::new();
15183 loop {
15184 if self.check_adverb() {
15185 if let TokenType::Adverb(adv) = self.advance().kind.clone() {
15186 adverbs.push(adv);
15187 }
15188 if self.check(&TokenType::And) {
15190 self.advance();
15191 }
15192 continue;
15193 }
15194 if let TokenType::Particle(p) = self.peek().kind {
15199 if matches!(
15200 self.tokens.get(self.current + 1).map(|t| &t.kind),
15201 Some(TokenType::Period) | Some(TokenType::EOF) | None
15202 ) {
15203 self.advance();
15204 let raw = self.interner.resolve(p).to_string();
15205 let mut capitalized = raw;
15206 if let Some(first) = capitalized.get_mut(0..1) {
15207 first.make_ascii_uppercase();
15208 }
15209 adverbs.push(self.interner.intern(&capitalized));
15210 continue;
15211 }
15212 }
15213 break;
15214 }
15215 adverbs
15216 }
15217
15218 fn check_auxiliary(&self) -> bool {
15219 matches!(self.peek().kind, TokenType::Auxiliary(_))
15220 }
15221
15222 fn is_true_auxiliary_usage(&self) -> bool {
15229 if self.current + 1 >= self.tokens.len() {
15230 return false;
15231 }
15232
15233 let next_token = &self.tokens[self.current + 1].kind;
15234
15235 if matches!(next_token, TokenType::Not) {
15237 return true;
15238 }
15239
15240 if matches!(next_token, TokenType::Verb { .. }) {
15242 return true;
15243 }
15244
15245 if matches!(
15247 next_token,
15248 TokenType::Pronoun { .. }
15249 | TokenType::Article(_)
15250 | TokenType::Noun(_)
15251 | TokenType::ProperName(_)
15252 ) {
15253 return false;
15254 }
15255
15256 true
15258 }
15259
15260 fn check_auxiliary_as_main_verb(&self) -> bool {
15263 if let TokenType::Auxiliary(Time::Past) = self.peek().kind {
15264 if self.current + 1 < self.tokens.len() {
15266 let next = &self.tokens[self.current + 1].kind;
15267 matches!(
15268 next,
15269 TokenType::Pronoun { .. }
15270 | TokenType::Article(_)
15271 | TokenType::Noun(_)
15272 | TokenType::ProperName(_)
15273 | TokenType::Number(_)
15276 )
15277 } else {
15278 false
15279 }
15280 } else {
15281 false
15282 }
15283 }
15284
15285 fn parse_do_as_main_verb(&mut self, subject_term: Term<'a>) -> ParseResult<&'a LogicExpr<'a>> {
15288 let aux_token = self.advance();
15290 let verb_time = if let TokenType::Auxiliary(time) = aux_token.kind {
15291 time
15292 } else {
15293 Time::Past
15294 };
15295
15296 let verb = self.interner.intern("Do");
15298
15299 let mut object_cardinal: Option<(u32, crate::intern::Symbol, &'a LogicExpr<'a>)> = None;
15300
15301 let object_term = if let TokenType::Pronoun { .. } = self.peek().kind {
15303 self.advance();
15305 let it_sym = self.interner.intern("it");
15308 Term::Constant(it_sym)
15309 } else if let Some(n) = self.counting_np_lookahead() {
15310 self.advance(); let obj_var = self.next_var_name();
15314 self.nominal_np_context = true;
15315 let obj_np_result = self.parse_noun_phrase(false);
15316 self.nominal_np_context = false;
15317 let obj_np = obj_np_result?;
15318 let mut restr: &'a LogicExpr<'a> = self.ctx.exprs.alloc(LogicExpr::Predicate {
15319 name: obj_np.noun,
15320 args: self.ctx.terms.alloc_slice([Term::Variable(obj_var)]),
15321 world: None,
15322 });
15323 for &adj in obj_np.adjectives {
15324 let adj_pred = self.adjective_restriction(adj, obj_var, obj_np.noun);
15325 restr = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
15326 left: restr,
15327 op: TokenType::And,
15328 right: adj_pred,
15329 });
15330 }
15331 for pp in obj_np.pps {
15332 let pp_sub = self.substitute_pp_placeholder(pp, obj_var);
15333 restr = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
15334 left: restr,
15335 op: TokenType::And,
15336 right: pp_sub,
15337 });
15338 }
15339 object_cardinal = Some((n, obj_var, restr));
15340 Term::Variable(obj_var)
15341 } else if self.check_number() {
15342 *self.parse_measure_phrase()?
15345 } else {
15346 let object = self.parse_noun_phrase(false)?;
15347 self.noun_phrase_to_term(&object)
15348 };
15349
15350 let event_var = self.get_event_var();
15352 let suppress_existential = self.drs.in_conditional_antecedent();
15353
15354 let mut modifiers = Vec::new();
15355 if verb_time == Time::Past {
15356 modifiers.push(self.interner.intern("Past"));
15357 } else if verb_time == Time::Future {
15358 modifiers.push(self.interner.intern("Future"));
15359 }
15360
15361 let neo_event = self.ctx.exprs.alloc(LogicExpr::NeoEvent(Box::new(NeoEventData {
15362 event_var,
15363 verb,
15364 roles: self.ctx.roles.alloc_slice(vec![
15365 (ThematicRole::Agent, subject_term),
15366 (ThematicRole::Theme, object_term),
15367 ]),
15368 modifiers: self.ctx.syms.alloc_slice(modifiers),
15369 suppress_existential,
15370 world: None,
15371 })));
15372
15373 if let Some((n, obj_var, restr)) = object_cardinal {
15376 let body = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
15377 left: restr,
15378 op: TokenType::And,
15379 right: neo_event,
15380 });
15381 return Ok(self.ctx.exprs.alloc(LogicExpr::Quantifier {
15382 kind: QuantifierKind::Cardinal(n),
15383 variable: obj_var,
15384 body,
15385 island_id: self.current_island,
15386 }));
15387 }
15388
15389 Ok(neo_event)
15390 }
15391
15392 fn check_to(&self) -> bool {
15393 matches!(self.peek().kind, TokenType::To)
15394 }
15395
15396 pub(super) fn check_to_marker(&self) -> bool {
15400 self.check_to() || self.check_preposition_is("to")
15401 }
15402
15403 fn has_modal_subordination_ahead(&self) -> bool {
15407 for i in self.current..self.tokens.len() {
15410 match &self.tokens[i].kind {
15411 TokenType::Would | TokenType::Could | TokenType::Should | TokenType::Might => {
15412 return true;
15413 }
15414 TokenType::Period | TokenType::EOF => break,
15416 _ => {}
15417 }
15418 }
15419 false
15420 }
15421
15422 fn consume_verb(&mut self) -> Symbol {
15423 let t = self.advance().clone();
15424 match t.kind {
15425 TokenType::Verb { lemma, .. } => lemma,
15426 TokenType::Ambiguous { primary, .. } => match *primary {
15427 TokenType::Verb { lemma, .. } => lemma,
15428 _ => panic!("Expected verb in Ambiguous primary, got {:?}", primary),
15429 },
15430 _ => panic!("Expected verb, got {:?}", t.kind),
15431 }
15432 }
15433
15434 fn consume_verb_with_metadata(&mut self) -> (Symbol, Time, Aspect, VerbClass) {
15435 let t = self.advance().clone();
15436 match t.kind {
15437 TokenType::Verb { lemma, time, aspect, class } => (lemma, time, aspect, class),
15438 TokenType::Ambiguous { primary, .. } => match *primary {
15439 TokenType::Verb { lemma, time, aspect, class } => (lemma, time, aspect, class),
15440 _ => panic!("Expected verb in Ambiguous primary, got {:?}", primary),
15441 },
15442 _ => panic!("Expected verb, got {:?}", t.kind),
15443 }
15444 }
15445
15446 fn match_token(&mut self, types: &[TokenType]) -> bool {
15447 for t in types {
15448 if self.check(t) {
15449 self.advance();
15450 return true;
15451 }
15452 }
15453 false
15454 }
15455
15456 fn check_quantifier(&self) -> bool {
15457 matches!(
15458 self.peek().kind,
15459 TokenType::All
15460 | TokenType::No
15461 | TokenType::Some
15462 | TokenType::Any
15463 | TokenType::Most
15464 | TokenType::Few
15465 | TokenType::Many
15466 | TokenType::Cardinal(_)
15467 | TokenType::AtLeast(_)
15468 | TokenType::AtMost(_)
15469 )
15470 }
15471
15472 fn check_npi_quantifier(&self) -> bool {
15473 matches!(
15474 self.peek().kind,
15475 TokenType::Nobody | TokenType::Nothing | TokenType::NoOne
15476 )
15477 }
15478
15479 fn check_npi_object(&self) -> bool {
15480 matches!(
15481 self.peek().kind,
15482 TokenType::Anything | TokenType::Anyone
15483 )
15484 }
15485
15486 fn check_temporal_npi(&self) -> bool {
15487 matches!(
15488 self.peek().kind,
15489 TokenType::Ever | TokenType::Never
15490 )
15491 }
15492
15493 fn parse_npi_quantified(&mut self) -> ParseResult<&'a LogicExpr<'a>> {
15494 let npi_token = self.advance().kind.clone();
15495 let var_name = self.next_var_name();
15496
15497 let (restriction_name, is_person) = match npi_token {
15498 TokenType::Nobody | TokenType::NoOne => ("Person", true),
15499 TokenType::Nothing => ("Thing", false),
15500 _ => ("Thing", false),
15501 };
15502
15503 let restriction_sym = self.interner.intern(restriction_name);
15504 let subject_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
15505 name: restriction_sym,
15506 args: self.ctx.terms.alloc_slice([Term::Variable(var_name)]),
15507 world: None,
15508 });
15509
15510 self.negative_depth += 1;
15511
15512 let verb = self.consume_verb();
15513
15514 if self.check_npi_object() {
15515 let obj_npi_token = self.advance().kind.clone();
15516 let obj_var = self.next_var_name();
15517
15518 let obj_restriction_name = match obj_npi_token {
15519 TokenType::Anything => "Thing",
15520 TokenType::Anyone => "Person",
15521 _ => "Thing",
15522 };
15523
15524 let obj_restriction_sym = self.interner.intern(obj_restriction_name);
15525 let obj_restriction = self.ctx.exprs.alloc(LogicExpr::Predicate {
15526 name: obj_restriction_sym,
15527 args: self.ctx.terms.alloc_slice([Term::Variable(obj_var)]),
15528 world: None,
15529 });
15530
15531 let verb_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
15532 name: verb,
15533 args: self.ctx.terms.alloc_slice([Term::Variable(var_name), Term::Variable(obj_var)]),
15534 world: None,
15535 });
15536
15537 let verb_and_obj = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
15538 left: obj_restriction,
15539 op: TokenType::And,
15540 right: verb_pred,
15541 });
15542
15543 let inner_existential = self.ctx.exprs.alloc(LogicExpr::Quantifier {
15544 kind: crate::ast::QuantifierKind::Existential,
15545 variable: obj_var,
15546 body: verb_and_obj,
15547 island_id: self.current_island,
15548 });
15549
15550 self.negative_depth -= 1;
15551
15552 let negated = self.ctx.exprs.alloc(LogicExpr::UnaryOp {
15553 op: TokenType::Not,
15554 operand: inner_existential,
15555 });
15556
15557 let body = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
15558 left: subject_pred,
15559 op: TokenType::Implies,
15560 right: negated,
15561 });
15562
15563 return Ok(self.ctx.exprs.alloc(LogicExpr::Quantifier {
15564 kind: crate::ast::QuantifierKind::Universal,
15565 variable: var_name,
15566 body,
15567 island_id: self.current_island,
15568 }));
15569 }
15570
15571 let verb_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
15572 name: verb,
15573 args: self.ctx.terms.alloc_slice([Term::Variable(var_name)]),
15574 world: None,
15575 });
15576
15577 self.negative_depth -= 1;
15578
15579 let negated_verb = self.ctx.exprs.alloc(LogicExpr::UnaryOp {
15580 op: TokenType::Not,
15581 operand: verb_pred,
15582 });
15583
15584 let body = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
15585 left: subject_pred,
15586 op: TokenType::Implies,
15587 right: negated_verb,
15588 });
15589
15590 Ok(self.ctx.exprs.alloc(LogicExpr::Quantifier {
15591 kind: crate::ast::QuantifierKind::Universal,
15592 variable: var_name,
15593 body,
15594 island_id: self.current_island,
15595 }))
15596 }
15597
15598 fn parse_temporal_npi(&mut self) -> ParseResult<&'a LogicExpr<'a>> {
15599 let npi_token = self.advance().kind.clone();
15600 let is_never = matches!(npi_token, TokenType::Never);
15601
15602 let subject = self.parse_noun_phrase(true)?;
15603
15604 if is_never {
15605 self.negative_depth += 1;
15606 }
15607
15608 let verb = self.consume_verb();
15609 let verb_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
15610 name: verb,
15611 args: self.ctx.terms.alloc_slice([Term::Constant(subject.noun)]),
15612 world: None,
15613 });
15614
15615 if is_never {
15616 self.negative_depth -= 1;
15617 Ok(self.ctx.exprs.alloc(LogicExpr::UnaryOp {
15618 op: TokenType::Not,
15619 operand: verb_pred,
15620 }))
15621 } else {
15622 Ok(verb_pred)
15623 }
15624 }
15625
15626 fn check(&self, kind: &TokenType) -> bool {
15627 if self.is_at_end() {
15628 return false;
15629 }
15630 std::mem::discriminant(&self.peek().kind) == std::mem::discriminant(kind)
15631 }
15632
15633 fn check_any(&self, kinds: &[TokenType]) -> bool {
15634 if self.is_at_end() {
15635 return false;
15636 }
15637 let current = std::mem::discriminant(&self.peek().kind);
15638 kinds.iter().any(|k| std::mem::discriminant(k) == current)
15639 }
15640
15641 fn check_article(&self) -> bool {
15642 matches!(self.peek().kind, TokenType::Article(_))
15643 }
15644
15645 fn advance(&mut self) -> &Token {
15646 if !self.is_at_end() {
15647 self.current += 1;
15648 }
15649 self.previous()
15650 }
15651
15652 fn is_at_end(&self) -> bool {
15653 self.peek().kind == TokenType::EOF
15654 }
15655
15656 fn peek(&self) -> &Token {
15657 self.tokens
15660 .get(self.current)
15661 .unwrap_or_else(|| self.tokens.last().expect("stream ends with EOF"))
15662 }
15663
15664 fn peek_next_is_string_literal(&self) -> bool {
15667 self.tokens.get(self.current + 1)
15668 .map(|t| matches!(t.kind, TokenType::StringLiteral(_)))
15669 .unwrap_or(false)
15670 }
15671
15672 fn previous(&self) -> &Token {
15673 &self.tokens[self.current - 1]
15674 }
15675
15676 fn current_span(&self) -> crate::token::Span {
15677 self.peek().span
15678 }
15679
15680 fn consume(&mut self, kind: TokenType) -> ParseResult<&Token> {
15681 if self.check(&kind) {
15682 Ok(self.advance())
15683 } else {
15684 Err(ParseError {
15685 kind: ParseErrorKind::UnexpectedToken {
15686 expected: kind,
15687 found: self.peek().kind.clone(),
15688 },
15689 span: self.current_span(),
15690 })
15691 }
15692 }
15693
15694 pub(super) fn absorb_multiword_proper_name(&mut self, first: Symbol) -> Symbol {
15701 let mut full = self.interner.resolve(first).to_string();
15702 loop {
15703 let next = self.peek();
15704 let is_content = matches!(
15705 next.kind,
15706 TokenType::ProperName(_)
15707 | TokenType::Noun(_)
15708 | TokenType::Adjective(_)
15709 | TokenType::Verb { .. }
15710 | TokenType::Ambiguous { .. }
15711 );
15712 let capitalized = self
15713 .interner
15714 .resolve(next.lexeme)
15715 .chars()
15716 .next()
15717 .map_or(false, |c| c.is_ascii_uppercase());
15718 if is_content && capitalized {
15719 full.push('_');
15720 full.push_str(&self.interner.resolve(self.peek().lexeme));
15721 self.advance();
15722 } else {
15723 break;
15724 }
15725 }
15726 self.interner.intern(&full)
15727 }
15728
15729 fn consume_content_word(&mut self) -> ParseResult<Symbol> {
15730 let t = self.advance().clone();
15731 match t.kind {
15732 TokenType::Noun(s) | TokenType::Adjective(s) | TokenType::NonIntersectiveAdjective(s) => Ok(s),
15733 TokenType::Item | TokenType::Items if self.mode == ParserMode::Declarative => {
15736 let lex = self.interner.resolve(t.lexeme);
15737 let mut chars = lex.chars();
15738 let cap = match chars.next() {
15739 Some(f) => f.to_uppercase().collect::<String>() + chars.as_str(),
15740 None => String::new(),
15741 };
15742 Ok(self.interner.intern(&cap))
15743 }
15744 TokenType::StringLiteral(s) => {
15746 let s_str = self.interner.resolve(s);
15747 let gender = Self::infer_gender(s_str);
15748 self.drs.introduce_proper_name(s, s, gender);
15749 Ok(s)
15750 }
15751 TokenType::Article(_) => Ok(t.lexeme),
15753 TokenType::May => Ok(self.interner.intern("May")),
15755 TokenType::Number(s) => Ok(s),
15757 TokenType::CalendarUnit(u) => {
15763 let lemma = match u {
15764 crate::token::CalendarUnit::Second => "Second",
15765 crate::token::CalendarUnit::Minute => "Minute",
15766 crate::token::CalendarUnit::Hour => "Hour",
15767 crate::token::CalendarUnit::Day => "Day",
15768 crate::token::CalendarUnit::Week => "Week",
15769 crate::token::CalendarUnit::Month => "Month",
15770 crate::token::CalendarUnit::Year => "Year",
15771 };
15772 Ok(self.interner.intern(lemma))
15773 }
15774 TokenType::ProperName(s) => {
15775 if self.mode == ParserMode::Imperative {
15777 if !self.drs.has_referent_by_variable(s) {
15778 return Err(ParseError {
15779 kind: ParseErrorKind::UndefinedVariable {
15780 name: self.interner.resolve(s).to_string()
15781 },
15782 span: t.span,
15783 });
15784 }
15785 return Ok(s);
15786 }
15787
15788 let s_str = self.interner.resolve(s);
15790 let gender = Self::infer_gender(s_str);
15791
15792 self.drs.introduce_proper_name(s, s, gender);
15794
15795 Ok(s)
15796 }
15797 TokenType::Verb { lemma, .. } => Ok(lemma),
15798 TokenType::Performative(s) => Ok(s),
15799 TokenType::Ambiguous { primary, .. } => {
15800 match *primary {
15801 TokenType::Noun(s) | TokenType::Adjective(s) | TokenType::NonIntersectiveAdjective(s) => Ok(s),
15802 TokenType::Verb { lemma, .. } => Ok(lemma),
15803 TokenType::Performative(s) => Ok(s),
15804 TokenType::ProperName(s) => {
15805 if self.mode == ParserMode::Imperative {
15807 if !self.drs.has_referent_by_variable(s) {
15808 return Err(ParseError {
15809 kind: ParseErrorKind::UndefinedVariable {
15810 name: self.interner.resolve(s).to_string()
15811 },
15812 span: t.span,
15813 });
15814 }
15815 return Ok(s);
15816 }
15817 let s_str = self.interner.resolve(s);
15819 let gender = Self::infer_gender(s_str);
15820 self.drs.introduce_proper_name(s, s, gender);
15821 Ok(s)
15822 }
15823 _ => Err(ParseError {
15824 kind: ParseErrorKind::ExpectedContentWord { found: *primary },
15825 span: self.current_span(),
15826 }),
15827 }
15828 }
15829 other => Err(ParseError {
15830 kind: ParseErrorKind::ExpectedContentWord { found: other },
15831 span: self.current_span(),
15832 }),
15833 }
15834 }
15835
15836 fn consume_copula(&mut self) -> ParseResult<()> {
15837 if self.match_token(&[TokenType::Is, TokenType::Are, TokenType::Was, TokenType::Were]) {
15838 Ok(())
15839 } else {
15840 Err(ParseError {
15841 kind: ParseErrorKind::ExpectedCopula,
15842 span: self.current_span(),
15843 })
15844 }
15845 }
15846
15847 fn check_comparative(&self) -> bool {
15848 matches!(self.peek().kind, TokenType::Comparative(_))
15849 }
15850
15851 fn is_contact_clause_pattern(&self) -> bool {
15852 let mut pos = self.current;
15855
15856 if pos < self.tokens.len() && matches!(self.tokens[pos].kind, TokenType::Article(_)) {
15858 pos += 1;
15859 } else {
15860 return false;
15861 }
15862
15863 while pos < self.tokens.len() && matches!(self.tokens[pos].kind, TokenType::Adjective(_)) {
15865 pos += 1;
15866 }
15867
15868 if pos < self.tokens.len() && matches!(self.tokens[pos].kind, TokenType::Noun(_) | TokenType::ProperName(_) | TokenType::Adjective(_)) {
15870 pos += 1;
15871 } else {
15872 return false;
15873 }
15874
15875 pos < self.tokens.len() && matches!(self.tokens[pos].kind, TokenType::Verb { .. } | TokenType::Article(_))
15877 }
15878
15879 fn check_superlative(&self) -> bool {
15880 matches!(self.peek().kind, TokenType::Superlative(_))
15881 }
15882
15883 fn check_scopal_adverb(&self) -> bool {
15884 matches!(self.peek().kind, TokenType::ScopalAdverb(_))
15885 }
15886
15887 fn check_temporal_adverb(&self) -> bool {
15888 matches!(self.peek().kind, TokenType::TemporalAdverb(_))
15889 }
15890
15891 fn check_non_intersective_adjective(&self) -> bool {
15892 matches!(self.peek().kind, TokenType::NonIntersectiveAdjective(_))
15893 }
15894
15895 fn check_focus(&self) -> bool {
15896 matches!(self.peek().kind, TokenType::Focus(_))
15897 }
15898
15899 fn check_measure(&self) -> bool {
15900 matches!(self.peek().kind, TokenType::Measure(_))
15901 }
15902
15903 fn check_presup_trigger(&self) -> bool {
15904 match &self.peek().kind {
15905 TokenType::PresupTrigger(_) => true,
15906 TokenType::Verb { lemma, .. } => {
15907 let s = self.interner.resolve(*lemma).to_lowercase();
15908 crate::lexicon::lookup_presup_trigger(&s).is_some()
15909 }
15910 TokenType::Ambiguous { primary, .. } => match primary.as_ref() {
15911 TokenType::Verb { lemma, .. } => {
15912 let s = self.interner.resolve(*lemma).to_lowercase();
15913 crate::lexicon::lookup_presup_trigger(&s).is_some()
15914 }
15915 _ => false,
15916 },
15917 _ => false,
15918 }
15919 }
15920
15921 fn consume_presup_trigger(&mut self) -> crate::token::PresupKind {
15922 let lemma = match self.advance().kind.clone() {
15923 TokenType::PresupTrigger(kind) => return kind,
15924 TokenType::Verb { lemma, .. } => lemma,
15925 TokenType::Ambiguous { primary, .. } => match *primary {
15926 TokenType::Verb { lemma, .. } => lemma,
15927 other => unreachable!("guarded by check_presup_trigger, got {other:?}"),
15928 },
15929 other => unreachable!("guarded by check_presup_trigger, got {other:?}"),
15930 };
15931 let s = self.interner.resolve(lemma).to_lowercase();
15932 crate::lexicon::lookup_presup_trigger(&s)
15933 .expect("Lexicon mismatch: Verb flagged as trigger but lookup failed")
15934 }
15935
15936 fn is_followed_by_np_object(&self) -> bool {
15937 if self.current + 1 >= self.tokens.len() {
15938 return false;
15939 }
15940 let next = &self.tokens[self.current + 1].kind;
15941 matches!(next,
15942 TokenType::ProperName(_) |
15943 TokenType::Article(_) |
15944 TokenType::Noun(_) |
15945 TokenType::Pronoun { .. } |
15946 TokenType::Reflexive |
15947 TokenType::Who |
15948 TokenType::What |
15949 TokenType::Where |
15950 TokenType::When |
15951 TokenType::Why
15952 )
15953 }
15954
15955 fn is_followed_by_gerund(&self) -> bool {
15956 if self.current + 1 >= self.tokens.len() {
15957 return false;
15958 }
15959 matches!(self.tokens[self.current + 1].kind, TokenType::Verb { .. })
15960 }
15961
15962 fn parse_spawn_statement(&mut self) -> ParseResult<Stmt<'a>> {
15968 self.advance(); if !self.check_article() {
15972 return Err(ParseError {
15973 kind: ParseErrorKind::ExpectedKeyword { keyword: "a/an".to_string() },
15974 span: self.current_span(),
15975 });
15976 }
15977 self.advance(); let agent_type = match &self.tokens[self.current].kind {
15981 TokenType::Noun(sym) | TokenType::ProperName(sym) => {
15982 let s = *sym;
15983 self.advance();
15984 s
15985 }
15986 _ => {
15987 return Err(ParseError {
15988 kind: ParseErrorKind::ExpectedKeyword { keyword: "agent type".to_string() },
15989 span: self.current_span(),
15990 });
15991 }
15992 };
15993
15994 if !self.check(&TokenType::Called) {
15996 return Err(ParseError {
15997 kind: ParseErrorKind::ExpectedKeyword { keyword: "called".to_string() },
15998 span: self.current_span(),
15999 });
16000 }
16001 self.advance(); let name = if let TokenType::StringLiteral(sym) = &self.tokens[self.current].kind {
16005 let s = *sym;
16006 self.advance();
16007 s
16008 } else {
16009 return Err(ParseError {
16010 kind: ParseErrorKind::ExpectedKeyword { keyword: "agent name".to_string() },
16011 span: self.current_span(),
16012 });
16013 };
16014
16015 Ok(Stmt::Spawn { agent_type, name })
16016 }
16017
16018 fn parse_send_statement(&mut self) -> ParseResult<Stmt<'a>> {
16020 self.advance(); let mut cached = false;
16025 let mut unchecked = false;
16026 let mut compression = None;
16027 let mut layout = None;
16028 let mut shared = false;
16029 let mut computed = false;
16030 let mut indexed = false;
16031 let mut deduped = false;
16032 loop {
16033 if !cached && self.check_word("cached") {
16034 self.advance();
16035 cached = true;
16036 } else if !shared && (self.check_word("shared") || self.check_word("known")) {
16037 self.advance();
16038 shared = true;
16039 } else if !indexed && (self.check_word("indexed") || self.check_word("addressable")) {
16040 self.advance();
16041 indexed = true;
16042 } else if !deduped && (self.check_word("deduped") || self.check_word("shared_refs")) {
16043 self.advance();
16044 deduped = true;
16045 } else if !computed && self.check_word("computed") {
16046 self.advance();
16047 computed = true;
16048 } else if !unchecked && self.check_word("unchecked") {
16049 self.advance();
16050 unchecked = true;
16051 } else if layout.is_none()
16052 && (self.check_word("fast") || self.check_word("quickly"))
16053 {
16054 self.advance();
16055 layout = Some(SendLayout::Fast);
16056 } else if layout.is_none()
16057 && (self.check_word("compact") || self.check_word("small"))
16058 {
16059 self.advance();
16060 layout = Some(SendLayout::Compact);
16061 } else if layout.is_none() && self.check_word("packed") {
16062 self.advance();
16063 layout = Some(SendLayout::Packed);
16064 } else if layout.is_none()
16065 && (self.check_word("smallest") || self.check_word("best"))
16066 {
16067 self.advance();
16068 layout = Some(SendLayout::Smallest);
16069 } else if layout.is_none()
16070 && (self.check_word("redundant") || self.check_word("tough"))
16071 {
16072 self.advance();
16073 layout = Some(SendLayout::Redundant);
16074 } else if compression.is_none() && self.check_word("compressed") {
16075 self.advance();
16076 let codec = if self.check_word("with") {
16077 self.advance();
16078 let name = self.interner.resolve(self.peek().lexeme).to_ascii_lowercase();
16079 let c = match name.as_str() {
16080 "deflate" => CompressionCodec::Deflate,
16081 "lz4" => CompressionCodec::Lz4,
16082 "zstd" => CompressionCodec::Zstd,
16083 _ => {
16084 return Err(ParseError {
16085 kind: ParseErrorKind::ExpectedKeyword {
16086 keyword: "a codec (deflate, lz4, or zstd)".to_string(),
16087 },
16088 span: self.current_span(),
16089 })
16090 }
16091 };
16092 self.advance(); c
16094 } else {
16095 CompressionCodec::Deflate
16096 };
16097 compression = Some(codec);
16098 } else {
16099 break;
16100 }
16101 }
16102
16103 let message = self.parse_imperative_expr()?;
16105
16106 if !self.check_preposition_is("to") {
16108 return Err(ParseError {
16109 kind: ParseErrorKind::ExpectedKeyword { keyword: "to".to_string() },
16110 span: self.current_span(),
16111 });
16112 }
16113 self.advance(); let destination = self.parse_imperative_expr()?;
16117
16118 Ok(Stmt::SendMessage {
16119 message,
16120 destination,
16121 compression,
16122 cached,
16123 unchecked,
16124 layout,
16125 shared,
16126 computed,
16127 indexed,
16128 deduped,
16129 })
16130 }
16131
16132 fn parse_await_statement(&mut self) -> ParseResult<Stmt<'a>> {
16134 self.advance(); let mut view = false;
16139 let mut stream = false;
16140 if self.check_word("view") || self.check_word("viewed") {
16141 view = true;
16142 self.advance();
16143 }
16144 if self.check_word("stream") {
16145 stream = true;
16146 self.advance();
16147 }
16148
16149 if self.check_word("response") {
16151 self.advance();
16152 }
16153
16154 if !self.check(&TokenType::From) && !self.check_preposition_is("from") {
16156 return Err(ParseError {
16157 kind: ParseErrorKind::ExpectedKeyword { keyword: "from".to_string() },
16158 span: self.current_span(),
16159 });
16160 }
16161 self.advance(); let source = self.parse_imperative_expr()?;
16165
16166 if !self.check_word("into") {
16168 return Err(ParseError {
16169 kind: ParseErrorKind::ExpectedKeyword { keyword: "into".to_string() },
16170 span: self.current_span(),
16171 });
16172 }
16173 self.advance(); let into = self.expect_identifier()?;
16180
16181 Ok(Stmt::AwaitMessage { source, into, view, stream })
16182 }
16183
16184 fn parse_stream_statement(&mut self) -> ParseResult<Stmt<'a>> {
16190 self.advance(); let values = self.parse_imperative_expr()?;
16192 if self.check(&TokenType::Into) || self.check_word("into") {
16194 self.advance();
16195 let pipe = self.parse_imperative_expr()?;
16196 return Ok(Stmt::SendPipe { value: values, pipe });
16197 }
16198 if self.check(&TokenType::To) || self.check_preposition_is("to") || self.check_word("to") {
16200 self.advance();
16201 let destination = self.parse_imperative_expr()?;
16202 return Ok(Stmt::StreamMessage { values, destination });
16203 }
16204 Err(ParseError {
16205 kind: ParseErrorKind::ExpectedKeyword { keyword: "to (relay) or into (pipe)".to_string() },
16206 span: self.current_span(),
16207 })
16208 }
16209
16210 fn parse_merge_statement(&mut self) -> ParseResult<Stmt<'a>> {
16216 self.advance(); let source = self.parse_imperative_expr()?;
16220
16221 if !self.check_word("into") {
16223 return Err(ParseError {
16224 kind: ParseErrorKind::ExpectedKeyword { keyword: "into".to_string() },
16225 span: self.current_span(),
16226 });
16227 }
16228 self.advance(); let target = self.parse_imperative_expr()?;
16232
16233 Ok(Stmt::MergeCrdt { source, target })
16234 }
16235
16236 fn parse_increase_statement(&mut self) -> ParseResult<Stmt<'a>> {
16238 self.advance(); let expr = self.parse_imperative_expr()?;
16242
16243 let (object, field) = if let Expr::FieldAccess { object, field } = expr {
16245 (object, field)
16246 } else {
16247 return Err(ParseError {
16248 kind: ParseErrorKind::ExpectedKeyword { keyword: "field access (e.g., 'x's count')".to_string() },
16249 span: self.current_span(),
16250 });
16251 };
16252
16253 if !self.check_preposition_is("by") {
16255 return Err(ParseError {
16256 kind: ParseErrorKind::ExpectedKeyword { keyword: "by".to_string() },
16257 span: self.current_span(),
16258 });
16259 }
16260 self.advance(); let amount = self.parse_imperative_expr()?;
16264
16265 Ok(Stmt::IncreaseCrdt { object, field: *field, amount })
16266 }
16267
16268 fn parse_decrease_statement(&mut self) -> ParseResult<Stmt<'a>> {
16270 self.advance(); let expr = self.parse_imperative_expr()?;
16274
16275 let (object, field) = if let Expr::FieldAccess { object, field } = expr {
16277 (object, field)
16278 } else {
16279 return Err(ParseError {
16280 kind: ParseErrorKind::ExpectedKeyword { keyword: "field access (e.g., 'x's count')".to_string() },
16281 span: self.current_span(),
16282 });
16283 };
16284
16285 if !self.check_preposition_is("by") {
16287 return Err(ParseError {
16288 kind: ParseErrorKind::ExpectedKeyword { keyword: "by".to_string() },
16289 span: self.current_span(),
16290 });
16291 }
16292 self.advance(); let amount = self.parse_imperative_expr()?;
16296
16297 Ok(Stmt::DecreaseCrdt { object, field: *field, amount })
16298 }
16299
16300 fn parse_append_statement(&mut self) -> ParseResult<Stmt<'a>> {
16302 self.advance(); let value = self.parse_imperative_expr()?;
16306
16307 if !self.check(&TokenType::To) && !self.check_preposition_is("to") {
16309 return Err(ParseError {
16310 kind: ParseErrorKind::ExpectedKeyword { keyword: "to".to_string() },
16311 span: self.current_span(),
16312 });
16313 }
16314 self.advance(); let sequence = self.parse_imperative_expr()?;
16318
16319 Ok(Stmt::AppendToSequence { sequence, value })
16320 }
16321
16322 fn parse_resolve_statement(&mut self) -> ParseResult<Stmt<'a>> {
16324 self.advance(); let expr = self.parse_imperative_expr()?;
16328
16329 let (object, field) = if let Expr::FieldAccess { object, field } = expr {
16331 (object, field)
16332 } else {
16333 return Err(ParseError {
16334 kind: ParseErrorKind::ExpectedKeyword { keyword: "field access (e.g., 'x's title')".to_string() },
16335 span: self.current_span(),
16336 });
16337 };
16338
16339 if !self.check(&TokenType::To) && !self.check_preposition_is("to") {
16341 return Err(ParseError {
16342 kind: ParseErrorKind::ExpectedKeyword { keyword: "to".to_string() },
16343 span: self.current_span(),
16344 });
16345 }
16346 self.advance(); let value = self.parse_imperative_expr()?;
16350
16351 Ok(Stmt::ResolveConflict { object, field: *field, value })
16352 }
16353
16354}
16355