1use super::clause::ClauseParsing;
22use super::noun::NounParsing;
23use super::pragmatics::PragmaticsParsing;
24use super::quantifier::QuantifierParsing;
25use super::{ParseResult, Parser};
26use crate::ast::{AspectOperator, LogicExpr, ModalDomain, ModalFlavor, ModalVector, NeoEventData, QuantifierKind, ThematicRole, VoiceOperator, Term};
27use crate::drs::TimeRelation;
28use crate::error::{ParseError, ParseErrorKind};
29use logicaffeine_base::Symbol;
30use crate::lexicon::{Time, Aspect};
31use crate::token::TokenType;
32
33pub trait ModalParsing<'a, 'ctx, 'int> {
38 fn parse_modal(&mut self) -> ParseResult<&'a LogicExpr<'a>>;
40 fn parse_aspect_chain(&mut self, subject_symbol: Symbol) -> ParseResult<&'a LogicExpr<'a>>;
42 fn parse_aspect_chain_with_term(&mut self, subject_term: Term<'a>) -> ParseResult<&'a LogicExpr<'a>>;
44 fn token_to_vector(&self, token: &TokenType) -> ModalVector;
46}
47
48impl<'a, 'ctx, 'int> ModalParsing<'a, 'ctx, 'int> for Parser<'a, 'ctx, 'int> {
49 fn parse_modal(&mut self) -> ParseResult<&'a LogicExpr<'a>> {
50 use crate::drs::BoxType;
51
52 let vector = self.token_to_vector(&self.previous().kind.clone());
53
54 self.drs.enter_box(BoxType::ModalScope);
56
57 if self.check(&TokenType::That) {
58 self.advance();
59 }
60
61 let content = self.parse_sentence()?;
62
63 self.drs.exit_box();
65
66 Ok(self.ctx.exprs.alloc(LogicExpr::Modal {
67 vector,
68 operand: content,
69 }))
70 }
71
72 fn parse_aspect_chain(&mut self, subject_symbol: Symbol) -> ParseResult<&'a LogicExpr<'a>> {
73 self.parse_aspect_chain_with_term(Term::Constant(subject_symbol))
74 }
75
76 fn parse_aspect_chain_with_term(&mut self, subject_term: Term<'a>) -> ParseResult<&'a LogicExpr<'a>> {
77 let mut has_modal = false;
78 let mut modal_vector = None;
79 let mut has_negation = false;
80 let mut has_perfect = false;
81 let mut has_passive = false;
82 let mut has_progressive = false;
83
84 if self.check(&TokenType::Would) || self.check(&TokenType::Could)
85 || self.check(&TokenType::Must) || self.check(&TokenType::Can)
86 || self.check(&TokenType::Should) || self.check(&TokenType::May)
87 || self.check(&TokenType::Cannot) || self.check(&TokenType::Might)
88 || self.check(&TokenType::Shall) {
89 let modal_token = self.peek().kind.clone();
90 self.advance();
91 has_modal = true;
92 let vector = self.token_to_vector(&modal_token);
93 modal_vector = Some(vector.clone());
94 self.drs.enter_box(crate::drs::BoxType::ModalScope);
97 let is_epistemic = matches!(vector.flavor, crate::ast::ModalFlavor::Epistemic);
100 self.world_state.enter_modal_context(is_epistemic, vector.force);
101 }
102
103 if self.check(&TokenType::Not) {
104 self.advance();
105 has_negation = true;
106 }
107
108 if self.check(&TokenType::Never) && !has_negation {
110 self.advance();
111 has_negation = true;
112 }
113
114 let mut nested_modal_vector = None;
117 if self.check_content_word() {
118 let word = self.interner.resolve(self.peek().lexeme).to_lowercase();
119 if word == "be" {
120 if let Some(next1) = self.tokens.get(self.current + 1) {
122 let next1_word = self.interner.resolve(next1.lexeme).to_lowercase();
123 if next1_word == "able" {
124 if let Some(next2) = self.tokens.get(self.current + 2) {
125 if matches!(next2.kind, TokenType::To) {
126 self.advance(); self.advance(); self.advance(); nested_modal_vector = Some(ModalVector {
131 domain: ModalDomain::Alethic,
132 force: 0.5, flavor: ModalFlavor::Root, modal_base: None,
135 ordering_source: None,
136 });
137 }
138 }
139 }
140 }
141 }
142 }
143
144 if self.check_content_word() {
145 let word = self.interner.resolve(self.peek().lexeme).to_lowercase();
146 if word == "have" || word == "has" || word == "had" {
147 self.advance();
148 has_perfect = true;
149 }
150 }
151
152 if self.check(&TokenType::Had) {
153 self.advance();
154 has_perfect = true;
155 let r_var = self.world_state.next_reference_time();
157 self.world_state.add_time_constraint(r_var, TimeRelation::Precedes, "S".to_string());
158 }
159
160 if self.check_content_word() {
161 let word = self.interner.resolve(self.peek().lexeme).to_lowercase();
162 if word == "been" {
163 self.advance();
164
165 if self.check_verb() {
166 match &self.peek().kind {
167 TokenType::Verb { aspect: Aspect::Progressive, .. } => {
168 has_progressive = true;
169 }
170 TokenType::Verb { .. } => {
171 let next_word = self.interner.resolve(self.peek().lexeme);
172 if next_word.ends_with("ing") {
173 has_progressive = true;
174 } else {
175 has_passive = true;
176 }
177 }
178 _ => {
179 has_passive = true;
180 }
181 }
182 }
183 }
184 }
185
186 if self.check_content_word() {
187 let word = self.interner.resolve(self.peek().lexeme).to_lowercase();
188 if word == "being" {
189 self.advance();
190 has_progressive = true;
191 }
192 }
193
194 if self.check_presup_trigger()
199 && !self.is_followed_by_np_object()
200 && self.is_followed_by_gerund()
201 {
202 if let Term::Constant(subj_sym) = subject_term {
203 let presup_kind = match self.advance().kind {
204 TokenType::PresupTrigger(kind) => kind,
205 TokenType::Verb { lemma, .. } => {
206 let s = self.interner.resolve(lemma).to_lowercase();
207 crate::lexicon::lookup_presup_trigger(&s).expect(
208 "Lexicon mismatch: Verb flagged as trigger but lookup failed",
209 )
210 }
211 _ => unreachable!("guarded by check_presup_trigger"),
212 };
213 let subject_np = crate::ast::NounPhrase::simple(subj_sym);
214 let parsed =
215 self.parse_presupposition(&subject_np, presup_kind, has_negation)?;
216 if has_modal {
217 self.drs.exit_box();
218 }
219 if let LogicExpr::Presupposition {
220 assertion,
221 presupposition,
222 } = parsed
223 {
224 let mut asserted: &'a LogicExpr<'a> = assertion;
225 if has_modal {
226 if let Some(vector) = modal_vector {
227 asserted = self.ctx.modal(vector, asserted);
228 }
229 }
230 return Ok(self.ctx.exprs.alloc(LogicExpr::Presupposition {
231 assertion: asserted,
232 presupposition,
233 }));
234 }
235 let mut result: &'a LogicExpr<'a> = parsed;
236 if has_modal {
237 if let Some(vector) = modal_vector {
238 result = self.ctx.modal(vector, result);
239 }
240 }
241 return Ok(result);
242 }
243 }
244
245 let verb = if self.check_verb() {
246 self.consume_verb()
247 } else if self.check_content_word() {
248 self.consume_content_word()?
249 } else {
250 return Err(ParseError {
251 kind: ParseErrorKind::ExpectedContentWord { found: self.peek().kind.clone() },
252 span: self.peek().span.clone(),
253 });
254 };
255
256 let subject_role = if has_passive {
257 ThematicRole::Theme
258 } else {
259 ThematicRole::Agent
260 };
261 let mut roles: Vec<(ThematicRole, Term<'a>)> = vec![(subject_role, subject_term)];
262 let mut object_quant: Option<(QuantifierKind, Symbol, &'a LogicExpr<'a>)> = None;
263 let mut agent_restr: Option<(Symbol, &'a LogicExpr<'a>)> = None;
268
269 if has_passive && self.check_preposition() {
270 if let TokenType::Preposition(sym) = self.peek().kind {
271 if self.interner.resolve(sym) == "by" {
272 self.advance();
273 let agent_np = self.parse_noun_phrase(true)?;
274 let (agent_term, restr) = self.possessor_entity(&agent_np);
275 agent_restr = restr;
276 roles.push((ThematicRole::Agent, agent_term));
277 }
278 }
279 } else if !has_passive && self.counting_np_lookahead().is_some() {
280 let n = self.counting_np_lookahead().unwrap();
284 self.advance(); let var = self.next_var_name();
286 self.nominal_np_context = true;
287 let obj_np_result = self.parse_noun_phrase(false);
288 self.nominal_np_context = false;
289 let obj_np = obj_np_result?;
290 let mut restriction: &'a LogicExpr<'a> = self.ctx.exprs.alloc(LogicExpr::Predicate {
291 name: obj_np.noun,
292 args: self.ctx.terms.alloc_slice([Term::Variable(var)]),
293 world: None,
294 });
295 for &adj in obj_np.adjectives {
296 let adj_pred = self.adjective_restriction(adj, var, obj_np.noun);
297 restriction = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
298 left: restriction,
299 op: TokenType::And,
300 right: adj_pred,
301 });
302 }
303 for pp in obj_np.pps {
304 let pp_sub = self.substitute_pp_placeholder(pp, var);
305 restriction = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
306 left: restriction,
307 op: TokenType::And,
308 right: pp_sub,
309 });
310 }
311 roles.push((ThematicRole::Theme, Term::Variable(var)));
312 object_quant = Some((QuantifierKind::Cardinal(n), var, restriction));
313 } else if !has_passive
314 && matches!(
315 self.peek().kind,
316 TokenType::All | TokenType::Some | TokenType::Cardinal(_)
317 )
318 {
319 let kind = match self.advance().kind {
324 TokenType::All => QuantifierKind::Universal,
325 TokenType::Cardinal(n) => QuantifierKind::Cardinal(n),
326 _ => QuantifierKind::Existential,
327 };
328 let obj_np = self.parse_noun_phrase(false)?;
329 let var = self.next_var_name();
330 roles.push((ThematicRole::Theme, Term::Variable(var)));
331 let restriction = self.ctx.exprs.alloc(LogicExpr::Predicate {
332 name: obj_np.noun,
333 args: self.ctx.terms.alloc_slice([Term::Variable(var)]),
334 world: None,
335 });
336 object_quant = Some((kind, var, restriction));
337 } else if !has_passive && (self.check_content_word() || self.check_article()) {
338 let obj_np = self.parse_noun_phrase(false)?;
339 let obj_term = self.noun_phrase_to_term(&obj_np);
340 roles.push((ThematicRole::Theme, obj_term));
341 } else if !has_passive && self.check_pronoun() {
342 let token = self.advance().clone();
345 let plex = self.interner.resolve(token.lexeme).to_lowercase();
346 let obj_term = match plex.as_str() {
347 "you" | "yourself" => Term::Constant(self.interner.intern("Addressee")),
348 "i" | "me" | "myself" => Term::Constant(self.interner.intern("Speaker")),
349 _ => {
350 let (gender, number) = match &token.kind {
351 TokenType::Pronoun { gender, number, .. } => (*gender, *number),
352 _ => (crate::drs::Gender::Unknown, crate::drs::Number::Singular),
353 };
354 match self.resolve_pronoun(gender, number)? {
355 super::ResolvedPronoun::Variable(s) => Term::Variable(s),
356 super::ResolvedPronoun::Constant(s) => Term::Constant(s),
357 }
358 }
359 };
360 roles.push((ThematicRole::Theme, obj_term));
361 }
362
363 let event_var = self.get_event_var();
364 let mut modifiers: Vec<Symbol> = Vec::new();
365 modifiers.extend(self.collect_adverbs());
367 if let Some(pending) = self.pending_time {
368 match pending {
369 Time::Past => modifiers.push(self.interner.intern("Past")),
370 Time::Future => modifiers.push(self.interner.intern("Future")),
371 _ => {}
372 }
373 }
374 let suppress_existential = self.drs.in_conditional_antecedent();
375 let base_pred = self.ctx.exprs.alloc(LogicExpr::NeoEvent(Box::new(NeoEventData {
376 event_var,
377 verb,
378 roles: self.ctx.roles.alloc_slice(roles.clone()),
379 modifiers: self.ctx.syms.alloc_slice(modifiers.clone()),
380 suppress_existential,
381 world: None,
382 })));
383
384 let mut base_pred: &'a LogicExpr<'a> = base_pred;
387 while self.check_preposition() {
388 let prep_name = if let TokenType::Preposition(sym) = self.peek().kind {
389 sym
390 } else {
391 break;
392 };
393 let head_after_unit = matches!(
399 self.tokens.get(self.current + 3).map(|t| &t.kind),
400 Some(TokenType::Noun(_)) | Some(TokenType::Ambiguous { .. })
401 );
402 let measure_follows = matches!(
403 self.tokens.get(self.current + 1).map(|t| &t.kind),
404 Some(TokenType::Number(_) | TokenType::Cardinal(_))
405 ) && !head_after_unit;
406 let np_follows = head_after_unit || match self.tokens.get(self.current + 1).map(|t| &t.kind) {
407 Some(TokenType::Noun(_) | TokenType::ProperName(_) | TokenType::Article(_)) => true,
408 Some(TokenType::Ambiguous { primary, alternatives }) => {
411 matches!(**primary, TokenType::Noun(_))
412 || alternatives.iter().any(|t| matches!(t, TokenType::Noun(_)))
413 }
414 _ => false,
415 };
416 let pp_pred = if measure_follows {
417 self.advance(); let measure = self.parse_measure_phrase()?;
419 self.ctx.exprs.alloc(LogicExpr::Predicate {
420 name: prep_name,
421 args: self.ctx.terms.alloc_slice([Term::Variable(event_var), *measure]),
422 world: None,
423 })
424 } else if np_follows {
425 self.advance(); let saved_ctx = self.nominal_np_context;
427 self.nominal_np_context = true;
428 let pp_np_result = self.parse_noun_phrase(false);
429 self.nominal_np_context = saved_ctx;
430 let pp_np = pp_np_result?;
431 let pred: &'a LogicExpr<'a> = self.ctx.exprs.alloc(LogicExpr::Predicate {
432 name: prep_name,
433 args: self.ctx.terms.alloc_slice([
434 Term::Variable(event_var),
435 Term::Constant(pp_np.noun),
436 ]),
437 world: None,
438 });
439 self.attach_pp_object_modifiers(pred, &pp_np)
442 } else {
443 self.advance(); if !self.at_clause_boundary()
445 || !crate::lexicon::is_particle(
446 &self.interner.resolve(prep_name).to_lowercase(),
447 )
448 {
449 self.current -= 1;
451 break;
452 }
453 self.ctx.exprs.alloc(LogicExpr::Predicate {
455 name: prep_name,
456 args: self.ctx.terms.alloc_slice([Term::Variable(event_var)]),
457 world: None,
458 })
459 };
460 base_pred = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
461 left: base_pred,
462 op: TokenType::And,
463 right: pp_pred,
464 });
465 }
466
467 self.capture_event_template(verb, &roles, &modifiers);
469
470 let mut result: &'a LogicExpr<'a> = base_pred;
471
472 if has_progressive {
473 result = self.ctx.aspectual(AspectOperator::Progressive, result);
474 }
475
476 if has_passive {
477 result = self.ctx.voice(VoiceOperator::Passive, result);
478 }
479
480 if has_perfect {
481 result = self.ctx.aspectual(AspectOperator::Perfect, result);
482
483 if let Some(pending) = self.pending_time.take() {
485 match pending {
486 Time::Future => {
487 let r_var = self.world_state.next_reference_time();
489 self.world_state.add_time_constraint("S".to_string(), TimeRelation::Precedes, r_var);
490 }
491 Time::Past => {
492 if self.world_state.current_reference_time() == "S" {
494 let r_var = self.world_state.next_reference_time();
495 self.world_state.add_time_constraint(r_var, TimeRelation::Precedes, "S".to_string());
496 }
497 }
498 _ => {}
499 }
500 }
501
502 let e_var = format!("e{}", self.world_state.event_history().len().max(1));
504 let r_var = self.world_state.current_reference_time();
505 self.world_state.add_time_constraint(e_var, TimeRelation::Precedes, r_var);
506 }
507
508 if has_negation {
509 result = self.ctx.exprs.alloc(LogicExpr::UnaryOp {
510 op: TokenType::Not,
511 operand: result,
512 });
513 }
514
515 if let Some(vector) = nested_modal_vector {
517 result = self.ctx.modal(vector, result);
518 }
519
520 if has_modal {
522 self.drs.exit_box();
524 if let Some(vector) = modal_vector {
528 result = self.ctx.modal(vector, result);
529 }
530 }
531
532 if let Some((kind, var, restriction)) = object_quant {
533 let connective = if matches!(kind, QuantifierKind::Universal) {
534 TokenType::Implies
535 } else {
536 TokenType::And
537 };
538 let body = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
539 left: restriction,
540 op: connective,
541 right: result,
542 });
543 result = self.ctx.exprs.alloc(LogicExpr::Quantifier {
544 kind,
545 variable: var,
546 body,
547 island_id: self.current_island,
548 });
549 }
550
551 let result = self.wrap_in_possessor_entity(agent_restr, result);
552 Ok(result)
553 }
554
555 fn token_to_vector(&self, token: &TokenType) -> ModalVector {
556 use crate::ast::ModalFlavor;
557 use super::ModalPreference;
558
559 match token {
560 TokenType::Must => ModalVector {
563 domain: ModalDomain::Alethic,
564 force: 1.0,
565 flavor: ModalFlavor::Root, modal_base: None, ordering_source: None
566 },
567 TokenType::Cannot => ModalVector {
568 domain: ModalDomain::Alethic,
569 force: 0.0,
570 flavor: ModalFlavor::Root, modal_base: None, ordering_source: None
571 },
572
573 TokenType::Can => {
577 match self.modal_preference {
578 ModalPreference::Deontic => {
579 ModalVector {
581 domain: ModalDomain::Deontic,
582 force: 0.5,
583 flavor: ModalFlavor::Root, modal_base: None, ordering_source: None
584 }
585 }
586 _ => {
587 ModalVector {
589 domain: ModalDomain::Alethic,
590 force: 0.5,
591 flavor: ModalFlavor::Root, modal_base: None, ordering_source: None
592 }
593 }
594 }
595 },
596
597 TokenType::Could => {
601 match self.modal_preference {
602 ModalPreference::Epistemic => {
603 ModalVector {
605 domain: ModalDomain::Alethic,
606 force: 0.5,
607 flavor: ModalFlavor::Epistemic, modal_base: None, ordering_source: None
608 }
609 }
610 _ => {
611 ModalVector {
613 domain: ModalDomain::Alethic,
614 force: 0.5,
615 flavor: ModalFlavor::Root, modal_base: None, ordering_source: None
616 }
617 }
618 }
619 },
620
621 TokenType::Would => ModalVector {
622 domain: ModalDomain::Alethic,
623 force: 0.5,
624 flavor: ModalFlavor::Root, modal_base: None, ordering_source: None
625 },
626 TokenType::Shall => ModalVector {
627 domain: ModalDomain::Deontic,
628 force: 0.9,
629 flavor: ModalFlavor::Root, modal_base: None, ordering_source: None
630 },
631 TokenType::Should => ModalVector {
632 domain: ModalDomain::Deontic,
633 force: 0.6,
634 flavor: ModalFlavor::Root, modal_base: None, ordering_source: None
635 },
636
637 TokenType::Might => ModalVector {
640 domain: ModalDomain::Alethic,
641 force: 0.3,
642 flavor: ModalFlavor::Epistemic, modal_base: None, ordering_source: None
643 },
644
645 TokenType::May => {
649 match self.modal_preference {
650 ModalPreference::Epistemic => {
651 ModalVector {
653 domain: ModalDomain::Alethic,
654 force: 0.5,
655 flavor: ModalFlavor::Epistemic, modal_base: None, ordering_source: None
656 }
657 }
658 _ => {
659 ModalVector {
661 domain: ModalDomain::Deontic,
662 force: 0.5,
663 flavor: ModalFlavor::Root, modal_base: None, ordering_source: None
664 }
665 }
666 }
667 },
668
669 _ => panic!("Unknown modal token: {:?}", token),
670 }
671 }
672}