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