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 || self.check(&TokenType::Shall) {
87 let modal_token = self.peek().kind.clone();
88 self.advance();
89 has_modal = true;
90 let vector = self.token_to_vector(&modal_token);
91 modal_vector = Some(vector.clone());
92 self.drs.enter_box(crate::drs::BoxType::ModalScope);
95 let is_epistemic = matches!(vector.flavor, crate::ast::ModalFlavor::Epistemic);
98 self.world_state.enter_modal_context(is_epistemic, vector.force);
99 }
100
101 if self.check(&TokenType::Not) {
102 self.advance();
103 has_negation = true;
104 }
105
106 if self.check(&TokenType::Never) && !has_negation {
108 self.advance();
109 has_negation = true;
110 }
111
112 let mut nested_modal_vector = None;
115 if self.check_content_word() {
116 let word = self.interner.resolve(self.peek().lexeme).to_lowercase();
117 if word == "be" {
118 if let Some(next1) = self.tokens.get(self.current + 1) {
120 let next1_word = self.interner.resolve(next1.lexeme).to_lowercase();
121 if next1_word == "able" {
122 if let Some(next2) = self.tokens.get(self.current + 2) {
123 if matches!(next2.kind, TokenType::To) {
124 self.advance(); self.advance(); self.advance(); nested_modal_vector = Some(ModalVector {
129 domain: ModalDomain::Alethic,
130 force: 0.5, flavor: ModalFlavor::Root, });
133 }
134 }
135 }
136 }
137 }
138 }
139
140 if self.check_content_word() {
141 let word = self.interner.resolve(self.peek().lexeme).to_lowercase();
142 if word == "have" || word == "has" || word == "had" {
143 self.advance();
144 has_perfect = true;
145 }
146 }
147
148 if self.check(&TokenType::Had) {
149 self.advance();
150 has_perfect = true;
151 let r_var = self.world_state.next_reference_time();
153 self.world_state.add_time_constraint(r_var, TimeRelation::Precedes, "S".to_string());
154 }
155
156 if self.check_content_word() {
157 let word = self.interner.resolve(self.peek().lexeme).to_lowercase();
158 if word == "been" {
159 self.advance();
160
161 if self.check_verb() {
162 match &self.peek().kind {
163 TokenType::Verb { aspect: Aspect::Progressive, .. } => {
164 has_progressive = true;
165 }
166 TokenType::Verb { .. } => {
167 let next_word = self.interner.resolve(self.peek().lexeme);
168 if next_word.ends_with("ing") {
169 has_progressive = true;
170 } else {
171 has_passive = true;
172 }
173 }
174 _ => {
175 has_passive = true;
176 }
177 }
178 }
179 }
180 }
181
182 if self.check_content_word() {
183 let word = self.interner.resolve(self.peek().lexeme).to_lowercase();
184 if word == "being" {
185 self.advance();
186 has_progressive = true;
187 }
188 }
189
190 let verb = if self.check_verb() {
191 self.consume_verb()
192 } else if self.check_content_word() {
193 self.consume_content_word()?
194 } else {
195 return Err(ParseError {
196 kind: ParseErrorKind::ExpectedContentWord { found: self.peek().kind.clone() },
197 span: self.peek().span.clone(),
198 });
199 };
200
201 let subject_role = if has_passive {
202 ThematicRole::Theme
203 } else {
204 ThematicRole::Agent
205 };
206 let mut roles: Vec<(ThematicRole, Term<'a>)> = vec![(subject_role, subject_term)];
207
208 if has_passive && self.check_preposition() {
209 if let TokenType::Preposition(sym) = self.peek().kind {
210 if self.interner.resolve(sym) == "by" {
211 self.advance();
212 let agent_np = self.parse_noun_phrase(true)?;
213 let agent_term = self.noun_phrase_to_term(&agent_np);
214 roles.push((ThematicRole::Agent, agent_term));
215 }
216 }
217 } else if !has_passive && (self.check_content_word() || self.check_article()) {
218 let obj_np = self.parse_noun_phrase(false)?;
219 let obj_term = self.noun_phrase_to_term(&obj_np);
220 roles.push((ThematicRole::Theme, obj_term));
221 }
222
223 let event_var = self.get_event_var();
224 let mut modifiers: Vec<Symbol> = Vec::new();
225 if let Some(pending) = self.pending_time {
226 match pending {
227 Time::Past => modifiers.push(self.interner.intern("Past")),
228 Time::Future => modifiers.push(self.interner.intern("Future")),
229 _ => {}
230 }
231 }
232 let suppress_existential = self.drs.in_conditional_antecedent();
233 let base_pred = self.ctx.exprs.alloc(LogicExpr::NeoEvent(Box::new(NeoEventData {
234 event_var,
235 verb,
236 roles: self.ctx.roles.alloc_slice(roles.clone()),
237 modifiers: self.ctx.syms.alloc_slice(modifiers.clone()),
238 suppress_existential,
239 world: None,
240 })));
241
242 self.capture_event_template(verb, &roles, &modifiers);
244
245 let mut result: &'a LogicExpr<'a> = base_pred;
246
247 if has_progressive {
248 result = self.ctx.aspectual(AspectOperator::Progressive, result);
249 }
250
251 if has_passive {
252 result = self.ctx.voice(VoiceOperator::Passive, result);
253 }
254
255 if has_perfect {
256 result = self.ctx.aspectual(AspectOperator::Perfect, result);
257
258 if let Some(pending) = self.pending_time.take() {
260 match pending {
261 Time::Future => {
262 let r_var = self.world_state.next_reference_time();
264 self.world_state.add_time_constraint("S".to_string(), TimeRelation::Precedes, r_var);
265 }
266 Time::Past => {
267 if self.world_state.current_reference_time() == "S" {
269 let r_var = self.world_state.next_reference_time();
270 self.world_state.add_time_constraint(r_var, TimeRelation::Precedes, "S".to_string());
271 }
272 }
273 _ => {}
274 }
275 }
276
277 let e_var = format!("e{}", self.world_state.event_history().len().max(1));
279 let r_var = self.world_state.current_reference_time();
280 self.world_state.add_time_constraint(e_var, TimeRelation::Precedes, r_var);
281 }
282
283 if has_negation {
284 result = self.ctx.exprs.alloc(LogicExpr::UnaryOp {
285 op: TokenType::Not,
286 operand: result,
287 });
288 }
289
290 if let Some(vector) = nested_modal_vector {
292 result = self.ctx.modal(vector, result);
293 }
294
295 if has_modal {
297 self.drs.exit_box();
299 if let Some(vector) = modal_vector {
303 result = self.ctx.modal(vector, result);
304 }
305 }
306
307 Ok(result)
308 }
309
310 fn token_to_vector(&self, token: &TokenType) -> ModalVector {
311 use crate::ast::ModalFlavor;
312 use super::ModalPreference;
313
314 match token {
315 TokenType::Must => ModalVector {
318 domain: ModalDomain::Alethic,
319 force: 1.0,
320 flavor: ModalFlavor::Root,
321 },
322 TokenType::Cannot => ModalVector {
323 domain: ModalDomain::Alethic,
324 force: 0.0,
325 flavor: ModalFlavor::Root,
326 },
327
328 TokenType::Can => {
332 match self.modal_preference {
333 ModalPreference::Deontic => {
334 ModalVector {
336 domain: ModalDomain::Deontic,
337 force: 0.5,
338 flavor: ModalFlavor::Root,
339 }
340 }
341 _ => {
342 ModalVector {
344 domain: ModalDomain::Alethic,
345 force: 0.5,
346 flavor: ModalFlavor::Root,
347 }
348 }
349 }
350 },
351
352 TokenType::Could => {
356 match self.modal_preference {
357 ModalPreference::Epistemic => {
358 ModalVector {
360 domain: ModalDomain::Alethic,
361 force: 0.5,
362 flavor: ModalFlavor::Epistemic,
363 }
364 }
365 _ => {
366 ModalVector {
368 domain: ModalDomain::Alethic,
369 force: 0.5,
370 flavor: ModalFlavor::Root,
371 }
372 }
373 }
374 },
375
376 TokenType::Would => ModalVector {
377 domain: ModalDomain::Alethic,
378 force: 0.5,
379 flavor: ModalFlavor::Root,
380 },
381 TokenType::Shall => ModalVector {
382 domain: ModalDomain::Deontic,
383 force: 0.9,
384 flavor: ModalFlavor::Root,
385 },
386 TokenType::Should => ModalVector {
387 domain: ModalDomain::Deontic,
388 force: 0.6,
389 flavor: ModalFlavor::Root,
390 },
391
392 TokenType::Might => ModalVector {
395 domain: ModalDomain::Alethic,
396 force: 0.3,
397 flavor: ModalFlavor::Epistemic,
398 },
399
400 TokenType::May => {
404 match self.modal_preference {
405 ModalPreference::Epistemic => {
406 ModalVector {
408 domain: ModalDomain::Alethic,
409 force: 0.5,
410 flavor: ModalFlavor::Epistemic,
411 }
412 }
413 _ => {
414 ModalVector {
416 domain: ModalDomain::Deontic,
417 force: 0.5,
418 flavor: ModalFlavor::Root,
419 }
420 }
421 }
422 },
423
424 _ => panic!("Unknown modal token: {:?}", token),
425 }
426 }
427}