Skip to main content

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| {
257                        RootedLambdaPool::parse(x).map_err(|e| Rich::custom(s, e.to_string()))
258                    })
259                    .separated_by(just(';'))
260                    .collect::<Vec<_>>(),
261            )
262            .or_not(),
263    );
264
265    scenario.map(|(mut scenario, questions)| {
266        if let Some(question) = questions {
267            scenario.question = question;
268        }
269        scenario
270    })
271}
272
273pub fn string_scenario_parser<'a>()
274-> impl Parser<'a, &'a str, (Vec<&'a str>, Scenario<'a>), extra::Err<Rich<'a, char>>> {
275    none_of("\"")
276        .repeated()
277        .to_slice()
278        .delimited_by(just('"'), just('"'))
279        .map(|x: &str| x.split(' ').collect::<Vec<_>>())
280        .then_ignore(inline_whitespace().at_least(1))
281        .then(scenario_parser())
282}
283
284pub fn scenario_dataset_parser<'a>()
285-> impl Parser<'a, &'a str, ScenarioDataset<'a>, extra::Err<Rich<'a, char>>> {
286    string_scenario_parser()
287        //this handles repeated empty lines by chunking them together
288        .separated_by(text::newline().repeated().at_least(1))
289        .at_least(1)
290        .collect::<Vec<_>>()
291        .map(|v| {
292            let mut scenarios = vec![];
293            let mut sentences = vec![];
294            for (a, b) in v {
295                sentences.push(a);
296                scenarios.push(b);
297            }
298            ScenarioDataset::new(scenarios, sentences).unwrap()
299        })
300        .padded()
301        .then_ignore(end())
302}
303
304type EventParseType<'a> = Option<(Vec<ThetaRoles<'a>>, BTreeMap<&'a str, Vec<Entity<'a>>>)>;
305
306fn new_scenario<'a>(
307    actors: Vec<Actor<'a>>,
308    actor_props: BTreeMap<&'a str, Vec<&'a str>>,
309    events: EventParseType<'a>,
310) -> Scenario<'a> {
311    let (events, event_props) = events.unwrap_or_else(|| (Vec::default(), BTreeMap::default()));
312
313    let mut properties: BTreeMap<&str, Vec<Entity>> = actor_props
314        .into_iter()
315        .map(|(k, v)| (k, v.into_iter().map(Entity::Actor).collect()))
316        .collect();
317
318    for (k, mut v) in event_props {
319        properties
320            .entry(k)
321            .and_modify(|value| value.append(&mut v))
322            .or_insert(v);
323    }
324
325    Scenario {
326        question: vec![],
327        actors,
328        thematic_relations: events,
329        properties,
330    }
331}
332
333mod utilities;
334use utilities::SetCounter;
335
336///Generates all scenarios that can be generated with a given set of primitives
337#[derive(Debug, Clone)]
338pub struct ScenarioIterator<'a> {
339    actors: ActorSetGenerator<'a>,
340    current_actors: Vec<Actor<'a>>,
341    current_props: BTreeMap<PropertyLabel<'a>, Vec<Entity<'a>>>,
342    current_event_set: Vec<(ThetaRoles<'a>, PropertyLabel<'a>)>,
343    event_kinds: Vec<PossibleEvent<'a>>,
344    counter: SetCounter,
345    max_number_of_events: Option<usize>,
346}
347
348///The kinds of possible events
349#[derive(Debug, Clone, Eq, PartialEq, Copy, Ord, PartialOrd, Hash, Serialize, Deserialize)]
350pub enum EventType {
351    ///An intransitive with only an agent
352    Unergative,
353
354    ///An intransitive with only a patient
355    Unaccusative,
356
357    ///A transitive verb which cannot be reflexive
358    TransitiveNonReflexive,
359
360    ///A transitive verb
361    Transitive,
362
363    ///No possible theta role (e.g. rains)
364    Avalent,
365}
366
367///A description of a possible kind of event (e.g. kind of verb)
368#[derive(Debug, Clone, Eq, PartialEq, Copy, Ord, PartialOrd, Hash, Serialize, Deserialize)]
369pub struct PossibleEvent<'a> {
370    ///Name of the event predicate
371    #[serde(borrow)]
372    pub label: PropertyLabel<'a>,
373    ///What kind of theta roles can be assigned to this event
374    pub event_type: EventType,
375}
376
377impl<'a> Scenario<'a> {
378    ///Returns a [`ScenarioIterator`] which goes over all possible scenarios with the provided
379    ///actors and event descriptions
380    ///
381    ///# Panics
382    ///Will panic if there are `actors` is empty
383    ///
384    #[must_use]
385    pub fn all_scenarios(
386        actors: &[Actor<'a>],
387        event_kinds: &[PossibleEvent<'a>],
388        actor_properties: &[PropertyLabel<'a>],
389        max_number_of_events: Option<usize>,
390        max_number_of_actors: Option<usize>,
391        max_number_of_properties: Option<usize>,
392    ) -> ScenarioIterator<'a> {
393        let mut actors = ActorSetGenerator::new(
394            actors,
395            actor_properties,
396            max_number_of_actors,
397            max_number_of_properties,
398        );
399        let (current_actors, current_props) = actors.next().unwrap();
400        let current_event_set = generate_all_events(&current_actors, event_kinds);
401        let counter = SetCounter::new(current_event_set.len(), max_number_of_events);
402
403        ScenarioIterator {
404            actors,
405            current_actors,
406            current_event_set,
407            current_props,
408            event_kinds: event_kinds.to_vec(),
409            counter,
410            max_number_of_events,
411        }
412    }
413}
414
415impl<'a> Iterator for ScenarioIterator<'a> {
416    type Item = Scenario<'a>;
417
418    fn next(&mut self) -> Option<Self::Item> {
419        if self.counter.done() {
420            if let Some((new_actors, new_props)) = self.actors.next() {
421                self.current_actors = new_actors;
422                self.current_props = new_props;
423                self.current_event_set =
424                    generate_all_events(&self.current_actors, &self.event_kinds);
425                self.counter =
426                    SetCounter::new(self.current_event_set.len(), self.max_number_of_events);
427            } else {
428                return None;
429            }
430        }
431
432        let mut properties = self.current_props.clone();
433        let mut thematic_relations = vec![];
434        for (i, (theta, label)) in self
435            .counter
436            .as_set(self.current_event_set.iter().copied())
437            .enumerate()
438        {
439            properties
440                .entry(label)
441                .or_default()
442                .push(Entity::Event(Event::try_from(i).expect("Too many events!")));
443            thematic_relations.push(theta);
444        }
445        self.counter.increment();
446        Some(Scenario::new(
447            self.current_actors.clone(),
448            thematic_relations,
449            properties,
450        ))
451    }
452}
453
454fn generate_all_events<'a>(
455    actors: &[Actor<'a>],
456    event_kinds: &[PossibleEvent<'a>],
457) -> Vec<(ThetaRoles<'a>, PropertyLabel<'a>)> {
458    let mut all_events = vec![];
459    for e in event_kinds {
460        match e.event_type {
461            EventType::Unergative => all_events.extend(actors.iter().copied().map(|x| {
462                (
463                    ThetaRoles {
464                        agent: Some(x),
465                        patient: None,
466                    },
467                    e.label,
468                )
469            })),
470            EventType::Unaccusative => all_events.extend(actors.iter().copied().map(|x| {
471                (
472                    ThetaRoles {
473                        agent: None,
474                        patient: Some(x),
475                    },
476                    e.label,
477                )
478            })),
479            EventType::TransitiveNonReflexive => {
480                all_events.extend(actors.iter().copied().permutations(2).map(|mut x| {
481                    let a = x.pop().unwrap();
482                    let b = x.pop().unwrap();
483                    (
484                        ThetaRoles {
485                            agent: Some(a),
486                            patient: Some(b),
487                        },
488                        e.label,
489                    )
490                }));
491            }
492            EventType::Transitive => all_events.extend(
493                itertools::repeat_n(actors.iter().copied(), 2)
494                    .multi_cartesian_product()
495                    .map(|mut x| {
496                        let a = x.pop().unwrap();
497                        let b = x.pop().unwrap();
498                        (
499                            ThetaRoles {
500                                agent: Some(a),
501                                patient: Some(b),
502                            },
503                            e.label,
504                        )
505                    }),
506            ),
507            EventType::Avalent => {
508                all_events.push((
509                    ThetaRoles {
510                        agent: None,
511                        patient: None,
512                    },
513                    e.label,
514                ));
515            }
516        }
517    }
518
519    all_events
520}
521
522#[derive(Debug, Clone)]
523struct ActorSetGenerator<'a> {
524    actors: Vec<Actor<'a>>,
525    actor_properties: Vec<PropertyLabel<'a>>,
526    property_counter: MultiProduct<SetCounter>,
527    max_number_of_properties: Option<usize>,
528    included: SetCounter,
529}
530
531impl<'a> ActorSetGenerator<'a> {
532    fn new(
533        actors: &[Actor<'a>],
534        actor_properties: &[PropertyLabel<'a>],
535        max_number_of_actors: Option<usize>,
536        max_number_of_properties: Option<usize>,
537    ) -> Self {
538        ActorSetGenerator {
539            property_counter: std::iter::empty::<SetCounter>().multi_cartesian_product(),
540            included: SetCounter::new(actors.len(), max_number_of_actors),
541            actors: actors.to_vec(),
542            max_number_of_properties,
543            actor_properties: actor_properties.to_vec(),
544        }
545    }
546}
547
548impl<'a> Iterator for ActorSetGenerator<'a> {
549    type Item = (Vec<Actor<'a>>, BTreeMap<PropertyLabel<'a>, Vec<Entity<'a>>>);
550
551    fn next(&mut self) -> Option<Self::Item> {
552        let props = self.property_counter.next().unwrap_or_else(|| {
553            self.included.increment();
554            let n_actors = self.included.current_size();
555            self.property_counter = (0..n_actors)
556                .map(|_| {
557                    SetCounter::new(self.actor_properties.len(), self.max_number_of_properties)
558                })
559                .multi_cartesian_product();
560            self.property_counter.next().unwrap()
561        });
562
563        if self.included.done() {
564            return None;
565        }
566
567        let mut actor_properties: BTreeMap<_, Vec<_>> = BTreeMap::new();
568
569        let actors: Vec<Actor<'a>> = self
570            .included
571            .included()
572            .as_set(&self.actors)
573            .copied()
574            .zip(props)
575            .map(|(x, props)| {
576                for prop in props.as_set(&self.actor_properties) {
577                    actor_properties
578                        .entry(*prop)
579                        .or_default()
580                        .push(Entity::Actor(x));
581                }
582                x
583            })
584            .collect();
585
586        Some((actors, actor_properties))
587    }
588}
589
590#[cfg(test)]
591mod test {
592    use crate::scenario::generate_all_events;
593
594    use super::*;
595    use ahash::HashSet;
596
597    #[test]
598    fn generate_all_actors() {
599        let s = ActorSetGenerator::new(&["John", "Mary"], &["man", "woman"], None, None);
600
601        let mut set = HashSet::default();
602        for p in s {
603            println!("{p:?}");
604            assert!(!set.contains(&p));
605            set.insert(p);
606        }
607        assert_eq!(set.len(), 25);
608    }
609
610    #[test]
611    fn generate_all_scenarios() {
612        let actors = ["John", "Mary"];
613        let event_kinds = [
614            PossibleEvent {
615                label: "rain",
616                event_type: EventType::Avalent,
617            },
618            PossibleEvent {
619                label: "runs",
620                event_type: EventType::Unergative,
621            },
622            PossibleEvent {
623                label: "falls",
624                event_type: EventType::Unaccusative,
625            },
626            PossibleEvent {
627                label: "loves",
628                event_type: EventType::TransitiveNonReflexive,
629            },
630        ];
631
632        let mut scenarios = HashSet::default();
633        for x in Scenario::all_scenarios(&actors, &event_kinds, &["man", "woman"], None, None, None)
634        {
635            assert!(!scenarios.contains(&x));
636            scenarios.insert(x);
637        }
638        assert_eq!(scenarios.len(), 2114);
639
640        let mut scenarios = HashSet::default();
641        let mut at_least_1 = false;
642        let mut at_least_2 = false;
643        for x in Scenario::all_scenarios(
644            &actors,
645            &event_kinds,
646            &["man", "woman"],
647            Some(2),
648            Some(1),
649            None,
650        ) {
651            assert!(!scenarios.contains(&x));
652            assert!(x.actors.len() <= 1);
653            if x.actors.len() == 1 {
654                at_least_1 = true;
655            }
656
657            if x.events().count() == 2 {
658                at_least_2 = true;
659            }
660            assert!(x.events().count() <= 2);
661            scenarios.insert(x);
662        }
663
664        assert!(at_least_1);
665        assert!(at_least_2);
666        assert_eq!(scenarios.len(), 58);
667    }
668
669    #[test]
670    fn generate_event_test() {
671        let actors = ["John", "Mary", "Phil"];
672        let event_kinds = [
673            PossibleEvent {
674                label: "rain",
675                event_type: EventType::Avalent,
676            },
677            PossibleEvent {
678                label: "runs",
679                event_type: EventType::Unergative,
680            },
681            PossibleEvent {
682                label: "falls",
683                event_type: EventType::Unaccusative,
684            },
685            PossibleEvent {
686                label: "likes",
687                event_type: EventType::Transitive,
688            },
689            PossibleEvent {
690                label: "loves",
691                event_type: EventType::TransitiveNonReflexive,
692            },
693        ];
694
695        let e = generate_all_events(&actors, &event_kinds);
696
697        assert_eq!(
698            e,
699            [
700                (
701                    ThetaRoles {
702                        agent: None,
703                        patient: None
704                    },
705                    "rain"
706                ),
707                (
708                    ThetaRoles {
709                        agent: Some("John"),
710                        patient: None
711                    },
712                    "runs"
713                ),
714                (
715                    ThetaRoles {
716                        agent: Some("Mary"),
717                        patient: None
718                    },
719                    "runs"
720                ),
721                (
722                    ThetaRoles {
723                        agent: Some("Phil"),
724                        patient: None
725                    },
726                    "runs"
727                ),
728                (
729                    ThetaRoles {
730                        agent: None,
731                        patient: Some("John")
732                    },
733                    "falls"
734                ),
735                (
736                    ThetaRoles {
737                        agent: None,
738                        patient: Some("Mary")
739                    },
740                    "falls"
741                ),
742                (
743                    ThetaRoles {
744                        agent: None,
745                        patient: Some("Phil")
746                    },
747                    "falls"
748                ),
749                (
750                    ThetaRoles {
751                        agent: Some("John"),
752                        patient: Some("John")
753                    },
754                    "likes"
755                ),
756                (
757                    ThetaRoles {
758                        agent: Some("Mary"),
759                        patient: Some("John")
760                    },
761                    "likes"
762                ),
763                (
764                    ThetaRoles {
765                        agent: Some("Phil"),
766                        patient: Some("John")
767                    },
768                    "likes"
769                ),
770                (
771                    ThetaRoles {
772                        agent: Some("John"),
773                        patient: Some("Mary")
774                    },
775                    "likes"
776                ),
777                (
778                    ThetaRoles {
779                        agent: Some("Mary"),
780                        patient: Some("Mary")
781                    },
782                    "likes"
783                ),
784                (
785                    ThetaRoles {
786                        agent: Some("Phil"),
787                        patient: Some("Mary")
788                    },
789                    "likes"
790                ),
791                (
792                    ThetaRoles {
793                        agent: Some("John"),
794                        patient: Some("Phil")
795                    },
796                    "likes"
797                ),
798                (
799                    ThetaRoles {
800                        agent: Some("Mary"),
801                        patient: Some("Phil")
802                    },
803                    "likes"
804                ),
805                (
806                    ThetaRoles {
807                        agent: Some("Phil"),
808                        patient: Some("Phil")
809                    },
810                    "likes"
811                ),
812                (
813                    ThetaRoles {
814                        agent: Some("Mary"),
815                        patient: Some("John")
816                    },
817                    "loves"
818                ),
819                (
820                    ThetaRoles {
821                        agent: Some("Phil"),
822                        patient: Some("John")
823                    },
824                    "loves"
825                ),
826                (
827                    ThetaRoles {
828                        agent: Some("John"),
829                        patient: Some("Mary")
830                    },
831                    "loves"
832                ),
833                (
834                    ThetaRoles {
835                        agent: Some("Phil"),
836                        patient: Some("Mary")
837                    },
838                    "loves"
839                ),
840                (
841                    ThetaRoles {
842                        agent: Some("John"),
843                        patient: Some("Phil")
844                    },
845                    "loves"
846                ),
847                (
848                    ThetaRoles {
849                        agent: Some("Mary"),
850                        patient: Some("Phil")
851                    },
852                    "loves"
853                )
854            ]
855        );
856    }
857
858    #[test]
859    #[should_panic]
860    fn parse_trailing() {
861        scenario_dataset_parser().parse("<John>trailing").unwrap();
862    }
863
864    #[test]
865    fn white_space_shenanigans() -> anyhow::Result<()> {
866        scenario_dataset_parser()
867            .parse("\"blah\" <John; {A: John (run)}>")
868            .unwrap();
869        scenario_dataset_parser()
870            .parse("\" s\" <John ; {A: John (run)}>")
871            .unwrap();
872        scenario_dataset_parser()
873            .parse("\"\" < John ; { A : John (run)}>")
874            .unwrap();
875        scenario_dataset_parser()
876            .parse("\"aaa\"      < John ; { A :  John ( run )  } >")
877            .unwrap();
878        scenario_dataset_parser()
879            .parse("\"aaa\" < John; {A: John ( run)}>")
880            .unwrap();
881        Ok(())
882    }
883
884    #[test]
885    fn parse_multiple_scenarios() -> anyhow::Result<()> {
886        let scenarios = vec![
887            Scenario {
888                question: vec![],
889                actors: vec!["John"],
890                thematic_relations: vec![],
891                properties: BTreeMap::default(),
892            },
893            Scenario {
894                question: vec![],
895                actors: vec!["Mary"],
896                thematic_relations: vec![],
897                properties: BTreeMap::default(),
898            },
899            Scenario {
900                question: vec![],
901                actors: vec!["John"],
902                thematic_relations: vec![],
903                properties: BTreeMap::default(),
904            },
905        ];
906
907        assert_eq!(
908            scenarios,
909            *scenario_dataset_parser()
910                .parse("\"John\" <John>\n\"Mary\" <Mary>\n\"John\" <John>")
911                .unwrap()
912                .scenarios
913        );
914
915        let scenarios = vec![
916            Scenario {
917                question: vec![],
918                actors: vec!["John"],
919                thematic_relations: vec![ThetaRoles {
920                    agent: Some("John"),
921                    patient: None,
922                }],
923                properties: BTreeMap::from_iter([("run", vec![Entity::Event(0)])]),
924            },
925            Scenario {
926                question: vec![],
927                actors: vec!["Mary"],
928                thematic_relations: vec![ThetaRoles {
929                    agent: Some("Mary"),
930                    patient: None,
931                }],
932                properties: BTreeMap::from_iter([("run", vec![Entity::Event(0)])]),
933            },
934            Scenario {
935                question: vec![],
936                actors: vec!["Mary", "John"],
937                thematic_relations: vec![ThetaRoles {
938                    agent: Some("John"),
939                    patient: Some("Mary"),
940                }],
941                properties: BTreeMap::from_iter([("see", vec![Entity::Event(0)])]),
942            },
943        ];
944
945        assert_eq!(
946            scenarios,
947            *scenario_dataset_parser()
948                .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)}>")
949                .unwrap()
950                .scenarios
951        );
952        Ok(())
953    }
954
955    #[test]
956    fn parse_scenarios_with_questions() -> anyhow::Result<()> {
957        let scenarios = scenario_dataset_parser()
958                .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")
959                .unwrap();
960
961        assert_eq!(
962            scenarios.scenarios[0].question.first().unwrap().to_string(),
963            "lambda a x x"
964        );
965        assert_eq!(scenarios.scenarios[1].question, vec![]);
966        assert_eq!(
967            scenarios.scenarios[2].question.first().unwrap().to_string(),
968            "a_0"
969        );
970
971        let scenarios = scenario_dataset_parser()
972                .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")
973                .unwrap();
974        assert_eq!(scenarios.scenarios[2].question.len(), 3);
975
976        assert_eq!(
977            scenarios.scenarios[2].question.last().unwrap().to_string(),
978            "a_3"
979        );
980        Ok(())
981    }
982
983    #[test]
984    fn parse_scenario() -> anyhow::Result<()> {
985        let scenario = Scenario {
986            question: vec![],
987            actors: vec!["John"],
988            thematic_relations: vec![],
989            properties: BTreeMap::default(),
990        };
991
992        assert_eq!(
993            scenario,
994            *scenario_dataset_parser()
995                .parse("\"John\" <John>")
996                .unwrap()
997                .scenarios
998                .first()
999                .unwrap()
1000        );
1001        assert_eq!(
1002            scenario,
1003            *scenario_dataset_parser()
1004                .parse("\"John\" <John;>")
1005                .unwrap()
1006                .scenarios
1007                .first()
1008                .unwrap()
1009        );
1010        assert_eq!(
1011            scenario,
1012            *scenario_dataset_parser()
1013                .parse("\"John\" < John; >")
1014                .unwrap()
1015                .scenarios
1016                .first()
1017                .unwrap()
1018        );
1019
1020        let scenario = Scenario {
1021            question: vec![],
1022            actors: vec!["john"],
1023            thematic_relations: vec![ThetaRoles {
1024                agent: None,
1025                patient: None,
1026            }],
1027            properties: BTreeMap::default(),
1028        };
1029        assert_eq!(
1030            scenario,
1031            *scenario_dataset_parser()
1032                .parse("\"john\" <john;{}>")
1033                .unwrap()
1034                .scenarios
1035                .first()
1036                .unwrap()
1037        );
1038
1039        let scenario = Scenario {
1040            question: vec![],
1041            actors: vec!["john", "mary", "phil"],
1042            thematic_relations: vec![
1043                ThetaRoles {
1044                    agent: Some("john"),
1045                    patient: Some("mary"),
1046                },
1047                ThetaRoles {
1048                    agent: Some("mary"),
1049                    patient: None,
1050                },
1051                ThetaRoles {
1052                    agent: None,
1053                    patient: Some("phil"),
1054                },
1055            ],
1056            properties: BTreeMap::default(),
1057        };
1058
1059        assert_eq!(
1060            scenario,
1061            *scenario_dataset_parser()
1062                .parse("\"john sees mary\" <john,mary,phil;{A: john,P: mary},{A: mary},{P: phil}>")
1063                .unwrap()
1064                .scenarios
1065                .first()
1066                .unwrap()
1067        );
1068
1069        let scenario = Scenario {
1070            question: vec![],
1071            actors: vec!["a", "b", "c"],
1072            thematic_relations: vec![
1073                ThetaRoles {
1074                    agent: None,
1075                    patient: None,
1076                },
1077                ThetaRoles {
1078                    agent: Some("a"),
1079                    patient: None,
1080                },
1081                ThetaRoles {
1082                    agent: None,
1083                    patient: Some("c"),
1084                },
1085            ],
1086            properties: BTreeMap::from_iter([
1087                ("Red", vec![Entity::Actor("a"), Entity::Actor("c")]),
1088                ("Green", vec![Entity::Event(0)]),
1089                ("Blue", vec![Entity::Actor("c"), Entity::Event(2)]),
1090            ]),
1091        };
1092
1093        assert_eq!(
1094            scenario,
1095            *scenario_dataset_parser()
1096                .parse("\"blue is blued\" <a (Red),b,c (Blue, Red);{(Green)},{A: a},{P: c (Blue)}>")
1097                .unwrap()
1098                .scenarios
1099                .first()
1100                .unwrap()
1101        );
1102        let s = serde_json::to_string(&scenario)?;
1103        let scenario_2: Scenario = serde_json::from_str(s.as_str())?;
1104        assert_eq!(scenario, scenario_2);
1105
1106        Ok(())
1107    }
1108}