logicaffeine_language/parser/
modal.rs1use super::clause::ClauseParsing;
22use super::noun::NounParsing;
23use super::{ParseResult, Parser};
24use crate::ast::{AspectOperator, LogicExpr, ModalDomain, ModalFlavor, ModalVector, NeoEventData, ThematicRole, VoiceOperator, Term};
25use crate::drs::TimeRelation;
26use crate::error::{ParseError, ParseErrorKind};
27use logicaffeine_base::Symbol;
28use crate::lexicon::{Time, Aspect};
29use crate::token::TokenType;
30
31pub trait ModalParsing<'a, 'ctx, 'int> {
36 fn parse_modal(&mut self) -> ParseResult<&'a LogicExpr<'a>>;
38 fn parse_aspect_chain(&mut self, subject_symbol: Symbol) -> ParseResult<&'a LogicExpr<'a>>;
40 fn parse_aspect_chain_with_term(&mut self, subject_term: Term<'a>) -> ParseResult<&'a LogicExpr<'a>>;
42 fn token_to_vector(&self, token: &TokenType) -> ModalVector;
44}
45
46impl<'a, 'ctx, 'int> ModalParsing<'a, 'ctx, 'int> for Parser<'a, 'ctx, 'int> {
47 fn parse_modal(&mut self) -> ParseResult<&'a LogicExpr<'a>> {
48 use crate::drs::BoxType;
49
50 let vector = self.token_to_vector(&self.previous().kind.clone());
51
52 self.drs.enter_box(BoxType::ModalScope);
54
55 if self.check(&TokenType::That) {
56 self.advance();
57 }
58
59 let content = self.parse_sentence()?;
60
61 self.drs.exit_box();
63
64 Ok(self.ctx.exprs.alloc(LogicExpr::Modal {
65 vector,
66 operand: content,
67 }))
68 }
69
70 fn parse_aspect_chain(&mut self, subject_symbol: Symbol) -> ParseResult<&'a LogicExpr<'a>> {
71 self.parse_aspect_chain_with_term(Term::Constant(subject_symbol))
72 }
73
74 fn parse_aspect_chain_with_term(&mut self, subject_term: Term<'a>) -> ParseResult<&'a LogicExpr<'a>> {
75 let mut has_modal = false;
76 let mut modal_vector = None;
77 let mut has_negation = false;
78 let mut has_perfect = false;
79 let mut has_passive = false;
80 let mut has_progressive = false;
81
82 if self.check(&TokenType::Would) || self.check(&TokenType::Could)
83 || self.check(&TokenType::Must) || self.check(&TokenType::Can)
84 || self.check(&TokenType::Should) || self.check(&TokenType::May)
85 || self.check(&TokenType::Cannot) || self.check(&TokenType::Might) {
86 let modal_token = self.peek().kind.clone();
87 self.advance();
88 has_modal = true;
89 let vector = self.token_to_vector(&modal_token);
90 modal_vector = Some(vector.clone());
91 self.drs.enter_box(crate::drs::BoxType::ModalScope);
94 let is_epistemic = matches!(vector.flavor, crate::ast::ModalFlavor::Epistemic);
97 self.world_state.enter_modal_context(is_epistemic, vector.force);
98 }
99
100 if self.check(&TokenType::Not) {
101 self.advance();
102 has_negation = true;
103 }
104
105 let mut nested_modal_vector = None;
108 if self.check_content_word() {
109 let word = self.interner.resolve(self.peek().lexeme).to_lowercase();
110 if word == "be" {
111 if let Some(next1) = self.tokens.get(self.current + 1) {
113 let next1_word = self.interner.resolve(next1.lexeme).to_lowercase();
114 if next1_word == "able" {
115 if let Some(next2) = self.tokens.get(self.current + 2) {
116 if matches!(next2.kind, TokenType::To) {
117 self.advance(); self.advance(); self.advance(); nested_modal_vector = Some(ModalVector {
122 domain: ModalDomain::Alethic,
123 force: 0.5, flavor: ModalFlavor::Root, });
126 }
127 }
128 }
129 }
130 }
131 }
132
133 if self.check_content_word() {
134 let word = self.interner.resolve(self.peek().lexeme).to_lowercase();
135 if word == "have" || word == "has" || word == "had" {
136 self.advance();
137 has_perfect = true;
138 }
139 }
140
141 if self.check(&TokenType::Had) {
142 self.advance();
143 has_perfect = true;
144 let r_var = self.world_state.next_reference_time();
146 self.world_state.add_time_constraint(r_var, TimeRelation::Precedes, "S".to_string());
147 }
148
149 if self.check_content_word() {
150 let word = self.interner.resolve(self.peek().lexeme).to_lowercase();
151 if word == "been" {
152 self.advance();
153
154 if self.check_verb() {
155 match &self.peek().kind {
156 TokenType::Verb { aspect: Aspect::Progressive, .. } => {
157 has_progressive = true;
158 }
159 TokenType::Verb { .. } => {
160 let next_word = self.interner.resolve(self.peek().lexeme);
161 if next_word.ends_with("ing") {
162 has_progressive = true;
163 } else {
164 has_passive = true;
165 }
166 }
167 _ => {
168 has_passive = true;
169 }
170 }
171 }
172 }
173 }
174
175 if self.check_content_word() {
176 let word = self.interner.resolve(self.peek().lexeme).to_lowercase();
177 if word == "being" {
178 self.advance();
179 has_progressive = true;
180 }
181 }
182
183 let verb = if self.check_verb() {
184 self.consume_verb()
185 } else if self.check_content_word() {
186 self.consume_content_word()?
187 } else {
188 return Err(ParseError {
189 kind: ParseErrorKind::ExpectedContentWord { found: self.peek().kind.clone() },
190 span: self.peek().span.clone(),
191 });
192 };
193
194 let subject_role = if has_passive {
195 ThematicRole::Theme
196 } else {
197 ThematicRole::Agent
198 };
199 let mut roles: Vec<(ThematicRole, Term<'a>)> = vec![(subject_role, subject_term)];
200
201 if has_passive && self.check_preposition() {
202 if let TokenType::Preposition(sym) = self.peek().kind {
203 if self.interner.resolve(sym) == "by" {
204 self.advance();
205 let agent_np = self.parse_noun_phrase(true)?;
206 let agent_term = self.noun_phrase_to_term(&agent_np);
207 roles.push((ThematicRole::Agent, agent_term));
208 }
209 }
210 } else if !has_passive && (self.check_content_word() || self.check_article()) {
211 let obj_np = self.parse_noun_phrase(false)?;
212 let obj_term = self.noun_phrase_to_term(&obj_np);
213 roles.push((ThematicRole::Theme, obj_term));
214 }
215
216 let event_var = self.get_event_var();
217 let mut modifiers: Vec<Symbol> = Vec::new();
218 if let Some(pending) = self.pending_time {
219 match pending {
220 Time::Past => modifiers.push(self.interner.intern("Past")),
221 Time::Future => modifiers.push(self.interner.intern("Future")),
222 _ => {}
223 }
224 }
225 let suppress_existential = self.drs.in_conditional_antecedent();
226 let base_pred = self.ctx.exprs.alloc(LogicExpr::NeoEvent(Box::new(NeoEventData {
227 event_var,
228 verb,
229 roles: self.ctx.roles.alloc_slice(roles.clone()),
230 modifiers: self.ctx.syms.alloc_slice(modifiers.clone()),
231 suppress_existential,
232 world: None,
233 })));
234
235 self.capture_event_template(verb, &roles, &modifiers);
237
238 let mut result: &'a LogicExpr<'a> = base_pred;
239
240 if has_progressive {
241 result = self.ctx.aspectual(AspectOperator::Progressive, result);
242 }
243
244 if has_passive {
245 result = self.ctx.voice(VoiceOperator::Passive, result);
246 }
247
248 if has_perfect {
249 result = self.ctx.aspectual(AspectOperator::Perfect, result);
250
251 if let Some(pending) = self.pending_time.take() {
253 match pending {
254 Time::Future => {
255 let r_var = self.world_state.next_reference_time();
257 self.world_state.add_time_constraint("S".to_string(), TimeRelation::Precedes, r_var);
258 }
259 Time::Past => {
260 if self.world_state.current_reference_time() == "S" {
262 let r_var = self.world_state.next_reference_time();
263 self.world_state.add_time_constraint(r_var, TimeRelation::Precedes, "S".to_string());
264 }
265 }
266 _ => {}
267 }
268 }
269
270 let e_var = format!("e{}", self.world_state.event_history().len().max(1));
272 let r_var = self.world_state.current_reference_time();
273 self.world_state.add_time_constraint(e_var, TimeRelation::Precedes, r_var);
274 }
275
276 if has_negation {
277 result = self.ctx.exprs.alloc(LogicExpr::UnaryOp {
278 op: TokenType::Not,
279 operand: result,
280 });
281 }
282
283 if let Some(vector) = nested_modal_vector {
285 result = self.ctx.modal(vector, result);
286 }
287
288 if has_modal {
290 self.drs.exit_box();
292 if let Some(vector) = modal_vector {
296 result = self.ctx.modal(vector, result);
297 }
298 }
299
300 Ok(result)
301 }
302
303 fn token_to_vector(&self, token: &TokenType) -> ModalVector {
304 use crate::ast::ModalFlavor;
305 use super::ModalPreference;
306
307 match token {
308 TokenType::Must => ModalVector {
311 domain: ModalDomain::Alethic,
312 force: 1.0,
313 flavor: ModalFlavor::Root,
314 },
315 TokenType::Cannot => ModalVector {
316 domain: ModalDomain::Alethic,
317 force: 0.0,
318 flavor: ModalFlavor::Root,
319 },
320
321 TokenType::Can => {
325 match self.modal_preference {
326 ModalPreference::Deontic => {
327 ModalVector {
329 domain: ModalDomain::Deontic,
330 force: 0.5,
331 flavor: ModalFlavor::Root,
332 }
333 }
334 _ => {
335 ModalVector {
337 domain: ModalDomain::Alethic,
338 force: 0.5,
339 flavor: ModalFlavor::Root,
340 }
341 }
342 }
343 },
344
345 TokenType::Could => {
349 match self.modal_preference {
350 ModalPreference::Epistemic => {
351 ModalVector {
353 domain: ModalDomain::Alethic,
354 force: 0.5,
355 flavor: ModalFlavor::Epistemic,
356 }
357 }
358 _ => {
359 ModalVector {
361 domain: ModalDomain::Alethic,
362 force: 0.5,
363 flavor: ModalFlavor::Root,
364 }
365 }
366 }
367 },
368
369 TokenType::Would => ModalVector {
370 domain: ModalDomain::Alethic,
371 force: 0.5,
372 flavor: ModalFlavor::Root,
373 },
374 TokenType::Shall => ModalVector {
375 domain: ModalDomain::Deontic,
376 force: 0.9,
377 flavor: ModalFlavor::Root,
378 },
379 TokenType::Should => ModalVector {
380 domain: ModalDomain::Deontic,
381 force: 0.6,
382 flavor: ModalFlavor::Root,
383 },
384
385 TokenType::Might => ModalVector {
388 domain: ModalDomain::Alethic,
389 force: 0.3,
390 flavor: ModalFlavor::Epistemic,
391 },
392
393 TokenType::May => {
397 match self.modal_preference {
398 ModalPreference::Epistemic => {
399 ModalVector {
401 domain: ModalDomain::Alethic,
402 force: 0.5,
403 flavor: ModalFlavor::Epistemic,
404 }
405 }
406 _ => {
407 ModalVector {
409 domain: ModalDomain::Deontic,
410 force: 0.5,
411 flavor: ModalFlavor::Root,
412 }
413 }
414 }
415 },
416
417 _ => panic!("Unknown modal token: {:?}", token),
418 }
419 }
420}