logicaffeine_language/parser/
question.rs1use super::noun::NounParsing;
19use super::quantifier::QuantifierParsing;
20use super::verb::LogicVerbParsing;
21use super::{ParseResult, Parser};
22use crate::ast::{AspectOperator, LogicExpr, ModalDomain, ModalVector, TemporalOperator, Term};
23use crate::lexicon::{Aspect, Time};
24use crate::token::TokenType;
25
26pub trait QuestionParsing<'a, 'ctx, 'int> {
31 fn parse_wh_question(&mut self) -> ParseResult<&'a LogicExpr<'a>>;
33 fn parse_yes_no_question(&mut self) -> ParseResult<&'a LogicExpr<'a>>;
35 fn aux_token_to_modal_vector(&self, token: &TokenType) -> ModalVector;
37}
38
39impl<'a, 'ctx, 'int> QuestionParsing<'a, 'ctx, 'int> for Parser<'a, 'ctx, 'int> {
40 fn parse_wh_question(&mut self) -> ParseResult<&'a LogicExpr<'a>> {
41 let pied_piping_prep = if self.check_preposition() {
42 let prep = self.advance().kind.clone();
43 Some(prep)
44 } else {
45 None
46 };
47
48 let wh_token = self.advance().kind.clone();
49 let var_name = self.interner.intern("x");
50 let var_term = Term::Variable(var_name);
51
52 if pied_piping_prep.is_some() && self.check_auxiliary() {
53 let aux_token = self.advance().clone();
54 if let TokenType::Auxiliary(time) = aux_token.kind {
55 self.pending_time = Some(time);
56 }
57
58 let subject = self.parse_noun_phrase(true)?;
59 let verb = self.consume_verb();
60
61 let mut args = vec![Term::Constant(subject.noun)];
62 if self.check_content_word() || self.check_article() {
63 let object = self.parse_noun_phrase(false)?;
64 args.push(Term::Constant(object.noun));
65 }
66 args.push(var_term);
67
68 let body = self.ctx.exprs.alloc(LogicExpr::Predicate {
69 name: verb,
70 args: self.ctx.terms.alloc_slice(args),
71 world: None,
72 });
73 return Ok(self.ctx.exprs.alloc(LogicExpr::Question {
74 wh_variable: var_name,
75 body,
76 }));
77 }
78
79 if matches!(
84 self.peek().kind,
85 TokenType::Is | TokenType::Are | TokenType::Was | TokenType::Were
86 ) {
87 self.advance(); if self.check_preposition() && !self.check_by_preposition() {
93 let prep_sym = match self.advance().kind {
94 TokenType::Preposition(s) => s,
95 _ => unreachable!("guarded by check_preposition"),
96 };
97 let obj = self.parse_noun_phrase(false)?;
98 let body = self.ctx.exprs.alloc(LogicExpr::Predicate {
99 name: prep_sym,
100 args: self
101 .ctx
102 .terms
103 .alloc_slice([var_term, Term::Constant(obj.noun)]),
104 world: None,
105 });
106 return Ok(self.ctx.exprs.alloc(LogicExpr::Question {
107 wh_variable: var_name,
108 body,
109 }));
110 }
111 if matches!(self.peek().kind, TokenType::Article(_)) {
112 self.advance(); }
114 let pred = self.consume_content_word()?;
115 let body = self.ctx.exprs.alloc(LogicExpr::Predicate {
116 name: pred,
117 args: self.ctx.terms.alloc_slice([var_term]),
118 world: None,
119 });
120 return Ok(self.ctx.exprs.alloc(LogicExpr::Question {
121 wh_variable: var_name,
122 body,
123 }));
124 }
125
126 if self.check_verb() {
127 let verb = self.consume_verb();
128 let mut args = vec![var_term];
129
130 if self.check_content_word() {
131 let object = self.parse_noun_phrase(false)?;
132 args.push(Term::Constant(object.noun));
133 }
134
135 let body = self.ctx.exprs.alloc(LogicExpr::Predicate {
136 name: verb,
137 args: self.ctx.terms.alloc_slice(args),
138 world: None,
139 });
140 return Ok(self.ctx.exprs.alloc(LogicExpr::Question {
141 wh_variable: var_name,
142 body,
143 }));
144 }
145
146 if self.check(&TokenType::Does) || self.check(&TokenType::Do) {
147 self.advance();
148 let subject = self.parse_noun_phrase(true)?;
149 let verb = self.consume_verb();
150
151 let body = self.ctx.exprs.alloc(LogicExpr::Predicate {
152 name: verb,
153 args: self.ctx.terms.alloc_slice([Term::Constant(subject.noun), var_term]),
154 world: None,
155 });
156 return Ok(self.ctx.exprs.alloc(LogicExpr::Question {
157 wh_variable: var_name,
158 body,
159 }));
160 }
161
162 if self.check_auxiliary() {
163 let aux_token = self.advance().clone();
164 if let TokenType::Auxiliary(time) = aux_token.kind {
165 self.pending_time = Some(time);
166 }
167
168 self.filler_gap = Some(var_name);
169
170 let subject = self.parse_noun_phrase(true)?;
171 let body = self.parse_predicate_with_subject(subject.noun)?;
172
173 self.filler_gap = None;
174
175 return Ok(self.ctx.exprs.alloc(LogicExpr::Question {
176 wh_variable: var_name,
177 body,
178 }));
179 }
180
181 let unknown = self.interner.intern(&format!("{:?}", wh_token));
182 Ok(self.ctx.exprs.alloc(LogicExpr::Atom(unknown)))
183 }
184
185 fn parse_yes_no_question(&mut self) -> ParseResult<&'a LogicExpr<'a>> {
186 let aux_token = self.advance().kind.clone();
187
188 let is_modal = matches!(aux_token, TokenType::Can | TokenType::Could | TokenType::Would | TokenType::May | TokenType::Must | TokenType::Should);
189 let is_copula = matches!(aux_token, TokenType::Is | TokenType::Are | TokenType::Was | TokenType::Were);
190 let copula_time = if matches!(aux_token, TokenType::Was | TokenType::Were) {
191 Time::Past
192 } else {
193 Time::Present
194 };
195
196 if self.check_quantifier() {
197 self.advance();
198 let quantified = self.parse_quantified()?;
199 let wrapped = if is_modal {
200 let vector = self.aux_token_to_modal_vector(&aux_token);
201 self.ctx.exprs.alloc(LogicExpr::Modal {
202 vector,
203 operand: quantified,
204 })
205 } else {
206 quantified
207 };
208 return Ok(self.ctx.exprs.alloc(LogicExpr::YesNoQuestion { body: wrapped }));
209 }
210
211 let subject_symbol = if self.check_pronoun() {
212 let token = self.advance().clone();
213 if let TokenType::Pronoun { gender, number, .. } = token.kind {
214 let token_text = self.interner.resolve(token.lexeme);
215 if token_text.eq_ignore_ascii_case("you") {
216 self.interner.intern("Addressee")
217 } else {
218 let resolved = self.resolve_pronoun(gender, number)?;
219 match resolved {
220 super::ResolvedPronoun::Variable(s) | super::ResolvedPronoun::Constant(s) => s,
221 }
222 }
223 } else {
224 self.interner.intern("?")
225 }
226 } else {
227 self.parse_noun_phrase(true)?.noun
228 };
229
230 let please_sym = self.interner.intern("please");
231 self.match_token(&[TokenType::Adverb(please_sym)]);
232
233 if is_copula {
234 let body = if self.check_verb() {
235 let (verb, _, verb_aspect, _) = self.consume_verb_with_metadata();
236 let predicate = self.ctx.exprs.alloc(LogicExpr::Predicate {
237 name: verb,
238 args: self.ctx.terms.alloc_slice([Term::Constant(subject_symbol)]),
239 world: None,
240 });
241 let with_aspect = if verb_aspect == Aspect::Progressive {
242 self.ctx.exprs.alloc(LogicExpr::Aspectual {
243 operator: AspectOperator::Progressive,
244 body: predicate,
245 })
246 } else {
247 predicate
248 };
249 if copula_time == Time::Past {
250 self.ctx.exprs.alloc(LogicExpr::Temporal {
251 operator: TemporalOperator::Past,
252 body: with_aspect,
253 })
254 } else {
255 with_aspect
256 }
257 } else if self.check_content_word() {
258 let adj = self.consume_content_word()?;
259 self.ctx.exprs.alloc(LogicExpr::Predicate {
260 name: adj,
261 args: self.ctx.terms.alloc_slice([Term::Constant(subject_symbol)]),
262 world: None,
263 })
264 } else {
265 self.ctx.exprs.alloc(LogicExpr::Atom(subject_symbol))
266 };
267 return Ok(self.ctx.exprs.alloc(LogicExpr::YesNoQuestion { body }));
268 }
269
270 let body = self.parse_predicate_with_subject(subject_symbol)?;
271
272 let wrapped_body = if is_modal {
273 let vector = self.aux_token_to_modal_vector(&aux_token);
274 self.ctx.exprs.alloc(LogicExpr::Modal {
275 vector,
276 operand: body,
277 })
278 } else {
279 body
280 };
281
282 Ok(self.ctx.exprs.alloc(LogicExpr::YesNoQuestion { body: wrapped_body }))
283 }
284
285 fn aux_token_to_modal_vector(&self, token: &TokenType) -> ModalVector {
286 use crate::ast::ModalFlavor;
287 match token {
288 TokenType::Can => ModalVector {
290 domain: ModalDomain::Alethic,
291 force: 0.5,
292 flavor: ModalFlavor::Root, modal_base: None, ordering_source: None
293 },
294 TokenType::Could => ModalVector {
295 domain: ModalDomain::Alethic,
296 force: 0.4,
297 flavor: ModalFlavor::Root, modal_base: None, ordering_source: None
298 },
299 TokenType::Would => ModalVector {
300 domain: ModalDomain::Alethic,
301 force: 0.6,
302 flavor: ModalFlavor::Root, modal_base: None, ordering_source: None
303 },
304 TokenType::Must => ModalVector {
305 domain: ModalDomain::Alethic,
306 force: 1.0,
307 flavor: ModalFlavor::Root, modal_base: None, ordering_source: None
308 },
309 TokenType::Should => ModalVector {
310 domain: ModalDomain::Deontic,
311 force: 0.6,
312 flavor: ModalFlavor::Root, modal_base: None, ordering_source: None
313 },
314 TokenType::May => ModalVector {
316 domain: ModalDomain::Deontic,
317 force: 0.5,
318 flavor: ModalFlavor::Epistemic, modal_base: None, ordering_source: None
319 },
320 TokenType::Might => ModalVector {
321 domain: ModalDomain::Alethic,
322 force: 0.3,
323 flavor: ModalFlavor::Epistemic, modal_base: None, ordering_source: None
324 },
325 _ => ModalVector {
326 domain: ModalDomain::Alethic,
327 force: 0.5,
328 flavor: ModalFlavor::Root, modal_base: None, ordering_source: None
329 },
330 }
331 }
332}