1use super::clause::ClauseParsing;
25use super::modal::ModalParsing;
26use super::noun::NounParsing;
27use super::pragmatics::PragmaticsParsing;
28use super::{NegativeScopeMode, ParseResult, Parser};
29use crate::ast::{LogicExpr, NeoEventData, NounPhrase, QuantifierKind, Term, ThematicRole};
30use crate::drs::{Gender, Number};
31use crate::drs::ReferentSource;
32use crate::error::{ParseError, ParseErrorKind};
33use logicaffeine_base::Symbol;
34use crate::lexer::Lexer;
35use crate::lexicon::{
36 get_canonical_verb, is_subsective, lookup_relational_adjective, lookup_verb_db, Definiteness,
37 Feature, Time,
38};
39use crate::token::{PresupKind, TokenType};
40
41pub trait QuantifierParsing<'a, 'ctx, 'int> {
46 fn parse_quantified(&mut self) -> ParseResult<&'a LogicExpr<'a>>;
48
49 fn parse_quantified_core(&mut self) -> ParseResult<&'a LogicExpr<'a>>;
52 fn parse_restriction(&mut self, var_name: Symbol) -> ParseResult<&'a LogicExpr<'a>>;
54 fn adjective_restriction(&mut self, adj: Symbol, var: Symbol, noun: Symbol) -> &'a LogicExpr<'a>;
58 fn parse_verb_phrase_for_restriction(&mut self, var_name: Symbol) -> ParseResult<&'a LogicExpr<'a>>;
60 fn combine_with_and(&self, exprs: Vec<&'a LogicExpr<'a>>) -> ParseResult<&'a LogicExpr<'a>>;
62 fn wrap_with_definiteness_full(
63 &mut self,
64 np: &NounPhrase<'a>,
65 predicate: &'a LogicExpr<'a>,
66 ) -> ParseResult<&'a LogicExpr<'a>>;
67 fn wrap_with_definiteness(
68 &mut self,
69 definiteness: Option<Definiteness>,
70 noun: Symbol,
71 predicate: &'a LogicExpr<'a>,
72 ) -> ParseResult<&'a LogicExpr<'a>>;
73 fn wrap_with_definiteness_and_adjectives(
74 &mut self,
75 definiteness: Option<Definiteness>,
76 noun: Symbol,
77 adjectives: &[Symbol],
78 predicate: &'a LogicExpr<'a>,
79 ) -> ParseResult<&'a LogicExpr<'a>>;
80 fn wrap_with_definiteness_and_adjectives_and_pps(
81 &mut self,
82 definiteness: Option<Definiteness>,
83 noun: Symbol,
84 adjectives: &[Symbol],
85 pps: &[&'a LogicExpr<'a>],
86 predicate: &'a LogicExpr<'a>,
87 ) -> ParseResult<&'a LogicExpr<'a>>;
88 fn wrap_with_definiteness_for_object(
89 &mut self,
90 definiteness: Option<Definiteness>,
91 noun: Symbol,
92 predicate: &'a LogicExpr<'a>,
93 ) -> ParseResult<&'a LogicExpr<'a>>;
94 fn substitute_pp_placeholder(&mut self, pp: &'a LogicExpr<'a>, var: Symbol) -> &'a LogicExpr<'a>;
95 fn substitute_constant_with_var(
96 &self,
97 expr: &'a LogicExpr<'a>,
98 constant_name: Symbol,
99 var_name: Symbol,
100 ) -> ParseResult<&'a LogicExpr<'a>>;
101 fn substitute_constant_with_var_sym(
102 &self,
103 expr: &'a LogicExpr<'a>,
104 constant_name: Symbol,
105 var_name: Symbol,
106 ) -> ParseResult<&'a LogicExpr<'a>>;
107 fn substitute_constant_with_sigma(
108 &self,
109 expr: &'a LogicExpr<'a>,
110 constant_name: Symbol,
111 sigma_term: Term<'a>,
112 ) -> ParseResult<&'a LogicExpr<'a>>;
113 fn substitute_variable_with_constant(
118 &self,
119 expr: &'a LogicExpr<'a>,
120 from_var: Symbol,
121 to_const: Symbol,
122 ) -> ParseResult<&'a LogicExpr<'a>>;
123 fn find_main_verb_name(&self, expr: &LogicExpr<'a>) -> Option<Symbol>;
124 fn transform_cardinal_to_group(&mut self, expr: &'a LogicExpr<'a>) -> ParseResult<&'a LogicExpr<'a>>;
125 fn build_verb_neo_event(
126 &mut self,
127 verb: Symbol,
128 subject_var: Symbol,
129 object: Option<Term<'a>>,
130 modifiers: Vec<Symbol>,
131 ) -> &'a LogicExpr<'a>;
132 fn parse_copula_pp_complement(
137 &mut self,
138 subj_var: Symbol,
139 ) -> ParseResult<&'a LogicExpr<'a>>;
140}
141
142impl<'a, 'ctx, 'int> QuantifierParsing<'a, 'ctx, 'int> for Parser<'a, 'ctx, 'int> {
143 fn parse_copula_pp_complement(
144 &mut self,
145 subj_var: Symbol,
146 ) -> ParseResult<&'a LogicExpr<'a>> {
147 let prep_sym = match self.advance().kind {
148 TokenType::Preposition(s) => s,
149 _ => unreachable!("guarded by check_preposition"),
150 };
151 let saved_ctx = self.nominal_np_context;
152 self.nominal_np_context = true;
153 let obj_res = self.parse_noun_phrase(true);
154 self.nominal_np_context = saved_ctx;
155 let obj = obj_res?;
156 let first: &'a LogicExpr<'a> = self.ctx.exprs.alloc(LogicExpr::Predicate {
157 name: prep_sym,
158 args: self
159 .ctx
160 .terms
161 .alloc_slice([Term::Variable(subj_var), Term::Constant(obj.noun)]),
162 world: None,
163 });
164 let mut base = self.attach_pp_object_modifiers(first, &obj);
165 while self.check(&TokenType::Or) {
166 let cp = self.checkpoint();
167 self.advance(); let disj_prep = if self.check_preposition() && !self.check_by_preposition() {
169 match self.advance().kind {
170 TokenType::Preposition(s) => s,
171 _ => prep_sym,
172 }
173 } else {
174 prep_sym
175 };
176 if !(self.check_content_word()
177 || self.check_number()
178 || matches!(self.peek().kind, TokenType::Article(_)))
179 {
180 self.restore(cp);
181 break;
182 }
183 let saved = self.nominal_np_context;
184 self.nominal_np_context = true;
185 let disj_obj_res = self.parse_noun_phrase(true);
186 self.nominal_np_context = saved;
187 let disj_obj = disj_obj_res?;
188 let disj: &'a LogicExpr<'a> = self.ctx.exprs.alloc(LogicExpr::Predicate {
189 name: disj_prep,
190 args: self
191 .ctx
192 .terms
193 .alloc_slice([Term::Variable(subj_var), Term::Constant(disj_obj.noun)]),
194 world: None,
195 });
196 let disj = self.attach_pp_object_modifiers(disj, &disj_obj);
197 base = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
198 left: base,
199 op: TokenType::Or,
200 right: disj,
201 });
202 }
203 Ok(base)
204 }
205
206 fn parse_quantified(&mut self) -> ParseResult<&'a LogicExpr<'a>> {
207 let cp = self.checkpoint();
213 let core = self.parse_quantified_core();
214 let core_complete = core.is_ok() && self.at_clause_boundary();
215 let result = if core_complete {
216 core?
217 } else {
218 let core_end = self.checkpoint();
219 let core_partitive = self.pending_partitive.take();
220 self.restore(cp);
221 match self.parse_quantified_delegating() {
222 Ok(r) if self.at_clause_boundary() => r,
223 _ => match core {
224 Ok(r) => {
225 self.restore(core_end);
226 self.pending_partitive = core_partitive;
227 r
228 }
229 Err(e) => return Err(e),
230 },
231 }
232 };
233 if let Some((n, restriction, var)) = self.pending_partitive.take() {
237 let superset = self.ctx.exprs.alloc(LogicExpr::Quantifier {
238 kind: QuantifierKind::Cardinal(n),
239 variable: var,
240 body: restriction,
241 island_id: self.current_island,
242 });
243 return Ok(self.ctx.exprs.alloc(LogicExpr::Presupposition {
244 assertion: result,
245 presupposition: superset,
246 }));
247 }
248 Ok(result)
249 }
250
251 fn parse_quantified_core(&mut self) -> ParseResult<&'a LogicExpr<'a>> {
252 let quantifier_token = self.previous().kind.clone();
253 let var_name = self.next_var_name();
254
255 let was_in_negative_quantifier = self.in_negative_quantifier;
258 if matches!(quantifier_token, TokenType::No) {
259 self.in_negative_quantifier = true;
260 }
261
262 let mut partitive_superset: Option<u32> = None;
268 if matches!(
269 quantifier_token,
270 TokenType::Cardinal(_)
271 | TokenType::Most
272 | TokenType::Few
273 | TokenType::Many
274 | TokenType::Some
275 | TokenType::AtLeast(_)
276 | TokenType::AtMost(_)
277 ) && self.check_preposition_is("of")
278 && self.current + 1 < self.tokens.len()
279 && matches!(self.tokens[self.current + 1].kind, TokenType::Article(_))
280 {
281 self.advance(); self.advance(); if let TokenType::Cardinal(n) = self.peek().kind {
284 partitive_superset = Some(n);
285 self.advance(); }
287 }
288 if matches!(quantifier_token, TokenType::AtMost(_) | TokenType::AtLeast(_) | TokenType::Cardinal(_))
290 && self.check_preposition_is("of")
291 {
292 self.advance(); let mut signal_names: Vec<Symbol> = Vec::new();
296 loop {
297 let name = self.consume_content_word()?;
298 signal_names.push(name);
299
300 if self.check(&TokenType::Comma) {
301 self.advance(); if self.check(&TokenType::And) {
304 self.advance();
305 }
306 } else if self.check(&TokenType::And) {
307 self.advance(); } else {
309 break;
310 }
311 }
312
313 let mut is_negated = false;
317 if self.check(&TokenType::Is) || self.check(&TokenType::Are) {
318 self.advance(); is_negated = self.check(&TokenType::Not);
320 if is_negated {
321 self.advance();
322 }
323 let _ = self.consume_content_word();
325 while self.check_preposition_is("at") {
327 self.advance();
328 if self.check(&TokenType::Any) {
329 self.advance();
330 }
331 if self.check_content_word() {
332 self.advance();
333 }
334 }
335 }
336
337 let mut signal_exprs: Vec<&'a LogicExpr<'a>> = Vec::new();
340 for &sig in &signal_names {
341 let atom: &'a LogicExpr<'a> = self.ctx.exprs.alloc(LogicExpr::Atom(sig));
342 let sig_expr = if is_negated {
343 self.ctx.exprs.alloc(LogicExpr::UnaryOp {
344 op: TokenType::Not,
345 operand: atom,
346 })
347 } else {
348 atom
349 };
350 signal_exprs.push(sig_expr);
351 }
352
353 let body = if signal_exprs.len() == 1 {
354 signal_exprs[0]
355 } else {
356 let mut combined = signal_exprs[0];
357 for &expr in &signal_exprs[1..] {
358 combined = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
359 left: combined,
360 op: TokenType::Or,
361 right: expr,
362 });
363 }
364 combined
365 };
366
367 let kind = match quantifier_token {
368 TokenType::AtMost(n) => QuantifierKind::AtMost(n),
369 TokenType::AtLeast(n) => QuantifierKind::AtLeast(n),
370 TokenType::Cardinal(n) => QuantifierKind::Cardinal(n),
371 _ => unreachable!(),
372 };
373
374 self.in_negative_quantifier = was_in_negative_quantifier;
375
376 return Ok(self.ctx.exprs.alloc(LogicExpr::Quantifier {
377 kind,
378 variable: var_name,
379 body,
380 island_id: self.current_island,
381 }));
382 }
383
384 let subject_pred = self.parse_restriction(var_name)?;
385
386 if let Some(n) = partitive_superset {
389 self.pending_partitive = Some((n, subject_pred, var_name));
390 }
391
392 if self.check_modal() {
393 use crate::ast::ModalFlavor;
394
395 self.advance();
396 let vector = self.token_to_vector(&self.previous().kind.clone());
397 let verb = self.consume_content_word()?;
398
399 let obj_term = if self.check_content_word() || self.check_article() {
401 let obj_np = self.parse_noun_phrase(false)?;
402 Some(self.noun_phrase_to_term(&obj_np))
403 } else {
404 None
405 };
406
407 let modifiers = self.collect_adverbs();
409 let verb_pred = self.build_verb_neo_event(verb, var_name, obj_term, modifiers);
410
411 let kind = match quantifier_token {
413 TokenType::All | TokenType::No => QuantifierKind::Universal,
414 TokenType::Any => {
415 if self.is_negative_context() {
416 QuantifierKind::Existential
417 } else {
418 QuantifierKind::Universal
419 }
420 }
421 TokenType::Some => QuantifierKind::Existential,
422 TokenType::Most => QuantifierKind::Most,
423 TokenType::Few => QuantifierKind::Few,
424 TokenType::Many => QuantifierKind::Many,
425 TokenType::Cardinal(n) => QuantifierKind::Cardinal(n),
426 TokenType::AtLeast(n) => QuantifierKind::AtLeast(n),
427 TokenType::AtMost(n) => QuantifierKind::AtMost(n),
428 _ => {
429 return Err(ParseError {
430 kind: ParseErrorKind::UnknownQuantifier {
431 found: quantifier_token.clone(),
432 },
433 span: self.current_span(),
434 })
435 }
436 };
437
438 if vector.flavor == ModalFlavor::Root {
440 let modal_verb = self.ctx.exprs.alloc(LogicExpr::Modal {
446 vector,
447 operand: verb_pred,
448 });
449
450 let body = match quantifier_token {
451 TokenType::All => self.ctx.exprs.alloc(LogicExpr::BinaryOp {
452 left: subject_pred,
453 op: TokenType::Implies,
454 right: modal_verb,
455 }),
456 TokenType::Any => {
457 if self.is_negative_context() {
458 self.ctx.exprs.alloc(LogicExpr::BinaryOp {
459 left: subject_pred,
460 op: TokenType::And,
461 right: modal_verb,
462 })
463 } else {
464 self.ctx.exprs.alloc(LogicExpr::BinaryOp {
465 left: subject_pred,
466 op: TokenType::Implies,
467 right: modal_verb,
468 })
469 }
470 }
471 TokenType::Some
472 | TokenType::Most
473 | TokenType::Few
474 | TokenType::Many
475 | TokenType::Cardinal(_)
476 | TokenType::AtLeast(_)
477 | TokenType::AtMost(_) => self.ctx.exprs.alloc(LogicExpr::BinaryOp {
478 left: subject_pred,
479 op: TokenType::And,
480 right: modal_verb,
481 }),
482 TokenType::No => {
483 let neg = self.ctx.exprs.alloc(LogicExpr::UnaryOp {
484 op: TokenType::Not,
485 operand: modal_verb,
486 });
487 self.ctx.exprs.alloc(LogicExpr::BinaryOp {
488 left: subject_pred,
489 op: TokenType::Implies,
490 right: neg,
491 })
492 }
493 _ => {
494 return Err(ParseError {
495 kind: ParseErrorKind::UnknownQuantifier {
496 found: quantifier_token.clone(),
497 },
498 span: self.current_span(),
499 })
500 }
501 };
502
503 let mut result = self.ctx.exprs.alloc(LogicExpr::Quantifier {
505 kind,
506 variable: var_name,
507 body,
508 island_id: self.current_island,
509 });
510
511 for (_noun, donkey_var, used, wide_neg) in self.donkey_bindings.iter().rev() {
513 if *used {
514 result = self.ctx.exprs.alloc(LogicExpr::Quantifier {
516 kind: QuantifierKind::Universal,
517 variable: *donkey_var,
518 body: result,
519 island_id: self.current_island,
520 });
521 } else {
522 result = self.wrap_donkey_in_restriction(result, *donkey_var, *wide_neg);
524 }
525 }
526 self.donkey_bindings.clear();
527
528 self.in_negative_quantifier = was_in_negative_quantifier;
529 return Ok(result);
530
531 } else {
532 let body = match quantifier_token {
537 TokenType::All => self.ctx.exprs.alloc(LogicExpr::BinaryOp {
538 left: subject_pred,
539 op: TokenType::Implies,
540 right: verb_pred,
541 }),
542 TokenType::Any => {
543 if self.is_negative_context() {
544 self.ctx.exprs.alloc(LogicExpr::BinaryOp {
545 left: subject_pred,
546 op: TokenType::And,
547 right: verb_pred,
548 })
549 } else {
550 self.ctx.exprs.alloc(LogicExpr::BinaryOp {
551 left: subject_pred,
552 op: TokenType::Implies,
553 right: verb_pred,
554 })
555 }
556 }
557 TokenType::Some
558 | TokenType::Most
559 | TokenType::Few
560 | TokenType::Many
561 | TokenType::Cardinal(_)
562 | TokenType::AtLeast(_)
563 | TokenType::AtMost(_) => self.ctx.exprs.alloc(LogicExpr::BinaryOp {
564 left: subject_pred,
565 op: TokenType::And,
566 right: verb_pred,
567 }),
568 TokenType::No => {
569 let neg = self.ctx.exprs.alloc(LogicExpr::UnaryOp {
570 op: TokenType::Not,
571 operand: verb_pred,
572 });
573 self.ctx.exprs.alloc(LogicExpr::BinaryOp {
574 left: subject_pred,
575 op: TokenType::Implies,
576 right: neg,
577 })
578 }
579 _ => {
580 return Err(ParseError {
581 kind: ParseErrorKind::UnknownQuantifier {
582 found: quantifier_token.clone(),
583 },
584 span: self.current_span(),
585 })
586 }
587 };
588
589 let mut result = self.ctx.exprs.alloc(LogicExpr::Quantifier {
590 kind,
591 variable: var_name,
592 body,
593 island_id: self.current_island,
594 });
595
596 for (_noun, donkey_var, used, wide_neg) in self.donkey_bindings.iter().rev() {
598 if *used {
599 result = self.ctx.exprs.alloc(LogicExpr::Quantifier {
601 kind: QuantifierKind::Universal,
602 variable: *donkey_var,
603 body: result,
604 island_id: self.current_island,
605 });
606 } else {
607 result = self.wrap_donkey_in_restriction(result, *donkey_var, *wide_neg);
609 }
610 }
611 self.donkey_bindings.clear();
612
613 self.in_negative_quantifier = was_in_negative_quantifier;
615 return Ok(self.ctx.exprs.alloc(LogicExpr::Modal {
616 vector,
617 operand: result,
618 }));
619 }
620 }
621
622 if self.check_auxiliary() {
623 let aux_token = self.advance();
624 let aux_time = if let TokenType::Auxiliary(time) = aux_token.kind.clone() {
625 time
626 } else {
627 Time::None
628 };
629 self.pending_time = Some(aux_time);
630
631 let is_negated = self.match_token(&[TokenType::Not]);
632 if is_negated {
633 self.negative_depth += 1;
634 }
635
636 while self.check(&TokenType::Ever) {
640 self.advance();
641 }
642
643 if self.check_verb() {
644 let verb = self.consume_verb();
645
646 let verb_lower = self.interner.resolve(verb).to_lowercase();
651 let obj_term = if matches!(verb_lower.as_str(), "be" | "been")
652 && self.check_verb()
653 {
654 Some(Term::Constant(self.consume_verb()))
655 } else {
656 None
657 };
658
659 let mut modifiers = match aux_time {
661 Time::Past => vec![self.interner.intern("Past")],
662 Time::Future => vec![self.interner.intern("Future")],
663 _ => vec![],
664 };
665 modifiers.extend(self.collect_adverbs());
667
668 if self.check_comparative() {
672 self.advance(); if self.check(&TokenType::Than) {
674 self.advance();
675 }
676 if self.check_content_word() || self.check_number() {
677 self.advance(); }
679 modifiers.push(self.interner.intern("MoreThanOnce"));
680 }
681
682 let verb_pred = self.build_verb_neo_event(verb, var_name, obj_term, modifiers);
683
684 let maybe_negated = if is_negated {
685 self.negative_depth -= 1;
686 self.ctx.exprs.alloc(LogicExpr::UnaryOp {
687 op: TokenType::Not,
688 operand: verb_pred,
689 })
690 } else {
691 verb_pred
692 };
693
694 let body = match quantifier_token {
695 TokenType::All | TokenType::Any => self.ctx.exprs.alloc(LogicExpr::BinaryOp {
696 left: subject_pred,
697 op: TokenType::Implies,
698 right: maybe_negated,
699 }),
700 TokenType::No => self.ctx.exprs.alloc(LogicExpr::BinaryOp {
704 left: subject_pred,
705 op: TokenType::Implies,
706 right: self.ctx.exprs.alloc(LogicExpr::UnaryOp {
707 op: TokenType::Not,
708 operand: maybe_negated,
709 }),
710 }),
711 _ => self.ctx.exprs.alloc(LogicExpr::BinaryOp {
712 left: subject_pred,
713 op: TokenType::And,
714 right: maybe_negated,
715 }),
716 };
717
718 let kind = match quantifier_token {
719 TokenType::All | TokenType::No => QuantifierKind::Universal,
720 TokenType::Some => QuantifierKind::Existential,
721 TokenType::Most => QuantifierKind::Most,
722 TokenType::Few => QuantifierKind::Few,
723 TokenType::Cardinal(n) => QuantifierKind::Cardinal(n),
724 TokenType::AtLeast(n) => QuantifierKind::AtLeast(n),
725 TokenType::AtMost(n) => QuantifierKind::AtMost(n),
726 _ => QuantifierKind::Universal,
727 };
728
729 self.in_negative_quantifier = was_in_negative_quantifier;
730 return Ok(self.ctx.exprs.alloc(LogicExpr::Quantifier {
731 kind,
732 variable: var_name,
733 body,
734 island_id: self.current_island,
735 }));
736 }
737 }
738
739 if self.check_presup_trigger() && self.is_followed_by_gerund() {
741 let presup_kind = match self.advance().kind {
742 TokenType::PresupTrigger(kind) => kind,
743 TokenType::Verb { lemma, .. } => {
744 let s = self.interner.resolve(lemma).to_lowercase();
745 crate::lexicon::lookup_presup_trigger(&s)
746 .expect("Lexicon mismatch: Verb flagged as trigger but lookup failed")
747 }
748 _ => panic!("Expected presupposition trigger"),
749 };
750
751 let complement = if self.check_verb() {
752 let verb = self.consume_verb();
753 let modifiers = self.collect_adverbs();
754 self.build_verb_neo_event(verb, var_name, None, modifiers)
755 } else {
756 let unknown = self.interner.intern("?");
757 self.ctx.exprs.alloc(LogicExpr::Atom(unknown))
758 };
759
760 let verb_pred = match presup_kind {
761 PresupKind::Stop => self.ctx.exprs.alloc(LogicExpr::UnaryOp {
762 op: TokenType::Not,
763 operand: complement,
764 }),
765 PresupKind::Start | PresupKind::Continue => complement,
766 PresupKind::Regret | PresupKind::Realize | PresupKind::Know => complement,
767 };
768
769 let body = match quantifier_token {
770 TokenType::All | TokenType::Any => self.ctx.exprs.alloc(LogicExpr::BinaryOp {
771 left: subject_pred,
772 op: TokenType::Implies,
773 right: verb_pred,
774 }),
775 _ => self.ctx.exprs.alloc(LogicExpr::BinaryOp {
776 left: subject_pred,
777 op: TokenType::And,
778 right: verb_pred,
779 }),
780 };
781
782 let kind = match quantifier_token {
783 TokenType::All | TokenType::No => QuantifierKind::Universal,
784 TokenType::Some => QuantifierKind::Existential,
785 TokenType::Most => QuantifierKind::Most,
786 TokenType::Few => QuantifierKind::Few,
787 TokenType::Many => QuantifierKind::Many,
788 TokenType::Cardinal(n) => QuantifierKind::Cardinal(n),
789 TokenType::AtLeast(n) => QuantifierKind::AtLeast(n),
790 TokenType::AtMost(n) => QuantifierKind::AtMost(n),
791 _ => QuantifierKind::Universal,
792 };
793
794 self.in_negative_quantifier = was_in_negative_quantifier;
795 return Ok(self.ctx.exprs.alloc(LogicExpr::Quantifier {
796 kind,
797 variable: var_name,
798 body,
799 island_id: self.current_island,
800 }));
801 }
802
803 if self.check_verb() {
804 let verb = self.consume_verb();
805 let mut args = vec![Term::Variable(var_name)];
806
807 if self.check_pronoun() {
808 let token = self.peek().clone();
809 if let TokenType::Pronoun { gender, .. } = token.kind {
810 self.advance();
811 if let Some(donkey_var) = self.resolve_donkey_pronoun(gender) {
812 args.push(Term::Variable(donkey_var));
813 } else {
814 let resolved = self.resolve_pronoun(gender, Number::Singular)?;
815 let term = match resolved {
816 super::ResolvedPronoun::Variable(s) => Term::Variable(s),
817 super::ResolvedPronoun::Constant(s) => Term::Constant(s),
818 };
819 args.push(term);
820 }
821 }
822 } else if self.check_npi_object() {
823 let npi_token = self.advance().kind.clone();
824 let obj_var = self.next_var_name();
825
826 let restriction_name = match npi_token {
827 TokenType::Anything => "Thing",
828 TokenType::Anyone => "Person",
829 _ => "Thing",
830 };
831
832 let restriction_sym = self.interner.intern(restriction_name);
833 let obj_restriction = self.ctx.exprs.alloc(LogicExpr::Predicate {
834 name: restriction_sym,
835 args: self.ctx.terms.alloc_slice([Term::Variable(obj_var)]),
836 world: None,
837 });
838
839 let npi_modifiers = self.collect_adverbs();
840 let verb_with_obj = self.build_verb_neo_event(
841 verb,
842 var_name,
843 Some(Term::Variable(obj_var)),
844 npi_modifiers,
845 );
846
847 let npi_body = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
848 left: obj_restriction,
849 op: TokenType::And,
850 right: verb_with_obj,
851 });
852
853 let npi_quantified = self.ctx.exprs.alloc(LogicExpr::Quantifier {
854 kind: QuantifierKind::Existential,
855 variable: obj_var,
856 body: npi_body,
857 island_id: self.current_island,
858 });
859
860 let negated_npi = self.ctx.exprs.alloc(LogicExpr::UnaryOp {
861 op: TokenType::Not,
862 operand: npi_quantified,
863 });
864
865 let body = match quantifier_token {
866 TokenType::All | TokenType::No => self.ctx.exprs.alloc(LogicExpr::BinaryOp {
867 left: subject_pred,
868 op: TokenType::Implies,
869 right: negated_npi,
870 }),
871 _ => self.ctx.exprs.alloc(LogicExpr::BinaryOp {
872 left: subject_pred,
873 op: TokenType::And,
874 right: negated_npi,
875 }),
876 };
877
878 let kind = match quantifier_token {
879 TokenType::All | TokenType::No => QuantifierKind::Universal,
880 TokenType::Some => QuantifierKind::Existential,
881 TokenType::Most => QuantifierKind::Most,
882 TokenType::Few => QuantifierKind::Few,
883 TokenType::Many => QuantifierKind::Many,
884 TokenType::Cardinal(n) => QuantifierKind::Cardinal(n),
885 TokenType::AtLeast(n) => QuantifierKind::AtLeast(n),
886 TokenType::AtMost(n) => QuantifierKind::AtMost(n),
887 _ => QuantifierKind::Universal,
888 };
889
890 self.in_negative_quantifier = was_in_negative_quantifier;
891 return Ok(self.ctx.exprs.alloc(LogicExpr::Quantifier {
892 kind,
893 variable: var_name,
894 body,
895 island_id: self.current_island,
896 }));
897 } else if self.check_quantifier() || self.check_article() || self.check_possessive_pronoun() {
898 let obj_quantifier = if self.check_possessive_pronoun() {
899 None
902 } else if self.check_quantifier() {
903 Some(self.advance().kind.clone())
904 } else {
905 let art = self.advance().kind.clone();
906 if let TokenType::Article(def) = art {
907 if def == Definiteness::Indefinite {
908 Some(TokenType::Some)
909 } else {
910 None
911 }
912 } else {
913 None
914 }
915 };
916
917 let object = self.parse_noun_phrase(false)?;
918
919 if let Some(obj_q) = obj_quantifier {
920 let obj_var = self.next_var_name();
921
922 let obj_gender = Self::infer_noun_gender(self.interner.resolve(object.noun));
925 let obj_number = if Self::is_plural_noun(self.interner.resolve(object.noun)) {
926 Number::Plural
927 } else {
928 Number::Singular
929 };
930 if self.in_negative_quantifier {
931 self.drs.introduce_referent_with_source(obj_var, object.noun, obj_gender, obj_number, ReferentSource::NegationScope);
932 } else {
933 self.drs.introduce_referent(obj_var, object.noun, obj_gender, obj_number);
934 }
935
936 let mut obj_restriction: &'a LogicExpr<'a> = self.ctx.exprs.alloc(LogicExpr::Predicate {
937 name: object.noun,
938 args: self.ctx.terms.alloc_slice([Term::Variable(obj_var)]),
939 world: None,
940 });
941 for &adj in object.adjectives {
945 let adj_pred = self.adjective_restriction(adj, obj_var, object.noun);
946 obj_restriction = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
947 left: obj_restriction,
948 op: TokenType::And,
949 right: adj_pred,
950 });
951 }
952 for pp in object.pps {
953 let pp_sub = self.substitute_pp_placeholder(pp, obj_var);
954 obj_restriction = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
955 left: obj_restriction,
956 op: TokenType::And,
957 right: pp_sub,
958 });
959 }
960
961 let obj_modifiers = self.collect_adverbs();
962 let verb_with_obj = self.build_verb_neo_event(
963 verb,
964 var_name,
965 Some(Term::Variable(obj_var)),
966 obj_modifiers,
967 );
968
969 let obj_kind = match obj_q {
970 TokenType::All => QuantifierKind::Universal,
971 TokenType::Some => QuantifierKind::Existential,
972 TokenType::No => QuantifierKind::Universal,
973 TokenType::Most => QuantifierKind::Most,
974 TokenType::Few => QuantifierKind::Few,
975 TokenType::Many => QuantifierKind::Many,
976 TokenType::Cardinal(n) => QuantifierKind::Cardinal(n),
977 TokenType::AtLeast(n) => QuantifierKind::AtLeast(n),
978 TokenType::AtMost(n) => QuantifierKind::AtMost(n),
979 _ => QuantifierKind::Existential,
980 };
981
982 let obj_body = match obj_q {
983 TokenType::All => self.ctx.exprs.alloc(LogicExpr::BinaryOp {
984 left: obj_restriction,
985 op: TokenType::Implies,
986 right: verb_with_obj,
987 }),
988 TokenType::No => {
989 let neg = self.ctx.exprs.alloc(LogicExpr::UnaryOp {
990 op: TokenType::Not,
991 operand: verb_with_obj,
992 });
993 self.ctx.exprs.alloc(LogicExpr::BinaryOp {
994 left: obj_restriction,
995 op: TokenType::Implies,
996 right: neg,
997 })
998 }
999 _ => self.ctx.exprs.alloc(LogicExpr::BinaryOp {
1000 left: obj_restriction,
1001 op: TokenType::And,
1002 right: verb_with_obj,
1003 }),
1004 };
1005
1006 let obj_quantified = self.ctx.exprs.alloc(LogicExpr::Quantifier {
1007 kind: obj_kind,
1008 variable: obj_var,
1009 body: obj_body,
1010 island_id: self.current_island,
1011 });
1012
1013 let subj_kind = match quantifier_token {
1014 TokenType::All | TokenType::No => QuantifierKind::Universal,
1015 TokenType::Any => {
1016 if self.is_negative_context() {
1017 QuantifierKind::Existential
1018 } else {
1019 QuantifierKind::Universal
1020 }
1021 }
1022 TokenType::Some => QuantifierKind::Existential,
1023 TokenType::Most => QuantifierKind::Most,
1024 TokenType::Few => QuantifierKind::Few,
1025 TokenType::Many => QuantifierKind::Many,
1026 TokenType::Cardinal(n) => QuantifierKind::Cardinal(n),
1027 TokenType::AtLeast(n) => QuantifierKind::AtLeast(n),
1028 TokenType::AtMost(n) => QuantifierKind::AtMost(n),
1029 _ => QuantifierKind::Universal,
1030 };
1031
1032 let subj_body = match quantifier_token {
1033 TokenType::All => self.ctx.exprs.alloc(LogicExpr::BinaryOp {
1034 left: subject_pred,
1035 op: TokenType::Implies,
1036 right: obj_quantified,
1037 }),
1038 TokenType::No => {
1039 let neg = self.ctx.exprs.alloc(LogicExpr::UnaryOp {
1040 op: TokenType::Not,
1041 operand: obj_quantified,
1042 });
1043 self.ctx.exprs.alloc(LogicExpr::BinaryOp {
1044 left: subject_pred,
1045 op: TokenType::Implies,
1046 right: neg,
1047 })
1048 }
1049 _ => self.ctx.exprs.alloc(LogicExpr::BinaryOp {
1050 left: subject_pred,
1051 op: TokenType::And,
1052 right: obj_quantified,
1053 }),
1054 };
1055
1056 self.in_negative_quantifier = was_in_negative_quantifier;
1057 let mut result = self.ctx.exprs.alloc(LogicExpr::Quantifier {
1058 kind: subj_kind,
1059 variable: var_name,
1060 body: subj_body,
1061 island_id: self.current_island,
1062 });
1063 for (_noun, donkey_var, used, wide_neg) in self.donkey_bindings.iter().rev() {
1069 if *used {
1070 result = self.ctx.exprs.alloc(LogicExpr::Quantifier {
1071 kind: QuantifierKind::Universal,
1072 variable: *donkey_var,
1073 body: result,
1074 island_id: self.current_island,
1075 });
1076 } else {
1077 result = self.wrap_donkey_in_restriction(result, *donkey_var, *wide_neg);
1078 }
1079 }
1080 self.donkey_bindings.clear();
1081 return Ok(result);
1082 } else {
1083 args.push(Term::Constant(object.noun));
1084 }
1085 } else if self.check_content_word() {
1086 let object = self.parse_noun_phrase(false)?;
1087 args.push(Term::Constant(object.noun));
1088 }
1089
1090 let obj_term = if args.len() > 1 {
1092 Some(args.remove(1))
1093 } else {
1094 None
1095 };
1096 let modifiers = self.collect_adverbs();
1098 let verb_pred = self.build_verb_neo_event(verb, var_name, obj_term, modifiers);
1099
1100 let body = match quantifier_token {
1101 TokenType::All => self.ctx.exprs.alloc(LogicExpr::BinaryOp {
1102 left: subject_pred,
1103 op: TokenType::Implies,
1104 right: verb_pred,
1105 }),
1106 TokenType::Any => {
1107 if self.is_negative_context() {
1108 self.ctx.exprs.alloc(LogicExpr::BinaryOp {
1109 left: subject_pred,
1110 op: TokenType::And,
1111 right: verb_pred,
1112 })
1113 } else {
1114 self.ctx.exprs.alloc(LogicExpr::BinaryOp {
1115 left: subject_pred,
1116 op: TokenType::Implies,
1117 right: verb_pred,
1118 })
1119 }
1120 }
1121 TokenType::Some
1122 | TokenType::Most
1123 | TokenType::Few
1124 | TokenType::Many
1125 | TokenType::Cardinal(_)
1126 | TokenType::AtLeast(_)
1127 | TokenType::AtMost(_) => self.ctx.exprs.alloc(LogicExpr::BinaryOp {
1128 left: subject_pred,
1129 op: TokenType::And,
1130 right: verb_pred,
1131 }),
1132 TokenType::No => {
1133 let neg = self.ctx.exprs.alloc(LogicExpr::UnaryOp {
1134 op: TokenType::Not,
1135 operand: verb_pred,
1136 });
1137 self.ctx.exprs.alloc(LogicExpr::BinaryOp {
1138 left: subject_pred,
1139 op: TokenType::Implies,
1140 right: neg,
1141 })
1142 }
1143 _ => {
1144 return Err(ParseError {
1145 kind: ParseErrorKind::UnknownQuantifier {
1146 found: quantifier_token.clone(),
1147 },
1148 span: self.current_span(),
1149 })
1150 }
1151 };
1152
1153 let kind = match quantifier_token {
1154 TokenType::All | TokenType::No => QuantifierKind::Universal,
1155 TokenType::Any => {
1156 if self.is_negative_context() {
1157 QuantifierKind::Existential
1158 } else {
1159 QuantifierKind::Universal
1160 }
1161 }
1162 TokenType::Some => QuantifierKind::Existential,
1163 TokenType::Most => QuantifierKind::Most,
1164 TokenType::Few => QuantifierKind::Few,
1165 TokenType::Many => QuantifierKind::Many,
1166 TokenType::Cardinal(n) => QuantifierKind::Cardinal(n),
1167 TokenType::AtLeast(n) => QuantifierKind::AtLeast(n),
1168 TokenType::AtMost(n) => QuantifierKind::AtMost(n),
1169 _ => {
1170 return Err(ParseError {
1171 kind: ParseErrorKind::UnknownQuantifier {
1172 found: quantifier_token.clone(),
1173 },
1174 span: self.current_span(),
1175 })
1176 }
1177 };
1178
1179 let mut result = self.ctx.exprs.alloc(LogicExpr::Quantifier {
1180 kind,
1181 variable: var_name,
1182 body,
1183 island_id: self.current_island,
1184 });
1185
1186 for (_noun, donkey_var, used, wide_neg) in self.donkey_bindings.iter().rev() {
1187 if *used {
1188 result = self.ctx.exprs.alloc(LogicExpr::Quantifier {
1190 kind: QuantifierKind::Universal,
1191 variable: *donkey_var,
1192 body: result,
1193 island_id: self.current_island,
1194 });
1195 } else {
1196 result = self.wrap_donkey_in_restriction(result, *donkey_var, *wide_neg);
1198 }
1199 }
1200 self.donkey_bindings.clear();
1201
1202 self.in_negative_quantifier = was_in_negative_quantifier;
1203 return Ok(result);
1204 }
1205
1206 if self.check(&TokenType::Does) || self.check(&TokenType::Do) {
1208 self.advance(); let negative = self.match_token(&[TokenType::Not]);
1210 let verb_sym = self.consume_verb();
1212 let predicate_expr = self.ctx.exprs.alloc(LogicExpr::Predicate {
1213 name: verb_sym,
1214 args: self.ctx.terms.alloc_slice([Term::Variable(var_name)]),
1215 world: None,
1216 });
1217 let final_predicate = if negative {
1218 self.ctx.exprs.alloc(LogicExpr::UnaryOp {
1219 op: TokenType::Not,
1220 operand: predicate_expr,
1221 })
1222 } else {
1223 predicate_expr
1224 };
1225
1226 let body = match quantifier_token {
1227 TokenType::All => self.ctx.exprs.alloc(LogicExpr::BinaryOp {
1228 left: subject_pred,
1229 op: TokenType::Implies,
1230 right: final_predicate,
1231 }),
1232 _ => self.ctx.exprs.alloc(LogicExpr::BinaryOp {
1233 left: subject_pred,
1234 op: TokenType::And,
1235 right: final_predicate,
1236 }),
1237 };
1238
1239 let result = self.ctx.exprs.alloc(LogicExpr::Quantifier {
1240 kind: match quantifier_token {
1241 TokenType::All => QuantifierKind::Universal,
1242 _ => QuantifierKind::Existential,
1243 },
1244 variable: var_name,
1245 body: body,
1246 island_id: self.current_island,
1247 });
1248 self.in_negative_quantifier = was_in_negative_quantifier;
1249 return Ok(result);
1250 }
1251
1252 self.consume_copula()?;
1253
1254 let negative = self.match_token(&[TokenType::Not]);
1255
1256 let is_pp_complement = self.check_preposition() && !self.check_by_preposition();
1263 let mut final_predicate = if is_pp_complement {
1264 let pp = self.parse_copula_pp_complement(var_name)?;
1265 if negative {
1266 self.ctx.exprs.alloc(LogicExpr::UnaryOp { op: TokenType::Not, operand: pp })
1267 } else {
1268 pp
1269 }
1270 } else {
1271 let predicate_np = self.parse_noun_phrase(true)?;
1272 let predicate_expr = self.ctx.exprs.alloc(LogicExpr::Predicate {
1273 name: predicate_np.noun,
1274 args: self.ctx.terms.alloc_slice([Term::Variable(var_name)]),
1275 world: None,
1276 });
1277 if negative {
1278 self.ctx.exprs.alloc(LogicExpr::UnaryOp {
1279 op: TokenType::Not,
1280 operand: predicate_expr,
1281 })
1282 } else {
1283 predicate_expr
1284 }
1285 };
1286
1287 while !is_pp_complement {
1296 let is_or = self.check(&TokenType::Or);
1297 let is_comma_list = self.check(&TokenType::Comma)
1298 && matches!(
1299 self.tokens.get(self.current + 1).map(|t| &t.kind),
1300 Some(TokenType::Adjective(_))
1301 | Some(TokenType::Noun(_))
1302 | Some(TokenType::ProperName(_))
1303 | Some(TokenType::Or)
1304 );
1305 if !is_or && !is_comma_list {
1306 break;
1307 }
1308 if is_comma_list {
1309 self.advance(); if self.check(&TokenType::Or) || self.check(&TokenType::And) {
1312 self.advance();
1313 }
1314 } else {
1315 self.advance(); }
1317
1318 let disj_negative = self.match_token(&[TokenType::Not]);
1319 let disj_np = self.parse_noun_phrase(true)?;
1320 let disj_pred: &'a LogicExpr<'a> = self.ctx.exprs.alloc(LogicExpr::Predicate {
1321 name: disj_np.noun,
1322 args: self.ctx.terms.alloc_slice([Term::Variable(var_name)]),
1323 world: None,
1324 });
1325 let disj_pred = if disj_negative {
1326 self.ctx.exprs.alloc(LogicExpr::UnaryOp {
1327 op: TokenType::Not,
1328 operand: disj_pred,
1329 })
1330 } else {
1331 disj_pred
1332 };
1333 final_predicate = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
1334 left: final_predicate,
1335 op: TokenType::Or,
1336 right: disj_pred,
1337 });
1338 }
1339
1340 let body = match quantifier_token {
1341 TokenType::All => self.ctx.exprs.alloc(LogicExpr::BinaryOp {
1342 left: subject_pred,
1343 op: TokenType::Implies,
1344 right: final_predicate,
1345 }),
1346 TokenType::Any => {
1347 if self.is_negative_context() {
1348 self.ctx.exprs.alloc(LogicExpr::BinaryOp {
1349 left: subject_pred,
1350 op: TokenType::And,
1351 right: final_predicate,
1352 })
1353 } else {
1354 self.ctx.exprs.alloc(LogicExpr::BinaryOp {
1355 left: subject_pred,
1356 op: TokenType::Implies,
1357 right: final_predicate,
1358 })
1359 }
1360 }
1361 TokenType::Some
1362 | TokenType::Most
1363 | TokenType::Few
1364 | TokenType::Many
1365 | TokenType::Cardinal(_)
1366 | TokenType::AtLeast(_)
1367 | TokenType::AtMost(_) => self.ctx.exprs.alloc(LogicExpr::BinaryOp {
1368 left: subject_pred,
1369 op: TokenType::And,
1370 right: final_predicate,
1371 }),
1372 TokenType::No => {
1373 let neg = self.ctx.exprs.alloc(LogicExpr::UnaryOp {
1374 op: TokenType::Not,
1375 operand: final_predicate,
1376 });
1377 self.ctx.exprs.alloc(LogicExpr::BinaryOp {
1378 left: subject_pred,
1379 op: TokenType::Implies,
1380 right: neg,
1381 })
1382 }
1383 _ => {
1384 return Err(ParseError {
1385 kind: ParseErrorKind::UnknownQuantifier {
1386 found: quantifier_token.clone(),
1387 },
1388 span: self.current_span(),
1389 })
1390 }
1391 };
1392
1393 let kind = match quantifier_token {
1394 TokenType::All | TokenType::No => QuantifierKind::Universal,
1395 TokenType::Any => {
1396 if self.is_negative_context() {
1397 QuantifierKind::Existential
1398 } else {
1399 QuantifierKind::Universal
1400 }
1401 }
1402 TokenType::Some => QuantifierKind::Existential,
1403 TokenType::Most => QuantifierKind::Most,
1404 TokenType::Few => QuantifierKind::Few,
1405 TokenType::Many => QuantifierKind::Many,
1406 TokenType::Cardinal(n) => QuantifierKind::Cardinal(n),
1407 TokenType::AtLeast(n) => QuantifierKind::AtLeast(n),
1408 TokenType::AtMost(n) => QuantifierKind::AtMost(n),
1409 _ => {
1410 return Err(ParseError {
1411 kind: ParseErrorKind::UnknownQuantifier {
1412 found: quantifier_token.clone(),
1413 },
1414 span: self.current_span(),
1415 })
1416 }
1417 };
1418
1419 let mut result = self.ctx.exprs.alloc(LogicExpr::Quantifier {
1420 kind,
1421 variable: var_name,
1422 body,
1423 island_id: self.current_island,
1424 });
1425
1426 for (_noun, donkey_var, used, wide_neg) in self.donkey_bindings.iter().rev() {
1427 if *used {
1428 result = self.ctx.exprs.alloc(LogicExpr::Quantifier {
1430 kind: QuantifierKind::Universal,
1431 variable: *donkey_var,
1432 body: result,
1433 island_id: self.current_island,
1434 });
1435 } else {
1436 result = self.wrap_donkey_in_restriction(result, *donkey_var, *wide_neg);
1438 }
1439 }
1440 self.donkey_bindings.clear();
1441
1442 self.in_negative_quantifier = was_in_negative_quantifier;
1443 Ok(result)
1444 }
1445
1446 fn adjective_restriction(
1459 &mut self,
1460 adj: Symbol,
1461 var: Symbol,
1462 noun: Symbol,
1463 ) -> &'a LogicExpr<'a> {
1464 let adj_str = self.interner.resolve(adj).to_lowercase();
1465
1466 if let Some((base, relation, level)) = lookup_relational_adjective(&adj_str) {
1467 let base_sym = self.interner.intern(base);
1468 let rel_sym = self.interner.intern(relation);
1469 if level == "Instance" {
1470 let y = self.next_var_name();
1472 let base_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
1473 name: base_sym,
1474 args: self.ctx.terms.alloc_slice([Term::Variable(y)]),
1475 world: None,
1476 });
1477 let rel_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
1478 name: rel_sym,
1479 args: self
1480 .ctx
1481 .terms
1482 .alloc_slice([Term::Variable(var), Term::Variable(y)]),
1483 world: None,
1484 });
1485 let body = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
1486 left: base_pred,
1487 op: TokenType::And,
1488 right: rel_pred,
1489 });
1490 return self.ctx.exprs.alloc(LogicExpr::Quantifier {
1491 kind: QuantifierKind::Existential,
1492 variable: y,
1493 body,
1494 island_id: self.current_island,
1495 });
1496 }
1497 return self.ctx.exprs.alloc(LogicExpr::Predicate {
1499 name: rel_sym,
1500 args: self
1501 .ctx
1502 .terms
1503 .alloc_slice([Term::Variable(var), Term::Kind(base_sym)]),
1504 world: None,
1505 });
1506 }
1507
1508 if is_subsective(&adj_str) {
1509 return self.ctx.exprs.alloc(LogicExpr::Predicate {
1510 name: adj,
1511 args: self
1512 .ctx
1513 .terms
1514 .alloc_slice([Term::Variable(var), Term::Intension(noun)]),
1515 world: None,
1516 });
1517 }
1518
1519 self.ctx.exprs.alloc(LogicExpr::Predicate {
1520 name: adj,
1521 args: self.ctx.terms.alloc_slice([Term::Variable(var)]),
1522 world: None,
1523 })
1524 }
1525
1526 fn parse_restriction(&mut self, var_name: Symbol) -> ParseResult<&'a LogicExpr<'a>> {
1527 let mut adj_syms: Vec<Symbol> = Vec::new();
1531
1532 loop {
1533 if self.is_at_end() {
1534 break;
1535 }
1536
1537 let is_adjective = matches!(self.peek().kind, TokenType::Adjective(_));
1538 if !is_adjective {
1539 break;
1540 }
1541
1542 let next_is_content = if self.current + 1 < self.tokens.len() {
1543 matches!(
1544 self.tokens[self.current + 1].kind,
1545 TokenType::Noun(_) | TokenType::Adjective(_) | TokenType::ProperName(_)
1546 )
1547 } else {
1548 false
1549 };
1550
1551 if next_is_content {
1552 if let TokenType::Adjective(adj) = self.advance().kind.clone() {
1553 adj_syms.push(adj);
1554 }
1555 } else {
1556 break;
1557 }
1558 }
1559
1560 let mut noun = self.consume_content_word()?;
1561 while let TokenType::Noun(next) = self.peek().kind {
1565 self.advance();
1566 noun = self.interner.intern(&format!(
1567 "{}_{}",
1568 self.interner.resolve(noun),
1569 self.interner.resolve(next)
1570 ));
1571 }
1572
1573 let mut conditions: Vec<&'a LogicExpr<'a>> = Vec::new();
1574 for adj in &adj_syms {
1575 let adj_pred = self.adjective_restriction(*adj, var_name, noun);
1576 conditions.push(adj_pred);
1577 }
1578 conditions.push(self.ctx.exprs.alloc(LogicExpr::Predicate {
1579 name: noun,
1580 args: self.ctx.terms.alloc_slice([Term::Variable(var_name)]),
1581 world: None,
1582 }));
1583
1584 while self.check_preposition() {
1591 let object_follows = matches!(
1592 self.tokens.get(self.current + 1).map(|t| &t.kind),
1593 Some(TokenType::Article(_))
1594 | Some(TokenType::Noun(_))
1595 | Some(TokenType::ProperName(_))
1596 | Some(TokenType::All)
1597 | Some(TokenType::Some)
1598 | Some(TokenType::Any)
1599 | Some(TokenType::Cardinal(_))
1600 | Some(TokenType::Number(_))
1601 );
1602 if !object_follows {
1603 break;
1604 }
1605 let prep_token = self.advance().clone();
1606 let prep_name = if let TokenType::Preposition(sym) = prep_token.kind {
1607 sym
1608 } else {
1609 self.current -= 1;
1610 break;
1611 };
1612 if matches!(
1616 self.peek().kind,
1617 TokenType::Any | TokenType::All | TokenType::Some | TokenType::No
1618 | TokenType::Most | TokenType::Few | TokenType::Many
1619 ) && matches!(
1620 self.tokens.get(self.current + 1).map(|t| &t.kind),
1621 Some(TokenType::Noun(_)) | Some(TokenType::Adjective(_))
1622 ) {
1623 self.advance();
1624 }
1625 let pp_np = self.parse_noun_phrase(false)?;
1626 conditions.push(self.ctx.exprs.alloc(LogicExpr::Predicate {
1627 name: prep_name,
1628 args: self
1629 .ctx
1630 .terms
1631 .alloc_slice([Term::Variable(var_name), Term::Constant(pp_np.noun)]),
1632 world: None,
1633 }));
1634 }
1635
1636 while self.check(&TokenType::That) || self.check(&TokenType::Who) {
1637 self.advance();
1638 let clause_pred = self.parse_relative_clause(var_name)?;
1639 conditions.push(clause_pred);
1640 }
1641
1642 self.combine_with_and(conditions)
1643 }
1644
1645 fn parse_verb_phrase_for_restriction(&mut self, var_name: Symbol) -> ParseResult<&'a LogicExpr<'a>> {
1646 let var_term = Term::Variable(var_name);
1647 let verb = self.consume_verb();
1648 let verb_str_owned = self.interner.resolve(verb).to_string();
1649
1650 let (canonical_verb, is_negative) = get_canonical_verb(&verb_str_owned.to_lowercase())
1653 .map(|(lemma, neg)| (self.interner.intern(lemma), neg))
1654 .unwrap_or((verb, false));
1655
1656 let needs_wide_scope = is_negative && self.negative_scope_mode == NegativeScopeMode::Wide;
1658
1659 if Lexer::is_raising_verb(&verb_str_owned) && self.check_to() {
1660 self.advance();
1661 if self.check_verb() {
1662 let inf_verb = self.consume_verb();
1663 let inf_verb_str = self.interner.resolve(inf_verb).to_lowercase();
1664
1665 if inf_verb_str == "be" && self.check_content_word() {
1666 let adj = self.consume_content_word()?;
1667 let embedded = self.ctx.exprs.alloc(LogicExpr::Predicate {
1668 name: adj,
1669 args: self.ctx.terms.alloc_slice([Term::Variable(var_name)]),
1670 world: None,
1671 });
1672 return Ok(self.ctx.exprs.alloc(LogicExpr::Scopal {
1673 operator: verb,
1674 body: embedded,
1675 }));
1676 }
1677
1678 let embedded = self.ctx.exprs.alloc(LogicExpr::Predicate {
1679 name: inf_verb,
1680 args: self.ctx.terms.alloc_slice([Term::Variable(var_name)]),
1681 world: None,
1682 });
1683 return Ok(self.ctx.exprs.alloc(LogicExpr::Scopal {
1684 operator: verb,
1685 body: embedded,
1686 }));
1687 } else if self.check(&TokenType::Is) || self.check(&TokenType::Are) {
1688 self.advance();
1689 if self.check_content_word() {
1690 let adj = self.consume_content_word()?;
1691 let embedded = self.ctx.exprs.alloc(LogicExpr::Predicate {
1692 name: adj,
1693 args: self.ctx.terms.alloc_slice([Term::Variable(var_name)]),
1694 world: None,
1695 });
1696 return Ok(self.ctx.exprs.alloc(LogicExpr::Scopal {
1697 operator: verb,
1698 body: embedded,
1699 }));
1700 }
1701 }
1702 }
1703
1704 let mut args = vec![var_term];
1705 let mut extra_conditions: Vec<&'a LogicExpr<'a>> = Vec::new();
1706 let mut object_cardinal: Option<(u32, crate::intern::Symbol)> = None;
1709
1710 if self.check(&TokenType::Reflexive) {
1711 self.advance();
1712 args.push(Term::Variable(var_name));
1713 } else if let Some(n) = self.counting_np_lookahead() {
1714 self.advance(); let obj_var = self.next_var_name();
1721 self.nominal_np_context = true;
1722 let obj_np_result = self.parse_noun_phrase(false);
1723 self.nominal_np_context = false;
1724 let obj_np = obj_np_result?;
1725 let mut obj_restr: &'a LogicExpr<'a> = self.ctx.exprs.alloc(LogicExpr::Predicate {
1726 name: obj_np.noun,
1727 args: self.ctx.terms.alloc_slice([Term::Variable(obj_var)]),
1728 world: None,
1729 });
1730 for &adj in obj_np.adjectives {
1731 let adj_pred = self.adjective_restriction(adj, obj_var, obj_np.noun);
1732 obj_restr = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
1733 left: obj_restr,
1734 op: TokenType::And,
1735 right: adj_pred,
1736 });
1737 }
1738 for pp in obj_np.pps {
1739 let pp_sub = self.substitute_pp_placeholder(pp, obj_var);
1740 obj_restr = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
1741 left: obj_restr,
1742 op: TokenType::And,
1743 right: pp_sub,
1744 });
1745 }
1746 extra_conditions.push(obj_restr);
1747 args.push(Term::Variable(obj_var));
1748 object_cardinal = Some((n, obj_var));
1749 } else if self.check_number() {
1750 let premodified_noun = matches!(
1758 self.tokens.get(self.current + 2).map(|t| &t.kind),
1759 Some(TokenType::Noun(_)) | Some(TokenType::Ambiguous { .. })
1760 );
1761 if premodified_noun {
1762 let saved_ctx = self.nominal_np_context;
1763 self.nominal_np_context = true;
1764 let np_result = self.parse_noun_phrase(false);
1765 self.nominal_np_context = saved_ctx;
1766 let np = np_result?;
1767 args.push(Term::Constant(np.noun));
1768 } else {
1769 let measure = self.parse_measure_phrase()?;
1772 args.push(*measure);
1773 }
1774 } else if (self.check_content_word() || self.check_article())
1775 && (!self.check_verb() || {
1776 matches!(
1781 self.peek().kind,
1782 TokenType::Verb { aspect: crate::lexicon::Aspect::Progressive, .. }
1783 ) && matches!(
1784 self.tokens.get(self.current + 1).map(|t| &t.kind),
1785 Some(TokenType::Noun(_))
1786 )
1787 })
1788 {
1789 if matches!(
1790 self.peek().kind,
1791 TokenType::Article(Definiteness::Indefinite)
1792 ) {
1793 let obj_np = self.parse_noun_phrase(false)?;
1802 let noun = obj_np.noun;
1803 let donkey_var = self.next_var_name();
1804
1805 if needs_wide_scope {
1806 let restriction_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
1814 name: noun,
1815 args: self.ctx.terms.alloc_slice([Term::Variable(donkey_var)]),
1816 world: None,
1817 });
1818
1819 let inner_modifiers = self.collect_adverbs();
1822 let verb_pred = self.build_verb_neo_event(
1823 canonical_verb,
1824 var_name,
1825 Some(Term::Variable(donkey_var)),
1826 inner_modifiers,
1827 );
1828
1829 let body = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
1831 left: restriction_pred,
1832 op: TokenType::And,
1833 right: verb_pred,
1834 });
1835
1836 let existential = self.ctx.exprs.alloc(LogicExpr::Quantifier {
1838 kind: QuantifierKind::Existential,
1839 variable: donkey_var,
1840 body,
1841 island_id: self.current_island,
1842 });
1843
1844 let negated_existential = self.ctx.exprs.alloc(LogicExpr::UnaryOp {
1846 op: TokenType::Not,
1847 operand: existential,
1848 });
1849
1850 return Ok(negated_existential);
1852 }
1853
1854 self.donkey_bindings.push((noun, donkey_var, false, false));
1857
1858 let mut obj_restr: &'a LogicExpr<'a> = self.ctx.exprs.alloc(LogicExpr::Predicate {
1859 name: noun,
1860 args: self.ctx.terms.alloc_slice([Term::Variable(donkey_var)]),
1861 world: None,
1862 });
1863 for &adj in obj_np.adjectives {
1864 let adj_pred = self.adjective_restriction(adj, donkey_var, noun);
1865 obj_restr = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
1866 left: obj_restr,
1867 op: TokenType::And,
1868 right: adj_pred,
1869 });
1870 }
1871 for pp in obj_np.pps {
1872 let pp_sub = self.substitute_pp_placeholder(pp, donkey_var);
1873 obj_restr = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
1874 left: obj_restr,
1875 op: TokenType::And,
1876 right: pp_sub,
1877 });
1878 }
1879 extra_conditions.push(obj_restr);
1880
1881 args.push(Term::Variable(donkey_var));
1882 } else {
1883 let object = self.parse_noun_phrase(false)?;
1884
1885 if self.check(&TokenType::That) || self.check(&TokenType::Who) {
1886 self.advance();
1887 let nested_var = self.next_var_name();
1888 let nested_rel = self.parse_relative_clause(nested_var)?;
1889
1890 extra_conditions.push(self.ctx.exprs.alloc(LogicExpr::Predicate {
1891 name: object.noun,
1892 args: self.ctx.terms.alloc_slice([Term::Variable(nested_var)]),
1893 world: None,
1894 }));
1895 extra_conditions.push(nested_rel);
1896 args.push(Term::Variable(nested_var));
1897 } else {
1898 args.push(Term::Constant(object.noun));
1899 for pp in object.pps {
1903 let pp_sub =
1904 self.substitute_pp_self_term(pp, Term::Constant(object.noun));
1905 extra_conditions.push(pp_sub);
1906 }
1907 }
1908 }
1909 }
1910
1911 while self.check_preposition() {
1912 let prep_sym = match self.peek().kind {
1913 TokenType::Preposition(s) => Some(s),
1914 _ => None,
1915 };
1916 self.advance();
1917 let attach_to_event = prep_sym.is_some() && args.len() > 1;
1926 if self.check(&TokenType::Reflexive) {
1927 self.advance();
1928 args.push(Term::Variable(var_name));
1929 } else if self.check_number() {
1930 let measure = self.parse_measure_phrase()?;
1933 if attach_to_event {
1934 let ev = self.get_event_var();
1935 extra_conditions.push(self.ctx.exprs.alloc(LogicExpr::Predicate {
1936 name: prep_sym.unwrap(),
1937 args: self.ctx.terms.alloc_slice([Term::Variable(ev), *measure]),
1938 world: None,
1939 }));
1940 } else {
1941 args.push(*measure);
1942 }
1943 } else if self.check_content_word() || self.check_article() {
1944 let object = self.parse_noun_phrase(false)?;
1945
1946 if self.check(&TokenType::That) || self.check(&TokenType::Who) {
1947 self.advance();
1948 let nested_var = self.next_var_name();
1949 let nested_rel = self.parse_relative_clause(nested_var)?;
1950 extra_conditions.push(self.ctx.exprs.alloc(LogicExpr::Predicate {
1951 name: object.noun,
1952 args: self.ctx.terms.alloc_slice([Term::Variable(nested_var)]),
1953 world: None,
1954 }));
1955 extra_conditions.push(nested_rel);
1956 args.push(Term::Variable(nested_var));
1957 } else if attach_to_event {
1958 let ev = self.get_event_var();
1959 extra_conditions.push(self.ctx.exprs.alloc(LogicExpr::Predicate {
1960 name: prep_sym.unwrap(),
1961 args: self
1962 .ctx
1963 .terms
1964 .alloc_slice([Term::Variable(ev), Term::Constant(object.noun)]),
1965 world: None,
1966 }));
1967 } else {
1968 args.push(Term::Constant(object.noun));
1969 }
1970 }
1971 }
1972
1973 let obj_term = if args.len() > 1 {
1976 Some(args.remove(1))
1977 } else {
1978 None
1979 };
1980 let final_modifiers = self.collect_adverbs();
1981 let base_pred = self.build_verb_neo_event(canonical_verb, var_name, obj_term, final_modifiers);
1982
1983 let verb_pred = if is_negative && self.negative_scope_mode == NegativeScopeMode::Narrow {
1988 self.ctx.exprs.alloc(LogicExpr::UnaryOp {
1989 op: TokenType::Not,
1990 operand: base_pred,
1991 })
1992 } else {
1993 base_pred
1994 };
1995
1996 let mut restriction = if extra_conditions.is_empty() {
1997 verb_pred
1998 } else {
1999 extra_conditions.push(verb_pred);
2000 self.combine_with_and(extra_conditions)?
2001 };
2002
2003 if self.check_temporal_adverb() {
2008 if let TokenType::TemporalAdverb(anchor) = self.advance().kind.clone() {
2009 restriction = self.ctx.exprs.alloc(LogicExpr::TemporalAnchor {
2010 anchor,
2011 body: restriction,
2012 });
2013 }
2014 }
2015
2016 if let Some((n, obj_var)) = object_cardinal {
2021 restriction = self.ctx.exprs.alloc(LogicExpr::Quantifier {
2022 kind: QuantifierKind::Cardinal(n),
2023 variable: obj_var,
2024 body: restriction,
2025 island_id: self.current_island,
2026 });
2027 }
2028
2029 Ok(restriction)
2030 }
2031
2032 fn combine_with_and(&self, mut exprs: Vec<&'a LogicExpr<'a>>) -> ParseResult<&'a LogicExpr<'a>> {
2033 if exprs.is_empty() {
2034 return Err(ParseError {
2035 kind: ParseErrorKind::EmptyRestriction,
2036 span: self.current_span(),
2037 });
2038 }
2039 if exprs.len() == 1 {
2040 return Ok(exprs.remove(0));
2041 }
2042 let mut root = exprs.remove(0);
2043 for expr in exprs {
2044 root = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
2045 left: root,
2046 op: TokenType::And,
2047 right: expr,
2048 });
2049 }
2050 Ok(root)
2051 }
2052
2053 fn wrap_with_definiteness_full(
2054 &mut self,
2055 np: &NounPhrase<'a>,
2056 predicate: &'a LogicExpr<'a>,
2057 ) -> ParseResult<&'a LogicExpr<'a>> {
2058 let result = self.wrap_with_definiteness_and_adjectives_and_pps(
2059 np.definiteness,
2060 np.noun,
2061 np.adjectives,
2062 np.pps,
2063 predicate,
2064 )?;
2065
2066 let result = if let Some(adj) = np.superlative {
2068 let superlative_expr = self.ctx.exprs.alloc(LogicExpr::Superlative {
2069 adjective: adj,
2070 subject: self.ctx.terms.alloc(Term::Constant(np.noun)),
2071 domain: np.noun,
2072 });
2073 self.ctx.exprs.alloc(LogicExpr::BinaryOp {
2074 left: result,
2075 op: TokenType::And,
2076 right: superlative_expr,
2077 })
2078 } else {
2079 result
2080 };
2081
2082 if let Some(possessor) = np.possessor {
2087 use crate::ast::logic::NeoEventData;
2088 use crate::ast::ThematicRole;
2089 let possessed = Term::Constant(np.noun);
2090 let (agent_term, agent_restr) = self.possessor_entity(possessor);
2098 let have = self.ctx.exprs.alloc(LogicExpr::NeoEvent(Box::new(NeoEventData {
2099 event_var: self.interner.intern("e"),
2100 verb: self.interner.intern("Have"),
2101 roles: self.ctx.roles.alloc_slice(vec![
2102 (ThematicRole::Agent, agent_term),
2103 (ThematicRole::Theme, possessed),
2104 ]),
2105 modifiers: self.ctx.syms.alloc_slice(vec![]),
2106 suppress_existential: false,
2107 world: None,
2108 })));
2109 let presupposition = self.wrap_in_possessor_entity(agent_restr, have);
2110 return Ok(self.ctx.exprs.alloc(LogicExpr::Presupposition {
2111 assertion: result,
2112 presupposition,
2113 }));
2114 }
2115
2116 Ok(result)
2117 }
2118
2119 fn wrap_with_definiteness(
2120 &mut self,
2121 definiteness: Option<Definiteness>,
2122 noun: Symbol,
2123 predicate: &'a LogicExpr<'a>,
2124 ) -> ParseResult<&'a LogicExpr<'a>> {
2125 self.wrap_with_definiteness_and_adjectives_and_pps(definiteness, noun, &[], &[], predicate)
2126 }
2127
2128 fn wrap_with_definiteness_and_adjectives(
2129 &mut self,
2130 definiteness: Option<Definiteness>,
2131 noun: Symbol,
2132 adjectives: &[Symbol],
2133 predicate: &'a LogicExpr<'a>,
2134 ) -> ParseResult<&'a LogicExpr<'a>> {
2135 self.wrap_with_definiteness_and_adjectives_and_pps(
2136 definiteness,
2137 noun,
2138 adjectives,
2139 &[],
2140 predicate,
2141 )
2142 }
2143
2144 fn wrap_with_definiteness_and_adjectives_and_pps(
2145 &mut self,
2146 definiteness: Option<Definiteness>,
2147 noun: Symbol,
2148 adjectives: &[Symbol],
2149 pps: &[&'a LogicExpr<'a>],
2150 predicate: &'a LogicExpr<'a>,
2151 ) -> ParseResult<&'a LogicExpr<'a>> {
2152 let predicate = match self.pending_subject_restriction {
2157 Some((restr_noun, restr)) if restr_noun == noun => {
2158 self.pending_subject_restriction = None;
2159 self.ctx.exprs.alloc(LogicExpr::BinaryOp {
2160 left: restr,
2161 op: TokenType::And,
2162 right: predicate,
2163 })
2164 }
2165 _ => predicate,
2166 };
2167 match definiteness {
2168 Some(Definiteness::Indefinite) => {
2169 let var = self.next_var_name();
2170
2171 let gender = Self::infer_noun_gender(self.interner.resolve(noun));
2174 let number = if Self::is_plural_noun(self.interner.resolve(noun)) {
2175 Number::Plural
2176 } else {
2177 Number::Singular
2178 };
2179 if self.in_negative_quantifier {
2180 self.drs.introduce_referent_with_source(var, noun, gender, number, ReferentSource::NegationScope);
2181 } else {
2182 self.drs.introduce_referent(var, noun, gender, number);
2183 }
2184
2185 let mut restriction = self.ctx.exprs.alloc(LogicExpr::Predicate {
2186 name: noun,
2187 args: self.ctx.terms.alloc_slice([Term::Variable(var)]),
2188 world: None,
2189 });
2190
2191 for adj in adjectives {
2192 let adj_pred = self.adjective_restriction(*adj, var, noun);
2193 restriction = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
2194 left: restriction,
2195 op: TokenType::And,
2196 right: adj_pred,
2197 });
2198 }
2199
2200 for pp in pps {
2201 let substituted_pp = self.substitute_pp_placeholder(pp, var);
2202 restriction = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
2203 left: restriction,
2204 op: TokenType::And,
2205 right: substituted_pp,
2206 });
2207 }
2208
2209 let substituted = self.substitute_constant_with_var_sym(predicate, noun, var)?;
2210 let body = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
2211 left: restriction,
2212 op: TokenType::And,
2213 right: substituted,
2214 });
2215 Ok(self.ctx.exprs.alloc(LogicExpr::Quantifier {
2216 kind: QuantifierKind::Existential,
2217 variable: var,
2218 body,
2219 island_id: self.current_island,
2220 }))
2221 }
2222 Some(Definiteness::Definite) => {
2223 let noun_str = self.interner.resolve(noun).to_string();
2224
2225 if Self::is_plural_noun(&noun_str) {
2226 let singular = Self::singularize_noun(&noun_str);
2227 let singular_sym = self.interner.intern(&singular);
2228 let sigma_term = Term::Sigma(singular_sym);
2229
2230 let mut substituted =
2231 self.substitute_constant_with_sigma(predicate, noun, sigma_term)?;
2232
2233 for adj in adjectives {
2237 let adj_pred = self.adjective_restriction(*adj, singular_sym, noun);
2238 let adj_on_sigma =
2239 self.substitute_constant_with_sigma(adj_pred, singular_sym, sigma_term)?;
2240 substituted = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
2241 left: adj_on_sigma,
2242 op: TokenType::And,
2243 right: substituted,
2244 });
2245 }
2246 let placeholder = self.interner.intern("_PP_SELF_");
2247 for pp in pps {
2248 let pp_sub = match pp {
2249 LogicExpr::Predicate { name, args, world } => {
2250 let new_args: Vec<Term<'a>> = args
2251 .iter()
2252 .map(|a| match a {
2253 Term::Variable(v) if *v == placeholder => sigma_term,
2254 other => *other,
2255 })
2256 .collect();
2257 self.ctx.exprs.alloc(LogicExpr::Predicate {
2258 name: *name,
2259 args: self.ctx.terms.alloc_slice(new_args),
2260 world: *world,
2261 })
2262 }
2263 other => *other,
2264 };
2265 substituted = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
2266 left: substituted,
2267 op: TokenType::And,
2268 right: pp_sub,
2269 });
2270 }
2271
2272 let verb_name = self.find_main_verb_name(predicate);
2273 let is_collective = verb_name
2274 .map(|v| {
2275 let lemma = self.interner.resolve(v);
2276 Lexer::is_collective_verb(lemma)
2277 || (Lexer::is_mixed_verb(lemma) && !self.distributive_marker)
2282 })
2283 .unwrap_or(false);
2284
2285 let gender = Gender::Unknown; self.drs.introduce_referent_with_source(singular_sym, singular_sym, gender, Number::Plural, ReferentSource::MainClause);
2290
2291 if is_collective {
2292 Ok(substituted)
2293 } else {
2294 Ok(self.ctx.exprs.alloc(LogicExpr::Distributive {
2295 predicate: substituted,
2296 }))
2297 }
2298 } else {
2299 if adjectives.is_empty() && pps.is_empty() {
2304 if let Some(prior) =
2305 self.drs.resolve_definite(self.drs.current_box_index(), noun)
2306 {
2307 if prior == noun {
2308 return Ok(predicate);
2309 }
2310 return self.substitute_constant_with_var_sym(
2311 predicate, noun, prior,
2312 );
2313 }
2314 }
2315
2316 if !adjectives.is_empty() && pps.is_empty() {
2325 if let Some(prior) = self.drs.resolve_definite_by_modifier(
2326 self.interner,
2327 self.drs.current_box_index(),
2328 noun,
2329 adjectives,
2330 ) {
2331 return self.substitute_constant_with_var_sym(
2332 predicate, noun, prior,
2333 );
2334 }
2335 }
2336
2337 if self.world_state.in_discourse_mode()
2345 && adjectives.is_empty()
2346 && pps.is_empty()
2347 && self.drs.resolve_bridging(self.interner, noun).is_none()
2348 {
2349 let y = self.next_var_name();
2350 let gender = Self::infer_noun_gender(self.interner.resolve(noun));
2351 let number = if Self::is_plural_noun(self.interner.resolve(noun)) {
2352 Number::Plural
2353 } else {
2354 Number::Singular
2355 };
2356 self.drs.introduce_referent_with_source(
2359 noun,
2360 noun,
2361 gender,
2362 number,
2363 ReferentSource::ProperName,
2364 );
2365 let restriction = self.ctx.exprs.alloc(LogicExpr::Predicate {
2366 name: noun,
2367 args: self.ctx.terms.alloc_slice([Term::Constant(noun)]),
2368 world: None,
2369 });
2370 let y_restriction = self.ctx.exprs.alloc(LogicExpr::Predicate {
2371 name: noun,
2372 args: self.ctx.terms.alloc_slice([Term::Variable(y)]),
2373 world: None,
2374 });
2375 let identity = self.ctx.exprs.alloc(LogicExpr::Identity {
2376 left: self.ctx.terms.alloc(Term::Variable(y)),
2377 right: self.ctx.terms.alloc(Term::Constant(noun)),
2378 });
2379 let uniqueness = self.ctx.exprs.alloc(LogicExpr::Quantifier {
2380 kind: QuantifierKind::Universal,
2381 variable: y,
2382 body: self.ctx.exprs.alloc(LogicExpr::BinaryOp {
2383 left: y_restriction,
2384 op: TokenType::Implies,
2385 right: identity,
2386 }),
2387 island_id: self.current_island,
2388 });
2389 let described = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
2390 left: restriction,
2391 op: TokenType::And,
2392 right: uniqueness,
2393 });
2394 return Ok(self.ctx.exprs.alloc(LogicExpr::BinaryOp {
2395 left: described,
2396 op: TokenType::And,
2397 right: predicate,
2398 }));
2399 }
2400
2401 let x = self.next_var_name();
2402 let y = self.next_var_name();
2403
2404 let mut restriction = self.ctx.exprs.alloc(LogicExpr::Predicate {
2405 name: noun,
2406 args: self.ctx.terms.alloc_slice([Term::Variable(x)]),
2407 world: None,
2408 });
2409
2410 for adj in adjectives {
2411 let adj_pred = self.adjective_restriction(*adj, x, noun);
2412 restriction = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
2413 left: restriction,
2414 op: TokenType::And,
2415 right: adj_pred,
2416 });
2417 }
2418
2419 for pp in pps {
2420 let substituted_pp = self.substitute_pp_placeholder(pp, x);
2421 restriction = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
2422 left: restriction,
2423 op: TokenType::And,
2424 right: substituted_pp,
2425 });
2426 }
2427
2428 let has_prior_antecedent = self.drs.resolve_definite(
2431 self.drs.current_box_index(),
2432 noun
2433 ).is_some();
2434
2435 if !has_prior_antecedent {
2436 if let Some((whole_var, _whole_name)) = self.drs.resolve_bridging(self.interner, noun) {
2437 let part_of_sym = self.interner.intern("PartOf");
2438 let part_of_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
2439 name: part_of_sym,
2440 args: self.ctx.terms.alloc_slice([
2441 Term::Variable(x),
2442 Term::Constant(whole_var),
2443 ]),
2444 world: None,
2445 });
2446 restriction = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
2447 left: restriction,
2448 op: TokenType::And,
2449 right: part_of_pred,
2450 });
2451 }
2452 }
2453
2454 let gender = Self::infer_noun_gender(self.interner.resolve(noun));
2459 let number = if Self::is_plural_noun(self.interner.resolve(noun)) {
2460 Number::Plural
2461 } else {
2462 Number::Singular
2463 };
2464 self.drs.introduce_referent_with_modifiers(
2469 x,
2470 noun,
2471 gender,
2472 number,
2473 ReferentSource::MainClause,
2474 adjectives.to_vec(),
2475 );
2476
2477 let mut y_restriction = self.ctx.exprs.alloc(LogicExpr::Predicate {
2478 name: noun,
2479 args: self.ctx.terms.alloc_slice([Term::Variable(y)]),
2480 world: None,
2481 });
2482 for adj in adjectives {
2483 let adj_pred = self.adjective_restriction(*adj, y, noun);
2484 y_restriction = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
2485 left: y_restriction,
2486 op: TokenType::And,
2487 right: adj_pred,
2488 });
2489 }
2490
2491 for pp in pps {
2492 let substituted_pp = self.substitute_pp_placeholder(pp, y);
2493 y_restriction = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
2494 left: y_restriction,
2495 op: TokenType::And,
2496 right: substituted_pp,
2497 });
2498 }
2499
2500 let identity = self.ctx.exprs.alloc(LogicExpr::Identity {
2501 left: self.ctx.terms.alloc(Term::Variable(y)),
2502 right: self.ctx.terms.alloc(Term::Variable(x)),
2503 });
2504 let uniqueness_body = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
2505 left: y_restriction,
2506 op: TokenType::Implies,
2507 right: identity,
2508 });
2509 let uniqueness = self.ctx.exprs.alloc(LogicExpr::Quantifier {
2510 kind: QuantifierKind::Universal,
2511 variable: y,
2512 body: uniqueness_body,
2513 island_id: self.current_island,
2514 });
2515
2516 let main_pred = self.substitute_constant_with_var_sym(predicate, noun, x)?;
2517
2518 let inner = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
2519 left: restriction,
2520 op: TokenType::And,
2521 right: uniqueness,
2522 });
2523 let body = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
2524 left: inner,
2525 op: TokenType::And,
2526 right: main_pred,
2527 });
2528
2529 Ok(self.ctx.exprs.alloc(LogicExpr::Quantifier {
2530 kind: QuantifierKind::Existential,
2531 variable: x,
2532 body,
2533 island_id: self.current_island,
2534 }))
2535 }
2536 }
2537 Some(Definiteness::Proximal) | Some(Definiteness::Distal) => {
2538 let var = self.next_var_name();
2539
2540 let mut restriction = self.ctx.exprs.alloc(LogicExpr::Predicate {
2541 name: noun,
2542 args: self.ctx.terms.alloc_slice([Term::Variable(var)]),
2543 world: None,
2544 });
2545
2546 let deictic_name = if matches!(definiteness, Some(Definiteness::Proximal)) {
2547 self.interner.intern("Proximal")
2548 } else {
2549 self.interner.intern("Distal")
2550 };
2551 let deictic_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
2552 name: deictic_name,
2553 args: self.ctx.terms.alloc_slice([Term::Variable(var)]),
2554 world: None,
2555 });
2556 restriction = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
2557 left: restriction,
2558 op: TokenType::And,
2559 right: deictic_pred,
2560 });
2561
2562 for adj in adjectives {
2563 let adj_pred = self.adjective_restriction(*adj, var, noun);
2564 restriction = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
2565 left: restriction,
2566 op: TokenType::And,
2567 right: adj_pred,
2568 });
2569 }
2570
2571 for pp in pps {
2572 let substituted_pp = self.substitute_pp_placeholder(pp, var);
2573 restriction = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
2574 left: restriction,
2575 op: TokenType::And,
2576 right: substituted_pp,
2577 });
2578 }
2579
2580 let substituted = self.substitute_constant_with_var_sym(predicate, noun, var)?;
2581 let body = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
2582 left: restriction,
2583 op: TokenType::And,
2584 right: substituted,
2585 });
2586 Ok(self.ctx.exprs.alloc(LogicExpr::Quantifier {
2587 kind: QuantifierKind::Existential,
2588 variable: var,
2589 body,
2590 island_id: self.current_island,
2591 }))
2592 }
2593 None => Ok(predicate),
2594 }
2595 }
2596
2597 fn wrap_with_definiteness_for_object(
2598 &mut self,
2599 definiteness: Option<Definiteness>,
2600 noun: Symbol,
2601 predicate: &'a LogicExpr<'a>,
2602 ) -> ParseResult<&'a LogicExpr<'a>> {
2603 match definiteness {
2604 Some(Definiteness::Indefinite) => {
2605 let var = self.next_var_name();
2606
2607 let gender = Self::infer_noun_gender(self.interner.resolve(noun));
2610 let number = if Self::is_plural_noun(self.interner.resolve(noun)) {
2611 Number::Plural
2612 } else {
2613 Number::Singular
2614 };
2615 if self.in_negative_quantifier {
2616 self.drs.introduce_referent_with_source(var, noun, gender, number, ReferentSource::NegationScope);
2617 } else {
2618 self.drs.introduce_referent(var, noun, gender, number);
2619 }
2620
2621 let type_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
2622 name: noun,
2623 args: self.ctx.terms.alloc_slice([Term::Variable(var)]),
2624 world: None,
2625 });
2626 let substituted = self.substitute_constant_with_var(predicate, noun, var)?;
2627 let body = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
2628 left: type_pred,
2629 op: TokenType::And,
2630 right: substituted,
2631 });
2632 Ok(self.ctx.exprs.alloc(LogicExpr::Quantifier {
2633 kind: QuantifierKind::Existential,
2634 variable: var,
2635 body,
2636 island_id: self.current_island,
2637 }))
2638 }
2639 Some(Definiteness::Definite) => {
2640 let x = self.next_var_name();
2641 let y = self.next_var_name();
2642
2643 let type_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
2644 name: noun,
2645 args: self.ctx.terms.alloc_slice([Term::Variable(x)]),
2646 world: None,
2647 });
2648
2649 let identity = self.ctx.exprs.alloc(LogicExpr::Identity {
2650 left: self.ctx.terms.alloc(Term::Variable(y)),
2651 right: self.ctx.terms.alloc(Term::Variable(x)),
2652 });
2653 let inner_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
2654 name: noun,
2655 args: self.ctx.terms.alloc_slice([Term::Variable(y)]),
2656 world: None,
2657 });
2658 let uniqueness_body = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
2659 left: inner_pred,
2660 op: TokenType::Implies,
2661 right: identity,
2662 });
2663 let uniqueness = self.ctx.exprs.alloc(LogicExpr::Quantifier {
2664 kind: QuantifierKind::Universal,
2665 variable: y,
2666 body: uniqueness_body,
2667 island_id: self.current_island,
2668 });
2669
2670 let main_pred = self.substitute_constant_with_var(predicate, noun, x)?;
2671
2672 let type_and_unique = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
2673 left: type_pred,
2674 op: TokenType::And,
2675 right: uniqueness,
2676 });
2677 let body = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
2678 left: type_and_unique,
2679 op: TokenType::And,
2680 right: main_pred,
2681 });
2682
2683 Ok(self.ctx.exprs.alloc(LogicExpr::Quantifier {
2684 kind: QuantifierKind::Existential,
2685 variable: x,
2686 body,
2687 island_id: self.current_island,
2688 }))
2689 }
2690 Some(Definiteness::Proximal) | Some(Definiteness::Distal) => {
2691 let var = self.next_var_name();
2692
2693 let mut restriction = self.ctx.exprs.alloc(LogicExpr::Predicate {
2694 name: noun,
2695 args: self.ctx.terms.alloc_slice([Term::Variable(var)]),
2696 world: None,
2697 });
2698
2699 let deictic_name = if matches!(definiteness, Some(Definiteness::Proximal)) {
2700 self.interner.intern("Proximal")
2701 } else {
2702 self.interner.intern("Distal")
2703 };
2704 let deictic_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
2705 name: deictic_name,
2706 args: self.ctx.terms.alloc_slice([Term::Variable(var)]),
2707 world: None,
2708 });
2709 restriction = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
2710 left: restriction,
2711 op: TokenType::And,
2712 right: deictic_pred,
2713 });
2714
2715 let substituted = self.substitute_constant_with_var(predicate, noun, var)?;
2716 let body = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
2717 left: restriction,
2718 op: TokenType::And,
2719 right: substituted,
2720 });
2721 Ok(self.ctx.exprs.alloc(LogicExpr::Quantifier {
2722 kind: QuantifierKind::Existential,
2723 variable: var,
2724 body,
2725 island_id: self.current_island,
2726 }))
2727 }
2728 None => Ok(predicate),
2729 }
2730 }
2731
2732 fn substitute_pp_placeholder(&mut self, pp: &'a LogicExpr<'a>, var: Symbol) -> &'a LogicExpr<'a> {
2733 let placeholder = self.interner.intern("_PP_SELF_");
2734 match pp {
2735 LogicExpr::Predicate { name, args, .. } => {
2736 let new_args: Vec<Term<'a>> = args
2737 .iter()
2738 .map(|arg| match arg {
2739 Term::Variable(v) if *v == placeholder => Term::Variable(var),
2740 other => *other,
2741 })
2742 .collect();
2743 self.ctx.exprs.alloc(LogicExpr::Predicate {
2744 name: *name,
2745 args: self.ctx.terms.alloc_slice(new_args),
2746 world: None,
2747 })
2748 }
2749 LogicExpr::BinaryOp { left, op, right } => {
2754 let l = self.substitute_pp_placeholder(left, var);
2755 let r = self.substitute_pp_placeholder(right, var);
2756 self.ctx.exprs.alloc(LogicExpr::BinaryOp { left: l, op: op.clone(), right: r })
2757 }
2758 LogicExpr::UnaryOp { op, operand } => {
2759 let o = self.substitute_pp_placeholder(operand, var);
2760 self.ctx.exprs.alloc(LogicExpr::UnaryOp { op: op.clone(), operand: o })
2761 }
2762 LogicExpr::Quantifier { kind, variable, body, island_id } => {
2763 let b = self.substitute_pp_placeholder(body, var);
2764 self.ctx.exprs.alloc(LogicExpr::Quantifier {
2765 kind: *kind,
2766 variable: *variable,
2767 body: b,
2768 island_id: *island_id,
2769 })
2770 }
2771 LogicExpr::Temporal { operator, body } => {
2772 let b = self.substitute_pp_placeholder(body, var);
2773 self.ctx.exprs.alloc(LogicExpr::Temporal { operator: *operator, body: b })
2774 }
2775 LogicExpr::NeoEvent(data) => {
2776 let new_roles: Vec<(ThematicRole, Term<'a>)> = data
2777 .roles
2778 .iter()
2779 .map(|(role, term)| {
2780 let new_term = match term {
2781 Term::Variable(v) if *v == placeholder => Term::Variable(var),
2782 other => *other,
2783 };
2784 (*role, new_term)
2785 })
2786 .collect();
2787 self.ctx.exprs.alloc(LogicExpr::NeoEvent(Box::new(NeoEventData {
2788 event_var: data.event_var,
2789 verb: data.verb,
2790 roles: self.ctx.roles.alloc_slice(new_roles),
2791 modifiers: data.modifiers,
2792 suppress_existential: data.suppress_existential,
2793 world: data.world,
2794 })))
2795 }
2796 _ => pp,
2797 }
2798 }
2799
2800 fn substitute_constant_with_var(
2801 &self,
2802 expr: &'a LogicExpr<'a>,
2803 constant_name: Symbol,
2804 var_name: Symbol,
2805 ) -> ParseResult<&'a LogicExpr<'a>> {
2806 match expr {
2807 LogicExpr::Predicate { name, args, .. } => {
2808 let new_args: Vec<Term<'a>> = args
2809 .iter()
2810 .map(|arg| match arg {
2811 Term::Constant(c) if *c == constant_name => Term::Variable(var_name),
2812 Term::Constant(c) => Term::Constant(*c),
2813 Term::Variable(v) => Term::Variable(*v),
2814 Term::Function(n, a) => Term::Function(*n, *a),
2815 Term::Group(m) => Term::Group(*m),
2816 Term::Possessed { possessor, possessed } => Term::Possessed {
2817 possessor: *possessor,
2818 possessed: *possessed,
2819 },
2820 Term::Sigma(p) => Term::Sigma(*p),
2821 Term::Intension(p) => Term::Intension(*p),
2822 Term::Kind(k) => Term::Kind(*k),
2823 Term::Proposition(e) => Term::Proposition(*e),
2824 Term::Value { kind, unit, dimension } => Term::Value {
2825 kind: *kind,
2826 unit: *unit,
2827 dimension: *dimension,
2828 },
2829 })
2830 .collect();
2831 Ok(self.ctx.exprs.alloc(LogicExpr::Predicate {
2832 name: *name,
2833 args: self.ctx.terms.alloc_slice(new_args),
2834 world: None,
2835 }))
2836 }
2837 LogicExpr::Temporal { operator, body } => Ok(self.ctx.exprs.alloc(LogicExpr::Temporal {
2838 operator: *operator,
2839 body: self.substitute_constant_with_var(body, constant_name, var_name)?,
2840 })),
2841 LogicExpr::Aspectual { operator, body } => Ok(self.ctx.exprs.alloc(LogicExpr::Aspectual {
2842 operator: *operator,
2843 body: self.substitute_constant_with_var(body, constant_name, var_name)?,
2844 })),
2845 LogicExpr::UnaryOp { op, operand } => Ok(self.ctx.exprs.alloc(LogicExpr::UnaryOp {
2846 op: op.clone(),
2847 operand: self.substitute_constant_with_var(operand, constant_name, var_name)?,
2848 })),
2849 LogicExpr::BinaryOp { left, op, right } => Ok(self.ctx.exprs.alloc(LogicExpr::BinaryOp {
2850 left: self.substitute_constant_with_var(left, constant_name, var_name)?,
2851 op: op.clone(),
2852 right: self.substitute_constant_with_var(right, constant_name, var_name)?,
2853 })),
2854 LogicExpr::Event { predicate, adverbs } => Ok(self.ctx.exprs.alloc(LogicExpr::Event {
2855 predicate: self.substitute_constant_with_var(predicate, constant_name, var_name)?,
2856 adverbs: *adverbs,
2857 })),
2858 LogicExpr::TemporalAnchor { anchor, body } => {
2859 Ok(self.ctx.exprs.alloc(LogicExpr::TemporalAnchor {
2860 anchor: *anchor,
2861 body: self.substitute_constant_with_var(body, constant_name, var_name)?,
2862 }))
2863 }
2864 LogicExpr::NeoEvent(data) => {
2865 let new_roles: Vec<(crate::ast::ThematicRole, Term<'a>)> = data
2867 .roles
2868 .iter()
2869 .map(|(role, term)| {
2870 let new_term = match term {
2871 Term::Constant(c) if *c == constant_name => Term::Variable(var_name),
2872 Term::Constant(c) => Term::Constant(*c),
2873 Term::Variable(v) => Term::Variable(*v),
2874 Term::Function(n, a) => Term::Function(*n, *a),
2875 Term::Group(m) => Term::Group(*m),
2876 Term::Possessed { possessor, possessed } => Term::Possessed {
2877 possessor: *possessor,
2878 possessed: *possessed,
2879 },
2880 Term::Sigma(p) => Term::Sigma(*p),
2881 Term::Intension(p) => Term::Intension(*p),
2882 Term::Kind(k) => Term::Kind(*k),
2883 Term::Proposition(e) => Term::Proposition(*e),
2884 Term::Value { kind, unit, dimension } => Term::Value {
2885 kind: *kind,
2886 unit: *unit,
2887 dimension: *dimension,
2888 },
2889 };
2890 (*role, new_term)
2891 })
2892 .collect();
2893 Ok(self.ctx.exprs.alloc(LogicExpr::NeoEvent(Box::new(crate::ast::NeoEventData {
2894 event_var: data.event_var,
2895 verb: data.verb,
2896 roles: self.ctx.roles.alloc_slice(new_roles),
2897 modifiers: data.modifiers,
2898 suppress_existential: data.suppress_existential,
2899 world: None,
2900 }))))
2901 }
2902 LogicExpr::Quantifier { kind, variable, body, island_id } => {
2904 let new_body = self.substitute_constant_with_var(body, constant_name, var_name)?;
2905 Ok(self.ctx.exprs.alloc(LogicExpr::Quantifier {
2906 kind: *kind,
2907 variable: *variable,
2908 body: new_body,
2909 island_id: *island_id,
2910 }))
2911 }
2912 LogicExpr::Control { verb, subject, object, infinitive } => {
2913 let sub_term = |t: &Term<'a>| -> Term<'a> {
2914 match t {
2915 Term::Constant(c) if *c == constant_name => Term::Variable(var_name),
2916 other => other.clone(),
2917 }
2918 };
2919 Ok(self.ctx.exprs.alloc(LogicExpr::Control {
2920 verb: *verb,
2921 subject: self.ctx.terms.alloc(sub_term(subject)),
2922 object: match object {
2923 Some(o) => Some(&*self.ctx.terms.alloc(sub_term(o))),
2924 None => None,
2925 },
2926 infinitive: self.substitute_constant_with_var(infinitive, constant_name, var_name)?,
2927 }))
2928 }
2929 _ => Ok(expr),
2930 }
2931 }
2932
2933 fn substitute_constant_with_var_sym(
2934 &self,
2935 expr: &'a LogicExpr<'a>,
2936 constant_name: Symbol,
2937 var_name: Symbol,
2938 ) -> ParseResult<&'a LogicExpr<'a>> {
2939 self.substitute_constant_with_var(expr, constant_name, var_name)
2940 }
2941
2942 fn substitute_variable_with_constant(
2943 &self,
2944 expr: &'a LogicExpr<'a>,
2945 from_var: Symbol,
2946 to_const: Symbol,
2947 ) -> ParseResult<&'a LogicExpr<'a>> {
2948 let map_term = |t: &Term<'a>| -> Term<'a> {
2949 match t {
2950 Term::Variable(v) if *v == from_var => Term::Constant(to_const),
2951 other => other.clone(),
2952 }
2953 };
2954 match expr {
2955 LogicExpr::Predicate { name, args, world } => {
2956 let new_args: Vec<Term<'a>> = args.iter().map(&map_term).collect();
2957 Ok(self.ctx.exprs.alloc(LogicExpr::Predicate {
2958 name: *name,
2959 args: self.ctx.terms.alloc_slice(new_args),
2960 world: *world,
2961 }))
2962 }
2963 LogicExpr::Identity { left, right } => Ok(self.ctx.exprs.alloc(LogicExpr::Identity {
2964 left: self.ctx.terms.alloc(map_term(left)),
2965 right: self.ctx.terms.alloc(map_term(right)),
2966 })),
2967 LogicExpr::Temporal { operator, body } => Ok(self.ctx.exprs.alloc(LogicExpr::Temporal {
2968 operator: *operator,
2969 body: self.substitute_variable_with_constant(body, from_var, to_const)?,
2970 })),
2971 LogicExpr::Aspectual { operator, body } => {
2972 Ok(self.ctx.exprs.alloc(LogicExpr::Aspectual {
2973 operator: *operator,
2974 body: self.substitute_variable_with_constant(body, from_var, to_const)?,
2975 }))
2976 }
2977 LogicExpr::UnaryOp { op, operand } => Ok(self.ctx.exprs.alloc(LogicExpr::UnaryOp {
2978 op: op.clone(),
2979 operand: self.substitute_variable_with_constant(operand, from_var, to_const)?,
2980 })),
2981 LogicExpr::BinaryOp { left, op, right } => Ok(self.ctx.exprs.alloc(LogicExpr::BinaryOp {
2982 left: self.substitute_variable_with_constant(left, from_var, to_const)?,
2983 op: op.clone(),
2984 right: self.substitute_variable_with_constant(right, from_var, to_const)?,
2985 })),
2986 LogicExpr::Event { predicate, adverbs } => Ok(self.ctx.exprs.alloc(LogicExpr::Event {
2987 predicate: self.substitute_variable_with_constant(predicate, from_var, to_const)?,
2988 adverbs: *adverbs,
2989 })),
2990 LogicExpr::TemporalAnchor { anchor, body } => {
2991 Ok(self.ctx.exprs.alloc(LogicExpr::TemporalAnchor {
2992 anchor: *anchor,
2993 body: self.substitute_variable_with_constant(body, from_var, to_const)?,
2994 }))
2995 }
2996 LogicExpr::NeoEvent(data) => {
2997 let new_roles: Vec<(crate::ast::ThematicRole, Term<'a>)> =
2998 data.roles.iter().map(|(role, term)| (*role, map_term(term))).collect();
2999 Ok(self.ctx.exprs.alloc(LogicExpr::NeoEvent(Box::new(crate::ast::NeoEventData {
3000 event_var: data.event_var,
3001 verb: data.verb,
3002 roles: self.ctx.roles.alloc_slice(new_roles),
3003 modifiers: data.modifiers,
3004 suppress_existential: data.suppress_existential,
3005 world: None,
3006 }))))
3007 }
3008 LogicExpr::Quantifier { kind, variable, body, island_id } => {
3009 if *variable == from_var {
3012 return Ok(expr);
3013 }
3014 Ok(self.ctx.exprs.alloc(LogicExpr::Quantifier {
3015 kind: *kind,
3016 variable: *variable,
3017 body: self.substitute_variable_with_constant(body, from_var, to_const)?,
3018 island_id: *island_id,
3019 }))
3020 }
3021 LogicExpr::Control { verb, subject, object, infinitive } => {
3022 Ok(self.ctx.exprs.alloc(LogicExpr::Control {
3023 verb: *verb,
3024 subject: self.ctx.terms.alloc(map_term(subject)),
3025 object: object.map(|o| &*self.ctx.terms.alloc(map_term(o))),
3026 infinitive: self.substitute_variable_with_constant(infinitive, from_var, to_const)?,
3027 }))
3028 }
3029 _ => Ok(expr),
3030 }
3031 }
3032
3033 fn substitute_constant_with_sigma(
3034 &self,
3035 expr: &'a LogicExpr<'a>,
3036 constant_name: Symbol,
3037 sigma_term: Term<'a>,
3038 ) -> ParseResult<&'a LogicExpr<'a>> {
3039 match expr {
3040 LogicExpr::Predicate { name, args, .. } => {
3041 let new_args: Vec<Term<'a>> = args
3042 .iter()
3043 .map(|arg| match arg {
3044 Term::Constant(c) if *c == constant_name => sigma_term.clone(),
3045 Term::Constant(c) => Term::Constant(*c),
3046 Term::Variable(v) => Term::Variable(*v),
3047 Term::Function(n, a) => Term::Function(*n, *a),
3048 Term::Group(m) => Term::Group(*m),
3049 Term::Possessed { possessor, possessed } => Term::Possessed {
3050 possessor: *possessor,
3051 possessed: *possessed,
3052 },
3053 Term::Sigma(p) => Term::Sigma(*p),
3054 Term::Intension(p) => Term::Intension(*p),
3055 Term::Kind(k) => Term::Kind(*k),
3056 Term::Proposition(e) => Term::Proposition(*e),
3057 Term::Value { kind, unit, dimension } => Term::Value {
3058 kind: *kind,
3059 unit: *unit,
3060 dimension: *dimension,
3061 },
3062 })
3063 .collect();
3064 Ok(self.ctx.exprs.alloc(LogicExpr::Predicate {
3065 name: *name,
3066 args: self.ctx.terms.alloc_slice(new_args),
3067 world: None,
3068 }))
3069 }
3070 LogicExpr::Temporal { operator, body } => Ok(self.ctx.exprs.alloc(LogicExpr::Temporal {
3071 operator: *operator,
3072 body: self.substitute_constant_with_sigma(body, constant_name, sigma_term)?,
3073 })),
3074 LogicExpr::Aspectual { operator, body } => Ok(self.ctx.exprs.alloc(LogicExpr::Aspectual {
3075 operator: *operator,
3076 body: self.substitute_constant_with_sigma(body, constant_name, sigma_term)?,
3077 })),
3078 LogicExpr::UnaryOp { op, operand } => Ok(self.ctx.exprs.alloc(LogicExpr::UnaryOp {
3079 op: op.clone(),
3080 operand: self.substitute_constant_with_sigma(operand, constant_name, sigma_term)?,
3081 })),
3082 LogicExpr::BinaryOp { left, op, right } => Ok(self.ctx.exprs.alloc(LogicExpr::BinaryOp {
3083 left: self.substitute_constant_with_sigma(
3084 left,
3085 constant_name,
3086 sigma_term.clone(),
3087 )?,
3088 op: op.clone(),
3089 right: self.substitute_constant_with_sigma(right, constant_name, sigma_term)?,
3090 })),
3091 LogicExpr::Event { predicate, adverbs } => Ok(self.ctx.exprs.alloc(LogicExpr::Event {
3092 predicate: self.substitute_constant_with_sigma(
3093 predicate,
3094 constant_name,
3095 sigma_term,
3096 )?,
3097 adverbs: *adverbs,
3098 })),
3099 LogicExpr::TemporalAnchor { anchor, body } => {
3100 Ok(self.ctx.exprs.alloc(LogicExpr::TemporalAnchor {
3101 anchor: *anchor,
3102 body: self.substitute_constant_with_sigma(body, constant_name, sigma_term)?,
3103 }))
3104 }
3105 LogicExpr::NeoEvent(data) => {
3106 let new_roles: Vec<(crate::ast::ThematicRole, Term<'a>)> = data
3107 .roles
3108 .iter()
3109 .map(|(role, term)| {
3110 let new_term = match term {
3111 Term::Constant(c) if *c == constant_name => sigma_term.clone(),
3112 Term::Constant(c) => Term::Constant(*c),
3113 Term::Variable(v) => Term::Variable(*v),
3114 Term::Function(n, a) => Term::Function(*n, *a),
3115 Term::Group(m) => Term::Group(*m),
3116 Term::Possessed { possessor, possessed } => Term::Possessed {
3117 possessor: *possessor,
3118 possessed: *possessed,
3119 },
3120 Term::Sigma(p) => Term::Sigma(*p),
3121 Term::Intension(p) => Term::Intension(*p),
3122 Term::Kind(k) => Term::Kind(*k),
3123 Term::Proposition(e) => Term::Proposition(*e),
3124 Term::Value { kind, unit, dimension } => Term::Value {
3125 kind: *kind,
3126 unit: *unit,
3127 dimension: *dimension,
3128 },
3129 };
3130 (*role, new_term)
3131 })
3132 .collect();
3133 Ok(self.ctx.exprs.alloc(LogicExpr::NeoEvent(Box::new(crate::ast::NeoEventData {
3134 event_var: data.event_var,
3135 verb: data.verb,
3136 roles: self.ctx.roles.alloc_slice(new_roles),
3137 modifiers: data.modifiers,
3138 suppress_existential: data.suppress_existential,
3139 world: None,
3140 }))))
3141 }
3142 LogicExpr::Distributive { predicate } => Ok(self.ctx.exprs.alloc(LogicExpr::Distributive {
3143 predicate: self.substitute_constant_with_sigma(predicate, constant_name, sigma_term)?,
3144 })),
3145 _ => Ok(expr),
3146 }
3147 }
3148
3149 fn find_main_verb_name(&self, expr: &LogicExpr<'a>) -> Option<Symbol> {
3150 match expr {
3151 LogicExpr::Predicate { name, .. } => Some(*name),
3152 LogicExpr::NeoEvent(data) => Some(data.verb),
3153 LogicExpr::Temporal { body, .. } => self.find_main_verb_name(body),
3154 LogicExpr::Aspectual { body, .. } => self.find_main_verb_name(body),
3155 LogicExpr::Event { predicate, .. } => self.find_main_verb_name(predicate),
3156 LogicExpr::TemporalAnchor { body, .. } => self.find_main_verb_name(body),
3157 LogicExpr::UnaryOp { operand, .. } => self.find_main_verb_name(operand),
3158 LogicExpr::BinaryOp { left, .. } => self.find_main_verb_name(left),
3159 _ => None,
3160 }
3161 }
3162
3163 fn transform_cardinal_to_group(&mut self, expr: &'a LogicExpr<'a>) -> ParseResult<&'a LogicExpr<'a>> {
3164 match expr {
3165 LogicExpr::Quantifier { kind: QuantifierKind::Cardinal(n), variable, body, .. } => {
3166 let group_var = self.interner.intern("g");
3167 let member_var = *variable;
3168
3169 let (restriction, body_rest) = match body {
3172 LogicExpr::BinaryOp { left, op: TokenType::And, right } => (*left, *right),
3173 _ => return Ok(expr),
3174 };
3175
3176 let transformed_body = self.substitute_constant_with_var_sym(body_rest, member_var, group_var)?;
3178
3179 Ok(self.ctx.exprs.alloc(LogicExpr::GroupQuantifier {
3180 group_var,
3181 count: *n,
3182 member_var,
3183 restriction,
3184 body: transformed_body,
3185 }))
3186 }
3187 LogicExpr::Temporal { operator, body } => {
3189 let transformed = self.transform_cardinal_to_group(body)?;
3190 Ok(self.ctx.exprs.alloc(LogicExpr::Temporal {
3191 operator: *operator,
3192 body: transformed,
3193 }))
3194 }
3195 LogicExpr::Aspectual { operator, body } => {
3196 let transformed = self.transform_cardinal_to_group(body)?;
3197 Ok(self.ctx.exprs.alloc(LogicExpr::Aspectual {
3198 operator: *operator,
3199 body: transformed,
3200 }))
3201 }
3202 LogicExpr::UnaryOp { op, operand } => {
3203 let transformed = self.transform_cardinal_to_group(operand)?;
3204 Ok(self.ctx.exprs.alloc(LogicExpr::UnaryOp {
3205 op: op.clone(),
3206 operand: transformed,
3207 }))
3208 }
3209 LogicExpr::BinaryOp { left, op, right } => {
3210 let transformed_left = self.transform_cardinal_to_group(left)?;
3211 let transformed_right = self.transform_cardinal_to_group(right)?;
3212 Ok(self.ctx.exprs.alloc(LogicExpr::BinaryOp {
3213 left: transformed_left,
3214 op: op.clone(),
3215 right: transformed_right,
3216 }))
3217 }
3218 LogicExpr::Distributive { predicate } => {
3219 let transformed = self.transform_cardinal_to_group(predicate)?;
3220 Ok(self.ctx.exprs.alloc(LogicExpr::Distributive {
3221 predicate: transformed,
3222 }))
3223 }
3224 LogicExpr::Quantifier { kind, variable, body, island_id } => {
3225 let transformed = self.transform_cardinal_to_group(body)?;
3226 Ok(self.ctx.exprs.alloc(LogicExpr::Quantifier {
3227 kind: kind.clone(),
3228 variable: *variable,
3229 body: transformed,
3230 island_id: *island_id,
3231 }))
3232 }
3233 _ => Ok(expr),
3234 }
3235 }
3236
3237 fn build_verb_neo_event(
3238 &mut self,
3239 verb: Symbol,
3240 subject_var: Symbol,
3241 object: Option<Term<'a>>,
3242 modifiers: Vec<Symbol>,
3243 ) -> &'a LogicExpr<'a> {
3244 let event_var = self.get_event_var();
3245
3246 let verb_str = self.interner.resolve(verb).to_lowercase();
3248 let is_unaccusative = lookup_verb_db(&verb_str)
3249 .map(|meta| meta.features.contains(&Feature::Unaccusative))
3250 .unwrap_or(false);
3251
3252 let has_object = object.is_some();
3254 let subject_role = if is_unaccusative && !has_object {
3255 ThematicRole::Theme
3256 } else {
3257 ThematicRole::Agent
3258 };
3259
3260 let mut roles = vec![(subject_role, Term::Variable(subject_var))];
3262 if let Some(obj_term) = object {
3263 roles.push((ThematicRole::Theme, obj_term));
3264 }
3265
3266 self.ctx.exprs.alloc(LogicExpr::NeoEvent(Box::new(NeoEventData {
3269 event_var,
3270 verb,
3271 roles: self.ctx.roles.alloc_slice(roles),
3272 modifiers: self.ctx.syms.alloc_slice(modifiers),
3273 suppress_existential: false,
3274 world: None,
3275 })))
3276 }
3277}
3278
3279impl<'a, 'ctx, 'int> Parser<'a, 'ctx, 'int> {
3281 pub(super) fn at_clause_boundary(&self) -> bool {
3284 matches!(
3285 self.peek().kind,
3286 TokenType::Period
3287 | TokenType::Exclamation
3288 | TokenType::EOF
3289 | TokenType::Comma
3290 | TokenType::RParen
3291 | TokenType::And
3292 | TokenType::Or
3293 | TokenType::Iff
3294 | TokenType::Then
3295 )
3296 }
3297
3298 fn parse_quantified_delegating(&mut self) -> ParseResult<&'a LogicExpr<'a>> {
3304 use super::verb::LogicVerbParsing;
3305
3306 let quantifier_token = self.previous().kind.clone();
3307 let var_name = self.next_var_name();
3308
3309 let was_in_negative_quantifier = self.in_negative_quantifier;
3310 if matches!(quantifier_token, TokenType::No) {
3311 self.in_negative_quantifier = true;
3312 }
3313
3314 let restriction = self.parse_restriction(var_name)?;
3315
3316 let mut copula_vp: Option<&'a LogicExpr<'a>> = None;
3320 if matches!(self.peek().kind, TokenType::Verb { .. })
3321 && matches!(
3322 self.tokens.get(self.current + 1).map(|t| t.kind.clone()),
3323 Some(TokenType::Reciprocal)
3324 )
3325 {
3326 let (verb, recip_time, _, _) = self.consume_verb_with_metadata();
3327 self.advance(); let other_var = self.next_var_name();
3329 let other_restriction = self.rename_var_in_expr(restriction, var_name, other_var);
3330 let distinct = self.ctx.exprs.alloc(LogicExpr::UnaryOp {
3331 op: TokenType::Not,
3332 operand: self.ctx.exprs.alloc(LogicExpr::Identity {
3333 left: self.ctx.terms.alloc(Term::Variable(other_var)),
3334 right: self.ctx.terms.alloc(Term::Variable(var_name)),
3335 }),
3336 });
3337 let modifiers = match recip_time {
3338 Time::Past => vec![self.interner.intern("Past")],
3339 Time::Future => vec![self.interner.intern("Future")],
3340 _ => vec![],
3341 };
3342 let event_var = self.get_event_var();
3343 let suppress_existential = self.drs.in_conditional_antecedent();
3344 let event = self.ctx.exprs.alloc(LogicExpr::NeoEvent(Box::new(NeoEventData {
3345 event_var,
3346 verb,
3347 roles: self.ctx.roles.alloc_slice(vec![
3348 (ThematicRole::Agent, Term::Variable(var_name)),
3349 (ThematicRole::Theme, Term::Variable(other_var)),
3350 ]),
3351 modifiers: self.ctx.syms.alloc_slice(modifiers),
3352 suppress_existential,
3353 world: None,
3354 })));
3355 let antecedent = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
3356 left: other_restriction,
3357 op: TokenType::And,
3358 right: distinct,
3359 });
3360 let pair_body = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
3361 left: antecedent,
3362 op: TokenType::Implies,
3363 right: event,
3364 });
3365 copula_vp = Some(self.ctx.exprs.alloc(LogicExpr::Quantifier {
3366 kind: QuantifierKind::Universal,
3367 variable: other_var,
3368 body: pair_body,
3369 island_id: self.current_island,
3370 }));
3371 }
3372
3373 if matches!(
3378 self.peek().kind,
3379 TokenType::Is | TokenType::Are | TokenType::Was | TokenType::Were
3380 ) {
3381 let copula_past = matches!(self.peek().kind, TokenType::Was | TokenType::Were);
3382 if let Some(TokenType::Verb { aspect, .. }) =
3383 self.tokens.get(self.current + 1).map(|t| t.kind.clone())
3384 {
3385 if aspect == crate::lexicon::Aspect::Progressive {
3386 self.advance(); self.pending_time =
3388 Some(if copula_past { Time::Past } else { Time::None });
3389 } else {
3390 self.advance(); let (verb, _, _, _) = self.consume_verb_with_metadata();
3392 let mut modifiers = if copula_past {
3393 vec![self.interner.intern("Past")]
3394 } else {
3395 vec![]
3396 };
3397 modifiers.extend(self.collect_adverbs());
3398
3399 let mut roles = vec![(ThematicRole::Theme, Term::Variable(var_name))];
3400 let mut agent_quant: Option<(TokenType, Symbol, Symbol)> = None;
3401 if self.check_preposition_is("by") {
3402 self.advance(); if self.check_quantifier() {
3404 let q = self.advance().kind.clone();
3405 let a_np = self.parse_noun_phrase(false)?;
3406 let a_var = self.next_var_name();
3407 roles.push((ThematicRole::Agent, Term::Variable(a_var)));
3408 agent_quant = Some((q, a_var, a_np.noun));
3409 } else if self.check_content_word() || self.check_article() {
3410 let a_np = self.parse_noun_phrase(false)?;
3411 roles.push((ThematicRole::Agent, Term::Constant(a_np.noun)));
3412 }
3413 }
3414
3415 let event_var = self.get_event_var();
3416 let suppress_existential = self.drs.in_conditional_antecedent();
3417 let passive = self.ctx.exprs.alloc(LogicExpr::NeoEvent(Box::new(
3418 NeoEventData {
3419 event_var,
3420 verb,
3421 roles: self.ctx.roles.alloc_slice(roles),
3422 modifiers: self.ctx.syms.alloc_slice(modifiers),
3423 suppress_existential,
3424 world: None,
3425 },
3426 )));
3427 copula_vp = Some(if let Some((q, a_var, a_noun)) = agent_quant {
3428 let a_restriction = self.ctx.exprs.alloc(LogicExpr::Predicate {
3429 name: a_noun,
3430 args: self.ctx.terms.alloc_slice([Term::Variable(a_var)]),
3431 world: None,
3432 });
3433 let (a_kind, a_op) = match q {
3434 TokenType::All => (QuantifierKind::Universal, TokenType::Implies),
3435 TokenType::Most => (QuantifierKind::Most, TokenType::And),
3436 TokenType::Few => (QuantifierKind::Few, TokenType::And),
3437 TokenType::Many => (QuantifierKind::Many, TokenType::And),
3438 _ => (QuantifierKind::Existential, TokenType::And),
3439 };
3440 let a_body = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
3441 left: a_restriction,
3442 op: a_op,
3443 right: passive,
3444 });
3445 self.ctx.exprs.alloc(LogicExpr::Quantifier {
3446 kind: a_kind,
3447 variable: a_var,
3448 body: a_body,
3449 island_id: self.current_island,
3450 })
3451 } else {
3452 passive
3453 });
3454 }
3455 }
3456 }
3457
3458 let vp = match copula_vp {
3459 Some(vp) => vp,
3460 None => self.parse_predicate_with_subject_as_var(var_name)?,
3461 };
3462 let vp = if self.check_temporal_adverb() {
3465 if let TokenType::TemporalAdverb(anchor) = self.advance().kind.clone() {
3466 &*self.ctx.exprs.alloc(LogicExpr::TemporalAnchor { anchor, body: vp })
3467 } else {
3468 vp
3469 }
3470 } else {
3471 vp
3472 };
3473 self.in_negative_quantifier = was_in_negative_quantifier;
3474
3475 let consequent = if matches!(quantifier_token, TokenType::No) {
3477 self.ctx.exprs.alloc(LogicExpr::UnaryOp {
3478 op: TokenType::Not,
3479 operand: vp,
3480 })
3481 } else {
3482 vp
3483 };
3484
3485 let universal_frame = matches!(
3486 quantifier_token,
3487 TokenType::All | TokenType::Any | TokenType::No
3488 );
3489 let body = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
3490 left: restriction,
3491 op: if universal_frame { TokenType::Implies } else { TokenType::And },
3492 right: consequent,
3493 });
3494
3495 let mut restriction_vars = Vec::new();
3500 self.collect_unbound_vars(restriction, &mut vec![var_name], &mut restriction_vars);
3501 let mut body = body;
3502 for donkey_var in restriction_vars {
3503 if self.expr_mentions_var(consequent, donkey_var) {
3504 body = self.ctx.exprs.alloc(LogicExpr::Quantifier {
3505 kind: if universal_frame {
3506 QuantifierKind::Universal
3507 } else {
3508 QuantifierKind::Existential
3509 },
3510 variable: donkey_var,
3511 body,
3512 island_id: self.current_island,
3513 });
3514 }
3515 }
3516
3517 let kind = match quantifier_token {
3518 TokenType::All | TokenType::Any | TokenType::No => QuantifierKind::Universal,
3519 TokenType::Some => QuantifierKind::Existential,
3520 TokenType::Most => QuantifierKind::Most,
3521 TokenType::Few => QuantifierKind::Few,
3522 TokenType::Many => QuantifierKind::Many,
3523 TokenType::Cardinal(n) => QuantifierKind::Cardinal(n),
3524 TokenType::AtLeast(n) => QuantifierKind::AtLeast(n),
3525 TokenType::AtMost(n) => QuantifierKind::AtMost(n),
3526 _ => QuantifierKind::Universal,
3527 };
3528
3529 Ok(self.ctx.exprs.alloc(LogicExpr::Quantifier {
3530 kind,
3531 variable: var_name,
3532 body,
3533 island_id: self.current_island,
3534 }))
3535 }
3536
3537 fn rename_var_in_expr(
3540 &self,
3541 expr: &'a LogicExpr<'a>,
3542 from: Symbol,
3543 to: Symbol,
3544 ) -> &'a LogicExpr<'a> {
3545 let rename_term = |t: &Term<'a>| -> Term<'a> {
3546 match t {
3547 Term::Variable(v) if *v == from => Term::Variable(to),
3548 other => other.clone(),
3549 }
3550 };
3551 match expr {
3552 LogicExpr::Predicate { name, args, world } => {
3553 let new_args: Vec<Term<'a>> = args.iter().map(|a| rename_term(a)).collect();
3554 self.ctx.exprs.alloc(LogicExpr::Predicate {
3555 name: *name,
3556 args: self.ctx.terms.alloc_slice(new_args),
3557 world: world.clone(),
3558 })
3559 }
3560 LogicExpr::Identity { left, right } => self.ctx.exprs.alloc(LogicExpr::Identity {
3561 left: self.ctx.terms.alloc(rename_term(left)),
3562 right: self.ctx.terms.alloc(rename_term(right)),
3563 }),
3564 LogicExpr::NeoEvent(data) => {
3565 let new_roles: Vec<(ThematicRole, Term<'a>)> = data
3566 .roles
3567 .iter()
3568 .map(|(role, term)| (*role, rename_term(term)))
3569 .collect();
3570 self.ctx.exprs.alloc(LogicExpr::NeoEvent(Box::new(NeoEventData {
3571 event_var: data.event_var,
3572 verb: data.verb,
3573 roles: self.ctx.roles.alloc_slice(new_roles),
3574 modifiers: data.modifiers,
3575 suppress_existential: data.suppress_existential,
3576 world: data.world.clone(),
3577 })))
3578 }
3579 LogicExpr::BinaryOp { left, op, right } => self.ctx.exprs.alloc(LogicExpr::BinaryOp {
3580 left: self.rename_var_in_expr(left, from, to),
3581 op: op.clone(),
3582 right: self.rename_var_in_expr(right, from, to),
3583 }),
3584 LogicExpr::UnaryOp { op, operand } => self.ctx.exprs.alloc(LogicExpr::UnaryOp {
3585 op: op.clone(),
3586 operand: self.rename_var_in_expr(operand, from, to),
3587 }),
3588 LogicExpr::Quantifier { kind, variable, body, island_id } if *variable != from => {
3589 self.ctx.exprs.alloc(LogicExpr::Quantifier {
3590 kind: *kind,
3591 variable: *variable,
3592 body: self.rename_var_in_expr(body, from, to),
3593 island_id: *island_id,
3594 })
3595 }
3596 LogicExpr::Temporal { operator, body } => self.ctx.exprs.alloc(LogicExpr::Temporal {
3597 operator: *operator,
3598 body: self.rename_var_in_expr(body, from, to),
3599 }),
3600 LogicExpr::Aspectual { operator, body } => {
3601 self.ctx.exprs.alloc(LogicExpr::Aspectual {
3602 operator: *operator,
3603 body: self.rename_var_in_expr(body, from, to),
3604 })
3605 }
3606 LogicExpr::Event { predicate, adverbs } => self.ctx.exprs.alloc(LogicExpr::Event {
3607 predicate: self.rename_var_in_expr(predicate, from, to),
3608 adverbs: *adverbs,
3609 }),
3610 other => other,
3611 }
3612 }
3613
3614 fn collect_unbound_vars(
3617 &self,
3618 expr: &LogicExpr<'a>,
3619 bound: &mut Vec<Symbol>,
3620 out: &mut Vec<Symbol>,
3621 ) {
3622 fn term_vars(term: &Term<'_>, bound: &[Symbol], out: &mut Vec<Symbol>) {
3623 match term {
3624 Term::Variable(v) => {
3625 if !bound.contains(v) && !out.contains(v) {
3626 out.push(*v);
3627 }
3628 }
3629 Term::Function(_, args) => {
3630 for t in args.iter() {
3631 term_vars(t, bound, out);
3632 }
3633 }
3634 _ => {}
3635 }
3636 }
3637
3638 match expr {
3639 LogicExpr::Predicate { args, .. } => {
3640 for t in args.iter() {
3641 term_vars(t, bound, out);
3642 }
3643 }
3644 LogicExpr::NeoEvent(data) => {
3645 for (_, t) in data.roles.iter() {
3646 term_vars(t, bound, out);
3647 }
3648 }
3649 LogicExpr::BinaryOp { left, right, .. } => {
3650 self.collect_unbound_vars(left, bound, out);
3651 self.collect_unbound_vars(right, bound, out);
3652 }
3653 LogicExpr::UnaryOp { operand, .. } => self.collect_unbound_vars(operand, bound, out),
3654 LogicExpr::Quantifier { variable, body, .. } => {
3655 bound.push(*variable);
3656 self.collect_unbound_vars(body, bound, out);
3657 bound.pop();
3658 }
3659 LogicExpr::Temporal { body, .. } => self.collect_unbound_vars(body, bound, out),
3660 LogicExpr::Aspectual { body, .. } => self.collect_unbound_vars(body, bound, out),
3661 LogicExpr::Event { predicate, .. } => self.collect_unbound_vars(predicate, bound, out),
3662 LogicExpr::Modal { operand, .. } => self.collect_unbound_vars(operand, bound, out),
3663 LogicExpr::Scopal { body, .. } => self.collect_unbound_vars(body, bound, out),
3664 _ => {}
3665 }
3666 }
3667
3668 fn expr_mentions_var(&self, expr: &LogicExpr<'a>, var: Symbol) -> bool {
3670 match expr {
3671 LogicExpr::Predicate { args, .. } => {
3672 args.iter().any(|term| self.term_mentions_var(term, var))
3673 }
3674 LogicExpr::BinaryOp { left, right, .. } => {
3675 self.expr_mentions_var(left, var) || self.expr_mentions_var(right, var)
3676 }
3677 LogicExpr::UnaryOp { operand, .. } => self.expr_mentions_var(operand, var),
3678 LogicExpr::Quantifier { body, .. } => self.expr_mentions_var(body, var),
3679 LogicExpr::NeoEvent(data) => {
3680 data.roles.iter().any(|(_, term)| self.term_mentions_var(term, var))
3681 }
3682 LogicExpr::Temporal { body, .. } => self.expr_mentions_var(body, var),
3683 LogicExpr::Aspectual { body, .. } => self.expr_mentions_var(body, var),
3684 LogicExpr::Event { predicate, .. } => self.expr_mentions_var(predicate, var),
3685 LogicExpr::Modal { operand, .. } => self.expr_mentions_var(operand, var),
3686 LogicExpr::Scopal { body, .. } => self.expr_mentions_var(body, var),
3687 _ => false,
3688 }
3689 }
3690
3691 fn term_mentions_var(&self, term: &Term<'a>, var: Symbol) -> bool {
3692 match term {
3693 Term::Variable(v) => *v == var,
3694 Term::Function(_, args) => args.iter().any(|t| self.term_mentions_var(t, var)),
3695 _ => false,
3696 }
3697 }
3698
3699 fn collect_conjuncts(&self, expr: &'a LogicExpr<'a>) -> Vec<&'a LogicExpr<'a>> {
3701 match expr {
3702 LogicExpr::BinaryOp { left, op: TokenType::And, right } => {
3703 let mut result = self.collect_conjuncts(left);
3704 result.extend(self.collect_conjuncts(right));
3705 result
3706 }
3707 _ => vec![expr],
3708 }
3709 }
3710
3711 fn wrap_donkey_in_restriction(
3724 &self,
3725 body: &'a LogicExpr<'a>,
3726 donkey_var: Symbol,
3727 wide_scope_negation: bool,
3728 ) -> &'a LogicExpr<'a> {
3729 if let LogicExpr::Quantifier { kind, variable, body: inner_body, island_id } = body {
3731 let transformed = self.wrap_donkey_in_restriction(inner_body, donkey_var, wide_scope_negation);
3732 return self.ctx.exprs.alloc(LogicExpr::Quantifier {
3733 kind: kind.clone(),
3734 variable: *variable,
3735 body: transformed,
3736 island_id: *island_id,
3737 });
3738 }
3739
3740 if let LogicExpr::BinaryOp { left, op: TokenType::Implies, right } = body {
3742 return self.wrap_in_implication(*left, *right, donkey_var, wide_scope_negation);
3743 }
3744
3745 if let LogicExpr::BinaryOp { left: _, op: TokenType::And, right: _ } = body {
3747 return self.wrap_in_conjunction(body, donkey_var, wide_scope_negation);
3748 }
3749
3750 body
3752 }
3753
3754 fn wrap_in_implication(
3756 &self,
3757 restriction: &'a LogicExpr<'a>,
3758 consequent: &'a LogicExpr<'a>,
3759 donkey_var: Symbol,
3760 wide_scope_negation: bool,
3761 ) -> &'a LogicExpr<'a> {
3762 let conjuncts = self.collect_conjuncts(restriction);
3764
3765 let (with_var, without_var): (Vec<_>, Vec<_>) = conjuncts
3767 .into_iter()
3768 .partition(|c| self.expr_mentions_var(c, donkey_var));
3769
3770 if with_var.is_empty() {
3771 return self.ctx.exprs.alloc(LogicExpr::BinaryOp {
3773 left: restriction,
3774 op: TokenType::Implies,
3775 right: consequent,
3776 });
3777 }
3778
3779 let with_var_combined = self.combine_conjuncts(&with_var);
3781
3782 let existential = self.ctx.exprs.alloc(LogicExpr::Quantifier {
3784 kind: QuantifierKind::Existential,
3785 variable: donkey_var,
3786 body: with_var_combined,
3787 island_id: self.current_island,
3788 });
3789
3790 let wrapped = if wide_scope_negation {
3792 self.ctx.exprs.alloc(LogicExpr::UnaryOp {
3793 op: TokenType::Not,
3794 operand: existential,
3795 })
3796 } else {
3797 existential
3798 };
3799
3800 let new_restriction = if without_var.is_empty() {
3802 wrapped
3803 } else {
3804 let without_combined = self.combine_conjuncts(&without_var);
3805 self.ctx.exprs.alloc(LogicExpr::BinaryOp {
3806 left: without_combined,
3807 op: TokenType::And,
3808 right: wrapped,
3809 })
3810 };
3811
3812 self.ctx.exprs.alloc(LogicExpr::BinaryOp {
3814 left: new_restriction,
3815 op: TokenType::Implies,
3816 right: consequent,
3817 })
3818 }
3819
3820 fn wrap_in_conjunction(
3822 &self,
3823 body: &'a LogicExpr<'a>,
3824 donkey_var: Symbol,
3825 wide_scope_negation: bool,
3826 ) -> &'a LogicExpr<'a> {
3827 let conjuncts = self.collect_conjuncts(body);
3829
3830 let (with_var, without_var): (Vec<_>, Vec<_>) = conjuncts
3832 .into_iter()
3833 .partition(|c| self.expr_mentions_var(c, donkey_var));
3834
3835 if with_var.is_empty() {
3836 return body;
3838 }
3839
3840 let with_var_combined = self.combine_conjuncts(&with_var);
3842
3843 let existential = self.ctx.exprs.alloc(LogicExpr::Quantifier {
3845 kind: QuantifierKind::Existential,
3846 variable: donkey_var,
3847 body: with_var_combined,
3848 island_id: self.current_island,
3849 });
3850
3851 let wrapped = if wide_scope_negation {
3853 self.ctx.exprs.alloc(LogicExpr::UnaryOp {
3854 op: TokenType::Not,
3855 operand: existential,
3856 })
3857 } else {
3858 existential
3859 };
3860
3861 if without_var.is_empty() {
3863 wrapped
3864 } else {
3865 let without_combined = self.combine_conjuncts(&without_var);
3866 self.ctx.exprs.alloc(LogicExpr::BinaryOp {
3867 left: without_combined,
3868 op: TokenType::And,
3869 right: wrapped,
3870 })
3871 }
3872 }
3873
3874 fn combine_conjuncts(&self, conjuncts: &[&'a LogicExpr<'a>]) -> &'a LogicExpr<'a> {
3875 if conjuncts.is_empty() {
3876 panic!("Cannot combine empty conjuncts");
3877 }
3878 if conjuncts.len() == 1 {
3879 return conjuncts[0];
3880 }
3881 let mut result = conjuncts[0];
3882 for c in &conjuncts[1..] {
3883 result = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
3884 left: result,
3885 op: TokenType::And,
3886 right: *c,
3887 });
3888 }
3889 result
3890 }
3891}