simple_semantics/
scenario.rs

1use crate::{ScenarioParsingError, lambda::RootedLambdaPool};
2use chumsky::{prelude::*, text::inline_whitespace};
3use itertools::{Itertools, MultiProduct};
4use serde::{Deserialize, Serialize};
5use std::{collections::BTreeMap, fmt::Display};
6
7use crate::{Actor, Entity, Event, PropertyLabel, Scenario, ScenarioDataset, ThetaRoles};
8
9impl Display for Scenario<'_> {
10    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
11        write!(f, "<")?;
12        let mut first = true;
13        for actor in &self.actors {
14            if !first {
15                write!(f, ", ")?;
16            }
17
18            write!(f, "{actor}")?;
19            let mut first_property = true;
20            for (property, prop_actors) in &self.properties {
21                if prop_actors.contains(&Entity::Actor(actor)) {
22                    if first_property {
23                        first_property = false;
24                        write!(f, " (")?;
25                    } else {
26                        write!(f, ", ")?;
27                    }
28                    write!(f, "{property}")?;
29                }
30            }
31            if !first_property {
32                write!(f, ")")?;
33            }
34
35            first = false;
36        }
37        if self.thematic_relations.is_empty() {
38            return write!(f, ">");
39        }
40
41        write!(f, ";")?;
42        let mut first = true;
43
44        for (i, e) in self.thematic_relations.iter().enumerate() {
45            if !first {
46                write!(f, ", ")?;
47            } else {
48                write!(f, " ")?;
49            }
50            first = false;
51
52            write!(f, "{{")?;
53
54            if let Some(a) = e.agent {
55                write!(f, "A: {a}")?;
56                if e.patient.is_some() {
57                    write!(f, ", ")?;
58                }
59            }
60
61            if let Some(p) = e.patient {
62                write!(f, "P: {p}")?;
63            }
64
65            let mut first_property = true;
66            for (property, prop_actors) in &self.properties {
67                if prop_actors.contains(&Entity::Event(u8::try_from(i).unwrap())) {
68                    if first_property {
69                        first_property = false;
70                        if e.agent.is_some() || e.patient.is_some() {
71                            write!(f, " (")?;
72                        } else {
73                            write!(f, "(")?;
74                        }
75                    } else {
76                        write!(f, ", ")?;
77                    }
78                    write!(f, "{property}")?;
79                }
80            }
81            if !first_property {
82                write!(f, ")")?;
83            }
84
85            write!(f, "}}")?;
86        }
87
88        write!(f, ">")?;
89
90        let mut first = true;
91        for q in self.questions() {
92            if !first {
93                write!(f, "; {q}")?;
94            } else {
95                write!(f, " {q}")?;
96            }
97            first = false;
98        }
99        Ok(())
100    }
101}
102
103impl<'a> Scenario<'a> {
104    ///Parses a scenario from a string.
105    ///```
106    ///# use simple_semantics::Scenario;
107    ///let s = "<a (Red), b, c (Blue, Red); {(Green)}, {A: a}, {P: c (Blue)}> lambda a x pa_Blue(x); lambda a x pa_Red(x)";
108    ///let scenario = Scenario::parse(s).unwrap();
109    ///assert_eq!(scenario.to_string(), s);
110    ///```
111    ///
112    ///# Errors
113    ///Will return an error if the [`Scenario`] is incorrectly formatted.
114    pub fn parse(s: &'a str) -> Result<Self, ScenarioParsingError> {
115        Ok(scenario_parser()
116            .padded()
117            .then_ignore(end())
118            .parse(s)
119            .into_result()?)
120    }
121}
122
123pub fn theta_role_parser<'a>()
124-> impl Parser<'a, &'a str, ThetaRoles<'a>, extra::Err<Rich<'a, char>>> + Copy {
125    let theta_role = |c: char| {
126        just(c)
127            .padded()
128            .ignore_then(just(':'))
129            .ignore_then(text::ident().padded())
130            .padded()
131    };
132
133    choice((
134        theta_role('A')
135            .then_ignore(just(','))
136            .then(theta_role('P'))
137            .map(|(a, p)| ThetaRoles {
138                agent: Some(a),
139                patient: Some(p),
140            }),
141        theta_role('P')
142            .then_ignore(just(','))
143            .then(theta_role('A'))
144            .map(|(p, a)| ThetaRoles {
145                agent: Some(a),
146                patient: Some(p),
147            }),
148        theta_role('P').map(|n| ThetaRoles {
149            agent: None,
150            patient: Some(n),
151        }),
152        theta_role('A').map(|n| ThetaRoles {
153            agent: Some(n),
154            patient: None,
155        }),
156        empty().map(|()| ThetaRoles {
157            agent: None,
158            patient: None,
159        }),
160    ))
161}
162
163pub fn scenario_parser<'a>() -> impl Parser<'a, &'a str, Scenario<'a>, extra::Err<Rich<'a, char>>> {
164    let properties = text::ident()
165        .padded()
166        .separated_by(just(','))
167        .collect::<Vec<&str>>()
168        .delimited_by(just('('), just(')'))
169        .padded();
170
171    let actor = text::ident().padded().then(properties.or_not());
172
173    let actors = actor
174        .map(|(a, p)| {
175            let mut properties: BTreeMap<&str, Vec<_>> = BTreeMap::default();
176            if let Some(property_labels) = p {
177                for property in property_labels {
178                    properties.insert(property, vec![a]);
179                }
180            }
181            (vec![a], properties)
182        })
183        .foldl(
184            just(',').ignore_then(actor).repeated(),
185            |(mut actors, mut properties), (actor, actor_props)| {
186                if let Some(property_labels) = actor_props {
187                    for property in property_labels {
188                        properties
189                            .entry(property)
190                            .and_modify(|x| x.push(actor))
191                            .or_insert(vec![actor]);
192                    }
193                }
194
195                actors.push(actor);
196                (actors, properties)
197            },
198        );
199
200    let event = theta_role_parser()
201        .then(properties.or_not())
202        .delimited_by(just('{'), just('}'))
203        .padded();
204
205    let events = event
206        .or_not()
207        .map(|event_data| {
208            let mut properties: BTreeMap<&str, Vec<Entity>> = BTreeMap::default();
209
210            let events = match event_data {
211                Some((e, None)) => {
212                    vec![e]
213                }
214                Some((e, Some(p))) => {
215                    for property_label in p {
216                        properties.insert(property_label, vec![Entity::Event(0)]);
217                    }
218
219                    vec![e]
220                }
221                None => vec![],
222            };
223
224            (events, properties)
225        })
226        .foldl(
227            just(',').ignore_then(event).repeated().enumerate(),
228            |(mut acc_event, mut acc_props), (i, (event, event_props))| {
229                acc_event.push(event);
230                if let Some(event_props) = event_props {
231                    for property_label in event_props {
232                        let e = Entity::Event(Event::try_from(i + 1).unwrap());
233                        acc_props
234                            .entry(property_label)
235                            .and_modify(|x| x.push(e))
236                            .or_insert_with(|| vec![e]);
237                    }
238                }
239                (acc_event, acc_props)
240            },
241        );
242
243    let scenario = actors
244        .then((just(';')).ignore_then(events).or_not())
245        .padded()
246        .delimited_by(just('<'), just('>'))
247        .map(|((actors, actor_props), events)| new_scenario(actors, actor_props, events));
248
249    let scenario = scenario.then(
250        inline_whitespace()
251            .at_least(1)
252            .ignore_then(
253                none_of("\n;")
254                    .repeated()
255                    .to_slice()
256                    .try_map(|x, s| RootedLambdaPool::parse(x).map_err(|e| Rich::custom(s, e)))
257                    .separated_by(just(';'))
258                    .collect::<Vec<_>>(),
259            )
260            .or_not(),
261    );
262
263    scenario.map(|(mut scenario, questions)| {
264        if let Some(question) = questions {
265            scenario.question = question;
266        }
267        scenario
268    })
269}
270
271#[allow(clippy::too_many_lines)]
272pub fn scenario_dataset_parser<'a>()
273-> impl Parser<'a, &'a str, ScenarioDataset<'a>, extra::Err<Rich<'a, char>>> {
274    let string_scenario_pair = none_of("\"")
275        .repeated()
276        .to_slice()
277        .delimited_by(just('"'), just('"'))
278        .map(|x: &str| x.split(' '))
279        .then_ignore(inline_whitespace().at_least(1))
280        .then(scenario_parser());
281
282    string_scenario_pair
283        .separated_by(text::newline())
284        .at_least(1)
285        .collect::<Vec<_>>()
286        .map(|v| {
287            let mut scenarios = vec![];
288            let mut sentences = vec![];
289            for (a, b) in v {
290                sentences.push(a.collect());
291                scenarios.push(b);
292            }
293            ScenarioDataset::new(scenarios, sentences).unwrap()
294        })
295        .padded()
296        .then_ignore(end())
297}
298
299type EventParseType<'a> = Option<(Vec<ThetaRoles<'a>>, BTreeMap<&'a str, Vec<Entity<'a>>>)>;
300
301fn new_scenario<'a>(
302    actors: Vec<Actor<'a>>,
303    actor_props: BTreeMap<&'a str, Vec<&'a str>>,
304    events: EventParseType<'a>,
305) -> Scenario<'a> {
306    let (events, event_props) = events.unwrap_or_else(|| (Vec::default(), BTreeMap::default()));
307
308    let mut properties: BTreeMap<&str, Vec<Entity>> = actor_props
309        .into_iter()
310        .map(|(k, v)| (k, v.into_iter().map(Entity::Actor).collect()))
311        .collect();
312
313    for (k, mut v) in event_props {
314        properties
315            .entry(k)
316            .and_modify(|value| value.append(&mut v))
317            .or_insert(v);
318    }
319
320    Scenario {
321        question: vec![],
322        actors,
323        thematic_relations: events,
324        properties,
325    }
326}
327
328mod utilities;
329use utilities::SetCounter;
330
331///Generates all scenarios that can be generated with a given set of primitives
332#[derive(Debug, Clone)]
333pub struct ScenarioIterator<'a> {
334    actors: ActorSetGenerator<'a>,
335    current_actors: Vec<Actor<'a>>,
336    current_props: BTreeMap<PropertyLabel<'a>, Vec<Entity<'a>>>,
337    current_event_set: Vec<(ThetaRoles<'a>, PropertyLabel<'a>)>,
338    event_kinds: Vec<PossibleEvent<'a>>,
339    counter: SetCounter,
340    max_number_of_events: Option<usize>,
341}
342
343///The kinds of possible events
344#[derive(Debug, Clone, Eq, PartialEq, Copy, Ord, PartialOrd, Hash, Serialize, Deserialize)]
345pub enum EventType {
346    ///An intransitive with only an agent
347    Unergative,
348
349    ///An intransitive with only a patient
350    Unaccusative,
351
352    ///A transitive verb which cannot be reflexive
353    TransitiveNonReflexive,
354
355    ///A transitive verb
356    Transitive,
357
358    ///No possible theta role (e.g. rains)
359    Avalent,
360}
361
362///A description of a possible kind of event (e.g. kind of verb)
363#[derive(Debug, Clone, Eq, PartialEq, Copy, Ord, PartialOrd, Hash, Serialize, Deserialize)]
364pub struct PossibleEvent<'a> {
365    ///Name of the event predicate
366    #[serde(borrow)]
367    pub label: PropertyLabel<'a>,
368    ///What kind of theta roles can be assigned to this event
369    pub event_type: EventType,
370}
371
372impl<'a> Scenario<'a> {
373    ///Returns a [`ScenarioIterator`] which goes over all possible scenarios with the provided
374    ///actors and event descriptions
375    ///
376    #[must_use]
377    pub fn all_scenarios(
378        actors: &[Actor<'a>],
379        event_kinds: &[PossibleEvent<'a>],
380        actor_properties: &[PropertyLabel<'a>],
381        max_number_of_events: Option<usize>,
382        max_number_of_actors: Option<usize>,
383        max_number_of_properties: Option<usize>,
384    ) -> ScenarioIterator<'a> {
385        let mut actors = ActorSetGenerator::new(
386            actors,
387            actor_properties,
388            max_number_of_actors,
389            max_number_of_properties,
390        );
391        let (current_actors, current_props) = actors.next().unwrap();
392        let current_event_set = generate_all_events(&current_actors, event_kinds);
393        let counter = SetCounter::new(current_event_set.len(), max_number_of_events);
394
395        ScenarioIterator {
396            actors,
397            current_actors,
398            current_event_set,
399            current_props,
400            event_kinds: event_kinds.to_vec(),
401            counter,
402            max_number_of_events,
403        }
404    }
405}
406
407impl<'a> Iterator for ScenarioIterator<'a> {
408    type Item = Scenario<'a>;
409
410    fn next(&mut self) -> Option<Self::Item> {
411        if self.counter.done() {
412            if let Some((new_actors, new_props)) = self.actors.next() {
413                self.current_actors = new_actors;
414                self.current_props = new_props;
415                self.current_event_set =
416                    generate_all_events(&self.current_actors, &self.event_kinds);
417                self.counter =
418                    SetCounter::new(self.current_event_set.len(), self.max_number_of_events);
419            } else {
420                return None;
421            }
422        }
423
424        let mut properties = self.current_props.clone();
425        let mut thematic_relations = vec![];
426        for (i, (theta, label)) in self
427            .counter
428            .as_set(self.current_event_set.iter().copied())
429            .enumerate()
430        {
431            properties
432                .entry(label)
433                .or_default()
434                .push(Entity::Event(Event::try_from(i).expect("Too many events!")));
435            thematic_relations.push(theta);
436        }
437        self.counter.increment();
438        Some(Scenario::new(
439            self.current_actors.clone(),
440            thematic_relations,
441            properties,
442        ))
443    }
444}
445
446fn generate_all_events<'a>(
447    actors: &[Actor<'a>],
448    event_kinds: &[PossibleEvent<'a>],
449) -> Vec<(ThetaRoles<'a>, PropertyLabel<'a>)> {
450    let mut all_events = vec![];
451    for e in event_kinds {
452        match e.event_type {
453            EventType::Unergative => all_events.extend(actors.iter().copied().map(|x| {
454                (
455                    ThetaRoles {
456                        agent: Some(x),
457                        patient: None,
458                    },
459                    e.label,
460                )
461            })),
462            EventType::Unaccusative => all_events.extend(actors.iter().copied().map(|x| {
463                (
464                    ThetaRoles {
465                        agent: None,
466                        patient: Some(x),
467                    },
468                    e.label,
469                )
470            })),
471            EventType::TransitiveNonReflexive => {
472                all_events.extend(actors.iter().copied().permutations(2).map(|mut x| {
473                    let a = x.pop().unwrap();
474                    let b = x.pop().unwrap();
475                    (
476                        ThetaRoles {
477                            agent: Some(a),
478                            patient: Some(b),
479                        },
480                        e.label,
481                    )
482                }));
483            }
484            EventType::Transitive => all_events.extend(
485                itertools::repeat_n(actors.iter().copied(), 2)
486                    .multi_cartesian_product()
487                    .map(|mut x| {
488                        let a = x.pop().unwrap();
489                        let b = x.pop().unwrap();
490                        (
491                            ThetaRoles {
492                                agent: Some(a),
493                                patient: Some(b),
494                            },
495                            e.label,
496                        )
497                    }),
498            ),
499            EventType::Avalent => {
500                all_events.push((
501                    ThetaRoles {
502                        agent: None,
503                        patient: None,
504                    },
505                    e.label,
506                ));
507            }
508        }
509    }
510
511    all_events
512}
513
514#[derive(Debug, Clone)]
515struct ActorSetGenerator<'a> {
516    actors: Vec<Actor<'a>>,
517    actor_properties: Vec<PropertyLabel<'a>>,
518    property_counter: MultiProduct<SetCounter>,
519    max_number_of_properties: Option<usize>,
520    included: SetCounter,
521}
522
523impl<'a> ActorSetGenerator<'a> {
524    fn new(
525        actors: &[Actor<'a>],
526        actor_properties: &[PropertyLabel<'a>],
527        max_number_of_actors: Option<usize>,
528        max_number_of_properties: Option<usize>,
529    ) -> Self {
530        ActorSetGenerator {
531            property_counter: std::iter::empty::<SetCounter>().multi_cartesian_product(),
532            included: SetCounter::new(actors.len(), max_number_of_actors),
533            actors: actors.to_vec(),
534            max_number_of_properties,
535            actor_properties: actor_properties.to_vec(),
536        }
537    }
538}
539
540impl<'a> Iterator for ActorSetGenerator<'a> {
541    type Item = (Vec<Actor<'a>>, BTreeMap<PropertyLabel<'a>, Vec<Entity<'a>>>);
542
543    fn next(&mut self) -> Option<Self::Item> {
544        let props = self.property_counter.next().unwrap_or_else(|| {
545            self.included.increment();
546            let n_actors = self.included.current_size();
547            self.property_counter = (0..n_actors)
548                .map(|_| {
549                    SetCounter::new(self.actor_properties.len(), self.max_number_of_properties)
550                })
551                .multi_cartesian_product();
552            self.property_counter.next().unwrap()
553        });
554
555        if self.included.done() {
556            return None;
557        }
558
559        let mut actor_properties: BTreeMap<_, Vec<_>> = BTreeMap::new();
560
561        let actors: Vec<Actor<'a>> = self
562            .included
563            .included()
564            .as_set(&self.actors)
565            .copied()
566            .zip(props)
567            .map(|(x, props)| {
568                for prop in props.as_set(&self.actor_properties) {
569                    actor_properties
570                        .entry(*prop)
571                        .or_default()
572                        .push(Entity::Actor(x));
573                }
574                x
575            })
576            .collect();
577
578        Some((actors, actor_properties))
579    }
580}
581
582#[cfg(test)]
583mod test {
584    use crate::scenario::generate_all_events;
585
586    use super::*;
587    use ahash::HashSet;
588
589    #[test]
590    fn generate_all_actors() {
591        let s = ActorSetGenerator::new(&["John", "Mary"], &["man", "woman"], None, None);
592
593        let mut set = HashSet::default();
594        for p in s {
595            println!("{p:?}");
596            assert!(!set.contains(&p));
597            set.insert(p);
598        }
599        assert_eq!(set.len(), 25);
600    }
601
602    #[test]
603    fn generate_all_scenarios() {
604        let actors = ["John", "Mary"];
605        let event_kinds = [
606            PossibleEvent {
607                label: "rain",
608                event_type: EventType::Avalent,
609            },
610            PossibleEvent {
611                label: "runs",
612                event_type: EventType::Unergative,
613            },
614            PossibleEvent {
615                label: "falls",
616                event_type: EventType::Unaccusative,
617            },
618            PossibleEvent {
619                label: "loves",
620                event_type: EventType::TransitiveNonReflexive,
621            },
622        ];
623
624        let mut scenarios = HashSet::default();
625        for x in Scenario::all_scenarios(&actors, &event_kinds, &["man", "woman"], None, None, None)
626        {
627            assert!(!scenarios.contains(&x));
628            scenarios.insert(x);
629        }
630        assert_eq!(scenarios.len(), 2114);
631
632        let mut scenarios = HashSet::default();
633        let mut at_least_1 = false;
634        let mut at_least_2 = false;
635        for x in Scenario::all_scenarios(
636            &actors,
637            &event_kinds,
638            &["man", "woman"],
639            Some(2),
640            Some(1),
641            None,
642        ) {
643            assert!(!scenarios.contains(&x));
644            assert!(x.actors.len() <= 1);
645            if x.actors.len() == 1 {
646                at_least_1 = true;
647            }
648
649            if x.events().count() == 2 {
650                at_least_2 = true;
651            }
652            assert!(x.events().count() <= 2);
653            scenarios.insert(x);
654        }
655
656        assert!(at_least_1);
657        assert!(at_least_2);
658        assert_eq!(scenarios.len(), 58);
659    }
660
661    #[test]
662    fn generate_event_test() {
663        let actors = ["John", "Mary", "Phil"];
664        let event_kinds = [
665            PossibleEvent {
666                label: "rain",
667                event_type: EventType::Avalent,
668            },
669            PossibleEvent {
670                label: "runs",
671                event_type: EventType::Unergative,
672            },
673            PossibleEvent {
674                label: "falls",
675                event_type: EventType::Unaccusative,
676            },
677            PossibleEvent {
678                label: "likes",
679                event_type: EventType::Transitive,
680            },
681            PossibleEvent {
682                label: "loves",
683                event_type: EventType::TransitiveNonReflexive,
684            },
685        ];
686
687        let e = generate_all_events(&actors, &event_kinds);
688
689        assert_eq!(
690            e,
691            [
692                (
693                    ThetaRoles {
694                        agent: None,
695                        patient: None
696                    },
697                    "rain"
698                ),
699                (
700                    ThetaRoles {
701                        agent: Some("John"),
702                        patient: None
703                    },
704                    "runs"
705                ),
706                (
707                    ThetaRoles {
708                        agent: Some("Mary"),
709                        patient: None
710                    },
711                    "runs"
712                ),
713                (
714                    ThetaRoles {
715                        agent: Some("Phil"),
716                        patient: None
717                    },
718                    "runs"
719                ),
720                (
721                    ThetaRoles {
722                        agent: None,
723                        patient: Some("John")
724                    },
725                    "falls"
726                ),
727                (
728                    ThetaRoles {
729                        agent: None,
730                        patient: Some("Mary")
731                    },
732                    "falls"
733                ),
734                (
735                    ThetaRoles {
736                        agent: None,
737                        patient: Some("Phil")
738                    },
739                    "falls"
740                ),
741                (
742                    ThetaRoles {
743                        agent: Some("John"),
744                        patient: Some("John")
745                    },
746                    "likes"
747                ),
748                (
749                    ThetaRoles {
750                        agent: Some("Mary"),
751                        patient: Some("John")
752                    },
753                    "likes"
754                ),
755                (
756                    ThetaRoles {
757                        agent: Some("Phil"),
758                        patient: Some("John")
759                    },
760                    "likes"
761                ),
762                (
763                    ThetaRoles {
764                        agent: Some("John"),
765                        patient: Some("Mary")
766                    },
767                    "likes"
768                ),
769                (
770                    ThetaRoles {
771                        agent: Some("Mary"),
772                        patient: Some("Mary")
773                    },
774                    "likes"
775                ),
776                (
777                    ThetaRoles {
778                        agent: Some("Phil"),
779                        patient: Some("Mary")
780                    },
781                    "likes"
782                ),
783                (
784                    ThetaRoles {
785                        agent: Some("John"),
786                        patient: Some("Phil")
787                    },
788                    "likes"
789                ),
790                (
791                    ThetaRoles {
792                        agent: Some("Mary"),
793                        patient: Some("Phil")
794                    },
795                    "likes"
796                ),
797                (
798                    ThetaRoles {
799                        agent: Some("Phil"),
800                        patient: Some("Phil")
801                    },
802                    "likes"
803                ),
804                (
805                    ThetaRoles {
806                        agent: Some("Mary"),
807                        patient: Some("John")
808                    },
809                    "loves"
810                ),
811                (
812                    ThetaRoles {
813                        agent: Some("Phil"),
814                        patient: Some("John")
815                    },
816                    "loves"
817                ),
818                (
819                    ThetaRoles {
820                        agent: Some("John"),
821                        patient: Some("Mary")
822                    },
823                    "loves"
824                ),
825                (
826                    ThetaRoles {
827                        agent: Some("Phil"),
828                        patient: Some("Mary")
829                    },
830                    "loves"
831                ),
832                (
833                    ThetaRoles {
834                        agent: Some("John"),
835                        patient: Some("Phil")
836                    },
837                    "loves"
838                ),
839                (
840                    ThetaRoles {
841                        agent: Some("Mary"),
842                        patient: Some("Phil")
843                    },
844                    "loves"
845                )
846            ]
847        );
848    }
849
850    #[test]
851    #[should_panic]
852    fn parse_trailing() {
853        scenario_dataset_parser().parse("<John>trailing").unwrap();
854    }
855
856    #[test]
857    fn white_space_shenanigans() -> anyhow::Result<()> {
858        scenario_dataset_parser()
859            .parse("\"blah\" <John; {A: John (run)}>")
860            .unwrap();
861        scenario_dataset_parser()
862            .parse("\" s\" <John ; {A: John (run)}>")
863            .unwrap();
864        scenario_dataset_parser()
865            .parse("\"\" < John ; { A : John (run)}>")
866            .unwrap();
867        scenario_dataset_parser()
868            .parse("\"aaa\"      < John ; { A :  John ( run )  } >")
869            .unwrap();
870        scenario_dataset_parser()
871            .parse("\"aaa\" < John; {A: John ( run)}>")
872            .unwrap();
873        Ok(())
874    }
875
876    #[test]
877    fn parse_multiple_scenarios() -> anyhow::Result<()> {
878        let scenarios = vec![
879            Scenario {
880                question: vec![],
881                actors: vec!["John"],
882                thematic_relations: vec![],
883                properties: BTreeMap::default(),
884            },
885            Scenario {
886                question: vec![],
887                actors: vec!["Mary"],
888                thematic_relations: vec![],
889                properties: BTreeMap::default(),
890            },
891            Scenario {
892                question: vec![],
893                actors: vec!["John"],
894                thematic_relations: vec![],
895                properties: BTreeMap::default(),
896            },
897        ];
898
899        assert_eq!(
900            scenarios,
901            *scenario_dataset_parser()
902                .parse("\"John\" <John>\n\"Mary\" <Mary>\n\"John\" <John>")
903                .unwrap()
904                .scenarios
905        );
906
907        let scenarios = vec![
908            Scenario {
909                question: vec![],
910                actors: vec!["John"],
911                thematic_relations: vec![ThetaRoles {
912                    agent: Some("John"),
913                    patient: None,
914                }],
915                properties: BTreeMap::from_iter([("run", vec![Entity::Event(0)])]),
916            },
917            Scenario {
918                question: vec![],
919                actors: vec!["Mary"],
920                thematic_relations: vec![ThetaRoles {
921                    agent: Some("Mary"),
922                    patient: None,
923                }],
924                properties: BTreeMap::from_iter([("run", vec![Entity::Event(0)])]),
925            },
926            Scenario {
927                question: vec![],
928                actors: vec!["Mary", "John"],
929                thematic_relations: vec![ThetaRoles {
930                    agent: Some("John"),
931                    patient: Some("Mary"),
932                }],
933                properties: BTreeMap::from_iter([("see", vec![Entity::Event(0)])]),
934            },
935        ];
936
937        assert_eq!(
938            scenarios,
939            *scenario_dataset_parser()
940                .parse("\"John runs\" <John; {A: John (run)}>\n\"Mary runs\" <Mary; {A: Mary (run)}>\n\"John sees Mary\" <Mary, John; {A: John, P: Mary (see)}>")
941                .unwrap()
942                .scenarios
943        );
944        Ok(())
945    }
946
947    #[test]
948    fn parse_scenarios_with_questions() -> anyhow::Result<()> {
949        let scenarios = scenario_dataset_parser()
950                .parse("\"John runs\" <John; {A: John (run)}> lambda a x (x)\n\"Mary runs\" <Mary; {A: Mary (run)}>\n\"John sees Mary\" <Mary, John; {A: John, P: Mary (see)}>  a_0")
951                .unwrap();
952
953        assert_eq!(
954            scenarios.scenarios[0].question.first().unwrap().to_string(),
955            "lambda a x x"
956        );
957        assert_eq!(scenarios.scenarios[1].question, vec![]);
958        assert_eq!(
959            scenarios.scenarios[2].question.first().unwrap().to_string(),
960            "a_0"
961        );
962
963        let scenarios = scenario_dataset_parser()
964                .parse("\"John runs\" <John; {A: John (run)}> lambda a x (x)\n\"Mary runs\" <Mary; {A: Mary (run)}>\n\"John sees Mary\" <Mary, John; {A: John, P: Mary (see)}>  a_0; a_1; a_3")
965                .unwrap();
966        assert_eq!(scenarios.scenarios[2].question.len(), 3);
967
968        assert_eq!(
969            scenarios.scenarios[2].question.last().unwrap().to_string(),
970            "a_3"
971        );
972        Ok(())
973    }
974
975    #[test]
976    fn parse_scenario() -> anyhow::Result<()> {
977        let scenario = Scenario {
978            question: vec![],
979            actors: vec!["John"],
980            thematic_relations: vec![],
981            properties: BTreeMap::default(),
982        };
983
984        assert_eq!(
985            scenario,
986            *scenario_dataset_parser()
987                .parse("\"John\" <John>")
988                .unwrap()
989                .scenarios
990                .first()
991                .unwrap()
992        );
993        assert_eq!(
994            scenario,
995            *scenario_dataset_parser()
996                .parse("\"John\" <John;>")
997                .unwrap()
998                .scenarios
999                .first()
1000                .unwrap()
1001        );
1002        assert_eq!(
1003            scenario,
1004            *scenario_dataset_parser()
1005                .parse("\"John\" < John; >")
1006                .unwrap()
1007                .scenarios
1008                .first()
1009                .unwrap()
1010        );
1011
1012        let scenario = Scenario {
1013            question: vec![],
1014            actors: vec!["john"],
1015            thematic_relations: vec![ThetaRoles {
1016                agent: None,
1017                patient: None,
1018            }],
1019            properties: BTreeMap::default(),
1020        };
1021        assert_eq!(
1022            scenario,
1023            *scenario_dataset_parser()
1024                .parse("\"john\" <john;{}>")
1025                .unwrap()
1026                .scenarios
1027                .first()
1028                .unwrap()
1029        );
1030
1031        let scenario = Scenario {
1032            question: vec![],
1033            actors: vec!["john", "mary", "phil"],
1034            thematic_relations: vec![
1035                ThetaRoles {
1036                    agent: Some("john"),
1037                    patient: Some("mary"),
1038                },
1039                ThetaRoles {
1040                    agent: Some("mary"),
1041                    patient: None,
1042                },
1043                ThetaRoles {
1044                    agent: None,
1045                    patient: Some("phil"),
1046                },
1047            ],
1048            properties: BTreeMap::default(),
1049        };
1050
1051        assert_eq!(
1052            scenario,
1053            *scenario_dataset_parser()
1054                .parse("\"john sees mary\" <john,mary,phil;{A: john,P: mary},{A: mary},{P: phil}>")
1055                .unwrap()
1056                .scenarios
1057                .first()
1058                .unwrap()
1059        );
1060
1061        let scenario = Scenario {
1062            question: vec![],
1063            actors: vec!["a", "b", "c"],
1064            thematic_relations: vec![
1065                ThetaRoles {
1066                    agent: None,
1067                    patient: None,
1068                },
1069                ThetaRoles {
1070                    agent: Some("a"),
1071                    patient: None,
1072                },
1073                ThetaRoles {
1074                    agent: None,
1075                    patient: Some("c"),
1076                },
1077            ],
1078            properties: BTreeMap::from_iter([
1079                ("Red", vec![Entity::Actor("a"), Entity::Actor("c")]),
1080                ("Green", vec![Entity::Event(0)]),
1081                ("Blue", vec![Entity::Actor("c"), Entity::Event(2)]),
1082            ]),
1083        };
1084
1085        assert_eq!(
1086            scenario,
1087            *scenario_dataset_parser()
1088                .parse("\"blue is blued\" <a (Red),b,c (Blue, Red);{(Green)},{A: a},{P: c (Blue)}>")
1089                .unwrap()
1090                .scenarios
1091                .first()
1092                .unwrap()
1093        );
1094        let s = serde_json::to_string(&scenario)?;
1095        let scenario_2: Scenario = serde_json::from_str(s.as_str())?;
1096        assert_eq!(scenario, scenario_2);
1097
1098        Ok(())
1099    }
1100}