1use std::{
2 collections::{HashMap, VecDeque},
3 fmt::{Debug, Display},
4};
5
6use crate::{
7 Actor, Entity, Event,
8 lambda::{
9 Bvar, LambdaExpr, LambdaExprRef, LambdaPool, ReductionError, RootedLambdaPool,
10 types::{LambdaType, TypeError, core_type_parser},
11 },
12 language::{Constant, Expr, MonOp, lambda_implementation::LambdaConversionError},
13};
14use chumsky::{
15 extra::ParserExtra,
16 input::ValueInput,
17 label::LabelError,
18 text::{TextExpected, inline_whitespace},
19 util::MaybeRef,
20};
21use chumsky::{pratt::*, prelude::*};
22
23use super::{ActorOrEvent, BinOp, LanguageExpression, Quantifier};
24use thiserror::Error;
25
26#[derive(Debug, Error, Clone)]
28pub enum LambdaParseError {
29 #[error("ParseError({0})")]
31 ParseError(String),
32
33 #[error("You must provide a type for unbound free variable {0} like so \"{0}#<e,t>\"")]
35 UnTypedFreeVariable(String),
36
37 #[error("Reduction Error: {0}")]
39 ReductionError(#[from] ReductionError),
40
41 #[error("{0}")]
43 TypeError(String),
44
45 #[error("Type error: {0}")]
47 InnerTypeError(#[from] TypeError),
48
49 #[error("{0}")]
51 ConversionError(#[from] LambdaConversionError),
52}
53
54impl<'a, T: Display> From<Vec<Rich<'a, T>>> for LambdaParseError {
55 fn from(value: Vec<Rich<'a, T>>) -> Self {
56 LambdaParseError::ParseError(
57 value
58 .into_iter()
59 .map(|x| x.to_string())
60 .collect::<Vec<_>>()
61 .join("\n"),
62 )
63 }
64}
65
66impl<'src> ParseTree<'src> {
67 fn add_to_pool(
68 &self,
69 pool: &mut LambdaPool<'src, Expr<'src>>,
70 variable_names: &mut VariableContext<'src>,
71 lambda_depth: usize,
72 ) -> Result<LambdaExprRef, LambdaParseError> {
73 let expr: LambdaExpr<'src, Expr<'src>> = match &self {
74 ParseTree::Constant(c) => LambdaExpr::LanguageOfThoughtExpr(Expr::Constant(*c)),
75 ParseTree::Entity(e) => LambdaExpr::LanguageOfThoughtExpr(match e {
76 Entity::Actor(a) => Expr::Actor(a),
77 Entity::Event(e) => Expr::Event(*e),
78 }),
79 ParseTree::Unary(m, x) => {
80 let x = x.add_to_pool(pool, variable_names, lambda_depth)?;
81 let x_type = pool.get_type(x)?;
82 if m.get_argument_type() != &x_type {
83 return Err(LambdaParseError::TypeError(format!(
84 "Can't apply {x_type} to {m} which takes type {}",
85 m.get_argument_type(),
86 )));
87 }
88 LambdaExpr::LanguageOfThoughtExpr(Expr::Unary(*m, x.into()))
89 }
90 ParseTree::Binary(b, x, y) => {
91 let x = x.add_to_pool(pool, variable_names, lambda_depth)?;
92 let y = y.add_to_pool(pool, variable_names, lambda_depth)?;
93
94 let x_type = pool.get_type(x)?;
95 let y_type = pool.get_type(y)?;
96 let b_type = b.get_argument_type();
97 if b_type != [&x_type, &y_type] {
98 return Err(LambdaParseError::TypeError(format!(
99 "Can't apply [{x_type}, {y_type}] to {b} which takes type [{}, {}]",
100 b_type[0], b_type[1]
101 )));
102 }
103
104 LambdaExpr::LanguageOfThoughtExpr(Expr::Binary(*b, x.into(), y.into()))
105 }
106 ParseTree::Iota { t, var, body } => {
107 let lambda_type: LambdaType = (*t).into();
108 variable_names.bind_var(var, lambda_depth + 1, lambda_type);
109 let body = body.add_to_pool(pool, variable_names, lambda_depth + 1)?;
110 let body_type = pool.get_type(body)?;
111 if &body_type != LambdaType::t() {
112 return Err(LambdaParseError::TypeError(format!(
113 "Iota body is {t} and not of t",
114 )));
115 }
116 variable_names.unbind(var);
117
118 LambdaExpr::LanguageOfThoughtExpr(Expr::Unary(MonOp::Iota(*t), body.into()))
119 }
120 ParseTree::Quantifier {
121 quantifier,
122 lambda_type: var_type,
123 variable,
124 restrictor,
125 subformula,
126 } => {
127 let lambda_type: LambdaType = (*var_type).into();
128 variable_names.bind_var(variable, lambda_depth + 1, lambda_type);
129 let restrictor = restrictor.add_to_pool(pool, variable_names, lambda_depth + 1)?;
130
131 let r_type = pool.get_type(restrictor)?;
132 let required_type = match var_type {
133 ActorOrEvent::Actor => LambdaType::at(),
134 ActorOrEvent::Event => LambdaType::et(),
135 };
136 if &r_type != required_type && &r_type != LambdaType::t() {
137 return Err(LambdaParseError::TypeError(format!(
138 "Quantifier restrictor is {r_type} and not of type {required_type} or t",
139 )));
140 }
141
142 let subformula = subformula.add_to_pool(pool, variable_names, lambda_depth + 1)?;
143 let sub_type = pool.get_type(subformula)?;
144 if &sub_type != LambdaType::t() {
145 return Err(LambdaParseError::TypeError(format!(
146 "Quantifier body is {sub_type} and not of t",
147 )));
148 }
149 variable_names.unbind(variable);
150
151 LambdaExpr::LanguageOfThoughtExpr(Expr::Quantifier {
152 quantifier: *quantifier,
153 var_type: *var_type,
154 restrictor: restrictor.into(),
155 subformula: subformula.into(),
156 })
157 }
158 ParseTree::Application {
159 subformula,
160 argument,
161 } => {
162 let subformula = subformula.add_to_pool(pool, variable_names, lambda_depth)?;
163 let argument = argument.add_to_pool(pool, variable_names, lambda_depth)?;
164
165 let f = pool.get_type(subformula)?;
166 let arg = pool.get_type(argument)?;
167
168 if !f.can_apply(&arg) {
169 return Err(LambdaParseError::TypeError(
170 "Can't apply subformula to argument".to_string(),
171 ));
172 }
173
174 LambdaExpr::Application {
175 subformula,
176 argument,
177 }
178 }
179 ParseTree::Lambda {
180 body,
181 var,
182 lambda_type,
183 } => {
184 variable_names.bind_var(var, lambda_depth + 1, lambda_type.clone());
185 let body = body.add_to_pool(pool, variable_names, lambda_depth + 1)?;
186 variable_names.unbind(var);
187 LambdaExpr::Lambda(body, lambda_type.clone())
188 }
189 ParseTree::Variable(var) => variable_names.to_expr(var, None, lambda_depth)?,
190 ParseTree::FreeVariable(var, lambda_type) => {
191 variable_names.to_expr(var, Some(lambda_type.clone()), lambda_depth)?
192 }
193 };
194 Ok(pool.add(expr))
195 }
196
197 fn to_pool(&self) -> Result<RootedLambdaPool<'src, Expr<'src>>, LambdaParseError> {
198 let mut pool = LambdaPool::new();
199
200 let mut var_labels = VariableContext::default();
201 let root = self.add_to_pool(&mut pool, &mut var_labels, 0)?;
202 Ok(RootedLambdaPool::new(pool, root))
203 }
204}
205
206#[derive(Debug, Clone, Eq, PartialEq, Default)]
207struct VariableContext<'src>(HashMap<&'src str, Vec<(Bvar, LambdaType)>>, u32);
208
209impl<'src> VariableContext<'src> {
210 fn to_expr(
211 &self,
212 variable: &'src str,
213 lambda_type: Option<LambdaType>,
214 lambda_depth: usize,
215 ) -> Result<LambdaExpr<'src, Expr<'src>>, LambdaParseError> {
216 Ok(match self.0.get(variable) {
217 Some(vars) if !vars.is_empty() => {
218 let (og_depth, lambda_type) = vars
219 .last()
220 .expect("There should never be an empty vec in the VariableContext");
221 LambdaExpr::BoundVariable(lambda_depth - og_depth, lambda_type.clone())
222 }
223 _ => match lambda_type {
225 Some(lambda_type) => LambdaExpr::FreeVariable(variable.into(), lambda_type),
226 None => {
227 return Err(LambdaParseError::UnTypedFreeVariable(variable.to_string()));
228 }
229 },
230 })
231 }
232
233 fn bind_var(&mut self, variable: &'src str, lambda_depth: usize, lambda_type: LambdaType) {
234 self.0
235 .entry(variable)
236 .or_default()
237 .push((lambda_depth, lambda_type));
238 }
239
240 fn unbind(&mut self, variable: &'src str) {
241 self.0.get_mut(variable).unwrap().pop();
242 }
243}
244
245#[derive(Debug, Clone, Eq, PartialEq)]
246enum ParseTree<'src> {
247 Lambda {
248 body: Box<ParseTree<'src>>,
249 lambda_type: LambdaType,
250 var: &'src str,
251 },
252 Variable(&'src str),
253 FreeVariable(&'src str, LambdaType),
254 Application {
255 subformula: Box<ParseTree<'src>>,
256 argument: Box<ParseTree<'src>>,
257 },
258 Constant(Constant<'src>),
259 Unary(MonOp<'src>, Box<ParseTree<'src>>),
260 Iota {
261 t: ActorOrEvent,
262 var: &'src str,
263 body: Box<ParseTree<'src>>,
264 },
265 Binary(BinOp, Box<ParseTree<'src>>, Box<ParseTree<'src>>),
266 Quantifier {
267 quantifier: Quantifier,
268 lambda_type: ActorOrEvent,
269 variable: &'src str,
270 restrictor: Box<ParseTree<'src>>,
271 subformula: Box<ParseTree<'src>>,
272 },
273 Entity(Entity<'src>),
274}
275
276fn keyword<'src, E>() -> impl Parser<'src, &'src str, &'src str, E> + Copy
277where
278 E: ParserExtra<'src, &'src str>,
279{
280 one_of("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-")
281 .repeated()
282 .at_least(1)
283 .to_slice()
284}
285
286fn unary_op<'tokens, 'src: 'tokens, I>(
287 expr: impl Parser<'tokens, I, ParseTree<'src>, ChumskyErr<'tokens, 'src>> + Clone,
288) -> impl Parser<'tokens, I, ParseTree<'src>, ChumskyErr<'tokens, 'src>> + Clone
289where
290 I: ValueInput<'tokens, Token = Token<'src>, Span = SimpleSpan> + Clone,
291{
292 choice((
293 select! {Token::Property(s, a) => MonOp::Property(s, a) }
294 .then(
295 expr.clone()
296 .delimited_by(just(Token::OpenDelim), just(Token::CloseDelim)),
297 )
298 .map(|(op, arg)| ParseTree::Unary(op, Box::new(arg))),
299 select! {Token::Iota(a) => a }
300 .then_ignore(just(Token::OpenDelim))
301 .then(select! {Token::Variable(v) => v})
302 .then_ignore(just(Token::ArgSep))
303 .then(expr.clone().map(Box::new))
304 .then_ignore(just(Token::CloseDelim))
305 .map(|((a_e, var), body)| ParseTree::Iota { t: a_e, var, body }),
306 ))
307}
308
309type ChumskyErr<'tokens, 'src> = extra::Err<Rich<'tokens, Token<'src>, Span>>;
310
311fn binary_operation<'tokens, 'src: 'tokens, I>(
312 a: impl Parser<'tokens, I, ParseTree<'src>, ChumskyErr<'tokens, 'src>> + Clone,
313 b: impl Parser<'tokens, I, ParseTree<'src>, ChumskyErr<'tokens, 'src>> + Clone,
314) -> impl Parser<'tokens, I, ParseTree<'src>, ChumskyErr<'tokens, 'src>> + Clone
315where
316 I: ValueInput<'tokens, Token = Token<'src>, Span = SimpleSpan> + Clone,
317{
318 select! { Token::BinOp(b) => b}
319 .labelled("binary operation")
320 .then_ignore(just(Token::OpenDelim))
321 .then(a)
322 .then_ignore(just(Token::ArgSep))
323 .then(b)
324 .then_ignore(just(Token::CloseDelim))
325 .map(|((binop, actor), event)| ParseTree::Binary(binop, Box::new(actor), Box::new(event)))
326}
327
328#[derive(Debug, Clone, Eq, PartialEq)]
329enum Token<'src> {
330 Bool(Constant<'src>),
331 And,
332 Or,
333 Not,
334 Actor(Actor<'src>),
335 Event(Event),
336 BinOp(BinOp),
337 OpenDelim,
338 ArgSep,
339 CloseDelim,
340 Constant(Constant<'src>),
341 Property(&'src str, ActorOrEvent),
342 Iota(ActorOrEvent),
343 Quantifier(Quantifier, ActorOrEvent),
344 Lambda(LambdaType, &'src str),
345 Variable(&'src str),
346 FreeVariable(&'src str, LambdaType),
347}
348impl Display for Token<'_> {
349 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
350 match self {
351 Token::Actor(a) => write!(f, "a_{a}"),
352 Token::Event(n) => write!(f, "e_{n}"),
353 Token::OpenDelim => write!(f, "("),
354 Token::ArgSep => write!(f, ","),
355 Token::CloseDelim => write!(f, ")"),
356 Token::Bool(constant) => write!(f, "{constant}"),
357 Token::And => write!(f, "&"),
358 Token::Or => write!(f, "|"),
359 Token::Not => write!(f, "~"),
360 Token::BinOp(bin_op) => write!(f, "{bin_op}"),
361 Token::Constant(constant) => write!(f, "{constant}"),
362 Token::Property(k, actor_or_event) => write!(f, "p{actor_or_event}_{k}"),
363 Token::Quantifier(quantifier, actor_or_event) => write!(
364 f,
365 "{quantifier}{}",
366 match actor_or_event {
367 ActorOrEvent::Actor => "",
368 ActorOrEvent::Event => "_e",
369 }
370 ),
371 Token::Lambda(lambda_type, t) => write!(f, "lambda {lambda_type} {t}"),
372 Token::Variable(v) => write!(f, "{v}"),
373 Token::FreeVariable(v, lambda_type) => write!(f, "{v}#{lambda_type}"),
374 Token::Iota(ActorOrEvent::Event) => write!(f, "iota_e"),
375 Token::Iota(ActorOrEvent::Actor) => write!(f, "iota"),
376 }
377 }
378}
379
380pub type Span = SimpleSpan;
381pub type Spanned<T> = (T, Span);
382
383fn lexer<'src, E>() -> impl Parser<'src, &'src str, Vec<Spanned<Token<'src>>>, E>
384where
385 E: ParserExtra<'src, &'src str> + 'src,
386 E::Error: LabelError<'src, &'src str, TextExpected<'src, &'src str>>
387 + LabelError<'src, &'src str, MaybeRef<'src, char>>
388 + LabelError<'src, &'src str, &'static str>,
389{
390 choice((
391 just(',').to(Token::ArgSep),
392 just('(').to(Token::OpenDelim),
393 just(')').to(Token::CloseDelim),
394 just("True").to(Token::Bool(Constant::Tautology)),
395 just("False").to(Token::Bool(Constant::Contradiction)),
396 just('&').to(Token::And),
397 just('|').to(Token::Or),
398 just('~').to(Token::Not),
399 just("AgentOf").to(Token::BinOp(BinOp::AgentOf)),
400 just("PatientOf").to(Token::BinOp(BinOp::PatientOf)),
401 just("iota_e").to(Token::Iota(ActorOrEvent::Event)),
402 just("iota").to(Token::Iota(ActorOrEvent::Actor)),
403 just("all_a").to(Token::Constant(Constant::Everyone)),
404 just("all_e").to(Token::Constant(Constant::EveryEvent)),
405 choice((
406 just("every").to(Quantifier::Universal),
407 just("some").to(Quantifier::Existential),
408 ))
409 .then(just("_e").or_not())
410 .map(|(q, t)| {
411 Token::Quantifier(
412 q,
413 if t.is_some() {
414 ActorOrEvent::Event
415 } else {
416 ActorOrEvent::Actor
417 },
418 )
419 }),
420 just("a_").ignore_then(keyword()).map(Token::Actor),
421 just("e_")
422 .ignore_then(text::int(10))
423 .map(|s: &str| Token::Event(s.parse().unwrap())),
424 just("p")
425 .ignore_then(
426 just("a")
427 .to(ActorOrEvent::Actor)
428 .or(just("e").to(ActorOrEvent::Event)),
429 )
430 .then_ignore(just("_"))
431 .then(keyword())
432 .map(|(t, s)| Token::Property(s, t)),
433 just("lambda")
434 .then(inline_whitespace().at_least(1))
435 .ignore_then(core_type_parser())
436 .then_ignore(inline_whitespace().at_least(1))
437 .then(keyword())
438 .then_ignore(inline_whitespace().at_least(1))
439 .map(|(t, x)| Token::Lambda(t, x)),
440 keyword()
441 .then(just("#").ignore_then(core_type_parser()).or_not())
442 .map(|(var, lambda_type)| {
443 if let Some(t) = lambda_type {
444 Token::FreeVariable(var, t)
445 } else {
446 Token::Variable(var)
447 }
448 }),
449 ))
450 .map_with(|t, e| (t, e.span()))
451 .padded()
452 .repeated()
453 .collect()
454}
455
456fn language_parser<'tokens, 'src: 'tokens, I>()
457-> impl Parser<'tokens, I, ParseTree<'src>, extra::Err<Rich<'tokens, Token<'src>, Span>>> + Clone
458where
459 I: ValueInput<'tokens, Token = Token<'src>, Span = SimpleSpan> + Clone,
460{
461 let var = select! {
462 Token::Variable(a) => ParseTree::Variable(a),
463 Token::FreeVariable(a, t) => ParseTree::FreeVariable(a, t)
464 }
465 .labelled("variable");
466
467 let ent = select! {
468 Token::Actor(a) => ParseTree::Entity(Entity::Actor(a)),
469 Token::Event(a) => ParseTree::Entity(Entity::Event(a)),
470 }
471 .labelled("entity");
472
473 let bool = select! {
474 Token::Bool(b) => ParseTree::Constant(b)
475 }
476 .labelled("boolean");
477
478 let sets = select! {
479 Token::Constant(c) => ParseTree::Constant(c),
480 Token::Property(s, a) => ParseTree::Constant(Constant::Property(s,a))
481 }
482 .labelled("constant set");
483 recursive(|expr| {
484 let bin_op = binary_operation(expr.clone(), expr.clone());
485 let mon_op = unary_op(expr.clone());
486
487 let application = choice((
488 var,
489 expr.clone()
490 .delimited_by(just(Token::OpenDelim), just(Token::CloseDelim)),
491 ))
492 .then_ignore(just(Token::OpenDelim))
493 .then(
494 expr.clone()
495 .separated_by(just(Token::ArgSep))
496 .at_least(1)
497 .collect::<VecDeque<_>>(),
498 )
499 .then_ignore(just(Token::CloseDelim))
500 .map(|(t, mut args)| {
501 let mut tree = ParseTree::Application {
502 subformula: Box::new(t),
503 argument: Box::new(args.pop_front().expect("previous primitive has at least 1")),
504 };
505 while let Some(x) = args.pop_front() {
506 tree = ParseTree::Application {
507 subformula: Box::new(tree),
508 argument: Box::new(x),
509 };
510 }
511
512 tree
513 });
514
515 let quantified = select!(Token::Quantifier(q, a) => (q,a))
516 .then_ignore(just(Token::OpenDelim))
517 .then(select! {Token::Variable(v) => v})
518 .then_ignore(just(Token::ArgSep))
519 .then(expr.clone())
520 .then_ignore(just(Token::ArgSep))
521 .then(expr.clone())
522 .then_ignore(just(Token::CloseDelim))
523 .map(
524 |((((quantifier, lambda_type), variable), restrictor), subformula)| {
525 ParseTree::Quantifier {
526 quantifier,
527 variable,
528 lambda_type,
529 restrictor: Box::new(restrictor),
530 subformula: Box::new(subformula),
531 }
532 },
533 );
534
535 let atom = choice((
536 application,
537 ent,
538 var,
539 bin_op,
540 mon_op,
541 quantified,
542 bool,
543 sets,
544 expr.delimited_by(just(Token::OpenDelim), just(Token::CloseDelim)),
545 ));
546 atom.pratt((
547 prefix(2, just(Token::Not), |_, r, _| {
548 ParseTree::Unary(MonOp::Not, Box::new(r))
549 }),
550 prefix(
551 0,
552 select! {Token::Lambda(t, var) => (t, var)},
553 |(lambda_type, var), r, _| ParseTree::Lambda {
554 body: Box::new(r),
555 var,
556 lambda_type,
557 },
558 ),
559 infix(left(1), just(Token::And), |l, _, r, _| {
560 ParseTree::Binary(BinOp::And, Box::new(l), Box::new(r))
561 }),
562 infix(left(1), just(Token::Or), |l, _, r, _| {
563 ParseTree::Binary(BinOp::Or, Box::new(l), Box::new(r))
564 }),
565 ))
566 })
567}
568
569pub fn parse_lot<'a>(s: &'a str) -> Result<RootedLambdaPool<'a, Expr<'a>>, LambdaParseError> {
571 let tokens = lexer::<extra::Err<Rich<char>>>()
572 .then_ignore(end())
573 .parse(s)
574 .into_result()?;
575
576 language_parser()
577 .parse(
578 tokens
579 .as_slice()
580 .map((s.len()..s.len()).into(), |(t, s)| (t, s)),
581 )
582 .into_result()?
583 .to_pool()
584}
585
586pub fn parse_executable<'a>(s: &'a str) -> Result<LanguageExpression<'a>, LambdaParseError> {
588 let mut pool = parse_lot(s)?;
589 pool.reduce()?;
590 Ok(pool.into_pool()?)
591}
592
593#[cfg(test)]
594mod tests {
595 use super::*;
596 use crate::language::{ExprRef, LanguageResult};
597 use crate::{Scenario, ThetaRoles};
598 use std::collections::BTreeMap;
599
600 #[test]
601 fn parse_entity() {
602 for n in [1, 6, 3, 4, 5, 100, 40] {
603 let str = format!("e_{n}");
604 assert_eq!(
605 parse_lot(&str).unwrap(),
606 RootedLambdaPool::new(
607 LambdaPool(vec![LambdaExpr::LanguageOfThoughtExpr(Expr::Event(n))]),
608 LambdaExprRef(0)
609 )
610 );
611 }
612 for keyword in ["john", "mary", "phil", "Anna"] {
613 let str = format!("a_{keyword}");
614 assert_eq!(
615 parse_lot(&str).unwrap(),
616 RootedLambdaPool::new(
617 LambdaPool(vec![LambdaExpr::LanguageOfThoughtExpr(Expr::Actor(
618 keyword
619 ))]),
620 LambdaExprRef(0)
621 )
622 );
623 }
624 }
625
626 #[test]
627 fn parse_sets() {
628 assert_eq!(
629 parse_lot("all_e").unwrap(),
630 RootedLambdaPool::new(
631 LambdaPool(vec![LambdaExpr::LanguageOfThoughtExpr(Expr::Constant(
632 Constant::EveryEvent
633 ))]),
634 LambdaExprRef(0)
635 )
636 );
637 assert_eq!(
638 parse_lot("all_a").unwrap(),
639 RootedLambdaPool::new(
640 LambdaPool(vec![LambdaExpr::LanguageOfThoughtExpr(Expr::Constant(
641 Constant::Everyone
642 ))]),
643 LambdaExprRef(0)
644 )
645 );
646 for keyword in ["john", "mary", "phil", "Anna"] {
647 let str = format!("pa_{keyword}");
648 assert_eq!(
649 parse_lot(&str).unwrap(),
650 RootedLambdaPool::new(
651 LambdaPool(vec![LambdaExpr::LanguageOfThoughtExpr(Expr::Constant(
652 Constant::Property(keyword, ActorOrEvent::Actor)
653 ))]),
654 LambdaExprRef(0)
655 )
656 );
657 let str = format!("pe_{keyword}");
658 assert_eq!(
659 parse_lot(&str).unwrap(),
660 RootedLambdaPool::new(
661 LambdaPool(vec![LambdaExpr::LanguageOfThoughtExpr(Expr::Constant(
662 Constant::Property(keyword, ActorOrEvent::Event)
663 ))]),
664 LambdaExprRef(0)
665 )
666 );
667 }
668 }
669
670 fn get_parse<'a>(
671 s: &'a str,
672 simple_scenario: &'a Scenario,
673 ) -> anyhow::Result<LanguageResult<'a>> {
674 let pool = LanguageExpression::parse(s)?;
675 Ok(pool.run(simple_scenario, None)?)
676 }
677
678 fn check_lambdas(
679 statement: &str,
680 lambda_type: &str,
681 gold_pool: RootedLambdaPool<Expr>,
682 ) -> anyhow::Result<()> {
683 println!("{statement}");
684 let pool = parse_lot(statement)?;
685
686 assert_eq!(
687 pool.get_type()?,
688 LambdaType::from_string(lambda_type).map_err(|e| anyhow::anyhow!(e.to_string()))?
689 );
690 assert_eq!(pool, gold_pool);
691
692 Ok(())
693 }
694
695 #[test]
696 fn parse_lambda() -> anyhow::Result<()> {
697 check_lambdas(
698 "lambda e x (pe_Red(x))",
699 "<e,t>",
700 RootedLambdaPool::new(
701 LambdaPool::from(vec![
702 LambdaExpr::BoundVariable(0, LambdaType::e().clone()),
703 LambdaExpr::LanguageOfThoughtExpr(Expr::Unary(
704 MonOp::Property("Red", ActorOrEvent::Event),
705 ExprRef(0),
706 )),
707 LambdaExpr::Lambda(LambdaExprRef(1), LambdaType::e().clone()),
708 ]),
709 LambdaExprRef(2),
710 ),
711 )?;
712 check_lambdas(
713 "lambda <e,t> P (lambda e x (P(x)))",
714 "<<e,t>, <e,t>>",
715 RootedLambdaPool::new(
716 LambdaPool::from(vec![
717 LambdaExpr::BoundVariable(1, LambdaType::et().clone()),
718 LambdaExpr::BoundVariable(0, LambdaType::e().clone()),
719 LambdaExpr::Application {
720 subformula: LambdaExprRef(0),
721 argument: LambdaExprRef(1),
722 },
723 LambdaExpr::Lambda(LambdaExprRef(2), LambdaType::e().clone()),
724 LambdaExpr::Lambda(LambdaExprRef(3), LambdaType::et().clone()),
725 ]),
726 LambdaExprRef(4),
727 ),
728 )?;
729 check_lambdas(
730 "lambda <a,t> P (P(a_0))",
731 "<<a,t>,t>",
732 RootedLambdaPool::new(
733 LambdaPool::from(vec![
734 LambdaExpr::BoundVariable(0, LambdaType::at().clone()),
735 LambdaExpr::LanguageOfThoughtExpr(Expr::Actor("0")),
736 LambdaExpr::Application {
737 subformula: LambdaExprRef(0),
738 argument: LambdaExprRef(1),
739 },
740 LambdaExpr::Lambda(LambdaExprRef(2), LambdaType::at().clone()),
741 ]),
742 LambdaExprRef(3),
743 ),
744 )?;
745 check_lambdas(
746 "~hey#<e,t>(lol#e)",
747 "t",
748 RootedLambdaPool::new(
749 LambdaPool::from(vec![
750 LambdaExpr::FreeVariable("hey".into(), LambdaType::et().clone()),
751 LambdaExpr::FreeVariable("lol".into(), LambdaType::e().clone()),
752 LambdaExpr::Application {
753 subformula: LambdaExprRef(0),
754 argument: LambdaExprRef(1),
755 },
756 LambdaExpr::LanguageOfThoughtExpr(Expr::Unary(MonOp::Not, ExprRef(2))),
757 ]),
758 LambdaExprRef(3),
759 ),
760 )?;
761
762 check_lambdas(
763 "(lambda <a,t> P (P(a_0)))(lambda a x (pa_Red(x)))",
764 "t",
765 RootedLambdaPool::new(
766 LambdaPool::from(vec![
767 LambdaExpr::BoundVariable(0, LambdaType::at().clone()),
768 LambdaExpr::LanguageOfThoughtExpr(Expr::Actor("0")),
769 LambdaExpr::Application {
770 subformula: LambdaExprRef(0),
771 argument: LambdaExprRef(1),
772 },
773 LambdaExpr::Lambda(LambdaExprRef(2), LambdaType::at().clone()),
774 LambdaExpr::BoundVariable(0, LambdaType::a().clone()),
775 LambdaExpr::LanguageOfThoughtExpr(Expr::Unary(
776 MonOp::Property("Red", ActorOrEvent::Actor),
777 ExprRef(4),
778 )),
779 LambdaExpr::Lambda(LambdaExprRef(5), LambdaType::a().clone()),
780 LambdaExpr::Application {
781 subformula: LambdaExprRef(3),
782 argument: LambdaExprRef(6),
783 },
784 ]),
785 LambdaExprRef(7),
786 ),
787 )?;
788 check_lambdas(
789 "lambda t phi (lambda t psi (phi & psi))",
790 "<t,<t,t>>",
791 RootedLambdaPool::new(
792 LambdaPool::from(vec![
793 LambdaExpr::BoundVariable(1, LambdaType::t().clone()),
794 LambdaExpr::BoundVariable(0, LambdaType::t().clone()),
795 LambdaExpr::LanguageOfThoughtExpr(Expr::Binary(
796 BinOp::And,
797 ExprRef(0),
798 ExprRef(1),
799 )),
800 LambdaExpr::Lambda(LambdaExprRef(2), LambdaType::t().clone()),
801 LambdaExpr::Lambda(LambdaExprRef(3), LambdaType::t().clone()),
802 ]),
803 LambdaExprRef(4),
804 ),
805 )?;
806
807 Ok(())
808 }
809
810 #[test]
811 fn test_parse_with_beta_reduction() -> anyhow::Result<()> {
812 parse_executable("(lambda <a,t> P (P(a_0)))(lambda a x (pa_Red(x)))")?;
813 Ok(())
814 }
815
816 #[test]
817 fn parse_with_keywords() -> anyhow::Result<()> {
818 let mut properties = BTreeMap::default();
819
820 properties.insert("Red", vec![Entity::Actor("John")]);
821 properties.insert("Blue", vec![Entity::Actor("Mary"), Entity::Actor("John")]);
822
823 let scenario = Scenario {
824 question: vec![],
825 actors: vec!["Mary", "John"],
826 thematic_relations: vec![
827 ThetaRoles {
828 agent: Some("Mary"),
829 patient: Some("Mary"),
830 },
831 ThetaRoles {
832 agent: Some("John"),
833 patient: Some("Mary"),
834 },
835 ],
836 properties,
837 };
838
839 for statement in [
840 "~AgentOf(a_John, e_0)",
841 "pa_Red(a_John) & ~pa_Red(a_Mary)",
842 "pa_Red(a_John) & ~pa_Red(a_Mary) & pa_Red(a_John)",
843 "~(pa_Red(a_John) & ~(True & pa_Red(a_John)))",
844 "every(x0, all_a, pa_Blue(x0))",
845 "every(x0, pa_Blue, pa_Blue(x0))",
846 "every(x, pa_Red, pa_Blue(x))",
847 "every(x0, pa_Red, pa_Blue(x0))",
848 "every_e(x0, all_e, (some(x1, all_a, AgentOf(x1, x0))))",
849 "every_e(x0, all_e, (some(x1, all_a, PatientOf(x1, x0))))",
850 "every_e(x0, all_e, PatientOf(a_Mary, x0))",
851 "some(x0, (PatientOf(x0, e_0) & PatientOf(x0, e_1)), pa_Blue(x0))",
852 ] {
853 println!("{statement}");
854 let expression = parse_executable(statement)?;
855 assert_eq!(expression.run(&scenario, None)?, LanguageResult::Bool(true));
856 }
857
858 for (statement, result) in [
859 ("a_Mary", LanguageResult::Actor("Mary")),
860 ("pa_Red", LanguageResult::ActorSet(vec!["John"])),
861 ("pa_Blue", LanguageResult::ActorSet(vec!["Mary", "John"])),
862 ] {
863 println!("{statement}");
864 let expression = parse_executable(statement)?;
865 assert_eq!(expression.run(&scenario, None)?, result);
866 }
867
868 Ok(())
869 }
870
871 #[test]
872 fn parse_test() -> anyhow::Result<()> {
873 let mut properties = BTreeMap::default();
874
875 properties.insert("Red", vec![Entity::Actor("John")]);
876 properties.insert("Blue", vec![Entity::Actor("Mary"), Entity::Actor("John")]);
877
878 let scenario = Scenario {
879 question: vec![],
880 actors: vec!["Mary", "John"],
881 thematic_relations: vec![
882 ThetaRoles {
883 agent: Some("Mary"),
884 patient: Some("Mary"),
885 },
886 ThetaRoles {
887 agent: Some("John"),
888 patient: Some("Mary"),
889 },
890 ],
891 properties,
892 };
893
894 for statement in [
895 "True",
896 "~~~False",
897 "~AgentOf(a_John, e_0)",
898 "~(True & False)",
899 "True | False",
900 "(True & False) | True",
901 "~(True & False) | False",
902 "pa_Red(a_John) & ~pa_Red(a_Mary)",
903 "pa_Red(a_John) & ~pa_Red(a_Mary) & pa_Red(a_John)",
904 "~(pa_Red(a_John) & ~(True & pa_Red(a_John)))",
905 "every(x0, all_a, pa_Blue(x0))",
906 "every(x0, pa_Blue, pa_Blue(x0))",
907 "every_e(x0, all_e, (some(x1, all_a, AgentOf(x1, x0))))",
908 "every_e(x0, all_e, (some(x1, all_a, PatientOf(x1, x0))))",
909 "every_e(x0, all_e, PatientOf(a_Mary, x0))",
910 "some(x0, (PatientOf(x0, e_0) & PatientOf(x0, e_1)), pa_Blue(x0))",
911 ] {
912 println!("{statement}");
913 assert_eq!(get_parse(statement, &scenario)?, LanguageResult::Bool(true));
914 }
915 for (statement, result) in [
916 ("a_Mary", LanguageResult::Actor("Mary")),
917 ("e_0", LanguageResult::Event(0)),
918 ("all_e", LanguageResult::EventSet(vec![0, 1])),
919 ("all_a", LanguageResult::ActorSet(vec!["Mary", "John"])),
920 ("pa_Red", LanguageResult::ActorSet(vec!["John"])),
921 ("pa_Blue", LanguageResult::ActorSet(vec!["Mary", "John"])),
922 ] {
923 println!("{statement}");
924 assert_eq!(get_parse(statement, &scenario)?, result);
925 }
926
927 Ok(())
928 }
929
930 #[test]
931 fn parse_errors_test() -> anyhow::Result<()> {
932 for statement in [
933 "(wow#<a,<e,t>>(nice#a))(cool#e)",
934 "every(x,lambda a y pa_John(y), pa_Blue(y#a))",
935 "pa_cool(iota(x, pa_man(x)))",
936 "pe_cool(iota_e(x, pe_man(x)))",
937 "pa_cool(iota(x, (lambda a x pa_man(x))(x)))",
938 ] {
939 RootedLambdaPool::parse(statement)?;
940 }
941
942 for statement in [
943 "wow#<e,t>(nice#a)",
944 "(wow#<a,<e,t>>(nice#a))(cool#a)",
945 "every(x,lambda a y pa_John(y), pa_Blue(y))",
946 ] {
947 let p = RootedLambdaPool::parse(statement);
948 assert!(p.is_err());
949 }
950 Ok(())
951 }
952}