1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
//! Provides parsers for atomic formulae.

use crate::parsers::parse_predicate;
use crate::parsers::{parens, space_separated_list0, ws};
use crate::types::AtomicFormula;
use nom::branch::alt;
use nom::bytes::complete::tag;
use nom::character::complete::{char, multispace1};
use nom::combinator::map;
use nom::sequence::{delimited, preceded, tuple};
use nom::IResult;

/// Parses an atomic formula, i.e. `(<predicate> t*) | (= t t)`.
///
/// ## Example
/// ```
/// # use nom::character::complete::alpha1;
/// # use pddl::parsers::atomic_formula;
/// # use pddl::parsers::parse_name;
/// # use pddl::{AtomicFormula, EqualityAtomicFormula, PredicateAtomicFormula, Predicate};
/// assert_eq!(atomic_formula(parse_name)("(= x y)"), Ok(("",
///     AtomicFormula::Equality(EqualityAtomicFormula::new("x".into(), "y".into()))
/// )));
/// assert_eq!(atomic_formula(parse_name)("(move a b)"), Ok(("",
///     AtomicFormula::Predicate(PredicateAtomicFormula::new(Predicate::from("move"), vec!["a".into(), "b".into()]))
/// )));
/// ```
pub fn atomic_formula<'a, F, O>(
    inner: F,
) -> impl FnMut(&'a str) -> IResult<&'a str, AtomicFormula<O>>
where
    F: Clone + FnMut(&'a str) -> IResult<&'a str, O>,
{
    let equality = map(
        delimited(
            tag("(="),
            preceded(
                multispace1,
                tuple((inner.clone(), preceded(multispace1, inner.clone()))),
            ),
            char(')'),
        ),
        |tuple| AtomicFormula::Equality(tuple.into()),
    );

    let predicate = map(
        parens(tuple((parse_predicate, ws(space_separated_list0(inner))))),
        |tuple| AtomicFormula::Predicate(tuple.into()),
    );

    alt((equality, predicate))
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::parsers::parse_term;

    #[test]
    fn it_works() {
        let input = "(can-move ?from-waypoint ?to-waypoint)";
        let (_, _effect) = atomic_formula(parse_term)(input).unwrap();
    }
}