1use super::modal::ModalParsing;
16use super::noun::NounParsing;
17use super::pragmatics::PragmaticsParsing;
18use super::quantifier::QuantifierParsing;
19use super::question::QuestionParsing;
20use super::verb::LogicVerbParsing;
21use super::{EventTemplate, ParseResult, Parser};
22use crate::ast::{AspectOperator, LogicExpr, NeoEventData, NounPhrase, QuantifierKind, TemporalOperator, Term, ThematicRole};
23use crate::lexer::Lexer;
24use crate::lexicon::Time;
25use crate::drs::{BoxType, Gender, Number};
26use super::ParserMode;
27use crate::error::{ParseError, ParseErrorKind};
28use logicaffeine_base::Symbol;
29use crate::lexicon::Definiteness;
30use crate::token::TokenType;
31
32pub trait ClauseParsing<'a, 'ctx, 'int> {
37 fn parse_sentence(&mut self) -> ParseResult<&'a LogicExpr<'a>>;
39 fn parse_conditional(&mut self) -> ParseResult<&'a LogicExpr<'a>>;
41 fn parse_either_or(&mut self) -> ParseResult<&'a LogicExpr<'a>>;
43 fn parse_disjunction(&mut self) -> ParseResult<&'a LogicExpr<'a>>;
45 fn parse_conjunction(&mut self) -> ParseResult<&'a LogicExpr<'a>>;
47 fn parse_relative_clause(&mut self, gap_var: Symbol) -> ParseResult<&'a LogicExpr<'a>>;
49 fn parse_gapped_clause(&mut self, borrowed_verb: Symbol) -> ParseResult<&'a LogicExpr<'a>>;
51 fn parse_counterfactual_antecedent(&mut self) -> ParseResult<&'a LogicExpr<'a>>;
53 fn parse_counterfactual_consequent(&mut self) -> ParseResult<&'a LogicExpr<'a>>;
55 fn check_wh_word(&self) -> bool;
57 fn is_counterfactual_context(&self) -> bool;
59 fn is_complete_clause(&self, expr: &LogicExpr<'a>) -> bool;
61 fn extract_verb_from_expr(&self, expr: &LogicExpr<'a>) -> Option<Symbol>;
63 fn try_parse_ellipsis(&mut self) -> Option<ParseResult<&'a LogicExpr<'a>>>;
65 fn check_ellipsis_auxiliary(&self) -> bool;
67 fn check_ellipsis_terminator(&self) -> bool;
69}
70
71impl<'a, 'ctx, 'int> ClauseParsing<'a, 'ctx, 'int> for Parser<'a, 'ctx, 'int> {
72 fn parse_sentence(&mut self) -> ParseResult<&'a LogicExpr<'a>> {
73 if self.mode == ParserMode::Imperative && self.check(&TokenType::Let) {
77 self.advance(); let _var = self.expect_identifier()?;
79 if self.check(&TokenType::Is) || self.check(&TokenType::Be) || self.check(&TokenType::Equals) || self.check(&TokenType::Identity) || self.check(&TokenType::Assign) {
81 self.advance(); }
83 return self.parse_disjunction();
85 }
86
87 if let Some(result) = self.try_parse_ellipsis() {
89 return result;
90 }
91
92 if self.check_verb() {
93 let verb_pos = self.current;
94 let mut temp_pos = self.current + 1;
95 while temp_pos < self.tokens.len() {
96 if matches!(self.tokens[temp_pos].kind, TokenType::Exclamation) {
97 self.current = verb_pos;
98 let verb = self.consume_verb();
99 while !matches!(self.peek().kind, TokenType::Exclamation | TokenType::EOF) {
100 self.advance();
101 }
102 if self.check(&TokenType::Exclamation) {
103 self.advance();
104 }
105 let addressee = self.interner.intern("addressee");
106 let action = self.ctx.exprs.alloc(LogicExpr::Predicate {
107 name: verb,
108 args: self.ctx.terms.alloc_slice([Term::Variable(addressee)]),
109 world: None,
110 });
111 return Ok(self.ctx.exprs.alloc(LogicExpr::Imperative { action }));
112 }
113 if matches!(self.tokens[temp_pos].kind, TokenType::Period | TokenType::EOF) {
114 break;
115 }
116 temp_pos += 1;
117 }
118 }
119
120 if self.check_wh_word() {
121 return self.parse_wh_question();
122 }
123
124 if self.check(&TokenType::Does)
125 || self.check(&TokenType::Do)
126 || self.check(&TokenType::Is)
127 || self.check(&TokenType::Are)
128 || self.check(&TokenType::Was)
129 || self.check(&TokenType::Were)
130 || self.check(&TokenType::Would)
131 || self.check(&TokenType::Could)
132 || self.check(&TokenType::Can)
133 {
134 return self.parse_yes_no_question();
135 }
136
137 if self.match_token(&[TokenType::If]) {
138 return self.parse_conditional();
139 }
140
141 if self.match_token(&[TokenType::Either]) {
144 return self.parse_either_or();
145 }
146
147 if self.check_modal() {
148 self.advance();
149 return self.parse_modal();
150 }
151
152 if self.match_token(&[TokenType::Not]) {
153 self.negative_depth += 1;
154 let inner = self.parse_sentence()?;
155 self.negative_depth -= 1;
156 return Ok(self.ctx.exprs.alloc(LogicExpr::UnaryOp {
157 op: TokenType::Not,
158 operand: inner,
159 }));
160 }
161
162 {
168 let temporal_op = match &self.peek().kind {
169 TokenType::Adverb(sym) | TokenType::ScopalAdverb(sym) | TokenType::TemporalAdverb(sym) => {
170 let resolved = self.interner.resolve(*sym).to_string();
171 match resolved.as_str() {
172 "Always" => Some(crate::ast::logic::TemporalOperator::Always),
173 "Eventually" => Some(crate::ast::logic::TemporalOperator::Eventually),
174 "Next" => Some(crate::ast::logic::TemporalOperator::Next),
175 _ => None,
176 }
177 }
178 TokenType::Adjective(sym) => {
180 let resolved = self.interner.resolve(*sym).to_string();
181 if resolved == "Next" {
182 Some(crate::ast::logic::TemporalOperator::Next)
183 } else {
184 None
185 }
186 }
187 _ => None,
188 };
189 if let Some(op) = temporal_op {
190 self.advance(); if self.check(&TokenType::Comma) {
193 self.advance();
194 }
195 let body = self.parse_sentence()?;
196 return Ok(self.ctx.exprs.alloc(LogicExpr::Temporal {
197 operator: op,
198 body,
199 }));
200 }
201 }
202 if self.check(&TokenType::Never) {
204 self.advance(); if self.check(&TokenType::Comma) {
207 self.advance();
208 }
209 let body = self.parse_sentence()?;
210 let negated = self.ctx.exprs.alloc(LogicExpr::UnaryOp {
211 op: TokenType::Not,
212 operand: body,
213 });
214 return Ok(self.ctx.exprs.alloc(LogicExpr::Temporal {
215 operator: crate::ast::logic::TemporalOperator::Always,
216 body: negated,
217 }));
218 }
219
220 self.parse_disjunction()
221 }
222
223 fn check_wh_word(&self) -> bool {
224 if matches!(
225 self.peek().kind,
226 TokenType::Who
227 | TokenType::What
228 | TokenType::Where
229 | TokenType::When
230 | TokenType::Why
231 ) {
232 return true;
233 }
234 if self.check_preposition() && self.current + 1 < self.tokens.len() {
235 matches!(
236 self.tokens[self.current + 1].kind,
237 TokenType::Who
238 | TokenType::What
239 | TokenType::Where
240 | TokenType::When
241 | TokenType::Why
242 )
243 } else {
244 false
245 }
246 }
247
248 fn parse_conditional(&mut self) -> ParseResult<&'a LogicExpr<'a>> {
249 let is_counterfactual = self.is_counterfactual_context();
250
251 self.drs.enter_box(BoxType::ConditionalAntecedent);
253 let antecedent = self.parse_counterfactual_antecedent()?;
254 self.drs.exit_box();
255
256 if self.check(&TokenType::Comma) {
257 self.advance();
258 }
259
260 if self.check(&TokenType::Then) {
261 self.advance();
262 }
263
264 self.drs.enter_box(BoxType::ConditionalConsequent);
266 let consequent = self.parse_counterfactual_consequent()?;
267 self.drs.exit_box();
268
269 let universal_refs = self.drs.get_universal_referents();
271
272 let conditional = if is_counterfactual {
274 self.ctx.exprs.alloc(LogicExpr::Counterfactual {
275 antecedent,
276 consequent,
277 })
278 } else {
279 self.ctx.exprs.alloc(LogicExpr::BinaryOp {
280 left: antecedent,
281 op: TokenType::If,
282 right: consequent,
283 })
284 };
285
286 let mut result = conditional;
288 for var in universal_refs.into_iter().rev() {
289 result = self.ctx.exprs.alloc(LogicExpr::Quantifier {
290 kind: QuantifierKind::Universal,
291 variable: var,
292 body: result,
293 island_id: self.current_island,
294 });
295 }
296
297 Ok(result)
298 }
299
300 fn parse_either_or(&mut self) -> ParseResult<&'a LogicExpr<'a>> {
305 let start_pos = self.current;
307
308 if let TokenType::ProperName(name1) = self.peek().kind {
311 self.advance(); if self.check(&TokenType::Or) {
314 self.advance(); if let TokenType::ProperName(name2) = self.peek().kind {
317 self.advance(); let is_copula = matches!(
321 self.peek().kind,
322 TokenType::Is | TokenType::Are | TokenType::Was | TokenType::Were
323 );
324 if is_copula {
325 self.advance(); let is_negated = self.match_token(&[TokenType::Not]);
329
330 if let TokenType::Adjective(adj) = self.peek().kind {
332 self.advance(); let pred1 = self.ctx.exprs.alloc(LogicExpr::Predicate {
336 name: adj,
337 args: self.ctx.terms.alloc_slice(vec![
338 Term::Constant(name1)
339 ]),
340 world: None,
341 });
342 let pred2 = self.ctx.exprs.alloc(LogicExpr::Predicate {
343 name: adj,
344 args: self.ctx.terms.alloc_slice(vec![
345 Term::Constant(name2)
346 ]),
347 world: None,
348 });
349
350 let left = if is_negated {
352 self.ctx.exprs.alloc(LogicExpr::UnaryOp {
353 op: TokenType::Not,
354 operand: pred1,
355 })
356 } else {
357 pred1
358 };
359 let right = if is_negated {
360 self.ctx.exprs.alloc(LogicExpr::UnaryOp {
361 op: TokenType::Not,
362 operand: pred2,
363 })
364 } else {
365 pred2
366 };
367
368 return Ok(self.ctx.exprs.alloc(LogicExpr::BinaryOp {
369 left,
370 op: TokenType::Or,
371 right,
372 }));
373 }
374 }
375 }
376 }
377
378 self.current = start_pos;
380 }
381
382 self.drs.enter_box(BoxType::Disjunct);
385 let left = self.parse_conjunction()?;
386 self.drs.exit_box();
387
388 if !self.check(&TokenType::Or) {
389 return Err(ParseError {
390 kind: ParseErrorKind::ExpectedKeyword { keyword: "or".to_string() },
391 span: self.current_span(),
392 });
393 }
394 self.advance(); self.drs.enter_box(BoxType::Disjunct);
398 let right = self.parse_conjunction()?;
399 self.drs.exit_box();
400
401 Ok(self.ctx.exprs.alloc(LogicExpr::BinaryOp {
402 left,
403 op: TokenType::Or,
404 right,
405 }))
406 }
407
408 fn is_counterfactual_context(&self) -> bool {
409 for i in 0..5 {
410 if self.current + i >= self.tokens.len() {
411 break;
412 }
413 let token = &self.tokens[self.current + i];
414 if matches!(token.kind, TokenType::Were | TokenType::Had) {
415 return true;
416 }
417 if matches!(token.kind, TokenType::Comma | TokenType::Period) {
418 break;
419 }
420 }
421 false
422 }
423
424 fn parse_counterfactual_antecedent(&mut self) -> ParseResult<&'a LogicExpr<'a>> {
425 let unknown = self.interner.intern("?");
426 if self.check_content_word() || self.check_pronoun() || self.check_article() {
427 if self.check_pronoun() {
430 let token = self.peek();
431 let token_text = self.interner.resolve(token.lexeme);
432 if token_text.eq_ignore_ascii_case("it") {
433 if self.current + 1 < self.tokens.len() {
435 if let TokenType::Verb { lemma, time, .. } = &self.tokens[self.current + 1].kind {
437 let lemma_str = self.interner.resolve(*lemma);
438 if Lexer::is_weather_verb(lemma_str) {
439 let verb = *lemma;
440 let verb_time = *time;
441 self.advance(); self.advance(); let event_var = self.get_event_var();
445
446 let suppress_existential = self.drs.in_conditional_antecedent();
449
450 let mut result: &'a LogicExpr<'a> = self.ctx.exprs.alloc(LogicExpr::NeoEvent(Box::new(NeoEventData {
451 event_var,
452 verb,
453 roles: self.ctx.roles.alloc_slice(vec![]),
454 modifiers: self.ctx.syms.alloc_slice(vec![]),
455 suppress_existential,
456 world: None,
457 })));
458
459 while self.check(&TokenType::And) || self.check(&TokenType::Or) {
462 let is_disjunction = self.check(&TokenType::Or);
463 self.advance(); if let TokenType::Verb { lemma: lemma2, .. } = &self.peek().kind.clone() {
466 let lemma2_str = self.interner.resolve(*lemma2);
467 if Lexer::is_weather_verb(lemma2_str) {
468 let verb2 = *lemma2;
469 self.advance(); let neo_event2 = self.ctx.exprs.alloc(LogicExpr::NeoEvent(Box::new(NeoEventData {
473 event_var, verb: verb2,
475 roles: self.ctx.roles.alloc_slice(vec![]),
476 modifiers: self.ctx.syms.alloc_slice(vec![]),
477 suppress_existential,
478 world: None,
479 })));
480
481 let op = if is_disjunction { TokenType::Or } else { TokenType::And };
482 result = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
483 left: result,
484 op,
485 right: neo_event2,
486 });
487 } else {
488 break; }
490 } else {
491 break;
492 }
493 }
494
495 return Ok(match verb_time {
496 Time::Past => self.ctx.exprs.alloc(LogicExpr::Temporal {
497 operator: TemporalOperator::Past,
498 body: result,
499 }),
500 Time::Future => self.ctx.exprs.alloc(LogicExpr::Temporal {
501 operator: TemporalOperator::Future,
502 body: result,
503 }),
504 _ => result,
505 });
506 }
507 }
508 else if self.current + 2 < self.tokens.len() {
510 let is_copula = matches!(
511 self.tokens[self.current + 1].kind,
512 TokenType::Is | TokenType::Are | TokenType::Was | TokenType::Were
513 );
514 if is_copula {
515 if let TokenType::Verb { lemma, .. } = &self.tokens[self.current + 2].kind {
516 let lemma_str = self.interner.resolve(*lemma);
517 if Lexer::is_weather_verb(lemma_str) {
518 let verb = *lemma;
519 let verb_time = if matches!(
520 self.tokens[self.current + 1].kind,
521 TokenType::Was | TokenType::Were
522 ) {
523 Time::Past
524 } else {
525 Time::Present
526 };
527 self.advance(); self.advance(); self.advance(); let event_var = self.get_event_var();
532 let suppress_existential = self.drs.in_conditional_antecedent();
535
536 let neo_event = self.ctx.exprs.alloc(LogicExpr::NeoEvent(Box::new(NeoEventData {
537 event_var,
538 verb,
539 roles: self.ctx.roles.alloc_slice(vec![]),
540 modifiers: self.ctx.syms.alloc_slice(vec![]),
541 suppress_existential,
542 world: None,
543 })));
544
545 let with_aspect = self.ctx.exprs.alloc(LogicExpr::Aspectual {
547 operator: AspectOperator::Progressive,
548 body: neo_event,
549 });
550
551 return Ok(match verb_time {
552 Time::Past => self.ctx.exprs.alloc(LogicExpr::Temporal {
553 operator: TemporalOperator::Past,
554 body: with_aspect,
555 }),
556 _ => with_aspect,
557 });
558 }
559 }
560 }
561 }
562 }
563 }
564 }
565
566 let (subject, subject_type_pred) = if self.check_pronoun() {
568 let token = self.advance().clone();
569 let token_text = self.interner.resolve(token.lexeme);
570 let resolved = if token_text.eq_ignore_ascii_case("i") {
572 self.interner.intern("Speaker")
573 } else if token_text.eq_ignore_ascii_case("you") {
574 self.interner.intern("Addressee")
575 } else if let TokenType::Pronoun { gender, number, .. } = token.kind {
576 let resolved_pronoun = self.resolve_pronoun(gender, number)?;
577 match resolved_pronoun {
578 super::ResolvedPronoun::Variable(s) | super::ResolvedPronoun::Constant(s) => s,
579 }
580 } else {
581 unknown
582 };
583 (resolved, None)
584 } else {
585 let np = self.parse_noun_phrase(true)?;
586
587 if np.definiteness == Some(Definiteness::Indefinite)
591 || np.definiteness == Some(Definiteness::Definite)
592 || np.definiteness == Some(Definiteness::Distal) {
593 let gender = Self::infer_noun_gender(self.interner.resolve(np.noun));
594 let number = if Self::is_plural_noun(self.interner.resolve(np.noun)) {
595 Number::Plural
596 } else {
597 Number::Singular
598 };
599
600 if np.definiteness == Some(Definiteness::Definite) || np.definiteness == Some(Definiteness::Distal) {
605 self.drs.introduce_referent_with_source(np.noun, np.noun, gender, number, crate::drs::ReferentSource::MainClause);
606 } else {
607 self.drs.introduce_referent(np.noun, np.noun, gender, number);
608 }
609
610 let type_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
612 name: np.noun,
613 args: self.ctx.terms.alloc_slice([Term::Variable(np.noun)]),
614 world: None,
615 });
616
617 (np.noun, Some(type_pred))
618 } else {
619 (np.noun, None)
621 }
622 };
623
624 let subject_term = if subject_type_pred.is_some() {
626 Term::Variable(subject)
627 } else {
628 Term::Constant(subject)
629 };
630
631 if self.check_presup_trigger() && self.is_followed_by_gerund() {
634 let presup_kind = match self.advance().kind {
635 TokenType::PresupTrigger(kind) => kind,
636 TokenType::Verb { lemma, .. } => {
637 let s = self.interner.resolve(lemma).to_lowercase();
638 crate::lexicon::lookup_presup_trigger(&s)
639 .expect("Lexicon mismatch: Verb flagged as trigger but lookup failed")
640 }
641 _ => panic!("Expected presupposition trigger"),
642 };
643 let np = NounPhrase {
644 noun: subject,
645 definiteness: None,
646 adjectives: &[],
647 possessor: None,
648 pps: &[],
649 superlative: None,
650 };
651 return self.parse_presupposition(&np, presup_kind);
652 }
653
654 if self.check(&TokenType::Were) {
655 self.advance();
656 let predicate = if self.check_pronoun() {
657 let token = self.advance().clone();
658 if let TokenType::Pronoun { gender, number, .. } = token.kind {
659 let token_text = self.interner.resolve(token.lexeme);
660 if token_text.eq_ignore_ascii_case("i") {
661 self.interner.intern("Speaker")
662 } else if token_text.eq_ignore_ascii_case("you") {
663 self.interner.intern("Addressee")
664 } else {
665 let resolved_pronoun = self.resolve_pronoun(gender, number)?;
666 match resolved_pronoun {
667 super::ResolvedPronoun::Variable(s) | super::ResolvedPronoun::Constant(s) => s,
668 }
669 }
670 } else {
671 unknown
672 }
673 } else {
674 self.consume_content_word()?
675 };
676 let be = self.interner.intern("Be");
677 let be_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
678 name: be,
679 args: self.ctx.terms.alloc_slice([
680 subject_term,
681 Term::Constant(predicate),
682 ]),
683 world: None,
684 });
685 return Ok(if let Some(type_pred) = subject_type_pred {
687 self.ctx.exprs.alloc(LogicExpr::BinaryOp {
688 left: type_pred,
689 op: TokenType::And,
690 right: be_pred,
691 })
692 } else {
693 be_pred
694 });
695 }
696
697 if self.check(&TokenType::Had) {
698 self.advance();
699 let verb = self.consume_content_word()?;
700 let main_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
701 name: verb,
702 args: self.ctx.terms.alloc_slice([subject_term]),
703 world: None,
704 });
705
706 if self.check(&TokenType::Because) && !self.peek_next_is_string_literal() {
709 self.advance();
710 let cause = self.parse_atom()?;
711 let causal = self.ctx.exprs.alloc(LogicExpr::Causal {
712 effect: main_pred,
713 cause,
714 });
715 return Ok(if let Some(type_pred) = subject_type_pred {
717 self.ctx.exprs.alloc(LogicExpr::BinaryOp {
718 left: type_pred,
719 op: TokenType::And,
720 right: causal,
721 })
722 } else {
723 causal
724 });
725 }
726
727 return Ok(if let Some(type_pred) = subject_type_pred {
729 self.ctx.exprs.alloc(LogicExpr::BinaryOp {
730 left: type_pred,
731 op: TokenType::And,
732 right: main_pred,
733 })
734 } else {
735 main_pred
736 });
737 }
738
739 let verb_phrase = if subject_type_pred.is_some() {
742 self.parse_predicate_with_subject_as_var(subject)?
743 } else {
744 self.parse_predicate_with_subject(subject)?
745 };
746
747 return Ok(if let Some(type_pred) = subject_type_pred {
749 self.ctx.exprs.alloc(LogicExpr::BinaryOp {
750 left: type_pred,
751 op: TokenType::And,
752 right: verb_phrase,
753 })
754 } else {
755 verb_phrase
756 });
757 }
758
759 self.parse_sentence()
760 }
761
762 fn parse_counterfactual_consequent(&mut self) -> ParseResult<&'a LogicExpr<'a>> {
763 let unknown = self.interner.intern("?");
764 if self.check_content_word() || self.check_pronoun() {
765 if self.check_pronoun() {
768 let token = self.peek();
769 let token_text = self.interner.resolve(token.lexeme).to_lowercase();
770 if token_text == "its" {
771 if self.current + 1 < self.tokens.len() {
773 let next_token = &self.tokens[self.current + 1];
774 let next_str = self.interner.resolve(next_token.lexeme).to_lowercase();
775 if let Some(meta) = crate::lexicon::lookup_adjective_db(&next_str) {
776 if meta.features.contains(&crate::lexicon::Feature::Weather) {
777 return Err(ParseError {
778 kind: ParseErrorKind::GrammarError(
779 "Did you mean 'it's' (it is)? 'its' is a possessive pronoun.".to_string()
780 ),
781 span: self.current_span(),
782 });
783 }
784 }
785 }
786 }
787 }
788
789 if self.check_pronoun() {
791 let token_text = self.interner.resolve(self.peek().lexeme).to_lowercase();
792 if token_text == "it" {
793 if self.current + 2 < self.tokens.len() {
796 let next = &self.tokens[self.current + 1].kind;
797 if matches!(next, TokenType::Is | TokenType::Was | TokenType::Possessive) {
798 let adj_token = &self.tokens[self.current + 2];
800 let adj_sym = adj_token.lexeme;
801 let adj_str = self.interner.resolve(adj_sym).to_lowercase();
802 if let Some(meta) = crate::lexicon::lookup_adjective_db(&adj_str) {
803 if meta.features.contains(&crate::lexicon::Feature::Weather) {
804 self.advance(); self.advance(); self.advance(); let adj_lemma = self.interner.intern(meta.lemma);
810
811 let event_var = self.drs.get_last_event_referent(self.interner)
813 .unwrap_or_else(|| self.interner.intern("e"));
814
815 let mut result: &'a LogicExpr<'a> = self.ctx.exprs.alloc(LogicExpr::Predicate {
817 name: adj_lemma,
818 args: self.ctx.terms.alloc_slice([Term::Variable(event_var)]),
819 world: None,
820 });
821
822 while self.check(&TokenType::And) {
824 self.advance(); if self.check_content_word() {
826 let adj2_lexeme = self.peek().lexeme;
827 let adj2_str = self.interner.resolve(adj2_lexeme).to_lowercase();
828
829 if let Some(meta2) = crate::lexicon::lookup_adjective_db(&adj2_str) {
831 if meta2.features.contains(&crate::lexicon::Feature::Weather) {
832 self.advance(); let adj2_lemma = self.interner.intern(meta2.lemma);
835 let pred2 = self.ctx.exprs.alloc(LogicExpr::Predicate {
836 name: adj2_lemma,
837 args: self.ctx.terms.alloc_slice([Term::Variable(event_var)]),
838 world: None,
839 });
840 result = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
841 left: result,
842 op: TokenType::And,
843 right: pred2,
844 });
845 continue;
846 }
847 }
848 }
849 break;
850 }
851
852 return Ok(result);
853 }
854 }
855 }
856 }
857 }
858 }
859
860 let subject = if self.check_pronoun() {
861 let token = self.advance().clone();
862 let token_text = self.interner.resolve(token.lexeme);
863 if token_text.eq_ignore_ascii_case("i") {
865 self.interner.intern("Speaker")
866 } else if token_text.eq_ignore_ascii_case("you") {
867 self.interner.intern("Addressee")
868 } else if let TokenType::Pronoun { gender, number, .. } = token.kind {
869 let resolved_pronoun = self.resolve_pronoun(gender, number)?;
870 match resolved_pronoun {
871 super::ResolvedPronoun::Variable(s) | super::ResolvedPronoun::Constant(s) => s,
872 }
873 } else {
874 unknown
875 }
876 } else {
877 self.parse_noun_phrase(true)?.noun
878 };
879
880 if self.check(&TokenType::Would) {
881 self.advance();
882 if self.check_content_word() {
883 let next_word = self.interner.resolve(self.peek().lexeme).to_lowercase();
884 if next_word == "have" {
885 self.advance();
886 }
887 }
888 let verb = self.consume_content_word()?;
889 return Ok(self.ctx.exprs.alloc(LogicExpr::Predicate {
890 name: verb,
891 args: self.ctx.terms.alloc_slice([Term::Constant(subject)]),
892 world: None,
893 }));
894 }
895
896 return self.parse_predicate_with_subject(subject);
897 }
898
899 self.parse_sentence()
900 }
901
902 fn extract_verb_from_expr(&self, expr: &LogicExpr<'a>) -> Option<Symbol> {
903 match expr {
904 LogicExpr::NeoEvent(data) => Some(data.verb),
906 LogicExpr::Control { verb, .. } => Some(*verb),
908 LogicExpr::BinaryOp { left, right, .. } => {
913 if let Some(verb) = self.extract_neo_event_verb(left) {
915 return Some(verb);
916 }
917 if let Some(verb) = self.extract_neo_event_verb(right) {
919 return Some(verb);
920 }
921 self.extract_verb_from_expr(left)
923 .or_else(|| self.extract_verb_from_expr(right))
924 }
925 LogicExpr::Predicate { name, .. } => Some(*name),
927 LogicExpr::Modal { operand, .. } => self.extract_verb_from_expr(operand),
928 LogicExpr::Presupposition { assertion, .. } => self.extract_verb_from_expr(assertion),
929 LogicExpr::Temporal { body, .. } => self.extract_verb_from_expr(body),
930 LogicExpr::TemporalAnchor { body, .. } => self.extract_verb_from_expr(body),
931 LogicExpr::Aspectual { body, .. } => self.extract_verb_from_expr(body),
932 LogicExpr::Quantifier { body, .. } => self.extract_verb_from_expr(body),
933 _ => None,
934 }
935 }
936
937 fn parse_gapped_clause(&mut self, borrowed_verb: Symbol) -> ParseResult<&'a LogicExpr<'a>> {
940 let subject = self.parse_noun_phrase(true)?;
941
942 if self.check(&TokenType::Comma) {
943 self.advance();
944 }
945
946 let subject_term = self.noun_phrase_to_term(&subject);
947 let event_var = self.get_event_var();
948 let suppress_existential = self.drs.in_conditional_antecedent();
949
950 let template = self.last_event_template.clone();
952
953 let mut np_args: Vec<Term<'a>> = Vec::new();
955 let mut pp_args: Vec<(Symbol, Term<'a>)> = Vec::new();
956 let mut override_adverb: Option<Symbol> = None;
957
958 loop {
959 if self.check_temporal_adverb() {
960 if let TokenType::TemporalAdverb(sym) = self.advance().kind {
962 override_adverb = Some(sym);
963 }
964 } else if self.check_preposition() {
965 let prep = if let TokenType::Preposition(sym) = self.advance().kind {
967 sym
968 } else {
969 continue;
970 };
971 let np = self.parse_noun_phrase(false)?;
972 pp_args.push((prep, self.noun_phrase_to_term(&np)));
973 } else if self.check_content_word() || self.check_article() {
974 let np = self.parse_noun_phrase(false)?;
976 np_args.push(self.noun_phrase_to_term(&np));
977 if self.check(&TokenType::Comma) {
978 self.advance();
979 }
980 } else {
981 break;
982 }
983 }
984
985 let roles = self.build_gapped_roles(subject_term, &np_args, &pp_args, &template);
987
988 let modifiers = match (override_adverb, &template) {
990 (Some(adv), Some(tmpl)) => {
991 let mut mods: Vec<Symbol> = tmpl
993 .modifiers
994 .iter()
995 .filter(|m| !self.is_temporal_modifier(**m))
996 .cloned()
997 .collect();
998 mods.push(adv);
999 mods
1000 }
1001 (Some(adv), None) => vec![adv],
1002 (None, Some(tmpl)) => tmpl.modifiers.clone(),
1003 (None, None) => vec![],
1004 };
1005
1006 Ok(self.ctx.exprs.alloc(LogicExpr::NeoEvent(Box::new(NeoEventData {
1007 event_var,
1008 verb: borrowed_verb,
1009 roles: self.ctx.roles.alloc_slice(roles),
1010 modifiers: self.ctx.syms.alloc_slice(modifiers),
1011 suppress_existential,
1012 world: None,
1013 }))))
1014 }
1015
1016 fn is_complete_clause(&self, expr: &LogicExpr<'a>) -> bool {
1017 match expr {
1018 LogicExpr::Atom(_) => false,
1019 LogicExpr::Predicate { .. } => true,
1020 LogicExpr::Quantifier { .. } => true,
1021 LogicExpr::Modal { .. } => true,
1022 LogicExpr::Temporal { .. } => true,
1023 LogicExpr::Aspectual { .. } => true,
1024 LogicExpr::BinaryOp { .. } => true,
1025 LogicExpr::UnaryOp { .. } => true,
1026 LogicExpr::Control { .. } => true,
1027 LogicExpr::Presupposition { .. } => true,
1028 LogicExpr::Categorical(_) => true,
1029 LogicExpr::Relation(_) => true,
1030 _ => true,
1031 }
1032 }
1033
1034 fn parse_disjunction(&mut self) -> ParseResult<&'a LogicExpr<'a>> {
1037 let mut expr = self.parse_conjunction()?;
1038
1039 while self.check(&TokenType::Comma)
1040 || self.check(&TokenType::Or)
1041 || self.check(&TokenType::Iff)
1042 {
1043 if self.check(&TokenType::Comma) {
1044 self.advance();
1045 }
1046 if !self.match_token(&[TokenType::Or, TokenType::Iff]) {
1047 break;
1048 }
1049 let operator = self.previous().kind.clone();
1050 self.current_island += 1;
1051
1052 let saved_pos = self.current;
1053 let standard_attempt = self.try_parse(|p| p.parse_conjunction());
1054
1055 let use_gapping = match &standard_attempt {
1058 Some(right) => {
1059 !self.is_complete_clause(right)
1060 && (self.check(&TokenType::Comma) || self.check_content_word())
1061 && operator != TokenType::Iff }
1063 None => operator != TokenType::Iff, };
1065
1066 if !use_gapping {
1067 if let Some(right) = standard_attempt {
1068 expr = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
1069 left: expr,
1070 op: operator,
1071 right,
1072 });
1073 }
1074 } else {
1075 self.current = saved_pos;
1076
1077 let borrowed_verb = self.extract_verb_from_expr(expr).ok_or(ParseError {
1078 kind: ParseErrorKind::GappingResolutionFailed,
1079 span: self.current_span(),
1080 })?;
1081
1082 let right = self.parse_gapped_clause(borrowed_verb)?;
1083
1084 expr = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
1085 left: expr,
1086 op: operator,
1087 right,
1088 });
1089 }
1090 }
1091
1092 if self.check(&TokenType::Until) || self.check(&TokenType::Release) || self.check(&TokenType::WeakUntil) {
1097 let op = match self.peek().kind {
1098 TokenType::Release => crate::ast::logic::BinaryTemporalOp::Release,
1099 TokenType::WeakUntil => crate::ast::logic::BinaryTemporalOp::WeakUntil,
1100 _ => crate::ast::logic::BinaryTemporalOp::Until,
1101 };
1102 self.advance();
1103 let right = self.parse_conjunction()?;
1104 expr = self.ctx.exprs.alloc(LogicExpr::TemporalBinary {
1105 operator: op,
1106 left: expr,
1107 right,
1108 });
1109 }
1110
1111 Ok(expr)
1112 }
1113
1114 fn parse_conjunction(&mut self) -> ParseResult<&'a LogicExpr<'a>> {
1117 let mut expr = self.parse_atom()?;
1118
1119 if self.check(&TokenType::Because) && !self.peek_next_is_string_literal() {
1122 self.advance();
1123 let cause = self.parse_atom()?;
1124 return Ok(self.ctx.exprs.alloc(LogicExpr::Causal {
1125 effect: expr,
1126 cause,
1127 }));
1128 }
1129
1130 while self.check(&TokenType::Comma) || self.check(&TokenType::And) {
1131 if self.check(&TokenType::Comma) {
1132 self.advance();
1133 }
1134 if !self.match_token(&[TokenType::And]) {
1135 break;
1136 }
1137 let operator = self.previous().kind.clone();
1138 self.current_island += 1;
1139
1140 let saved_pos = self.current;
1141 let standard_attempt = self.try_parse(|p| p.parse_atom());
1142
1143 let use_gapping = match &standard_attempt {
1146 Some(right) => {
1147 !self.is_complete_clause(right)
1148 && (self.check(&TokenType::Comma)
1149 || self.check_content_word()
1150 || self.check_preposition()
1151 || self.check_temporal_adverb()
1152 || self.check(&TokenType::Period)
1153 || self.is_at_end())
1154 }
1155 None => true,
1156 };
1157
1158 if !use_gapping {
1159 if let Some(right) = standard_attempt {
1160 expr = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
1161 left: expr,
1162 op: operator,
1163 right,
1164 });
1165 }
1166 } else {
1167 self.current = saved_pos;
1168
1169 let borrowed_verb = self.extract_verb_from_expr(expr).ok_or(ParseError {
1170 kind: ParseErrorKind::GappingResolutionFailed,
1171 span: self.current_span(),
1172 })?;
1173
1174 let right = self.parse_gapped_clause(borrowed_verb)?;
1175
1176 expr = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
1177 left: expr,
1178 op: operator,
1179 right,
1180 });
1181 }
1182 }
1183
1184 Ok(expr)
1185 }
1186
1187 fn parse_relative_clause(&mut self, gap_var: Symbol) -> ParseResult<&'a LogicExpr<'a>> {
1188 if self.check_verb() {
1189 return self.parse_verb_phrase_for_restriction(gap_var);
1190 }
1191
1192 if self.check(&TokenType::Do) || self.check(&TokenType::Does) {
1194 self.advance(); let is_negated = self.check(&TokenType::Not);
1197 if is_negated {
1198 self.advance(); }
1200
1201 if self.check_verb() {
1202 let verb = self.consume_verb();
1203
1204 let roles = if self.check(&TokenType::Reflexive) {
1206 self.advance(); vec![
1208 (ThematicRole::Agent, Term::Variable(gap_var)),
1209 (ThematicRole::Theme, Term::Variable(gap_var)),
1210 ]
1211 } else if self.check_content_word() || self.check_article() {
1212 let obj = self.parse_noun_phrase(false)?;
1214 vec![
1215 (ThematicRole::Agent, Term::Variable(gap_var)),
1216 (ThematicRole::Theme, Term::Constant(obj.noun)),
1217 ]
1218 } else {
1219 vec![(ThematicRole::Agent, Term::Variable(gap_var))]
1221 };
1222
1223 let event_var = self.get_event_var();
1224 let suppress_existential = self.drs.in_conditional_antecedent();
1225 let event = self.ctx.exprs.alloc(LogicExpr::NeoEvent(Box::new(NeoEventData {
1226 event_var,
1227 verb,
1228 roles: self.ctx.roles.alloc_slice(roles),
1229 modifiers: self.ctx.syms.alloc_slice(vec![]),
1230 suppress_existential,
1231 world: None,
1232 })));
1233
1234 if is_negated {
1235 return Ok(self.ctx.exprs.alloc(LogicExpr::UnaryOp {
1236 op: TokenType::Not,
1237 operand: event,
1238 }));
1239 }
1240 return Ok(event);
1241 }
1242 }
1243
1244 if self.check_content_word() || self.check_article() {
1245 let rel_subject = self.parse_noun_phrase_for_relative()?;
1246
1247 let nested_relative = if matches!(self.peek().kind, TokenType::Article(_)) {
1248 let nested_var = self.next_var_name();
1249 Some((nested_var, self.parse_relative_clause(nested_var)?))
1250 } else {
1251 None
1252 };
1253
1254 if self.check_verb() {
1255 let verb = self.consume_verb();
1256
1257 let mut roles: Vec<(ThematicRole, Term<'a>)> = vec![
1258 (ThematicRole::Agent, Term::Constant(rel_subject.noun)),
1259 (ThematicRole::Theme, Term::Variable(gap_var)),
1260 ];
1261
1262 while self.check_to_preposition() {
1263 self.advance();
1264 if self.check_content_word() || self.check_article() {
1265 let recipient = self.parse_noun_phrase(false)?;
1266 roles.push((ThematicRole::Recipient, Term::Constant(recipient.noun)));
1267 }
1268 }
1269
1270 let event_var = self.get_event_var();
1271 let suppress_existential = self.drs.in_conditional_antecedent();
1272 let this_event = self.ctx.exprs.alloc(LogicExpr::NeoEvent(Box::new(NeoEventData {
1273 event_var,
1274 verb,
1275 roles: self.ctx.roles.alloc_slice(roles),
1276 modifiers: self.ctx.syms.alloc_slice(vec![]),
1277 suppress_existential,
1278 world: None,
1279 })));
1280
1281 if let Some((nested_var, nested_clause)) = nested_relative {
1282 let type_pred = self.ctx.exprs.alloc(LogicExpr::Predicate {
1283 name: rel_subject.noun,
1284 args: self.ctx.terms.alloc_slice([Term::Variable(nested_var)]),
1285 world: None,
1286 });
1287
1288 let inner = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
1289 left: type_pred,
1290 op: TokenType::And,
1291 right: nested_clause,
1292 });
1293
1294 let combined = self.ctx.exprs.alloc(LogicExpr::BinaryOp {
1295 left: inner,
1296 op: TokenType::And,
1297 right: this_event,
1298 });
1299
1300 return Ok(self.ctx.exprs.alloc(LogicExpr::Quantifier {
1301 kind: crate::ast::QuantifierKind::Existential,
1302 variable: nested_var,
1303 body: combined,
1304 island_id: self.current_island,
1305 }));
1306 }
1307
1308 return Ok(this_event);
1309 }
1310 }
1311
1312 if self.check_verb() {
1313 return self.parse_verb_phrase_for_restriction(gap_var);
1314 }
1315
1316 let unknown = self.interner.intern("?");
1317 Ok(self.ctx.exprs.alloc(LogicExpr::Atom(unknown)))
1318 }
1319
1320 fn check_ellipsis_auxiliary(&self) -> bool {
1321 matches!(
1322 self.peek().kind,
1323 TokenType::Does | TokenType::Do |
1324 TokenType::Can | TokenType::Could | TokenType::Would |
1325 TokenType::May | TokenType::Must | TokenType::Should
1326 )
1327 }
1328
1329 fn check_ellipsis_terminator(&self) -> bool {
1330 if self.is_at_end() || self.check(&TokenType::Period) {
1331 return true;
1332 }
1333 if self.check_content_word() {
1334 let word = self.interner.resolve(self.peek().lexeme).to_lowercase();
1335 return word == "too" || word == "also";
1336 }
1337 false
1338 }
1339
1340 fn try_parse_ellipsis(&mut self) -> Option<ParseResult<&'a LogicExpr<'a>>> {
1341 if self.last_event_template.is_none() {
1343 return None;
1344 }
1345
1346 let saved_pos = self.current;
1347
1348 let subject_sym = if matches!(self.peek().kind, TokenType::ProperName(_)) {
1351 if let TokenType::ProperName(sym) = self.advance().kind {
1352 sym
1353 } else {
1354 self.current = saved_pos;
1355 return None;
1356 }
1357 } else if self.check_pronoun() {
1358 let token = self.advance().clone();
1359 if let TokenType::Pronoun { gender, number, .. } = token.kind {
1360 match self.resolve_pronoun(gender, number) {
1361 Ok(resolved) => match resolved {
1362 super::ResolvedPronoun::Variable(s) | super::ResolvedPronoun::Constant(s) => s,
1363 },
1364 Err(e) => return Some(Err(e)),
1365 }
1366 } else {
1367 self.current = saved_pos;
1368 return None;
1369 }
1370 } else {
1371 return None;
1372 };
1373
1374 if !self.check_ellipsis_auxiliary() {
1376 self.current = saved_pos;
1377 return None;
1378 }
1379 let aux_token = self.advance().kind.clone();
1380
1381 let is_negated = self.match_token(&[TokenType::Not]);
1383
1384 if !self.check_ellipsis_terminator() {
1386 self.current = saved_pos;
1387 return None;
1388 }
1389
1390 if self.check_content_word() {
1392 let word = self.interner.resolve(self.peek().lexeme).to_lowercase();
1393 if word == "too" || word == "also" {
1394 self.advance();
1395 }
1396 }
1397
1398 let template = self.last_event_template.clone().unwrap();
1400 let event_var = self.get_event_var();
1401 let suppress_existential = self.drs.in_conditional_antecedent();
1402
1403 let mut roles: Vec<(ThematicRole, Term<'a>)> = vec![
1405 (ThematicRole::Agent, Term::Constant(subject_sym))
1406 ];
1407 roles.extend(template.non_agent_roles.iter().cloned());
1408
1409 let neo_event = self.ctx.exprs.alloc(LogicExpr::NeoEvent(Box::new(NeoEventData {
1410 event_var,
1411 verb: template.verb,
1412 roles: self.ctx.roles.alloc_slice(roles),
1413 modifiers: self.ctx.syms.alloc_slice(template.modifiers.clone()),
1414 suppress_existential,
1415 world: None,
1416 })));
1417
1418 let with_modal = match aux_token {
1420 TokenType::Can | TokenType::Could => {
1421 let vector = self.token_to_vector(&aux_token);
1422 self.ctx.modal(vector, neo_event)
1423 }
1424 TokenType::Would | TokenType::May | TokenType::Must | TokenType::Should => {
1425 let vector = self.token_to_vector(&aux_token);
1426 self.ctx.modal(vector, neo_event)
1427 }
1428 _ => neo_event,
1429 };
1430
1431 let result = if is_negated {
1433 self.ctx.exprs.alloc(LogicExpr::UnaryOp {
1434 op: TokenType::Not,
1435 operand: with_modal,
1436 })
1437 } else {
1438 with_modal
1439 };
1440
1441 Some(Ok(result))
1442 }
1443}
1444
1445impl<'a, 'ctx, 'int> Parser<'a, 'ctx, 'int> {
1447 fn extract_neo_event_verb(&self, expr: &LogicExpr<'a>) -> Option<Symbol> {
1449 match expr {
1450 LogicExpr::NeoEvent(data) => Some(data.verb),
1451 LogicExpr::Quantifier { body, .. } => self.extract_neo_event_verb(body),
1452 LogicExpr::BinaryOp { left, right, .. } => {
1453 self.extract_neo_event_verb(left)
1454 .or_else(|| self.extract_neo_event_verb(right))
1455 }
1456 LogicExpr::Temporal { body, .. } => self.extract_neo_event_verb(body),
1457 LogicExpr::Aspectual { body, .. } => self.extract_neo_event_verb(body),
1458 _ => None,
1459 }
1460 }
1461
1462 fn build_gapped_roles(
1465 &self,
1466 subject_term: Term<'a>,
1467 np_args: &[Term<'a>],
1468 pp_args: &[(Symbol, Term<'a>)],
1469 template: &Option<EventTemplate<'a>>,
1470 ) -> Vec<(ThematicRole, Term<'a>)> {
1471 let mut roles = vec![(ThematicRole::Agent, subject_term)];
1472
1473 match template {
1474 Some(tmpl) => {
1475 let template_roles = &tmpl.non_agent_roles;
1476
1477 let np_template_roles: Vec<_> = template_roles
1479 .iter()
1480 .filter(|(r, _)| {
1481 matches!(
1482 r,
1483 ThematicRole::Theme | ThematicRole::Recipient | ThematicRole::Patient
1484 )
1485 })
1486 .collect();
1487
1488 let pp_template_roles: Vec<_> = template_roles
1489 .iter()
1490 .filter(|(r, _)| {
1491 matches!(
1492 r,
1493 ThematicRole::Goal
1494 | ThematicRole::Source
1495 | ThematicRole::Location
1496 | ThematicRole::Instrument
1497 )
1498 })
1499 .collect();
1500
1501 match (np_template_roles.len(), np_args.len()) {
1503 (0, 0) => {} (_, 0) => {
1505 for (role, term) in &np_template_roles {
1507 roles.push((*role, term.clone()));
1508 }
1509 }
1510 (n, 1) if n > 0 => {
1511 for (role, term) in np_template_roles.iter().take(n - 1) {
1513 roles.push((*role, term.clone()));
1514 }
1515 if let Some((last_role, _)) = np_template_roles.last() {
1516 roles.push((*last_role, np_args[0].clone()));
1517 }
1518 }
1519 (n, m) if m == n => {
1520 for ((role, _), arg) in np_template_roles.iter().zip(np_args.iter()) {
1522 roles.push((*role, arg.clone()));
1523 }
1524 }
1525 (_, _) => {
1526 for (i, arg) in np_args.iter().enumerate() {
1528 let role = np_template_roles
1529 .get(i)
1530 .map(|(r, _)| *r)
1531 .unwrap_or(ThematicRole::Theme);
1532 roles.push((role, arg.clone()));
1533 }
1534 }
1535 }
1536
1537 if pp_args.is_empty() {
1539 for (role, term) in &pp_template_roles {
1541 roles.push((*role, term.clone()));
1542 }
1543 } else {
1544 for (prep, term) in pp_args {
1546 let role = self.preposition_to_role(*prep);
1547 roles.push((role, term.clone()));
1548 }
1549 }
1550 }
1551 None => {
1552 for arg in np_args {
1554 roles.push((ThematicRole::Theme, arg.clone()));
1555 }
1556 for (prep, term) in pp_args {
1557 let role = self.preposition_to_role(*prep);
1558 roles.push((role, term.clone()));
1559 }
1560 }
1561 }
1562 roles
1563 }
1564
1565 fn preposition_to_role(&self, prep: Symbol) -> ThematicRole {
1567 let prep_str = self.interner.resolve(prep).to_lowercase();
1568 match prep_str.as_str() {
1569 "to" | "toward" | "towards" => ThematicRole::Goal,
1570 "from" => ThematicRole::Source,
1571 "in" | "on" | "at" => ThematicRole::Location,
1572 "with" | "by" => ThematicRole::Instrument,
1573 _ => ThematicRole::Location, }
1575 }
1576
1577 fn is_temporal_modifier(&self, sym: Symbol) -> bool {
1579 let s = self.interner.resolve(sym).to_lowercase();
1580 matches!(
1581 s.as_str(),
1582 "yesterday" | "today" | "tomorrow" | "now" | "then" | "past" | "future"
1583 )
1584 }
1585}