1use super::clause::ClauseParsing;
25use super::modal::ModalParsing;
26use super::noun::NounParsing;
27use super::{NegativeScopeMode, ParseResult, Parser};
28use crate::ast::{LogicExpr, NeoEventData, NounPhrase, QuantifierKind, Term, ThematicRole};
29use crate::drs::{Gender, Number};
30use crate::drs::ReferentSource;
31use crate::error::{ParseError, ParseErrorKind};
32use logicaffeine_base::Symbol;
33use crate::lexer::Lexer;
34use crate::lexicon::{get_canonical_verb, is_subsective, lookup_verb_db, Definiteness, Feature, Time};
35use crate::token::{PresupKind, TokenType};
36
37pub trait QuantifierParsing<'a, 'ctx, 'int> {
42 fn parse_quantified(&mut self) -> ParseResult<&'a LogicExpr<'a>>;
44 fn parse_restriction(&mut self, var_name: Symbol) -> ParseResult<&'a LogicExpr<'a>>;
46 fn parse_verb_phrase_for_restriction(&mut self, var_name: Symbol) -> ParseResult<&'a LogicExpr<'a>>;
48 fn combine_with_and(&self, exprs: Vec<&'a LogicExpr<'a>>) -> ParseResult<&'a LogicExpr<'a>>;
50 fn wrap_with_definiteness_full(
51 &mut self,
52 np: &NounPhrase<'a>,
53 predicate: &'a LogicExpr<'a>,
54 ) -> ParseResult<&'a LogicExpr<'a>>;
55 fn wrap_with_definiteness(
56 &mut self,
57 definiteness: Option<Definiteness>,
58 noun: Symbol,
59 predicate: &'a LogicExpr<'a>,
60 ) -> ParseResult<&'a LogicExpr<'a>>;
61 fn wrap_with_definiteness_and_adjectives(
62 &mut self,
63 definiteness: Option<Definiteness>,
64 noun: Symbol,
65 adjectives: &[Symbol],
66 predicate: &'a LogicExpr<'a>,
67 ) -> ParseResult<&'a LogicExpr<'a>>;
68 fn wrap_with_definiteness_and_adjectives_and_pps(
69 &mut self,
70 definiteness: Option<Definiteness>,
71 noun: Symbol,
72 adjectives: &[Symbol],
73 pps: &[&'a LogicExpr<'a>],
74 predicate: &'a LogicExpr<'a>,
75 ) -> ParseResult<&'a LogicExpr<'a>>;
76 fn wrap_with_definiteness_for_object(
77 &mut self,
78 definiteness: Option<Definiteness>,
79 noun: Symbol,
80 predicate: &'a LogicExpr<'a>,
81 ) -> ParseResult<&'a LogicExpr<'a>>;
82 fn substitute_pp_placeholder(&mut self, pp: &'a LogicExpr<'a>, var: Symbol) -> &'a LogicExpr<'a>;
83 fn substitute_constant_with_var(
84 &self,
85 expr: &'a LogicExpr<'a>,
86 constant_name: Symbol,
87 var_name: Symbol,
88 ) -> ParseResult<&'a LogicExpr<'a>>;
89 fn substitute_constant_with_var_sym(
90 &self,
91 expr: &'a LogicExpr<'a>,
92 constant_name: Symbol,
93 var_name: Symbol,
94 ) -> ParseResult<&'a LogicExpr<'a>>;
95 fn substitute_constant_with_sigma(
96 &self,
97 expr: &'a LogicExpr<'a>,
98 constant_name: Symbol,
99 sigma_term: Term<'a>,
100 ) -> ParseResult<&'a LogicExpr<'a>>;
101 fn find_main_verb_name(&self, expr: &LogicExpr<'a>) -> Option<Symbol>;
102 fn transform_cardinal_to_group(&mut self, expr: &'a LogicExpr<'a>) -> ParseResult<&'a LogicExpr<'a>>;
103 fn build_verb_neo_event(
104 &mut self,
105 verb: Symbol,
106 subject_var: Symbol,
107 object: Option<Term<'a>>,
108 modifiers: Vec<Symbol>,
109 ) -> &'a LogicExpr<'a>;
110}
111
112impl<'a, 'ctx, 'int> QuantifierParsing<'a, 'ctx, 'int> for Parser<'a, 'ctx, 'int> {
113 fn parse_quantified(&mut self) -> ParseResult<&'a LogicExpr<'a>> {
114 let quantifier_token = self.previous().kind.clone();
115 let var_name = self.next_var_name();
116
117 let was_in_negative_quantifier = self.in_negative_quantifier;
120 if matches!(quantifier_token, TokenType::No) {
121 self.in_negative_quantifier = true;
122 }
123
124 if matches!(quantifier_token, TokenType::AtMost(_) | TokenType::AtLeast(_) | TokenType::Cardinal(_))
126 && self.check_preposition_is("of")
127 {
128 self.advance(); let mut signal_names: Vec<Symbol> = Vec::new();
132 loop {
133 let name = self.consume_content_word()?;
134 signal_names.push(name);
135
136 if self.check(&TokenType::Comma) {
137 self.advance(); if self.check(&TokenType::And) {
140 self.advance();
141 }
142 } else if self.check(&TokenType::And) {
143 self.advance(); } else {
145 break;
146 }
147 }
148
149 let mut is_negated = false;
153 if self.check(&TokenType::Is) || self.check(&TokenType::Are) {
154 self.advance(); is_negated = self.check(&TokenType::Not);
156 if is_negated {
157 self.advance();
158 }
159 let _ = self.consume_content_word();
161 while self.check_preposition_is("at") {
163 self.advance();
164 if self.check(&TokenType::Any) {
165 self.advance();
166 }
167 if self.check_content_word() {
168 self.advance();
169 }
170 }
171 }
172
173 let mut signal_exprs: Vec<&'a LogicExpr<'a>> = Vec::new();
176 for &sig in &signal_names {
177 let atom: &'a LogicExpr<'a> = self.ctx.exprs.alloc(LogicExpr::Atom(sig));
178 let sig_expr = if is_negated {
179 self.ctx.exprs.alloc(LogicExpr::UnaryOp {
180 op: TokenType::Not,
181 operand: atom,
182 })
183 } else {
184 atom
185 };
186 signal_exprs.push(sig_expr);
187 }
188
189 let body = if signal_exprs.len() == 1 {
190 signal_exprs[0]
191 } else {
192 let mut combined = signal_exprs[0];
193 for &expr in &signal_exprs[1..] {
194 combined = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
195 left: combined,
196 op: TokenType::Or,
197 right: expr,
198 });
199 }
200 combined
201 };
202
203 let kind = match quantifier_token {
204 TokenType::AtMost(n) => QuantifierKind::AtMost(n),
205 TokenType::AtLeast(n) => QuantifierKind::AtLeast(n),
206 TokenType::Cardinal(n) => QuantifierKind::Cardinal(n),
207 _ => unreachable!(),
208 };
209
210 self.in_negative_quantifier = was_in_negative_quantifier;
211
212 return Ok(self.ctx.exprs.alloc(LogicExpr::Quantifier {
213 kind,
214 variable: var_name,
215 body,
216 island_id: self.current_island,
217 }));
218 }
219
220 let subject_pred = self.parse_restriction(var_name)?;
221
222 if self.check_modal() {
223 use crate::ast::ModalFlavor;
224
225 self.advance();
226 let vector = self.token_to_vector(&self.previous().kind.clone());
227 let verb = self.consume_content_word()?;
228
229 let obj_term = if self.check_content_word() || self.check_article() {
231 let obj_np = self.parse_noun_phrase(false)?;
232 Some(self.noun_phrase_to_term(&obj_np))
233 } else {
234 None
235 };
236
237 let modifiers = self.collect_adverbs();
239 let verb_pred = self.build_verb_neo_event(verb, var_name, obj_term, modifiers);
240
241 let kind = match quantifier_token {
243 TokenType::All | TokenType::No => QuantifierKind::Universal,
244 TokenType::Any => {
245 if self.is_negative_context() {
246 QuantifierKind::Existential
247 } else {
248 QuantifierKind::Universal
249 }
250 }
251 TokenType::Some => QuantifierKind::Existential,
252 TokenType::Most => QuantifierKind::Most,
253 TokenType::Few => QuantifierKind::Few,
254 TokenType::Many => QuantifierKind::Many,
255 TokenType::Cardinal(n) => QuantifierKind::Cardinal(n),
256 TokenType::AtLeast(n) => QuantifierKind::AtLeast(n),
257 TokenType::AtMost(n) => QuantifierKind::AtMost(n),
258 _ => {
259 return Err(ParseError {
260 kind: ParseErrorKind::UnknownQuantifier {
261 found: quantifier_token.clone(),
262 },
263 span: self.current_span(),
264 })
265 }
266 };
267
268 if vector.flavor == ModalFlavor::Root {
270 let modal_verb = self.ctx.exprs.alloc(LogicExpr::Modal {
276 vector,
277 operand: verb_pred,
278 });
279
280 let body = match quantifier_token {
281 TokenType::All => self.ctx.exprs.alloc(LogicExpr::BinaryOp {
282 left: subject_pred,
283 op: TokenType::Implies,
284 right: modal_verb,
285 }),
286 TokenType::Any => {
287 if self.is_negative_context() {
288 self.ctx.exprs.alloc(LogicExpr::BinaryOp {
289 left: subject_pred,
290 op: TokenType::And,
291 right: modal_verb,
292 })
293 } else {
294 self.ctx.exprs.alloc(LogicExpr::BinaryOp {
295 left: subject_pred,
296 op: TokenType::Implies,
297 right: modal_verb,
298 })
299 }
300 }
301 TokenType::Some
302 | TokenType::Most
303 | TokenType::Few
304 | TokenType::Many
305 | TokenType::Cardinal(_)
306 | TokenType::AtLeast(_)
307 | TokenType::AtMost(_) => self.ctx.exprs.alloc(LogicExpr::BinaryOp {
308 left: subject_pred,
309 op: TokenType::And,
310 right: modal_verb,
311 }),
312 TokenType::No => {
313 let neg = self.ctx.exprs.alloc(LogicExpr::UnaryOp {
314 op: TokenType::Not,
315 operand: modal_verb,
316 });
317 self.ctx.exprs.alloc(LogicExpr::BinaryOp {
318 left: subject_pred,
319 op: TokenType::Implies,
320 right: neg,
321 })
322 }
323 _ => {
324 return Err(ParseError {
325 kind: ParseErrorKind::UnknownQuantifier {
326 found: quantifier_token.clone(),
327 },
328 span: self.current_span(),
329 })
330 }
331 };
332
333 let mut result = self.ctx.exprs.alloc(LogicExpr::Quantifier {
335 kind,
336 variable: var_name,
337 body,
338 island_id: self.current_island,
339 });
340
341 for (_noun, donkey_var, used, wide_neg) in self.donkey_bindings.iter().rev() {
343 if *used {
344 result = self.ctx.exprs.alloc(LogicExpr::Quantifier {
346 kind: QuantifierKind::Universal,
347 variable: *donkey_var,
348 body: result,
349 island_id: self.current_island,
350 });
351 } else {
352 result = self.wrap_donkey_in_restriction(result, *donkey_var, *wide_neg);
354 }
355 }
356 self.donkey_bindings.clear();
357
358 self.in_negative_quantifier = was_in_negative_quantifier;
359 return Ok(result);
360
361 } else {
362 let body = match quantifier_token {
367 TokenType::All => self.ctx.exprs.alloc(LogicExpr::BinaryOp {
368 left: subject_pred,
369 op: TokenType::Implies,
370 right: verb_pred,
371 }),
372 TokenType::Any => {
373 if self.is_negative_context() {
374 self.ctx.exprs.alloc(LogicExpr::BinaryOp {
375 left: subject_pred,
376 op: TokenType::And,
377 right: verb_pred,
378 })
379 } else {
380 self.ctx.exprs.alloc(LogicExpr::BinaryOp {
381 left: subject_pred,
382 op: TokenType::Implies,
383 right: verb_pred,
384 })
385 }
386 }
387 TokenType::Some
388 | TokenType::Most
389 | TokenType::Few
390 | TokenType::Many
391 | TokenType::Cardinal(_)
392 | TokenType::AtLeast(_)
393 | TokenType::AtMost(_) => self.ctx.exprs.alloc(LogicExpr::BinaryOp {
394 left: subject_pred,
395 op: TokenType::And,
396 right: verb_pred,
397 }),
398 TokenType::No => {
399 let neg = self.ctx.exprs.alloc(LogicExpr::UnaryOp {
400 op: TokenType::Not,
401 operand: verb_pred,
402 });
403 self.ctx.exprs.alloc(LogicExpr::BinaryOp {
404 left: subject_pred,
405 op: TokenType::Implies,
406 right: neg,
407 })
408 }
409 _ => {
410 return Err(ParseError {
411 kind: ParseErrorKind::UnknownQuantifier {
412 found: quantifier_token.clone(),
413 },
414 span: self.current_span(),
415 })
416 }
417 };
418
419 let mut result = self.ctx.exprs.alloc(LogicExpr::Quantifier {
420 kind,
421 variable: var_name,
422 body,
423 island_id: self.current_island,
424 });
425
426 for (_noun, donkey_var, used, wide_neg) in self.donkey_bindings.iter().rev() {
428 if *used {
429 result = self.ctx.exprs.alloc(LogicExpr::Quantifier {
431 kind: QuantifierKind::Universal,
432 variable: *donkey_var,
433 body: result,
434 island_id: self.current_island,
435 });
436 } else {
437 result = self.wrap_donkey_in_restriction(result, *donkey_var, *wide_neg);
439 }
440 }
441 self.donkey_bindings.clear();
442
443 self.in_negative_quantifier = was_in_negative_quantifier;
445 return Ok(self.ctx.exprs.alloc(LogicExpr::Modal {
446 vector,
447 operand: result,
448 }));
449 }
450 }
451
452 if self.check_auxiliary() {
453 let aux_token = self.advance();
454 let aux_time = if let TokenType::Auxiliary(time) = aux_token.kind.clone() {
455 time
456 } else {
457 Time::None
458 };
459 self.pending_time = Some(aux_time);
460
461 let is_negated = self.match_token(&[TokenType::Not]);
462 if is_negated {
463 self.negative_depth += 1;
464 }
465
466 if self.check_verb() {
467 let verb = self.consume_verb();
468
469 let modifiers = match aux_time {
471 Time::Past => vec![self.interner.intern("Past")],
472 Time::Future => vec![self.interner.intern("Future")],
473 _ => vec![],
474 };
475
476 let verb_pred = self.build_verb_neo_event(verb, var_name, None, modifiers);
477
478 let maybe_negated = if is_negated {
479 self.negative_depth -= 1;
480 self.ctx.exprs.alloc(LogicExpr::UnaryOp {
481 op: TokenType::Not,
482 operand: verb_pred,
483 })
484 } else {
485 verb_pred
486 };
487
488 let body = match quantifier_token {
489 TokenType::All | TokenType::Any => self.ctx.exprs.alloc(LogicExpr::BinaryOp {
490 left: subject_pred,
491 op: TokenType::Implies,
492 right: maybe_negated,
493 }),
494 _ => self.ctx.exprs.alloc(LogicExpr::BinaryOp {
495 left: subject_pred,
496 op: TokenType::And,
497 right: maybe_negated,
498 }),
499 };
500
501 let kind = match quantifier_token {
502 TokenType::All | TokenType::No => QuantifierKind::Universal,
503 TokenType::Some => QuantifierKind::Existential,
504 TokenType::Most => QuantifierKind::Most,
505 TokenType::Few => QuantifierKind::Few,
506 TokenType::Cardinal(n) => QuantifierKind::Cardinal(n),
507 TokenType::AtLeast(n) => QuantifierKind::AtLeast(n),
508 TokenType::AtMost(n) => QuantifierKind::AtMost(n),
509 _ => QuantifierKind::Universal,
510 };
511
512 self.in_negative_quantifier = was_in_negative_quantifier;
513 return Ok(self.ctx.exprs.alloc(LogicExpr::Quantifier {
514 kind,
515 variable: var_name,
516 body,
517 island_id: self.current_island,
518 }));
519 }
520 }
521
522 if self.check_presup_trigger() && self.is_followed_by_gerund() {
524 let presup_kind = match self.advance().kind {
525 TokenType::PresupTrigger(kind) => kind,
526 TokenType::Verb { lemma, .. } => {
527 let s = self.interner.resolve(lemma).to_lowercase();
528 crate::lexicon::lookup_presup_trigger(&s)
529 .expect("Lexicon mismatch: Verb flagged as trigger but lookup failed")
530 }
531 _ => panic!("Expected presupposition trigger"),
532 };
533
534 let complement = if self.check_verb() {
535 let verb = self.consume_verb();
536 let modifiers = self.collect_adverbs();
537 self.build_verb_neo_event(verb, var_name, None, modifiers)
538 } else {
539 let unknown = self.interner.intern("?");
540 self.ctx.exprs.alloc(LogicExpr::Atom(unknown))
541 };
542
543 let verb_pred = match presup_kind {
544 PresupKind::Stop => self.ctx.exprs.alloc(LogicExpr::UnaryOp {
545 op: TokenType::Not,
546 operand: complement,
547 }),
548 PresupKind::Start | PresupKind::Continue => complement,
549 PresupKind::Regret | PresupKind::Realize | PresupKind::Know => complement,
550 };
551
552 let body = match quantifier_token {
553 TokenType::All | TokenType::Any => self.ctx.exprs.alloc(LogicExpr::BinaryOp {
554 left: subject_pred,
555 op: TokenType::Implies,
556 right: verb_pred,
557 }),
558 _ => self.ctx.exprs.alloc(LogicExpr::BinaryOp {
559 left: subject_pred,
560 op: TokenType::And,
561 right: verb_pred,
562 }),
563 };
564
565 let kind = match quantifier_token {
566 TokenType::All | TokenType::No => QuantifierKind::Universal,
567 TokenType::Some => QuantifierKind::Existential,
568 TokenType::Most => QuantifierKind::Most,
569 TokenType::Few => QuantifierKind::Few,
570 TokenType::Many => QuantifierKind::Many,
571 TokenType::Cardinal(n) => QuantifierKind::Cardinal(n),
572 TokenType::AtLeast(n) => QuantifierKind::AtLeast(n),
573 TokenType::AtMost(n) => QuantifierKind::AtMost(n),
574 _ => QuantifierKind::Universal,
575 };
576
577 self.in_negative_quantifier = was_in_negative_quantifier;
578 return Ok(self.ctx.exprs.alloc(LogicExpr::Quantifier {
579 kind,
580 variable: var_name,
581 body,
582 island_id: self.current_island,
583 }));
584 }
585
586 if self.check_verb() {
587 let verb = self.consume_verb();
588 let mut args = vec![Term::Variable(var_name)];
589
590 if self.check_pronoun() {
591 let token = self.peek().clone();
592 if let TokenType::Pronoun { gender, .. } = token.kind {
593 self.advance();
594 if let Some(donkey_var) = self.resolve_donkey_pronoun(gender) {
595 args.push(Term::Variable(donkey_var));
596 } else {
597 let resolved = self.resolve_pronoun(gender, Number::Singular)?;
598 let term = match resolved {
599 super::ResolvedPronoun::Variable(s) => Term::Variable(s),
600 super::ResolvedPronoun::Constant(s) => Term::Constant(s),
601 };
602 args.push(term);
603 }
604 }
605 } else if self.check_npi_object() {
606 let npi_token = self.advance().kind.clone();
607 let obj_var = self.next_var_name();
608
609 let restriction_name = match npi_token {
610 TokenType::Anything => "Thing",
611 TokenType::Anyone => "Person",
612 _ => "Thing",
613 };
614
615 let restriction_sym = self.interner.intern(restriction_name);
616 let obj_restriction = self.ctx.exprs.alloc(LogicExpr::Predicate {
617 name: restriction_sym,
618 args: self.ctx.terms.alloc_slice([Term::Variable(obj_var)]),
619 world: None,
620 });
621
622 let npi_modifiers = self.collect_adverbs();
623 let verb_with_obj = self.build_verb_neo_event(
624 verb,
625 var_name,
626 Some(Term::Variable(obj_var)),
627 npi_modifiers,
628 );
629
630 let npi_body = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
631 left: obj_restriction,
632 op: TokenType::And,
633 right: verb_with_obj,
634 });
635
636 let npi_quantified = self.ctx.exprs.alloc(LogicExpr::Quantifier {
637 kind: QuantifierKind::Existential,
638 variable: obj_var,
639 body: npi_body,
640 island_id: self.current_island,
641 });
642
643 let negated_npi = self.ctx.exprs.alloc(LogicExpr::UnaryOp {
644 op: TokenType::Not,
645 operand: npi_quantified,
646 });
647
648 let body = match quantifier_token {
649 TokenType::All | TokenType::No => self.ctx.exprs.alloc(LogicExpr::BinaryOp {
650 left: subject_pred,
651 op: TokenType::Implies,
652 right: negated_npi,
653 }),
654 _ => self.ctx.exprs.alloc(LogicExpr::BinaryOp {
655 left: subject_pred,
656 op: TokenType::And,
657 right: negated_npi,
658 }),
659 };
660
661 let kind = match quantifier_token {
662 TokenType::All | TokenType::No => QuantifierKind::Universal,
663 TokenType::Some => QuantifierKind::Existential,
664 TokenType::Most => QuantifierKind::Most,
665 TokenType::Few => QuantifierKind::Few,
666 TokenType::Many => QuantifierKind::Many,
667 TokenType::Cardinal(n) => QuantifierKind::Cardinal(n),
668 TokenType::AtLeast(n) => QuantifierKind::AtLeast(n),
669 TokenType::AtMost(n) => QuantifierKind::AtMost(n),
670 _ => QuantifierKind::Universal,
671 };
672
673 self.in_negative_quantifier = was_in_negative_quantifier;
674 return Ok(self.ctx.exprs.alloc(LogicExpr::Quantifier {
675 kind,
676 variable: var_name,
677 body,
678 island_id: self.current_island,
679 }));
680 } else if self.check_quantifier() || self.check_article() {
681 let obj_quantifier = if self.check_quantifier() {
682 Some(self.advance().kind.clone())
683 } else {
684 let art = self.advance().kind.clone();
685 if let TokenType::Article(def) = art {
686 if def == Definiteness::Indefinite {
687 Some(TokenType::Some)
688 } else {
689 None
690 }
691 } else {
692 None
693 }
694 };
695
696 let object = self.parse_noun_phrase(false)?;
697
698 if let Some(obj_q) = obj_quantifier {
699 let obj_var = self.next_var_name();
700
701 let obj_gender = Self::infer_noun_gender(self.interner.resolve(object.noun));
704 let obj_number = if Self::is_plural_noun(self.interner.resolve(object.noun)) {
705 Number::Plural
706 } else {
707 Number::Singular
708 };
709 if self.in_negative_quantifier {
710 self.drs.introduce_referent_with_source(obj_var, object.noun, obj_gender, obj_number, ReferentSource::NegationScope);
711 } else {
712 self.drs.introduce_referent(obj_var, object.noun, obj_gender, obj_number);
713 }
714
715 let obj_restriction = self.ctx.exprs.alloc(LogicExpr::Predicate {
716 name: object.noun,
717 args: self.ctx.terms.alloc_slice([Term::Variable(obj_var)]),
718 world: None,
719 });
720
721 let obj_modifiers = self.collect_adverbs();
722 let verb_with_obj = self.build_verb_neo_event(
723 verb,
724 var_name,
725 Some(Term::Variable(obj_var)),
726 obj_modifiers,
727 );
728
729 let obj_kind = match obj_q {
730 TokenType::All => QuantifierKind::Universal,
731 TokenType::Some => QuantifierKind::Existential,
732 TokenType::No => QuantifierKind::Universal,
733 TokenType::Most => QuantifierKind::Most,
734 TokenType::Few => QuantifierKind::Few,
735 TokenType::Many => QuantifierKind::Many,
736 TokenType::Cardinal(n) => QuantifierKind::Cardinal(n),
737 TokenType::AtLeast(n) => QuantifierKind::AtLeast(n),
738 TokenType::AtMost(n) => QuantifierKind::AtMost(n),
739 _ => QuantifierKind::Existential,
740 };
741
742 let obj_body = match obj_q {
743 TokenType::All => self.ctx.exprs.alloc(LogicExpr::BinaryOp {
744 left: obj_restriction,
745 op: TokenType::Implies,
746 right: verb_with_obj,
747 }),
748 TokenType::No => {
749 let neg = self.ctx.exprs.alloc(LogicExpr::UnaryOp {
750 op: TokenType::Not,
751 operand: verb_with_obj,
752 });
753 self.ctx.exprs.alloc(LogicExpr::BinaryOp {
754 left: obj_restriction,
755 op: TokenType::Implies,
756 right: neg,
757 })
758 }
759 _ => self.ctx.exprs.alloc(LogicExpr::BinaryOp {
760 left: obj_restriction,
761 op: TokenType::And,
762 right: verb_with_obj,
763 }),
764 };
765
766 let obj_quantified = self.ctx.exprs.alloc(LogicExpr::Quantifier {
767 kind: obj_kind,
768 variable: obj_var,
769 body: obj_body,
770 island_id: self.current_island,
771 });
772
773 let subj_kind = match quantifier_token {
774 TokenType::All | TokenType::No => QuantifierKind::Universal,
775 TokenType::Any => {
776 if self.is_negative_context() {
777 QuantifierKind::Existential
778 } else {
779 QuantifierKind::Universal
780 }
781 }
782 TokenType::Some => QuantifierKind::Existential,
783 TokenType::Most => QuantifierKind::Most,
784 TokenType::Few => QuantifierKind::Few,
785 TokenType::Many => QuantifierKind::Many,
786 TokenType::Cardinal(n) => QuantifierKind::Cardinal(n),
787 TokenType::AtLeast(n) => QuantifierKind::AtLeast(n),
788 TokenType::AtMost(n) => QuantifierKind::AtMost(n),
789 _ => QuantifierKind::Universal,
790 };
791
792 let subj_body = match quantifier_token {
793 TokenType::All => self.ctx.exprs.alloc(LogicExpr::BinaryOp {
794 left: subject_pred,
795 op: TokenType::Implies,
796 right: obj_quantified,
797 }),
798 TokenType::No => {
799 let neg = self.ctx.exprs.alloc(LogicExpr::UnaryOp {
800 op: TokenType::Not,
801 operand: obj_quantified,
802 });
803 self.ctx.exprs.alloc(LogicExpr::BinaryOp {
804 left: subject_pred,
805 op: TokenType::Implies,
806 right: neg,
807 })
808 }
809 _ => self.ctx.exprs.alloc(LogicExpr::BinaryOp {
810 left: subject_pred,
811 op: TokenType::And,
812 right: obj_quantified,
813 }),
814 };
815
816 self.in_negative_quantifier = was_in_negative_quantifier;
817 return Ok(self.ctx.exprs.alloc(LogicExpr::Quantifier {
818 kind: subj_kind,
819 variable: var_name,
820 body: subj_body,
821 island_id: self.current_island,
822 }));
823 } else {
824 args.push(Term::Constant(object.noun));
825 }
826 } else if self.check_content_word() {
827 let object = self.parse_noun_phrase(false)?;
828 args.push(Term::Constant(object.noun));
829 }
830
831 let obj_term = if args.len() > 1 {
833 Some(args.remove(1))
834 } else {
835 None
836 };
837 let modifiers = self.collect_adverbs();
839 let verb_pred = self.build_verb_neo_event(verb, var_name, obj_term, modifiers);
840
841 let body = match quantifier_token {
842 TokenType::All => self.ctx.exprs.alloc(LogicExpr::BinaryOp {
843 left: subject_pred,
844 op: TokenType::Implies,
845 right: verb_pred,
846 }),
847 TokenType::Any => {
848 if self.is_negative_context() {
849 self.ctx.exprs.alloc(LogicExpr::BinaryOp {
850 left: subject_pred,
851 op: TokenType::And,
852 right: verb_pred,
853 })
854 } else {
855 self.ctx.exprs.alloc(LogicExpr::BinaryOp {
856 left: subject_pred,
857 op: TokenType::Implies,
858 right: verb_pred,
859 })
860 }
861 }
862 TokenType::Some
863 | TokenType::Most
864 | TokenType::Few
865 | TokenType::Many
866 | TokenType::Cardinal(_)
867 | TokenType::AtLeast(_)
868 | TokenType::AtMost(_) => self.ctx.exprs.alloc(LogicExpr::BinaryOp {
869 left: subject_pred,
870 op: TokenType::And,
871 right: verb_pred,
872 }),
873 TokenType::No => {
874 let neg = self.ctx.exprs.alloc(LogicExpr::UnaryOp {
875 op: TokenType::Not,
876 operand: verb_pred,
877 });
878 self.ctx.exprs.alloc(LogicExpr::BinaryOp {
879 left: subject_pred,
880 op: TokenType::Implies,
881 right: neg,
882 })
883 }
884 _ => {
885 return Err(ParseError {
886 kind: ParseErrorKind::UnknownQuantifier {
887 found: quantifier_token.clone(),
888 },
889 span: self.current_span(),
890 })
891 }
892 };
893
894 let kind = match quantifier_token {
895 TokenType::All | TokenType::No => QuantifierKind::Universal,
896 TokenType::Any => {
897 if self.is_negative_context() {
898 QuantifierKind::Existential
899 } else {
900 QuantifierKind::Universal
901 }
902 }
903 TokenType::Some => QuantifierKind::Existential,
904 TokenType::Most => QuantifierKind::Most,
905 TokenType::Few => QuantifierKind::Few,
906 TokenType::Many => QuantifierKind::Many,
907 TokenType::Cardinal(n) => QuantifierKind::Cardinal(n),
908 TokenType::AtLeast(n) => QuantifierKind::AtLeast(n),
909 TokenType::AtMost(n) => QuantifierKind::AtMost(n),
910 _ => {
911 return Err(ParseError {
912 kind: ParseErrorKind::UnknownQuantifier {
913 found: quantifier_token.clone(),
914 },
915 span: self.current_span(),
916 })
917 }
918 };
919
920 let mut result = self.ctx.exprs.alloc(LogicExpr::Quantifier {
921 kind,
922 variable: var_name,
923 body,
924 island_id: self.current_island,
925 });
926
927 for (_noun, donkey_var, used, wide_neg) in self.donkey_bindings.iter().rev() {
928 if *used {
929 result = self.ctx.exprs.alloc(LogicExpr::Quantifier {
931 kind: QuantifierKind::Universal,
932 variable: *donkey_var,
933 body: result,
934 island_id: self.current_island,
935 });
936 } else {
937 result = self.wrap_donkey_in_restriction(result, *donkey_var, *wide_neg);
939 }
940 }
941 self.donkey_bindings.clear();
942
943 self.in_negative_quantifier = was_in_negative_quantifier;
944 return Ok(result);
945 }
946
947 if self.check(&TokenType::Does) || self.check(&TokenType::Do) {
949 self.advance(); let negative = self.match_token(&[TokenType::Not]);
951 let verb_sym = self.consume_verb();
953 let predicate_expr = self.ctx.exprs.alloc(LogicExpr::Predicate {
954 name: verb_sym,
955 args: self.ctx.terms.alloc_slice([Term::Variable(var_name)]),
956 world: None,
957 });
958 let final_predicate = if negative {
959 self.ctx.exprs.alloc(LogicExpr::UnaryOp {
960 op: TokenType::Not,
961 operand: predicate_expr,
962 })
963 } else {
964 predicate_expr
965 };
966
967 let body = match quantifier_token {
968 TokenType::All => self.ctx.exprs.alloc(LogicExpr::BinaryOp {
969 left: subject_pred,
970 op: TokenType::Implies,
971 right: final_predicate,
972 }),
973 _ => self.ctx.exprs.alloc(LogicExpr::BinaryOp {
974 left: subject_pred,
975 op: TokenType::And,
976 right: final_predicate,
977 }),
978 };
979
980 let result = self.ctx.exprs.alloc(LogicExpr::Quantifier {
981 kind: match quantifier_token {
982 TokenType::All => QuantifierKind::Universal,
983 _ => QuantifierKind::Existential,
984 },
985 variable: var_name,
986 body: body,
987 island_id: self.current_island,
988 });
989 self.in_negative_quantifier = was_in_negative_quantifier;
990 return Ok(result);
991 }
992
993 self.consume_copula()?;
994
995 let negative = self.match_token(&[TokenType::Not]);
996 let predicate_np = self.parse_noun_phrase(true)?;
997
998 let predicate_expr = self.ctx.exprs.alloc(LogicExpr::Predicate {
999 name: predicate_np.noun,
1000 args: self.ctx.terms.alloc_slice([Term::Variable(var_name)]),
1001 world: None,
1002 });
1003
1004 let final_predicate = if negative {
1005 self.ctx.exprs.alloc(LogicExpr::UnaryOp {
1006 op: TokenType::Not,
1007 operand: predicate_expr,
1008 })
1009 } else {
1010 predicate_expr
1011 };
1012
1013 let body = match quantifier_token {
1014 TokenType::All => self.ctx.exprs.alloc(LogicExpr::BinaryOp {
1015 left: subject_pred,
1016 op: TokenType::Implies,
1017 right: final_predicate,
1018 }),
1019 TokenType::Any => {
1020 if self.is_negative_context() {
1021 self.ctx.exprs.alloc(LogicExpr::BinaryOp {
1022 left: subject_pred,
1023 op: TokenType::And,
1024 right: final_predicate,
1025 })
1026 } else {
1027 self.ctx.exprs.alloc(LogicExpr::BinaryOp {
1028 left: subject_pred,
1029 op: TokenType::Implies,
1030 right: final_predicate,
1031 })
1032 }
1033 }
1034 TokenType::Some
1035 | TokenType::Most
1036 | TokenType::Few
1037 | TokenType::Many
1038 | TokenType::Cardinal(_)
1039 | TokenType::AtLeast(_)
1040 | TokenType::AtMost(_) => self.ctx.exprs.alloc(LogicExpr::BinaryOp {
1041 left: subject_pred,
1042 op: TokenType::And,
1043 right: final_predicate,
1044 }),
1045 TokenType::No => {
1046 let neg_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
1047 name: predicate_np.noun,
1048 args: self.ctx.terms.alloc_slice([Term::Variable(var_name)]),
1049 world: None,
1050 });
1051 let neg = self.ctx.exprs.alloc(LogicExpr::UnaryOp {
1052 op: TokenType::Not,
1053 operand: neg_pred,
1054 });
1055 self.ctx.exprs.alloc(LogicExpr::BinaryOp {
1056 left: subject_pred,
1057 op: TokenType::Implies,
1058 right: neg,
1059 })
1060 }
1061 _ => {
1062 return Err(ParseError {
1063 kind: ParseErrorKind::UnknownQuantifier {
1064 found: quantifier_token.clone(),
1065 },
1066 span: self.current_span(),
1067 })
1068 }
1069 };
1070
1071 let kind = match quantifier_token {
1072 TokenType::All | TokenType::No => QuantifierKind::Universal,
1073 TokenType::Any => {
1074 if self.is_negative_context() {
1075 QuantifierKind::Existential
1076 } else {
1077 QuantifierKind::Universal
1078 }
1079 }
1080 TokenType::Some => QuantifierKind::Existential,
1081 TokenType::Most => QuantifierKind::Most,
1082 TokenType::Few => QuantifierKind::Few,
1083 TokenType::Many => QuantifierKind::Many,
1084 TokenType::Cardinal(n) => QuantifierKind::Cardinal(n),
1085 TokenType::AtLeast(n) => QuantifierKind::AtLeast(n),
1086 TokenType::AtMost(n) => QuantifierKind::AtMost(n),
1087 _ => {
1088 return Err(ParseError {
1089 kind: ParseErrorKind::UnknownQuantifier {
1090 found: quantifier_token.clone(),
1091 },
1092 span: self.current_span(),
1093 })
1094 }
1095 };
1096
1097 let mut result = self.ctx.exprs.alloc(LogicExpr::Quantifier {
1098 kind,
1099 variable: var_name,
1100 body,
1101 island_id: self.current_island,
1102 });
1103
1104 for (_noun, donkey_var, used, wide_neg) in self.donkey_bindings.iter().rev() {
1105 if *used {
1106 result = self.ctx.exprs.alloc(LogicExpr::Quantifier {
1108 kind: QuantifierKind::Universal,
1109 variable: *donkey_var,
1110 body: result,
1111 island_id: self.current_island,
1112 });
1113 } else {
1114 result = self.wrap_donkey_in_restriction(result, *donkey_var, *wide_neg);
1116 }
1117 }
1118 self.donkey_bindings.clear();
1119
1120 self.in_negative_quantifier = was_in_negative_quantifier;
1121 Ok(result)
1122 }
1123
1124 fn parse_restriction(&mut self, var_name: Symbol) -> ParseResult<&'a LogicExpr<'a>> {
1125 let mut conditions: Vec<&'a LogicExpr<'a>> = Vec::new();
1126
1127 loop {
1128 if self.is_at_end() {
1129 break;
1130 }
1131
1132 let is_adjective = matches!(self.peek().kind, TokenType::Adjective(_));
1133 if !is_adjective {
1134 break;
1135 }
1136
1137 let next_is_content = if self.current + 1 < self.tokens.len() {
1138 matches!(
1139 self.tokens[self.current + 1].kind,
1140 TokenType::Noun(_) | TokenType::Adjective(_) | TokenType::ProperName(_)
1141 )
1142 } else {
1143 false
1144 };
1145
1146 if next_is_content {
1147 if let TokenType::Adjective(adj) = self.advance().kind.clone() {
1148 conditions.push(self.ctx.exprs.alloc(LogicExpr::Predicate {
1149 name: adj,
1150 args: self.ctx.terms.alloc_slice([Term::Variable(var_name)]),
1151 world: None,
1152 }));
1153 }
1154 } else {
1155 break;
1156 }
1157 }
1158
1159 let noun = self.consume_content_word()?;
1160 conditions.push(self.ctx.exprs.alloc(LogicExpr::Predicate {
1161 name: noun,
1162 args: self.ctx.terms.alloc_slice([Term::Variable(var_name)]),
1163 world: None,
1164 }));
1165
1166 while self.check(&TokenType::That) || self.check(&TokenType::Who) {
1167 self.advance();
1168 let clause_pred = self.parse_relative_clause(var_name)?;
1169 conditions.push(clause_pred);
1170 }
1171
1172 self.combine_with_and(conditions)
1173 }
1174
1175 fn parse_verb_phrase_for_restriction(&mut self, var_name: Symbol) -> ParseResult<&'a LogicExpr<'a>> {
1176 let var_term = Term::Variable(var_name);
1177 let verb = self.consume_verb();
1178 let verb_str_owned = self.interner.resolve(verb).to_string();
1179
1180 let (canonical_verb, is_negative) = get_canonical_verb(&verb_str_owned.to_lowercase())
1183 .map(|(lemma, neg)| (self.interner.intern(lemma), neg))
1184 .unwrap_or((verb, false));
1185
1186 let needs_wide_scope = is_negative && self.negative_scope_mode == NegativeScopeMode::Wide;
1188
1189 if Lexer::is_raising_verb(&verb_str_owned) && self.check_to() {
1190 self.advance();
1191 if self.check_verb() {
1192 let inf_verb = self.consume_verb();
1193 let inf_verb_str = self.interner.resolve(inf_verb).to_lowercase();
1194
1195 if inf_verb_str == "be" && self.check_content_word() {
1196 let adj = self.consume_content_word()?;
1197 let embedded = self.ctx.exprs.alloc(LogicExpr::Predicate {
1198 name: adj,
1199 args: self.ctx.terms.alloc_slice([Term::Variable(var_name)]),
1200 world: None,
1201 });
1202 return Ok(self.ctx.exprs.alloc(LogicExpr::Scopal {
1203 operator: verb,
1204 body: embedded,
1205 }));
1206 }
1207
1208 let embedded = self.ctx.exprs.alloc(LogicExpr::Predicate {
1209 name: inf_verb,
1210 args: self.ctx.terms.alloc_slice([Term::Variable(var_name)]),
1211 world: None,
1212 });
1213 return Ok(self.ctx.exprs.alloc(LogicExpr::Scopal {
1214 operator: verb,
1215 body: embedded,
1216 }));
1217 } else if self.check(&TokenType::Is) || self.check(&TokenType::Are) {
1218 self.advance();
1219 if self.check_content_word() {
1220 let adj = self.consume_content_word()?;
1221 let embedded = self.ctx.exprs.alloc(LogicExpr::Predicate {
1222 name: adj,
1223 args: self.ctx.terms.alloc_slice([Term::Variable(var_name)]),
1224 world: None,
1225 });
1226 return Ok(self.ctx.exprs.alloc(LogicExpr::Scopal {
1227 operator: verb,
1228 body: embedded,
1229 }));
1230 }
1231 }
1232 }
1233
1234 let mut args = vec![var_term];
1235 let mut extra_conditions: Vec<&'a LogicExpr<'a>> = Vec::new();
1236
1237 if self.check(&TokenType::Reflexive) {
1238 self.advance();
1239 args.push(Term::Variable(var_name));
1240 } else if (self.check_content_word() || self.check_article()) && !self.check_verb() {
1241 if matches!(
1242 self.peek().kind,
1243 TokenType::Article(Definiteness::Indefinite)
1244 ) {
1245 self.advance();
1246 let noun = self.consume_content_word()?;
1247 let donkey_var = self.next_var_name();
1248
1249 if needs_wide_scope {
1250 let restriction_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
1258 name: noun,
1259 args: self.ctx.terms.alloc_slice([Term::Variable(donkey_var)]),
1260 world: None,
1261 });
1262
1263 let inner_modifiers = self.collect_adverbs();
1266 let verb_pred = self.build_verb_neo_event(
1267 canonical_verb,
1268 var_name,
1269 Some(Term::Variable(donkey_var)),
1270 inner_modifiers,
1271 );
1272
1273 let body = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
1275 left: restriction_pred,
1276 op: TokenType::And,
1277 right: verb_pred,
1278 });
1279
1280 let existential = self.ctx.exprs.alloc(LogicExpr::Quantifier {
1282 kind: QuantifierKind::Existential,
1283 variable: donkey_var,
1284 body,
1285 island_id: self.current_island,
1286 });
1287
1288 let negated_existential = self.ctx.exprs.alloc(LogicExpr::UnaryOp {
1290 op: TokenType::Not,
1291 operand: existential,
1292 });
1293
1294 return Ok(negated_existential);
1296 }
1297
1298 self.donkey_bindings.push((noun, donkey_var, false, false));
1301
1302 extra_conditions.push(self.ctx.exprs.alloc(LogicExpr::Predicate {
1303 name: noun,
1304 args: self.ctx.terms.alloc_slice([Term::Variable(donkey_var)]),
1305 world: None,
1306 }));
1307
1308 args.push(Term::Variable(donkey_var));
1309 } else {
1310 let object = self.parse_noun_phrase(false)?;
1311
1312 if self.check(&TokenType::That) || self.check(&TokenType::Who) {
1313 self.advance();
1314 let nested_var = self.next_var_name();
1315 let nested_rel = self.parse_relative_clause(nested_var)?;
1316
1317 extra_conditions.push(self.ctx.exprs.alloc(LogicExpr::Predicate {
1318 name: object.noun,
1319 args: self.ctx.terms.alloc_slice([Term::Variable(nested_var)]),
1320 world: None,
1321 }));
1322 extra_conditions.push(nested_rel);
1323 args.push(Term::Variable(nested_var));
1324 } else {
1325 args.push(Term::Constant(object.noun));
1326 }
1327 }
1328 }
1329
1330 while self.check_preposition() {
1331 self.advance();
1332 if self.check(&TokenType::Reflexive) {
1333 self.advance();
1334 args.push(Term::Variable(var_name));
1335 } else if self.check_content_word() || self.check_article() {
1336 let object = self.parse_noun_phrase(false)?;
1337
1338 if self.check(&TokenType::That) || self.check(&TokenType::Who) {
1339 self.advance();
1340 let nested_var = self.next_var_name();
1341 let nested_rel = self.parse_relative_clause(nested_var)?;
1342 extra_conditions.push(self.ctx.exprs.alloc(LogicExpr::Predicate {
1343 name: object.noun,
1344 args: self.ctx.terms.alloc_slice([Term::Variable(nested_var)]),
1345 world: None,
1346 }));
1347 extra_conditions.push(nested_rel);
1348 args.push(Term::Variable(nested_var));
1349 } else {
1350 args.push(Term::Constant(object.noun));
1351 }
1352 }
1353 }
1354
1355 let obj_term = if args.len() > 1 {
1358 Some(args.remove(1))
1359 } else {
1360 None
1361 };
1362 let final_modifiers = self.collect_adverbs();
1363 let base_pred = self.build_verb_neo_event(canonical_verb, var_name, obj_term, final_modifiers);
1364
1365 let verb_pred = if is_negative && self.negative_scope_mode == NegativeScopeMode::Narrow {
1370 self.ctx.exprs.alloc(LogicExpr::UnaryOp {
1371 op: TokenType::Not,
1372 operand: base_pred,
1373 })
1374 } else {
1375 base_pred
1376 };
1377
1378 if extra_conditions.is_empty() {
1379 Ok(verb_pred)
1380 } else {
1381 extra_conditions.push(verb_pred);
1382 self.combine_with_and(extra_conditions)
1383 }
1384 }
1385
1386 fn combine_with_and(&self, mut exprs: Vec<&'a LogicExpr<'a>>) -> ParseResult<&'a LogicExpr<'a>> {
1387 if exprs.is_empty() {
1388 return Err(ParseError {
1389 kind: ParseErrorKind::EmptyRestriction,
1390 span: self.current_span(),
1391 });
1392 }
1393 if exprs.len() == 1 {
1394 return Ok(exprs.remove(0));
1395 }
1396 let mut root = exprs.remove(0);
1397 for expr in exprs {
1398 root = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
1399 left: root,
1400 op: TokenType::And,
1401 right: expr,
1402 });
1403 }
1404 Ok(root)
1405 }
1406
1407 fn wrap_with_definiteness_full(
1408 &mut self,
1409 np: &NounPhrase<'a>,
1410 predicate: &'a LogicExpr<'a>,
1411 ) -> ParseResult<&'a LogicExpr<'a>> {
1412 let result = self.wrap_with_definiteness_and_adjectives_and_pps(
1413 np.definiteness,
1414 np.noun,
1415 np.adjectives,
1416 np.pps,
1417 predicate,
1418 )?;
1419
1420 if let Some(adj) = np.superlative {
1422 let superlative_expr = self.ctx.exprs.alloc(LogicExpr::Superlative {
1423 adjective: adj,
1424 subject: self.ctx.terms.alloc(Term::Constant(np.noun)),
1425 domain: np.noun,
1426 });
1427 Ok(self.ctx.exprs.alloc(LogicExpr::BinaryOp {
1428 left: result,
1429 op: TokenType::And,
1430 right: superlative_expr,
1431 }))
1432 } else {
1433 Ok(result)
1434 }
1435 }
1436
1437 fn wrap_with_definiteness(
1438 &mut self,
1439 definiteness: Option<Definiteness>,
1440 noun: Symbol,
1441 predicate: &'a LogicExpr<'a>,
1442 ) -> ParseResult<&'a LogicExpr<'a>> {
1443 self.wrap_with_definiteness_and_adjectives_and_pps(definiteness, noun, &[], &[], predicate)
1444 }
1445
1446 fn wrap_with_definiteness_and_adjectives(
1447 &mut self,
1448 definiteness: Option<Definiteness>,
1449 noun: Symbol,
1450 adjectives: &[Symbol],
1451 predicate: &'a LogicExpr<'a>,
1452 ) -> ParseResult<&'a LogicExpr<'a>> {
1453 self.wrap_with_definiteness_and_adjectives_and_pps(
1454 definiteness,
1455 noun,
1456 adjectives,
1457 &[],
1458 predicate,
1459 )
1460 }
1461
1462 fn wrap_with_definiteness_and_adjectives_and_pps(
1463 &mut self,
1464 definiteness: Option<Definiteness>,
1465 noun: Symbol,
1466 adjectives: &[Symbol],
1467 pps: &[&'a LogicExpr<'a>],
1468 predicate: &'a LogicExpr<'a>,
1469 ) -> ParseResult<&'a LogicExpr<'a>> {
1470 match definiteness {
1471 Some(Definiteness::Indefinite) => {
1472 let var = self.next_var_name();
1473
1474 let gender = Self::infer_noun_gender(self.interner.resolve(noun));
1477 let number = if Self::is_plural_noun(self.interner.resolve(noun)) {
1478 Number::Plural
1479 } else {
1480 Number::Singular
1481 };
1482 if self.in_negative_quantifier {
1483 self.drs.introduce_referent_with_source(var, noun, gender, number, ReferentSource::NegationScope);
1484 } else {
1485 self.drs.introduce_referent(var, noun, gender, number);
1486 }
1487
1488 let mut restriction = self.ctx.exprs.alloc(LogicExpr::Predicate {
1489 name: noun,
1490 args: self.ctx.terms.alloc_slice([Term::Variable(var)]),
1491 world: None,
1492 });
1493
1494 for adj in adjectives {
1495 let adj_str = self.interner.resolve(*adj).to_lowercase();
1496 let adj_pred = if is_subsective(&adj_str) {
1497 self.ctx.exprs.alloc(LogicExpr::Predicate {
1498 name: *adj,
1499 args: self.ctx.terms.alloc_slice([
1500 Term::Variable(var),
1501 Term::Intension(noun),
1502 ]),
1503 world: None,
1504 })
1505 } else {
1506 self.ctx.exprs.alloc(LogicExpr::Predicate {
1507 name: *adj,
1508 args: self.ctx.terms.alloc_slice([Term::Variable(var)]),
1509 world: None,
1510 })
1511 };
1512 restriction = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
1513 left: restriction,
1514 op: TokenType::And,
1515 right: adj_pred,
1516 });
1517 }
1518
1519 for pp in pps {
1520 let substituted_pp = self.substitute_pp_placeholder(pp, var);
1521 restriction = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
1522 left: restriction,
1523 op: TokenType::And,
1524 right: substituted_pp,
1525 });
1526 }
1527
1528 let substituted = self.substitute_constant_with_var_sym(predicate, noun, var)?;
1529 let body = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
1530 left: restriction,
1531 op: TokenType::And,
1532 right: substituted,
1533 });
1534 Ok(self.ctx.exprs.alloc(LogicExpr::Quantifier {
1535 kind: QuantifierKind::Existential,
1536 variable: var,
1537 body,
1538 island_id: self.current_island,
1539 }))
1540 }
1541 Some(Definiteness::Definite) => {
1542 let noun_str = self.interner.resolve(noun).to_string();
1543
1544 if Self::is_plural_noun(&noun_str) {
1545 let singular = Self::singularize_noun(&noun_str);
1546 let singular_sym = self.interner.intern(&singular);
1547 let sigma_term = Term::Sigma(singular_sym);
1548
1549 let substituted =
1550 self.substitute_constant_with_sigma(predicate, noun, sigma_term)?;
1551
1552 let verb_name = self.find_main_verb_name(predicate);
1553 let is_collective = verb_name
1554 .map(|v| {
1555 let lemma = self.interner.resolve(v);
1556 Lexer::is_collective_verb(lemma)
1557 || (Lexer::is_mixed_verb(lemma) && self.collective_mode)
1558 })
1559 .unwrap_or(false);
1560
1561 let gender = Gender::Unknown; self.drs.introduce_referent_with_source(singular_sym, singular_sym, gender, Number::Plural, ReferentSource::MainClause);
1566
1567 if is_collective {
1568 Ok(substituted)
1569 } else {
1570 Ok(self.ctx.exprs.alloc(LogicExpr::Distributive {
1571 predicate: substituted,
1572 }))
1573 }
1574 } else {
1575 let x = self.next_var_name();
1576 let y = self.next_var_name();
1577
1578 let mut restriction = self.ctx.exprs.alloc(LogicExpr::Predicate {
1579 name: noun,
1580 args: self.ctx.terms.alloc_slice([Term::Variable(x)]),
1581 world: None,
1582 });
1583
1584 for adj in adjectives {
1585 let adj_str = self.interner.resolve(*adj).to_lowercase();
1586 let adj_pred = if is_subsective(&adj_str) {
1587 self.ctx.exprs.alloc(LogicExpr::Predicate {
1588 name: *adj,
1589 args: self.ctx.terms.alloc_slice([
1590 Term::Variable(x),
1591 Term::Intension(noun),
1592 ]),
1593 world: None,
1594 })
1595 } else {
1596 self.ctx.exprs.alloc(LogicExpr::Predicate {
1597 name: *adj,
1598 args: self.ctx.terms.alloc_slice([Term::Variable(x)]),
1599 world: None,
1600 })
1601 };
1602 restriction = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
1603 left: restriction,
1604 op: TokenType::And,
1605 right: adj_pred,
1606 });
1607 }
1608
1609 for pp in pps {
1610 let substituted_pp = self.substitute_pp_placeholder(pp, x);
1611 restriction = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
1612 left: restriction,
1613 op: TokenType::And,
1614 right: substituted_pp,
1615 });
1616 }
1617
1618 let has_prior_antecedent = self.drs.resolve_definite(
1621 self.drs.current_box_index(),
1622 noun
1623 ).is_some();
1624
1625 if !has_prior_antecedent {
1626 if let Some((whole_var, _whole_name)) = self.drs.resolve_bridging(self.interner, noun) {
1627 let part_of_sym = self.interner.intern("PartOf");
1628 let part_of_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
1629 name: part_of_sym,
1630 args: self.ctx.terms.alloc_slice([
1631 Term::Variable(x),
1632 Term::Constant(whole_var),
1633 ]),
1634 world: None,
1635 });
1636 restriction = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
1637 left: restriction,
1638 op: TokenType::And,
1639 right: part_of_pred,
1640 });
1641 }
1642 }
1643
1644 let gender = Self::infer_noun_gender(self.interner.resolve(noun));
1649 let number = if Self::is_plural_noun(self.interner.resolve(noun)) {
1650 Number::Plural
1651 } else {
1652 Number::Singular
1653 };
1654 self.drs.introduce_referent_with_source(x, noun, gender, number, ReferentSource::MainClause);
1655
1656 let mut y_restriction = self.ctx.exprs.alloc(LogicExpr::Predicate {
1657 name: noun,
1658 args: self.ctx.terms.alloc_slice([Term::Variable(y)]),
1659 world: None,
1660 });
1661 for adj in adjectives {
1662 let adj_str = self.interner.resolve(*adj).to_lowercase();
1663 let adj_pred = if is_subsective(&adj_str) {
1664 self.ctx.exprs.alloc(LogicExpr::Predicate {
1665 name: *adj,
1666 args: self.ctx.terms.alloc_slice([
1667 Term::Variable(y),
1668 Term::Intension(noun),
1669 ]),
1670 world: None,
1671 })
1672 } else {
1673 self.ctx.exprs.alloc(LogicExpr::Predicate {
1674 name: *adj,
1675 args: self.ctx.terms.alloc_slice([Term::Variable(y)]),
1676 world: None,
1677 })
1678 };
1679 y_restriction = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
1680 left: y_restriction,
1681 op: TokenType::And,
1682 right: adj_pred,
1683 });
1684 }
1685
1686 for pp in pps {
1687 let substituted_pp = self.substitute_pp_placeholder(pp, y);
1688 y_restriction = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
1689 left: y_restriction,
1690 op: TokenType::And,
1691 right: substituted_pp,
1692 });
1693 }
1694
1695 let identity = self.ctx.exprs.alloc(LogicExpr::Identity {
1696 left: self.ctx.terms.alloc(Term::Variable(y)),
1697 right: self.ctx.terms.alloc(Term::Variable(x)),
1698 });
1699 let uniqueness_body = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
1700 left: y_restriction,
1701 op: TokenType::Implies,
1702 right: identity,
1703 });
1704 let uniqueness = self.ctx.exprs.alloc(LogicExpr::Quantifier {
1705 kind: QuantifierKind::Universal,
1706 variable: y,
1707 body: uniqueness_body,
1708 island_id: self.current_island,
1709 });
1710
1711 let main_pred = self.substitute_constant_with_var_sym(predicate, noun, x)?;
1712
1713 let inner = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
1714 left: restriction,
1715 op: TokenType::And,
1716 right: uniqueness,
1717 });
1718 let body = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
1719 left: inner,
1720 op: TokenType::And,
1721 right: main_pred,
1722 });
1723
1724 Ok(self.ctx.exprs.alloc(LogicExpr::Quantifier {
1725 kind: QuantifierKind::Existential,
1726 variable: x,
1727 body,
1728 island_id: self.current_island,
1729 }))
1730 }
1731 }
1732 Some(Definiteness::Proximal) | Some(Definiteness::Distal) => {
1733 let var = self.next_var_name();
1734
1735 let mut restriction = self.ctx.exprs.alloc(LogicExpr::Predicate {
1736 name: noun,
1737 args: self.ctx.terms.alloc_slice([Term::Variable(var)]),
1738 world: None,
1739 });
1740
1741 let deictic_name = if matches!(definiteness, Some(Definiteness::Proximal)) {
1742 self.interner.intern("Proximal")
1743 } else {
1744 self.interner.intern("Distal")
1745 };
1746 let deictic_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
1747 name: deictic_name,
1748 args: self.ctx.terms.alloc_slice([Term::Variable(var)]),
1749 world: None,
1750 });
1751 restriction = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
1752 left: restriction,
1753 op: TokenType::And,
1754 right: deictic_pred,
1755 });
1756
1757 for adj in adjectives {
1758 let adj_str = self.interner.resolve(*adj).to_lowercase();
1759 let adj_pred = if is_subsective(&adj_str) {
1760 self.ctx.exprs.alloc(LogicExpr::Predicate {
1761 name: *adj,
1762 args: self.ctx.terms.alloc_slice([
1763 Term::Variable(var),
1764 Term::Intension(noun),
1765 ]),
1766 world: None,
1767 })
1768 } else {
1769 self.ctx.exprs.alloc(LogicExpr::Predicate {
1770 name: *adj,
1771 args: self.ctx.terms.alloc_slice([Term::Variable(var)]),
1772 world: None,
1773 })
1774 };
1775 restriction = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
1776 left: restriction,
1777 op: TokenType::And,
1778 right: adj_pred,
1779 });
1780 }
1781
1782 for pp in pps {
1783 let substituted_pp = self.substitute_pp_placeholder(pp, var);
1784 restriction = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
1785 left: restriction,
1786 op: TokenType::And,
1787 right: substituted_pp,
1788 });
1789 }
1790
1791 let substituted = self.substitute_constant_with_var_sym(predicate, noun, var)?;
1792 let body = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
1793 left: restriction,
1794 op: TokenType::And,
1795 right: substituted,
1796 });
1797 Ok(self.ctx.exprs.alloc(LogicExpr::Quantifier {
1798 kind: QuantifierKind::Existential,
1799 variable: var,
1800 body,
1801 island_id: self.current_island,
1802 }))
1803 }
1804 None => Ok(predicate),
1805 }
1806 }
1807
1808 fn wrap_with_definiteness_for_object(
1809 &mut self,
1810 definiteness: Option<Definiteness>,
1811 noun: Symbol,
1812 predicate: &'a LogicExpr<'a>,
1813 ) -> ParseResult<&'a LogicExpr<'a>> {
1814 match definiteness {
1815 Some(Definiteness::Indefinite) => {
1816 let var = self.next_var_name();
1817
1818 let gender = Self::infer_noun_gender(self.interner.resolve(noun));
1821 let number = if Self::is_plural_noun(self.interner.resolve(noun)) {
1822 Number::Plural
1823 } else {
1824 Number::Singular
1825 };
1826 if self.in_negative_quantifier {
1827 self.drs.introduce_referent_with_source(var, noun, gender, number, ReferentSource::NegationScope);
1828 } else {
1829 self.drs.introduce_referent(var, noun, gender, number);
1830 }
1831
1832 let type_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
1833 name: noun,
1834 args: self.ctx.terms.alloc_slice([Term::Variable(var)]),
1835 world: None,
1836 });
1837 let substituted = self.substitute_constant_with_var(predicate, noun, var)?;
1838 let body = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
1839 left: type_pred,
1840 op: TokenType::And,
1841 right: substituted,
1842 });
1843 Ok(self.ctx.exprs.alloc(LogicExpr::Quantifier {
1844 kind: QuantifierKind::Existential,
1845 variable: var,
1846 body,
1847 island_id: self.current_island,
1848 }))
1849 }
1850 Some(Definiteness::Definite) => {
1851 let x = self.next_var_name();
1852 let y = self.next_var_name();
1853
1854 let type_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
1855 name: noun,
1856 args: self.ctx.terms.alloc_slice([Term::Variable(x)]),
1857 world: None,
1858 });
1859
1860 let identity = self.ctx.exprs.alloc(LogicExpr::Identity {
1861 left: self.ctx.terms.alloc(Term::Variable(y)),
1862 right: self.ctx.terms.alloc(Term::Variable(x)),
1863 });
1864 let inner_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
1865 name: noun,
1866 args: self.ctx.terms.alloc_slice([Term::Variable(y)]),
1867 world: None,
1868 });
1869 let uniqueness_body = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
1870 left: inner_pred,
1871 op: TokenType::Implies,
1872 right: identity,
1873 });
1874 let uniqueness = self.ctx.exprs.alloc(LogicExpr::Quantifier {
1875 kind: QuantifierKind::Universal,
1876 variable: y,
1877 body: uniqueness_body,
1878 island_id: self.current_island,
1879 });
1880
1881 let main_pred = self.substitute_constant_with_var(predicate, noun, x)?;
1882
1883 let type_and_unique = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
1884 left: type_pred,
1885 op: TokenType::And,
1886 right: uniqueness,
1887 });
1888 let body = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
1889 left: type_and_unique,
1890 op: TokenType::And,
1891 right: main_pred,
1892 });
1893
1894 Ok(self.ctx.exprs.alloc(LogicExpr::Quantifier {
1895 kind: QuantifierKind::Existential,
1896 variable: x,
1897 body,
1898 island_id: self.current_island,
1899 }))
1900 }
1901 Some(Definiteness::Proximal) | Some(Definiteness::Distal) => {
1902 let var = self.next_var_name();
1903
1904 let mut restriction = self.ctx.exprs.alloc(LogicExpr::Predicate {
1905 name: noun,
1906 args: self.ctx.terms.alloc_slice([Term::Variable(var)]),
1907 world: None,
1908 });
1909
1910 let deictic_name = if matches!(definiteness, Some(Definiteness::Proximal)) {
1911 self.interner.intern("Proximal")
1912 } else {
1913 self.interner.intern("Distal")
1914 };
1915 let deictic_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
1916 name: deictic_name,
1917 args: self.ctx.terms.alloc_slice([Term::Variable(var)]),
1918 world: None,
1919 });
1920 restriction = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
1921 left: restriction,
1922 op: TokenType::And,
1923 right: deictic_pred,
1924 });
1925
1926 let substituted = self.substitute_constant_with_var(predicate, noun, var)?;
1927 let body = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
1928 left: restriction,
1929 op: TokenType::And,
1930 right: substituted,
1931 });
1932 Ok(self.ctx.exprs.alloc(LogicExpr::Quantifier {
1933 kind: QuantifierKind::Existential,
1934 variable: var,
1935 body,
1936 island_id: self.current_island,
1937 }))
1938 }
1939 None => Ok(predicate),
1940 }
1941 }
1942
1943 fn substitute_pp_placeholder(&mut self, pp: &'a LogicExpr<'a>, var: Symbol) -> &'a LogicExpr<'a> {
1944 let placeholder = self.interner.intern("_PP_SELF_");
1945 match pp {
1946 LogicExpr::Predicate { name, args, .. } => {
1947 let new_args: Vec<Term<'a>> = args
1948 .iter()
1949 .map(|arg| match arg {
1950 Term::Variable(v) if *v == placeholder => Term::Variable(var),
1951 other => *other,
1952 })
1953 .collect();
1954 self.ctx.exprs.alloc(LogicExpr::Predicate {
1955 name: *name,
1956 args: self.ctx.terms.alloc_slice(new_args),
1957 world: None,
1958 })
1959 }
1960 _ => pp,
1961 }
1962 }
1963
1964 fn substitute_constant_with_var(
1965 &self,
1966 expr: &'a LogicExpr<'a>,
1967 constant_name: Symbol,
1968 var_name: Symbol,
1969 ) -> ParseResult<&'a LogicExpr<'a>> {
1970 match expr {
1971 LogicExpr::Predicate { name, args, .. } => {
1972 let new_args: Vec<Term<'a>> = args
1973 .iter()
1974 .map(|arg| match arg {
1975 Term::Constant(c) if *c == constant_name => Term::Variable(var_name),
1976 Term::Constant(c) => Term::Constant(*c),
1977 Term::Variable(v) => Term::Variable(*v),
1978 Term::Function(n, a) => Term::Function(*n, *a),
1979 Term::Group(m) => Term::Group(*m),
1980 Term::Possessed { possessor, possessed } => Term::Possessed {
1981 possessor: *possessor,
1982 possessed: *possessed,
1983 },
1984 Term::Sigma(p) => Term::Sigma(*p),
1985 Term::Intension(p) => Term::Intension(*p),
1986 Term::Proposition(e) => Term::Proposition(*e),
1987 Term::Value { kind, unit, dimension } => Term::Value {
1988 kind: *kind,
1989 unit: *unit,
1990 dimension: *dimension,
1991 },
1992 })
1993 .collect();
1994 Ok(self.ctx.exprs.alloc(LogicExpr::Predicate {
1995 name: *name,
1996 args: self.ctx.terms.alloc_slice(new_args),
1997 world: None,
1998 }))
1999 }
2000 LogicExpr::Temporal { operator, body } => Ok(self.ctx.exprs.alloc(LogicExpr::Temporal {
2001 operator: *operator,
2002 body: self.substitute_constant_with_var(body, constant_name, var_name)?,
2003 })),
2004 LogicExpr::Aspectual { operator, body } => Ok(self.ctx.exprs.alloc(LogicExpr::Aspectual {
2005 operator: *operator,
2006 body: self.substitute_constant_with_var(body, constant_name, var_name)?,
2007 })),
2008 LogicExpr::UnaryOp { op, operand } => Ok(self.ctx.exprs.alloc(LogicExpr::UnaryOp {
2009 op: op.clone(),
2010 operand: self.substitute_constant_with_var(operand, constant_name, var_name)?,
2011 })),
2012 LogicExpr::BinaryOp { left, op, right } => Ok(self.ctx.exprs.alloc(LogicExpr::BinaryOp {
2013 left: self.substitute_constant_with_var(left, constant_name, var_name)?,
2014 op: op.clone(),
2015 right: self.substitute_constant_with_var(right, constant_name, var_name)?,
2016 })),
2017 LogicExpr::Event { predicate, adverbs } => Ok(self.ctx.exprs.alloc(LogicExpr::Event {
2018 predicate: self.substitute_constant_with_var(predicate, constant_name, var_name)?,
2019 adverbs: *adverbs,
2020 })),
2021 LogicExpr::TemporalAnchor { anchor, body } => {
2022 Ok(self.ctx.exprs.alloc(LogicExpr::TemporalAnchor {
2023 anchor: *anchor,
2024 body: self.substitute_constant_with_var(body, constant_name, var_name)?,
2025 }))
2026 }
2027 LogicExpr::NeoEvent(data) => {
2028 let new_roles: Vec<(crate::ast::ThematicRole, Term<'a>)> = data
2030 .roles
2031 .iter()
2032 .map(|(role, term)| {
2033 let new_term = match term {
2034 Term::Constant(c) if *c == constant_name => Term::Variable(var_name),
2035 Term::Constant(c) => Term::Constant(*c),
2036 Term::Variable(v) => Term::Variable(*v),
2037 Term::Function(n, a) => Term::Function(*n, *a),
2038 Term::Group(m) => Term::Group(*m),
2039 Term::Possessed { possessor, possessed } => Term::Possessed {
2040 possessor: *possessor,
2041 possessed: *possessed,
2042 },
2043 Term::Sigma(p) => Term::Sigma(*p),
2044 Term::Intension(p) => Term::Intension(*p),
2045 Term::Proposition(e) => Term::Proposition(*e),
2046 Term::Value { kind, unit, dimension } => Term::Value {
2047 kind: *kind,
2048 unit: *unit,
2049 dimension: *dimension,
2050 },
2051 };
2052 (*role, new_term)
2053 })
2054 .collect();
2055 Ok(self.ctx.exprs.alloc(LogicExpr::NeoEvent(Box::new(crate::ast::NeoEventData {
2056 event_var: data.event_var,
2057 verb: data.verb,
2058 roles: self.ctx.roles.alloc_slice(new_roles),
2059 modifiers: data.modifiers,
2060 suppress_existential: data.suppress_existential,
2061 world: None,
2062 }))))
2063 }
2064 LogicExpr::Quantifier { kind, variable, body, island_id } => {
2066 let new_body = self.substitute_constant_with_var(body, constant_name, var_name)?;
2067 Ok(self.ctx.exprs.alloc(LogicExpr::Quantifier {
2068 kind: *kind,
2069 variable: *variable,
2070 body: new_body,
2071 island_id: *island_id,
2072 }))
2073 }
2074 _ => Ok(expr),
2075 }
2076 }
2077
2078 fn substitute_constant_with_var_sym(
2079 &self,
2080 expr: &'a LogicExpr<'a>,
2081 constant_name: Symbol,
2082 var_name: Symbol,
2083 ) -> ParseResult<&'a LogicExpr<'a>> {
2084 self.substitute_constant_with_var(expr, constant_name, var_name)
2085 }
2086
2087 fn substitute_constant_with_sigma(
2088 &self,
2089 expr: &'a LogicExpr<'a>,
2090 constant_name: Symbol,
2091 sigma_term: Term<'a>,
2092 ) -> ParseResult<&'a LogicExpr<'a>> {
2093 match expr {
2094 LogicExpr::Predicate { name, args, .. } => {
2095 let new_args: Vec<Term<'a>> = args
2096 .iter()
2097 .map(|arg| match arg {
2098 Term::Constant(c) if *c == constant_name => sigma_term.clone(),
2099 Term::Constant(c) => Term::Constant(*c),
2100 Term::Variable(v) => Term::Variable(*v),
2101 Term::Function(n, a) => Term::Function(*n, *a),
2102 Term::Group(m) => Term::Group(*m),
2103 Term::Possessed { possessor, possessed } => Term::Possessed {
2104 possessor: *possessor,
2105 possessed: *possessed,
2106 },
2107 Term::Sigma(p) => Term::Sigma(*p),
2108 Term::Intension(p) => Term::Intension(*p),
2109 Term::Proposition(e) => Term::Proposition(*e),
2110 Term::Value { kind, unit, dimension } => Term::Value {
2111 kind: *kind,
2112 unit: *unit,
2113 dimension: *dimension,
2114 },
2115 })
2116 .collect();
2117 Ok(self.ctx.exprs.alloc(LogicExpr::Predicate {
2118 name: *name,
2119 args: self.ctx.terms.alloc_slice(new_args),
2120 world: None,
2121 }))
2122 }
2123 LogicExpr::Temporal { operator, body } => Ok(self.ctx.exprs.alloc(LogicExpr::Temporal {
2124 operator: *operator,
2125 body: self.substitute_constant_with_sigma(body, constant_name, sigma_term)?,
2126 })),
2127 LogicExpr::Aspectual { operator, body } => Ok(self.ctx.exprs.alloc(LogicExpr::Aspectual {
2128 operator: *operator,
2129 body: self.substitute_constant_with_sigma(body, constant_name, sigma_term)?,
2130 })),
2131 LogicExpr::UnaryOp { op, operand } => Ok(self.ctx.exprs.alloc(LogicExpr::UnaryOp {
2132 op: op.clone(),
2133 operand: self.substitute_constant_with_sigma(operand, constant_name, sigma_term)?,
2134 })),
2135 LogicExpr::BinaryOp { left, op, right } => Ok(self.ctx.exprs.alloc(LogicExpr::BinaryOp {
2136 left: self.substitute_constant_with_sigma(
2137 left,
2138 constant_name,
2139 sigma_term.clone(),
2140 )?,
2141 op: op.clone(),
2142 right: self.substitute_constant_with_sigma(right, constant_name, sigma_term)?,
2143 })),
2144 LogicExpr::Event { predicate, adverbs } => Ok(self.ctx.exprs.alloc(LogicExpr::Event {
2145 predicate: self.substitute_constant_with_sigma(
2146 predicate,
2147 constant_name,
2148 sigma_term,
2149 )?,
2150 adverbs: *adverbs,
2151 })),
2152 LogicExpr::TemporalAnchor { anchor, body } => {
2153 Ok(self.ctx.exprs.alloc(LogicExpr::TemporalAnchor {
2154 anchor: *anchor,
2155 body: self.substitute_constant_with_sigma(body, constant_name, sigma_term)?,
2156 }))
2157 }
2158 LogicExpr::NeoEvent(data) => {
2159 let new_roles: Vec<(crate::ast::ThematicRole, Term<'a>)> = data
2160 .roles
2161 .iter()
2162 .map(|(role, term)| {
2163 let new_term = match term {
2164 Term::Constant(c) if *c == constant_name => sigma_term.clone(),
2165 Term::Constant(c) => Term::Constant(*c),
2166 Term::Variable(v) => Term::Variable(*v),
2167 Term::Function(n, a) => Term::Function(*n, *a),
2168 Term::Group(m) => Term::Group(*m),
2169 Term::Possessed { possessor, possessed } => Term::Possessed {
2170 possessor: *possessor,
2171 possessed: *possessed,
2172 },
2173 Term::Sigma(p) => Term::Sigma(*p),
2174 Term::Intension(p) => Term::Intension(*p),
2175 Term::Proposition(e) => Term::Proposition(*e),
2176 Term::Value { kind, unit, dimension } => Term::Value {
2177 kind: *kind,
2178 unit: *unit,
2179 dimension: *dimension,
2180 },
2181 };
2182 (*role, new_term)
2183 })
2184 .collect();
2185 Ok(self.ctx.exprs.alloc(LogicExpr::NeoEvent(Box::new(crate::ast::NeoEventData {
2186 event_var: data.event_var,
2187 verb: data.verb,
2188 roles: self.ctx.roles.alloc_slice(new_roles),
2189 modifiers: data.modifiers,
2190 suppress_existential: data.suppress_existential,
2191 world: None,
2192 }))))
2193 }
2194 LogicExpr::Distributive { predicate } => Ok(self.ctx.exprs.alloc(LogicExpr::Distributive {
2195 predicate: self.substitute_constant_with_sigma(predicate, constant_name, sigma_term)?,
2196 })),
2197 _ => Ok(expr),
2198 }
2199 }
2200
2201 fn find_main_verb_name(&self, expr: &LogicExpr<'a>) -> Option<Symbol> {
2202 match expr {
2203 LogicExpr::Predicate { name, .. } => Some(*name),
2204 LogicExpr::NeoEvent(data) => Some(data.verb),
2205 LogicExpr::Temporal { body, .. } => self.find_main_verb_name(body),
2206 LogicExpr::Aspectual { body, .. } => self.find_main_verb_name(body),
2207 LogicExpr::Event { predicate, .. } => self.find_main_verb_name(predicate),
2208 LogicExpr::TemporalAnchor { body, .. } => self.find_main_verb_name(body),
2209 LogicExpr::UnaryOp { operand, .. } => self.find_main_verb_name(operand),
2210 LogicExpr::BinaryOp { left, .. } => self.find_main_verb_name(left),
2211 _ => None,
2212 }
2213 }
2214
2215 fn transform_cardinal_to_group(&mut self, expr: &'a LogicExpr<'a>) -> ParseResult<&'a LogicExpr<'a>> {
2216 match expr {
2217 LogicExpr::Quantifier { kind: QuantifierKind::Cardinal(n), variable, body, .. } => {
2218 let group_var = self.interner.intern("g");
2219 let member_var = *variable;
2220
2221 let (restriction, body_rest) = match body {
2224 LogicExpr::BinaryOp { left, op: TokenType::And, right } => (*left, *right),
2225 _ => return Ok(expr),
2226 };
2227
2228 let transformed_body = self.substitute_constant_with_var_sym(body_rest, member_var, group_var)?;
2230
2231 Ok(self.ctx.exprs.alloc(LogicExpr::GroupQuantifier {
2232 group_var,
2233 count: *n,
2234 member_var,
2235 restriction,
2236 body: transformed_body,
2237 }))
2238 }
2239 LogicExpr::Temporal { operator, body } => {
2241 let transformed = self.transform_cardinal_to_group(body)?;
2242 Ok(self.ctx.exprs.alloc(LogicExpr::Temporal {
2243 operator: *operator,
2244 body: transformed,
2245 }))
2246 }
2247 LogicExpr::Aspectual { operator, body } => {
2248 let transformed = self.transform_cardinal_to_group(body)?;
2249 Ok(self.ctx.exprs.alloc(LogicExpr::Aspectual {
2250 operator: *operator,
2251 body: transformed,
2252 }))
2253 }
2254 LogicExpr::UnaryOp { op, operand } => {
2255 let transformed = self.transform_cardinal_to_group(operand)?;
2256 Ok(self.ctx.exprs.alloc(LogicExpr::UnaryOp {
2257 op: op.clone(),
2258 operand: transformed,
2259 }))
2260 }
2261 LogicExpr::BinaryOp { left, op, right } => {
2262 let transformed_left = self.transform_cardinal_to_group(left)?;
2263 let transformed_right = self.transform_cardinal_to_group(right)?;
2264 Ok(self.ctx.exprs.alloc(LogicExpr::BinaryOp {
2265 left: transformed_left,
2266 op: op.clone(),
2267 right: transformed_right,
2268 }))
2269 }
2270 LogicExpr::Distributive { predicate } => {
2271 let transformed = self.transform_cardinal_to_group(predicate)?;
2272 Ok(self.ctx.exprs.alloc(LogicExpr::Distributive {
2273 predicate: transformed,
2274 }))
2275 }
2276 LogicExpr::Quantifier { kind, variable, body, island_id } => {
2277 let transformed = self.transform_cardinal_to_group(body)?;
2278 Ok(self.ctx.exprs.alloc(LogicExpr::Quantifier {
2279 kind: kind.clone(),
2280 variable: *variable,
2281 body: transformed,
2282 island_id: *island_id,
2283 }))
2284 }
2285 _ => Ok(expr),
2286 }
2287 }
2288
2289 fn build_verb_neo_event(
2290 &mut self,
2291 verb: Symbol,
2292 subject_var: Symbol,
2293 object: Option<Term<'a>>,
2294 modifiers: Vec<Symbol>,
2295 ) -> &'a LogicExpr<'a> {
2296 let event_var = self.get_event_var();
2297
2298 let verb_str = self.interner.resolve(verb).to_lowercase();
2300 let is_unaccusative = lookup_verb_db(&verb_str)
2301 .map(|meta| meta.features.contains(&Feature::Unaccusative))
2302 .unwrap_or(false);
2303
2304 let has_object = object.is_some();
2306 let subject_role = if is_unaccusative && !has_object {
2307 ThematicRole::Theme
2308 } else {
2309 ThematicRole::Agent
2310 };
2311
2312 let mut roles = vec![(subject_role, Term::Variable(subject_var))];
2314 if let Some(obj_term) = object {
2315 roles.push((ThematicRole::Theme, obj_term));
2316 }
2317
2318 self.ctx.exprs.alloc(LogicExpr::NeoEvent(Box::new(NeoEventData {
2321 event_var,
2322 verb,
2323 roles: self.ctx.roles.alloc_slice(roles),
2324 modifiers: self.ctx.syms.alloc_slice(modifiers),
2325 suppress_existential: false,
2326 world: None,
2327 })))
2328 }
2329}
2330
2331impl<'a, 'ctx, 'int> Parser<'a, 'ctx, 'int> {
2333 fn expr_mentions_var(&self, expr: &LogicExpr<'a>, var: Symbol) -> bool {
2335 match expr {
2336 LogicExpr::Predicate { args, .. } => {
2337 args.iter().any(|term| self.term_mentions_var(term, var))
2338 }
2339 LogicExpr::BinaryOp { left, right, .. } => {
2340 self.expr_mentions_var(left, var) || self.expr_mentions_var(right, var)
2341 }
2342 LogicExpr::UnaryOp { operand, .. } => self.expr_mentions_var(operand, var),
2343 LogicExpr::Quantifier { body, .. } => self.expr_mentions_var(body, var),
2344 LogicExpr::NeoEvent(data) => {
2345 data.roles.iter().any(|(_, term)| self.term_mentions_var(term, var))
2346 }
2347 LogicExpr::Temporal { body, .. } => self.expr_mentions_var(body, var),
2348 LogicExpr::Aspectual { body, .. } => self.expr_mentions_var(body, var),
2349 LogicExpr::Event { predicate, .. } => self.expr_mentions_var(predicate, var),
2350 LogicExpr::Modal { operand, .. } => self.expr_mentions_var(operand, var),
2351 LogicExpr::Scopal { body, .. } => self.expr_mentions_var(body, var),
2352 _ => false,
2353 }
2354 }
2355
2356 fn term_mentions_var(&self, term: &Term<'a>, var: Symbol) -> bool {
2357 match term {
2358 Term::Variable(v) => *v == var,
2359 Term::Function(_, args) => args.iter().any(|t| self.term_mentions_var(t, var)),
2360 _ => false,
2361 }
2362 }
2363
2364 fn collect_conjuncts(&self, expr: &'a LogicExpr<'a>) -> Vec<&'a LogicExpr<'a>> {
2366 match expr {
2367 LogicExpr::BinaryOp { left, op: TokenType::And, right } => {
2368 let mut result = self.collect_conjuncts(left);
2369 result.extend(self.collect_conjuncts(right));
2370 result
2371 }
2372 _ => vec![expr],
2373 }
2374 }
2375
2376 fn wrap_donkey_in_restriction(
2389 &self,
2390 body: &'a LogicExpr<'a>,
2391 donkey_var: Symbol,
2392 wide_scope_negation: bool,
2393 ) -> &'a LogicExpr<'a> {
2394 if let LogicExpr::Quantifier { kind, variable, body: inner_body, island_id } = body {
2396 let transformed = self.wrap_donkey_in_restriction(inner_body, donkey_var, wide_scope_negation);
2397 return self.ctx.exprs.alloc(LogicExpr::Quantifier {
2398 kind: kind.clone(),
2399 variable: *variable,
2400 body: transformed,
2401 island_id: *island_id,
2402 });
2403 }
2404
2405 if let LogicExpr::BinaryOp { left, op: TokenType::Implies, right } = body {
2407 return self.wrap_in_implication(*left, *right, donkey_var, wide_scope_negation);
2408 }
2409
2410 if let LogicExpr::BinaryOp { left: _, op: TokenType::And, right: _ } = body {
2412 return self.wrap_in_conjunction(body, donkey_var, wide_scope_negation);
2413 }
2414
2415 body
2417 }
2418
2419 fn wrap_in_implication(
2421 &self,
2422 restriction: &'a LogicExpr<'a>,
2423 consequent: &'a LogicExpr<'a>,
2424 donkey_var: Symbol,
2425 wide_scope_negation: bool,
2426 ) -> &'a LogicExpr<'a> {
2427 let conjuncts = self.collect_conjuncts(restriction);
2429
2430 let (with_var, without_var): (Vec<_>, Vec<_>) = conjuncts
2432 .into_iter()
2433 .partition(|c| self.expr_mentions_var(c, donkey_var));
2434
2435 if with_var.is_empty() {
2436 return self.ctx.exprs.alloc(LogicExpr::BinaryOp {
2438 left: restriction,
2439 op: TokenType::Implies,
2440 right: consequent,
2441 });
2442 }
2443
2444 let with_var_combined = self.combine_conjuncts(&with_var);
2446
2447 let existential = self.ctx.exprs.alloc(LogicExpr::Quantifier {
2449 kind: QuantifierKind::Existential,
2450 variable: donkey_var,
2451 body: with_var_combined,
2452 island_id: self.current_island,
2453 });
2454
2455 let wrapped = if wide_scope_negation {
2457 self.ctx.exprs.alloc(LogicExpr::UnaryOp {
2458 op: TokenType::Not,
2459 operand: existential,
2460 })
2461 } else {
2462 existential
2463 };
2464
2465 let new_restriction = if without_var.is_empty() {
2467 wrapped
2468 } else {
2469 let without_combined = self.combine_conjuncts(&without_var);
2470 self.ctx.exprs.alloc(LogicExpr::BinaryOp {
2471 left: without_combined,
2472 op: TokenType::And,
2473 right: wrapped,
2474 })
2475 };
2476
2477 self.ctx.exprs.alloc(LogicExpr::BinaryOp {
2479 left: new_restriction,
2480 op: TokenType::Implies,
2481 right: consequent,
2482 })
2483 }
2484
2485 fn wrap_in_conjunction(
2487 &self,
2488 body: &'a LogicExpr<'a>,
2489 donkey_var: Symbol,
2490 wide_scope_negation: bool,
2491 ) -> &'a LogicExpr<'a> {
2492 let conjuncts = self.collect_conjuncts(body);
2494
2495 let (with_var, without_var): (Vec<_>, Vec<_>) = conjuncts
2497 .into_iter()
2498 .partition(|c| self.expr_mentions_var(c, donkey_var));
2499
2500 if with_var.is_empty() {
2501 return body;
2503 }
2504
2505 let with_var_combined = self.combine_conjuncts(&with_var);
2507
2508 let existential = self.ctx.exprs.alloc(LogicExpr::Quantifier {
2510 kind: QuantifierKind::Existential,
2511 variable: donkey_var,
2512 body: with_var_combined,
2513 island_id: self.current_island,
2514 });
2515
2516 let wrapped = if wide_scope_negation {
2518 self.ctx.exprs.alloc(LogicExpr::UnaryOp {
2519 op: TokenType::Not,
2520 operand: existential,
2521 })
2522 } else {
2523 existential
2524 };
2525
2526 if without_var.is_empty() {
2528 wrapped
2529 } else {
2530 let without_combined = self.combine_conjuncts(&without_var);
2531 self.ctx.exprs.alloc(LogicExpr::BinaryOp {
2532 left: without_combined,
2533 op: TokenType::And,
2534 right: wrapped,
2535 })
2536 }
2537 }
2538
2539 fn combine_conjuncts(&self, conjuncts: &[&'a LogicExpr<'a>]) -> &'a LogicExpr<'a> {
2540 if conjuncts.is_empty() {
2541 panic!("Cannot combine empty conjuncts");
2542 }
2543 if conjuncts.len() == 1 {
2544 return conjuncts[0];
2545 }
2546 let mut result = conjuncts[0];
2547 for c in &conjuncts[1..] {
2548 result = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
2549 left: result,
2550 op: TokenType::And,
2551 right: *c,
2552 });
2553 }
2554 result
2555 }
2556}