use crate::parsers::{parens, space_separated_list0, ws};
use crate::parsers::{parse_predicate, ParseResult, Span};
use crate::types::AtomicFormula;
use nom::branch::alt;
use nom::bytes::complete::tag;
use nom::character::complete::char;
use nom::combinator::map;
use nom::sequence::{delimited, tuple};
pub fn atomic_formula<'a, F, O>(
inner: F,
) -> impl FnMut(Span<'a>) -> ParseResult<'a, AtomicFormula<O>>
where
F: Clone + FnMut(Span<'a>) -> ParseResult<'a, O>,
{
let equality = map(
delimited(
ws(tag("(=")),
tuple((ws(inner.clone()), ws(inner.clone()))),
ws(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_name, parse_term, UnwrapValue};
use crate::{EqualityAtomicFormula, Predicate, PredicateAtomicFormula};
#[test]
fn it_works() {
let input = "(can-move ?from-waypoint ?to-waypoint)";
let (_, _effect) = atomic_formula(parse_term)(Span::new(input)).unwrap();
}
#[test]
fn test_parse() {
assert!(atomic_formula(parse_name)(Span::new("(= x y)")).is_value(
AtomicFormula::Equality(EqualityAtomicFormula::new("x".into(), "y".into()))
));
assert!(
atomic_formula(parse_name)(Span::new("(move a b)")).is_value(AtomicFormula::Predicate(
PredicateAtomicFormula::new(Predicate::from("move"), vec!["a".into(), "b".into()])
))
);
}
}