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 self.check_verb() {
80 let verb = self.consume_verb();
81 let mut args = vec![var_term];
82
83 if self.check_content_word() {
84 let object = self.parse_noun_phrase(false)?;
85 args.push(Term::Constant(object.noun));
86 }
87
88 let body = self.ctx.exprs.alloc(LogicExpr::Predicate {
89 name: verb,
90 args: self.ctx.terms.alloc_slice(args),
91 world: None,
92 });
93 return Ok(self.ctx.exprs.alloc(LogicExpr::Question {
94 wh_variable: var_name,
95 body,
96 }));
97 }
98
99 if self.check(&TokenType::Does) || self.check(&TokenType::Do) {
100 self.advance();
101 let subject = self.parse_noun_phrase(true)?;
102 let verb = self.consume_verb();
103
104 let body = self.ctx.exprs.alloc(LogicExpr::Predicate {
105 name: verb,
106 args: self.ctx.terms.alloc_slice([Term::Constant(subject.noun), var_term]),
107 world: None,
108 });
109 return Ok(self.ctx.exprs.alloc(LogicExpr::Question {
110 wh_variable: var_name,
111 body,
112 }));
113 }
114
115 if self.check_auxiliary() {
116 let aux_token = self.advance().clone();
117 if let TokenType::Auxiliary(time) = aux_token.kind {
118 self.pending_time = Some(time);
119 }
120
121 self.filler_gap = Some(var_name);
122
123 let subject = self.parse_noun_phrase(true)?;
124 let body = self.parse_predicate_with_subject(subject.noun)?;
125
126 self.filler_gap = None;
127
128 return Ok(self.ctx.exprs.alloc(LogicExpr::Question {
129 wh_variable: var_name,
130 body,
131 }));
132 }
133
134 let unknown = self.interner.intern(&format!("{:?}", wh_token));
135 Ok(self.ctx.exprs.alloc(LogicExpr::Atom(unknown)))
136 }
137
138 fn parse_yes_no_question(&mut self) -> ParseResult<&'a LogicExpr<'a>> {
139 let aux_token = self.advance().kind.clone();
140
141 let is_modal = matches!(aux_token, TokenType::Can | TokenType::Could | TokenType::Would | TokenType::May | TokenType::Must | TokenType::Should);
142 let is_copula = matches!(aux_token, TokenType::Is | TokenType::Are | TokenType::Was | TokenType::Were);
143 let copula_time = if matches!(aux_token, TokenType::Was | TokenType::Were) {
144 Time::Past
145 } else {
146 Time::Present
147 };
148
149 if self.check_quantifier() {
150 self.advance();
151 let quantified = self.parse_quantified()?;
152 let wrapped = if is_modal {
153 let vector = self.aux_token_to_modal_vector(&aux_token);
154 self.ctx.exprs.alloc(LogicExpr::Modal {
155 vector,
156 operand: quantified,
157 })
158 } else {
159 quantified
160 };
161 return Ok(self.ctx.exprs.alloc(LogicExpr::YesNoQuestion { body: wrapped }));
162 }
163
164 let subject_symbol = if self.check_pronoun() {
165 let token = self.advance().clone();
166 if let TokenType::Pronoun { gender, number, .. } = token.kind {
167 let token_text = self.interner.resolve(token.lexeme);
168 if token_text.eq_ignore_ascii_case("you") {
169 self.interner.intern("Addressee")
170 } else {
171 let resolved = self.resolve_pronoun(gender, number)?;
172 match resolved {
173 super::ResolvedPronoun::Variable(s) | super::ResolvedPronoun::Constant(s) => s,
174 }
175 }
176 } else {
177 self.interner.intern("?")
178 }
179 } else {
180 self.parse_noun_phrase(true)?.noun
181 };
182
183 let please_sym = self.interner.intern("please");
184 self.match_token(&[TokenType::Adverb(please_sym)]);
185
186 if is_copula {
187 let body = if self.check_verb() {
188 let (verb, _, verb_aspect, _) = self.consume_verb_with_metadata();
189 let predicate = self.ctx.exprs.alloc(LogicExpr::Predicate {
190 name: verb,
191 args: self.ctx.terms.alloc_slice([Term::Constant(subject_symbol)]),
192 world: None,
193 });
194 let with_aspect = if verb_aspect == Aspect::Progressive {
195 self.ctx.exprs.alloc(LogicExpr::Aspectual {
196 operator: AspectOperator::Progressive,
197 body: predicate,
198 })
199 } else {
200 predicate
201 };
202 if copula_time == Time::Past {
203 self.ctx.exprs.alloc(LogicExpr::Temporal {
204 operator: TemporalOperator::Past,
205 body: with_aspect,
206 })
207 } else {
208 with_aspect
209 }
210 } else if self.check_content_word() {
211 let adj = self.consume_content_word()?;
212 self.ctx.exprs.alloc(LogicExpr::Predicate {
213 name: adj,
214 args: self.ctx.terms.alloc_slice([Term::Constant(subject_symbol)]),
215 world: None,
216 })
217 } else {
218 self.ctx.exprs.alloc(LogicExpr::Atom(subject_symbol))
219 };
220 return Ok(self.ctx.exprs.alloc(LogicExpr::YesNoQuestion { body }));
221 }
222
223 let body = self.parse_predicate_with_subject(subject_symbol)?;
224
225 let wrapped_body = if is_modal {
226 let vector = self.aux_token_to_modal_vector(&aux_token);
227 self.ctx.exprs.alloc(LogicExpr::Modal {
228 vector,
229 operand: body,
230 })
231 } else {
232 body
233 };
234
235 Ok(self.ctx.exprs.alloc(LogicExpr::YesNoQuestion { body: wrapped_body }))
236 }
237
238 fn aux_token_to_modal_vector(&self, token: &TokenType) -> ModalVector {
239 use crate::ast::ModalFlavor;
240 match token {
241 TokenType::Can => ModalVector {
243 domain: ModalDomain::Alethic,
244 force: 0.5,
245 flavor: ModalFlavor::Root,
246 },
247 TokenType::Could => ModalVector {
248 domain: ModalDomain::Alethic,
249 force: 0.4,
250 flavor: ModalFlavor::Root,
251 },
252 TokenType::Would => ModalVector {
253 domain: ModalDomain::Alethic,
254 force: 0.6,
255 flavor: ModalFlavor::Root,
256 },
257 TokenType::Must => ModalVector {
258 domain: ModalDomain::Alethic,
259 force: 1.0,
260 flavor: ModalFlavor::Root,
261 },
262 TokenType::Should => ModalVector {
263 domain: ModalDomain::Deontic,
264 force: 0.6,
265 flavor: ModalFlavor::Root,
266 },
267 TokenType::May => ModalVector {
269 domain: ModalDomain::Deontic,
270 force: 0.5,
271 flavor: ModalFlavor::Epistemic,
272 },
273 TokenType::Might => ModalVector {
274 domain: ModalDomain::Alethic,
275 force: 0.3,
276 flavor: ModalFlavor::Epistemic,
277 },
278 _ => ModalVector {
279 domain: ModalDomain::Alethic,
280 force: 0.5,
281 flavor: ModalFlavor::Root,
282 },
283 }
284 }
285}