pddl 0.2.0

A PDDL 3.1 parser, strongly typed
Documentation
//! Provides parsers for domain structure definitions.

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

use crate::parsers::{parse_action_def, parse_da_def, parse_derived_predicate, ParseResult, Span};
use crate::types::StructureDef;

/// Parses a domain structure definition.
///
/// ## Example
///
/// ```
/// # use pddl::parsers::{parse_structure_def, preamble::*};
/// # use pddl::{ActionDefinition, ActionSymbol, AtomicFormula, ConditionalEffect, Effects, GoalDefinition, Literal, PrimitiveEffect, Predicate, Preference, PreferenceGoalDefinition, PreconditionGoalDefinitions, StructureDef, Term, Variable};
/// # use pddl::{Name, ToTyped, TypedList};
/// let input = r#"(:action take-out
///                     :parameters (?x - physob)
///                     :precondition (not (= ?x B))
///                     :effect (not (in ?x))
///                 )"#;
///
/// let action = parse_structure_def(input);
///
/// assert!(action.is_value(
///     StructureDef::action(ActionDefinition::new(
///         ActionSymbol::from("take-out"),
///         TypedList::from_iter([
///             Variable::from("x").to_typed("physob")
///         ]),
///         PreconditionGoalDefinitions::preference(PreferenceGoalDefinition::from_gd(
///             GoalDefinition::not(
///                 GoalDefinition::atomic_formula(
///                     AtomicFormula::equality(
///                         Term::Variable(Variable::from("x")),
///                         Term::Name(Name::new("B"))
///                     )
///                 )
///             )
///         )),
///         Some(Effects::new(ConditionalEffect::new_primitive_effect(
///             PrimitiveEffect::NotAtomicFormula(
///                 AtomicFormula::predicate(
///                     Predicate::from("in"),
///                     vec![Term::Variable(Variable::from("x"))]
///                 )
///             )
///         )))
///     )
/// )));
/// ```
pub fn parse_structure_def<'a, T: Into<Span<'a>>>(input: T) -> ParseResult<'a, StructureDef> {
    let action = map(parse_action_def, StructureDef::new_action);
    // :durative-actions
    let durative = map(parse_da_def, StructureDef::new_durative_action);
    // :derived-predicates
    let derived = map(parse_derived_predicate, StructureDef::new_derived);
    alt((derived, action, durative)).parse(input.into())
}

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

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

#[cfg(test)]
mod tests {
    use crate::parsers::preamble::*;
    use crate::{
        ActionDefinition, ActionSymbol, AtomicFormula, ConditionalEffect, Effects, GoalDefinition,
        Name, PreconditionGoalDefinitions, Predicate, PreferenceGoalDefinition, PrimitiveEffect,
        StructureDef, Term, ToTyped, TypedList, Variable,
    };

    #[test]
    fn test_parse() {
        let input = r#"(:action take-out
                             :parameters (?x - physob)
                             :precondition (not (= ?x B))
                             :effect (not (in ?x))
                         )"#;

        let action = StructureDef::parse(input);

        assert!(action.is_value(StructureDef::action(ActionDefinition::new(
            ActionSymbol::from("take-out"),
            TypedList::from_iter([Variable::from("x").to_typed("physob")]),
            PreconditionGoalDefinitions::preference(PreferenceGoalDefinition::from_gd(
                GoalDefinition::not(GoalDefinition::atomic_formula(AtomicFormula::equality(
                    Term::Variable(Variable::from("x")),
                    Term::Name(Name::new("B"))
                )))
            )),
            Some(Effects::new(ConditionalEffect::new_primitive_effect(
                PrimitiveEffect::NotAtomicFormula(AtomicFormula::predicate(
                    Predicate::from("in"),
                    vec![Term::Variable(Variable::from("x"))]
                ))
            )))
        ))));
    }
}