pddl 0.2.0

A PDDL 3.1 parser, strongly typed
Documentation
//! Provides parsers for effects.

use nom::branch::alt;
use nom::combinator::map;
use nom::Parser;

use crate::parsers::{parse_c_effect, ParseResult, Span};
use crate::parsers::{prefix_expr, space_separated_list0};
use crate::types::Effects;

/// Parser for effects.
///
/// ## Example
/// ```
/// # use pddl::parsers::{parse_effect, preamble::*};
/// # use pddl::{AtomicFormula, ConditionalEffect, Effects, EqualityAtomicFormula, PrimitiveEffect, Term};
/// assert!(parse_effect("(= x y)").is_value(
///     Effects::new(
///         ConditionalEffect::Effect(
///             PrimitiveEffect::AtomicFormula(AtomicFormula::Equality(
///                 EqualityAtomicFormula::new(
///                     Term::Name("x".into()),
///                     Term::Name("y".into()))
///                 )
///             )
///         )
///     )
/// ));
/// assert!(parse_effect("(and (= x y) (not (= ?a B)))").is_value(
///     Effects::from_iter([
///         ConditionalEffect::Effect(
///             PrimitiveEffect::AtomicFormula(AtomicFormula::Equality(
///                 EqualityAtomicFormula::new(
///                     Term::Name("x".into()),
///                     Term::Name("y".into()))
///                 )
///             )
///         ),
///         ConditionalEffect::Effect(
///             PrimitiveEffect::NotAtomicFormula(AtomicFormula::Equality(
///                 EqualityAtomicFormula::new(
///                     Term::Variable("a".into()),
///                     Term::Name("B".into()))
///                 )
///             )
///         )
///     ])
/// ));
/// ```
pub fn parse_effect<'a, T: Into<Span<'a>>>(input: T) -> ParseResult<'a, Effects> {
    let exactly = map(parse_c_effect, Effects::from);
    let all = map(
        prefix_expr("and", space_separated_list0(parse_c_effect)),
        Effects::from,
    );

    alt((all, exactly)).parse(input.into())
}

impl crate::parsers::Parser for Effects {
    type Item = Effects;

    /// See [`parse_effect`].
    fn parse<'a, S: Into<Span<'a>>>(input: S) -> ParseResult<'a, Self::Item> {
        parse_effect(input)
    }
}

#[cfg(test)]
mod tests {
    use crate::parsers::UnwrapValue;
    use crate::{
        AtomicFormula, ConditionalEffect, Effects, EqualityAtomicFormula, Parser, PrimitiveEffect,
        Term,
    };

    #[test]
    fn test_parse() {
        assert!(
            Effects::parse("(= x y)").is_value(Effects::new(ConditionalEffect::Effect(
                PrimitiveEffect::AtomicFormula(AtomicFormula::Equality(
                    EqualityAtomicFormula::new(Term::Name("x".into()), Term::Name("y".into()))
                ))
            )))
        );
        assert!(
            Effects::parse("(and (= x y) (not (= ?a B)))").is_value(Effects::from_iter([
                ConditionalEffect::Effect(PrimitiveEffect::AtomicFormula(AtomicFormula::Equality(
                    EqualityAtomicFormula::new(Term::Name("x".into()), Term::Name("y".into()))
                ))),
                ConditionalEffect::Effect(PrimitiveEffect::NotAtomicFormula(
                    AtomicFormula::Equality(EqualityAtomicFormula::new(
                        Term::Variable("a".into()),
                        Term::Name("B".into())
                    ))
                ))
            ]))
        );
    }
}