├── .github └── workflows │ └── rust.yml ├── .gitignore ├── CHANGELOG.md ├── Cargo.toml ├── ELEMENTS.md ├── LICENSE.md ├── README.md ├── src ├── lib.rs ├── parsers │ ├── action_def.rs │ ├── action_symbol.rs │ ├── assign_op.rs │ ├── assign_op_t.rs │ ├── atomic_formula.rs │ ├── atomic_formula_skeleton.rs │ ├── atomic_function_skeleton.rs │ ├── basic_function_term.rs │ ├── binary_comp.rs │ ├── binary_op.rs │ ├── c_effect.rs │ ├── comments.rs │ ├── con_gd.rs │ ├── cond_effect.rs │ ├── constants_def.rs │ ├── d_op.rs │ ├── d_value.rs │ ├── da_def.rs │ ├── da_effect.rs │ ├── da_gd.rs │ ├── da_symbol.rs │ ├── derived_predicate.rs │ ├── domain.rs │ ├── domain_constraints_def.rs │ ├── duration_constraint.rs │ ├── effects.rs │ ├── empty_or.rs │ ├── f_assign_da.rs │ ├── f_comp.rs │ ├── f_exp.rs │ ├── f_exp_da.rs │ ├── f_exp_t.rs │ ├── f_head.rs │ ├── function_symbol.rs │ ├── function_term.rs │ ├── function_type.rs │ ├── function_typed_list.rs │ ├── functions_def.rs │ ├── gd.rs │ ├── goal_def.rs │ ├── init_def.rs │ ├── init_el.rs │ ├── interval.rs │ ├── length_spec.rs │ ├── literal.rs │ ├── metric_f_exp.rs │ ├── metric_spec.rs │ ├── mod.rs │ ├── multi_op.rs │ ├── name.rs │ ├── number.rs │ ├── objects_def.rs │ ├── optimization.rs │ ├── p_effect.rs │ ├── pre_gd.rs │ ├── predicate.rs │ ├── predicates_def.rs │ ├── pref_con_gd.rs │ ├── pref_gd.rs │ ├── pref_name.rs │ ├── pref_timed_gd.rs │ ├── primitive_type.rs │ ├── problem.rs │ ├── problem_constraints_def.rs │ ├── requirements.rs │ ├── simple_duration_constraint.rs │ ├── structure_def.rs │ ├── term.rs │ ├── test_helpers.rs │ ├── time_specifier.rs │ ├── timed_effect.rs │ ├── timed_gd.rs │ ├── timeless_def.rs │ ├── type.rs │ ├── typed_list.rs │ ├── types_def.rs │ ├── utilities.rs │ └── variable.rs ├── types │ ├── action_definition.rs │ ├── action_symbols.rs │ ├── assign_op.rs │ ├── assign_op_t.rs │ ├── atomic_formula.rs │ ├── atomic_formula_skeleton.rs │ ├── atomic_function_skeleton.rs │ ├── basic_function_term.rs │ ├── binary_comp.rs │ ├── binary_op.rs │ ├── c_effect.rs │ ├── con_gd.rs │ ├── conditional_effect.rs │ ├── constants.rs │ ├── d_op.rs │ ├── d_value.rs │ ├── da_def.rs │ ├── da_effect.rs │ ├── da_gd.rs │ ├── da_symbol.rs │ ├── derived_predicate.rs │ ├── domain.rs │ ├── domain_constraints_def.rs │ ├── duration_constraint.rs │ ├── effects.rs │ ├── f_assign_da.rs │ ├── f_comp.rs │ ├── f_exp.rs │ ├── f_exp_da.rs │ ├── f_exp_t.rs │ ├── f_head.rs │ ├── function_symbols.rs │ ├── function_term.rs │ ├── function_type.rs │ ├── function_typed.rs │ ├── function_typed_list.rs │ ├── functions.rs │ ├── gd.rs │ ├── goal_def.rs │ ├── init_el.rs │ ├── init_els.rs │ ├── interval.rs │ ├── iterators.rs │ ├── length_spec.rs │ ├── literal.rs │ ├── metric_f_exp.rs │ ├── metric_spec.rs │ ├── mod.rs │ ├── multi_op.rs │ ├── name.rs │ ├── number.rs │ ├── objects.rs │ ├── optimization.rs │ ├── p_effect.rs │ ├── pre_gd.rs │ ├── predicate.rs │ ├── predicate_definitions.rs │ ├── pref_con_gd.rs │ ├── pref_gd.rs │ ├── pref_name.rs │ ├── pref_timed_gd.rs │ ├── preference.rs │ ├── problem.rs │ ├── problem_constraints_def.rs │ ├── requirement.rs │ ├── requirements.rs │ ├── simple_duration_constraint.rs │ ├── structure_def.rs │ ├── structure_defs.rs │ ├── term.rs │ ├── time_specifier.rs │ ├── timed_effect.rs │ ├── timed_gd.rs │ ├── timeless.rs │ ├── type.rs │ ├── typed.rs │ ├── typed_list.rs │ ├── types.rs │ └── variable.rs └── visitor.rs ├── tea.yaml └── tests └── briefcase_world.rs /.github/workflows/rust.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Rust 3 | 4 | on: 5 | push: 6 | branches: [ "main" ] 7 | paths: 8 | - 'Cargo.toml' 9 | - 'Cargo.lock' 10 | - 'src/**' 11 | - '.github/workflows/rust.yml' 12 | pull_request: 13 | branches: [ "main" ] 14 | paths: 15 | - 'Cargo.toml' 16 | - 'Cargo.lock' 17 | - 'src/**' 18 | - '.github/workflows/rust.yml' 19 | 20 | env: 21 | CARGO_TERM_COLOR: always 22 | 23 | jobs: 24 | build: 25 | name: Build and Test 26 | runs-on: ${{ matrix.os }} 27 | strategy: 28 | matrix: 29 | os: [ ubuntu-latest, macos-latest, windows-latest ] 30 | steps: 31 | - uses: actions/checkout@v4 32 | - name: Check format 33 | run: cargo fmt --check 34 | - name: Build 35 | run: cargo build --verbose 36 | - uses: taiki-e/install-action@nextest 37 | - name: Run tests 38 | run: cargo nextest run --verbose --all-features 39 | - name: Run doctests 40 | run: cargo test --doc --verbose --all-features 41 | 42 | codecov: 43 | name: Code Coverage 44 | runs-on: ubuntu-latest 45 | steps: 46 | - uses: actions/checkout@v4 47 | - name: Build 48 | run: cargo build --verbose 49 | - uses: dtolnay/rust-toolchain@stable 50 | with: 51 | components: llvm-tools-preview 52 | - name: Install cargo-llvm-cov 53 | uses: taiki-e/install-action@cargo-llvm-cov 54 | - name: Install nextest 55 | uses: taiki-e/install-action@nextest 56 | - name: Generate code coverage 57 | run: cargo llvm-cov nextest --all-features --workspace --lcov --output-path lcov.info 58 | - name: Upload coverage to Codecov 59 | uses: codecov/codecov-action@v4.0.1 60 | with: 61 | token: ${{ secrets.CODECOV_TOKEN }} 62 | files: lcov.info 63 | fail_ci_if_error: true 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /Cargo.lock 3 | /.idea 4 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "pddl" 3 | version = "0.1.0" 4 | description = "A PDDL 3.1 parser, strongly typed" 5 | license = "EUPL-1.2" 6 | documentation = "https://docs.rs/pddl" 7 | categories = ["parser-implementations", "science", "simulation"] 8 | keywords = ["pddl", "planning", "parser"] 9 | repository = "https://github.com/sunsided/pddl-rs" 10 | readme = "README.md" 11 | authors = ["Markus Mayer "] 12 | edition = "2021" 13 | rust-version = "1.68.0" 14 | 15 | [features] 16 | default = ["parser", "interning"] 17 | parser = ["dep:nom", "dep:nom-greedyerror", "dep:nom_locate", "dep:thiserror"] 18 | interning = ["dep:lazy_static"] 19 | 20 | [dependencies] 21 | lazy_static = { version = "1.4.0", optional = true } 22 | nom = { version = "7.1.3", optional = true } 23 | nom-greedyerror = { version = "0.5.0", optional = true } 24 | nom_locate = { version = "4.2.0", optional = true } 25 | thiserror = { version = "1.0.61", optional = true } 26 | 27 | [package.metadata.docs.rs] 28 | all-features = true 29 | rustdoc-args = ["--cfg", "docsrs"] 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # A PDDL 3.1 parser, strongly typed 2 | 3 | A parser for the Planning Domain Definition Language version 3.1: written in Rust, based on [nom](https://crates.io/crates/nom). 4 | 5 | ![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/sunsided/pddl-rs/rust.yml) 6 | ![docs.rs](https://img.shields.io/docsrs/pddl) 7 | [![codecov](https://codecov.io/gh/sunsided/pddl-rs/graph/badge.svg?token=8H8K6HW6AF)](https://codecov.io/gh/sunsided/pddl-rs) 8 | ![Crates.io](https://img.shields.io/crates/v/pddl) 9 | ![Crates.io](https://img.shields.io/crates/l/pddl) 10 | 11 | Crate documentation is available on [docs.rs/pddl](https://docs.rs/pddl). 12 | 13 | ```toml 14 | [dependencies] 15 | pddl = "*" 16 | ``` 17 | 18 | The domain/problem types can be used independently of the parser; the parser 19 | is however enabled by default via the `parser` crate feature. 20 | To disable the parser and its dependencies, use 21 | 22 | ```toml 23 | [dependencies] 24 | pddl = { version = "*", default-features = false } 25 | ``` 26 | 27 | Documentation comments are assembled from the PDDL papers and [nergmada/planning-wiki](https://github.com/nergmada/planning-wiki). 28 | 29 | ## Usage Example 30 | 31 | See [`tests/briefcase_world.rs`](tests/briefcase_world.rs) for the full example. 32 | 33 | ```rust 34 | use pddl::{Problem, Parser}; 35 | 36 | pub const BRIEFCASE_WORLD_PROBLEM: &'static str = r#" 37 | (define (problem get-paid) 38 | (:domain briefcase-world) 39 | (:init (place home) (place office) ; place types 40 | (object p) (object d) (object b) ; object types 41 | (at B home) (at P home) (at D home) (in P)) ; setup 42 | (:goal (and (at B office) (at D office) (at P home))) 43 | ) 44 | "#; 45 | 46 | fn main() { 47 | let problem = Problem::from_str(BRIEFCASE_WORLD_PROBLEM).unwrap(); 48 | 49 | assert_eq!(problem.name(), "get-paid"); 50 | assert_eq!(problem.domain(), "briefcase-world"); 51 | assert!(problem.requirements().is_empty()); 52 | assert_eq!(problem.init().len(), 9); 53 | assert_eq!(problem.goal().len(), 3); 54 | } 55 | ``` 56 | 57 | ### Caveat Emptor 58 | 59 | At this point the parser supports all domain and problem definition 60 | elements required to fully describe a PDDL 3.1 environment. 61 | However, since types and enum variants are named closely to the underlying 62 | BNF descriptions (see below), they may be a bit unwieldy to use still. 63 | 64 | ### Supported Elements 65 | 66 | Parsers were implemented based on the BNF elements listed in the paper: 67 | 68 | > "Complete BNF description of PDDL 3.1 (completely corrected)", 69 | > _Daniel L. Kovacs_ 70 | 71 | See [ELEMENTS.md](ELEMENTS.md) for a graph of BNF elements. 72 | -------------------------------------------------------------------------------- /src/parsers/action_symbol.rs: -------------------------------------------------------------------------------- 1 | //! Provides parsers for action symbols. 2 | 3 | use nom::combinator::map; 4 | 5 | use crate::parsers::{parse_name, ParseResult, Span}; 6 | use crate::types::ActionSymbol; 7 | 8 | /// Parses an action symbol, i.e. ``. 9 | /// 10 | /// ## Example 11 | /// ``` 12 | /// # use pddl::parsers::{parse_action_symbol, Span, UnwrapValue}; 13 | /// assert!(parse_action_symbol(Span::new("abcde")).is_value("abcde".into())); 14 | /// assert!(parse_action_symbol(Span::new("a-1_2")).is_value("a-1_2".into())); 15 | /// assert!(parse_action_symbol(Span::new("Z01")).is_value("Z01".into())); 16 | /// assert!(parse_action_symbol(Span::new("x-_-_")).is_value("x-_-_".into())); 17 | /// 18 | /// assert!(parse_action_symbol(Span::new("")).is_err()); 19 | /// assert!(parse_action_symbol(Span::new(".")).is_err()); 20 | /// assert!(parse_action_symbol(Span::new("-abc")).is_err()); 21 | /// assert!(parse_action_symbol(Span::new("0124")).is_err()); 22 | /// assert!(parse_action_symbol(Span::new("-1")).is_err()); 23 | ///``` 24 | pub fn parse_action_symbol<'a, T: Into>>(input: T) -> ParseResult<'a, ActionSymbol> { 25 | map(parse_name, ActionSymbol::new)(input.into()) 26 | } 27 | 28 | impl crate::parsers::Parser for ActionSymbol { 29 | type Item = ActionSymbol; 30 | 31 | /// Parses an action symbol. 32 | /// 33 | /// ## Example 34 | /// ``` 35 | /// # use pddl::{ActionSymbol, Parser}; 36 | /// let (_, action_symbol) = ActionSymbol::parse("abcde").unwrap(); 37 | /// assert_eq!(action_symbol, "abcde".into()); 38 | ///``` 39 | /// 40 | /// ## See also 41 | /// See [`parse_action_symbol`]. 42 | fn parse<'a, S: Into>>(input: S) -> ParseResult<'a, Self::Item> { 43 | parse_action_symbol(input) 44 | } 45 | } 46 | 47 | #[cfg(test)] 48 | mod tests { 49 | use crate::{ActionSymbol, Parser}; 50 | 51 | #[test] 52 | fn test_parse() { 53 | let (_, action_symbol) = ActionSymbol::parse("abcde").unwrap(); 54 | assert_eq!(action_symbol, "abcde".into()); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/parsers/assign_op.rs: -------------------------------------------------------------------------------- 1 | //! Provides parsers for assignment operations. 2 | 3 | use nom::branch::alt; 4 | use nom::bytes::complete::tag; 5 | use nom::combinator::map; 6 | 7 | use crate::parsers::{ParseResult, Span}; 8 | use crate::types::assign_op::names; 9 | use crate::types::AssignOp; 10 | 11 | /// Parses an assignment operation, i.e. `assign | scale-up | scale-down | increase | decrease`. 12 | /// 13 | /// ## Example 14 | /// ``` 15 | /// # use pddl::parsers::{parse_assign_op, Span, UnwrapValue}; 16 | /// # use pddl::{AssignOp}; 17 | /// assert!(parse_assign_op(Span::new("assign")).is_value(AssignOp::Assign)); 18 | /// assert!(parse_assign_op(Span::new("scale-up")).is_value(AssignOp::ScaleUp)); 19 | ///``` 20 | pub fn parse_assign_op<'a, T: Into>>(input: T) -> ParseResult<'a, AssignOp> { 21 | map( 22 | alt(( 23 | tag(names::CHANGE), // deprecated 24 | tag(names::ASSIGN), 25 | tag(names::SCALE_UP), 26 | tag(names::SCALE_DOWN), 27 | tag(names::INCREASE), 28 | tag(names::DECREASE), 29 | )), 30 | |x: Span| AssignOp::try_from(*x.fragment()).expect("unhandled variant"), 31 | )(input.into()) 32 | } 33 | 34 | impl crate::parsers::Parser for AssignOp { 35 | type Item = AssignOp; 36 | 37 | /// Parses an assignment operation. 38 | /// 39 | /// ## Example 40 | /// ``` 41 | /// # use pddl::parsers::{ Span, UnwrapValue}; 42 | /// # use pddl::{AssignOp, Parser}; 43 | /// let (_, assign_op) = AssignOp::parse("assign").unwrap(); 44 | /// assert_eq!(assign_op, AssignOp::Assign); 45 | /// 46 | /// let (_, assign_op) = AssignOp::parse("scale-up").unwrap(); 47 | /// assert_eq!(assign_op, AssignOp::ScaleUp); 48 | ///``` 49 | fn parse<'a, S: Into>>(input: S) -> ParseResult<'a, Self::Item> { 50 | parse_assign_op(input) 51 | } 52 | } 53 | 54 | #[cfg(test)] 55 | mod tests { 56 | use crate::{AssignOp, Parser}; 57 | 58 | #[test] 59 | fn test_parse() { 60 | let (_, assign_op) = AssignOp::parse("assign").unwrap(); 61 | assert_eq!(assign_op, AssignOp::Assign); 62 | 63 | let (_, assign_op) = AssignOp::parse("scale-up").unwrap(); 64 | assert_eq!(assign_op, AssignOp::ScaleUp); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/parsers/assign_op_t.rs: -------------------------------------------------------------------------------- 1 | //! Provides parsers for assignment operations. 2 | 3 | use nom::branch::alt; 4 | use nom::bytes::complete::tag; 5 | use nom::combinator::map; 6 | 7 | use crate::parsers::{ParseResult, Span}; 8 | use crate::types::assign_op_t::names; 9 | use crate::types::AssignOpT; 10 | 11 | /// Parses an assignment operation, i.e. `increase | decrease`. 12 | /// 13 | /// ## Example 14 | /// ``` 15 | /// # use pddl::parsers::{parse_assign_op_t, Span, UnwrapValue}; 16 | /// # use pddl::{AssignOpT}; 17 | /// assert!(parse_assign_op_t(Span::new("increase")).is_value(AssignOpT::Increase)); 18 | /// assert!(parse_assign_op_t(Span::new("decrease")).is_value(AssignOpT::Decrease)); 19 | ///``` 20 | pub fn parse_assign_op_t<'a, T: Into>>(input: T) -> ParseResult<'a, AssignOpT> { 21 | map( 22 | alt((tag(names::INCREASE), tag(names::DECREASE))), 23 | |x: Span| AssignOpT::try_from(*x.fragment()).expect("unhandled variant"), 24 | )(input.into()) 25 | } 26 | 27 | impl crate::parsers::Parser for AssignOpT { 28 | type Item = AssignOpT; 29 | 30 | /// Parses an assignment operation. 31 | /// 32 | /// ## Example 33 | /// ``` 34 | /// # use pddl::{AssignOpT, Parser}; 35 | /// let (_, value) = AssignOpT::parse("increase").unwrap(); 36 | /// assert_eq!(value, AssignOpT::Increase); 37 | ///``` 38 | /// 39 | /// ## See also 40 | /// See [`parse_assign_op_t`]. 41 | fn parse<'a, S: Into>>(input: S) -> ParseResult<'a, Self::Item> { 42 | parse_assign_op_t(input) 43 | } 44 | } 45 | 46 | #[cfg(test)] 47 | mod tests { 48 | use crate::{AssignOpT, Parser}; 49 | 50 | #[test] 51 | fn test_parse() { 52 | let (_, value) = AssignOpT::parse("increase").unwrap(); 53 | assert_eq!(value, AssignOpT::Increase); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/parsers/atomic_formula.rs: -------------------------------------------------------------------------------- 1 | //! Provides parsers for atomic formulae. 2 | 3 | use crate::parsers::{parens, space_separated_list0, ws}; 4 | use crate::parsers::{parse_predicate, ParseResult, Span}; 5 | use crate::types::AtomicFormula; 6 | use nom::branch::alt; 7 | use nom::bytes::complete::tag; 8 | use nom::character::complete::char; 9 | use nom::combinator::map; 10 | use nom::sequence::{delimited, tuple}; 11 | 12 | /// Parses an atomic formula, i.e. `( t*) | (= t t)`. 13 | /// 14 | /// ## Example 15 | /// ``` 16 | /// # use nom::character::complete::alpha1; 17 | /// # use pddl::parsers::{atomic_formula, Span, parse_name, UnwrapValue}; 18 | /// # use pddl::{AtomicFormula, EqualityAtomicFormula, PredicateAtomicFormula, Predicate}; 19 | /// assert!(atomic_formula(parse_name)(Span::new("(= x y)")).is_value( 20 | /// AtomicFormula::Equality(EqualityAtomicFormula::new("x".into(), "y".into())) 21 | /// )); 22 | /// assert!(atomic_formula(parse_name)(Span::new("(move a b)")).is_value( 23 | /// AtomicFormula::Predicate(PredicateAtomicFormula::new(Predicate::from("move"), vec!["a".into(), "b".into()])) 24 | /// )); 25 | /// ``` 26 | pub fn atomic_formula<'a, F, O>( 27 | inner: F, 28 | ) -> impl FnMut(Span<'a>) -> ParseResult<'a, AtomicFormula> 29 | where 30 | F: Clone + FnMut(Span<'a>) -> ParseResult<'a, O>, 31 | { 32 | let equality = map( 33 | delimited( 34 | ws(tag("(=")), 35 | tuple((ws(inner.clone()), ws(inner.clone()))), 36 | ws(char(')')), 37 | ), 38 | |tuple| AtomicFormula::Equality(tuple.into()), 39 | ); 40 | 41 | let predicate = map( 42 | parens(tuple((parse_predicate, ws(space_separated_list0(inner))))), 43 | |tuple| AtomicFormula::Predicate(tuple.into()), 44 | ); 45 | 46 | alt((equality, predicate)) 47 | } 48 | 49 | #[cfg(test)] 50 | mod tests { 51 | use super::*; 52 | use crate::parsers::{parse_name, parse_term, UnwrapValue}; 53 | use crate::{EqualityAtomicFormula, Predicate, PredicateAtomicFormula}; 54 | 55 | #[test] 56 | fn it_works() { 57 | let input = "(can-move ?from-waypoint ?to-waypoint)"; 58 | let (_, _effect) = atomic_formula(parse_term)(Span::new(input)).unwrap(); 59 | } 60 | 61 | #[test] 62 | fn test_parse() { 63 | assert!(atomic_formula(parse_name)(Span::new("(= x y)")).is_value( 64 | AtomicFormula::Equality(EqualityAtomicFormula::new("x".into(), "y".into())) 65 | )); 66 | assert!( 67 | atomic_formula(parse_name)(Span::new("(move a b)")).is_value(AtomicFormula::Predicate( 68 | PredicateAtomicFormula::new(Predicate::from("move"), vec!["a".into(), "b".into()]) 69 | )) 70 | ); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/parsers/atomic_formula_skeleton.rs: -------------------------------------------------------------------------------- 1 | //! Provides parsers for atomic formula skeletons. 2 | 3 | use crate::parsers::{parens, typed_list, ws, ParseResult, Span}; 4 | use crate::parsers::{parse_predicate, parse_variable}; 5 | use crate::types::AtomicFormulaSkeleton; 6 | use nom::combinator::map; 7 | use nom::sequence::tuple; 8 | 9 | /// Parses an atomic formula skeleton, i.e. `( )`. 10 | /// 11 | /// ## Example 12 | /// ``` 13 | /// # use pddl::parsers::{parse_atomic_formula_skeleton, Span, UnwrapValue}; 14 | /// # use pddl::{Variable, AtomicFormulaSkeleton, Predicate}; 15 | /// # use pddl::{ToTyped, TypedList}; 16 | /// assert!(parse_atomic_formula_skeleton(Span::new("(at ?x - physob ?y - location)")).is_value( 17 | /// AtomicFormulaSkeleton::new( 18 | /// Predicate::from("at"), 19 | /// TypedList::from_iter([ 20 | /// Variable::from("x").to_typed("physob"), 21 | /// Variable::from("y").to_typed("location") 22 | /// ])) 23 | /// )); 24 | /// ``` 25 | pub fn parse_atomic_formula_skeleton<'a, T: Into>>( 26 | input: T, 27 | ) -> ParseResult<'a, AtomicFormulaSkeleton> { 28 | map( 29 | parens(tuple((parse_predicate, ws(typed_list(parse_variable))))), 30 | AtomicFormulaSkeleton::from, 31 | )(input.into()) 32 | } 33 | 34 | impl crate::parsers::Parser for AtomicFormulaSkeleton { 35 | type Item = AtomicFormulaSkeleton; 36 | 37 | /// Parses an atomic formula skeleton. 38 | /// 39 | /// ## Example 40 | /// ``` 41 | /// # use pddl::parsers::{parse_atomic_formula_skeleton, Span, UnwrapValue}; 42 | /// # use pddl::{Variable, AtomicFormulaSkeleton, Predicate, Parser}; 43 | /// # use pddl::{ToTyped, TypedList}; 44 | /// let (_, value) = AtomicFormulaSkeleton::parse("(at ?x - physob ?y - location)").unwrap(); 45 | /// 46 | /// assert_eq!(value, 47 | /// AtomicFormulaSkeleton::new( 48 | /// Predicate::from("at"), 49 | /// TypedList::from_iter([ 50 | /// Variable::from("x").to_typed("physob"), 51 | /// Variable::from("y").to_typed("location") 52 | /// ])) 53 | /// ); 54 | /// ``` 55 | /// 56 | /// ## See also 57 | /// See [`parse_atomic_formula_skeleton`]. 58 | fn parse<'a, S: Into>>(input: S) -> ParseResult<'a, Self::Item> { 59 | parse_atomic_formula_skeleton(input) 60 | } 61 | } 62 | 63 | #[cfg(test)] 64 | mod tests { 65 | use crate::{AtomicFormulaSkeleton, Parser, Predicate, Variable}; 66 | use crate::{ToTyped, TypedList}; 67 | 68 | #[test] 69 | fn test_parse() { 70 | let (_, value) = AtomicFormulaSkeleton::parse("(at ?x - physob ?y - location)").unwrap(); 71 | 72 | assert_eq!( 73 | value, 74 | AtomicFormulaSkeleton::new( 75 | Predicate::from("at"), 76 | TypedList::from_iter([ 77 | Variable::from("x").to_typed("physob"), 78 | Variable::from("y").to_typed("location") 79 | ]) 80 | ) 81 | ); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/parsers/atomic_function_skeleton.rs: -------------------------------------------------------------------------------- 1 | //! Provides parsers for atomic function skeletons. 2 | 3 | use crate::parsers::{parens, typed_list, ws, ParseResult, Span}; 4 | use crate::parsers::{parse_function_symbol, parse_variable}; 5 | use crate::types::AtomicFunctionSkeleton; 6 | use nom::combinator::map; 7 | use nom::sequence::tuple; 8 | 9 | /// Parses an atomic function skeleton, i.e. `( )`. 10 | /// 11 | /// ## Example 12 | /// ``` 13 | /// # use pddl::parsers::{parse_atomic_function_skeleton, Span, UnwrapValue}; 14 | /// # use pddl::{Variable, AtomicFunctionSkeleton, Predicate, FunctionSymbol}; 15 | /// # use pddl::{ToTyped, TypedList}; 16 | /// assert!(parse_atomic_function_skeleton(Span::new("(battery-amount ?r - rover)")).is_value( 17 | /// AtomicFunctionSkeleton::new( 18 | /// FunctionSymbol::from("battery-amount"), 19 | /// TypedList::from_iter([ 20 | /// Variable::from("r").to_typed("rover") 21 | /// ])) 22 | /// )); 23 | /// ``` 24 | pub fn parse_atomic_function_skeleton<'a, T: Into>>( 25 | input: T, 26 | ) -> ParseResult<'a, AtomicFunctionSkeleton> { 27 | map( 28 | parens(tuple(( 29 | parse_function_symbol, 30 | ws(typed_list(parse_variable)), 31 | ))), 32 | AtomicFunctionSkeleton::from, 33 | )(input.into()) 34 | } 35 | 36 | impl crate::parsers::Parser for AtomicFunctionSkeleton { 37 | type Item = AtomicFunctionSkeleton; 38 | 39 | /// Parses an atomic function skeleton, i.e. `( )`. 40 | /// 41 | /// ## Example 42 | /// ``` 43 | /// # use pddl::{Variable, AtomicFunctionSkeleton, FunctionSymbol, Parser}; 44 | /// # use pddl::{ToTyped, TypedList}; 45 | /// let (_, value) = AtomicFunctionSkeleton::parse("(battery-amount ?r - rover)").unwrap(); 46 | /// 47 | /// assert_eq!(value, 48 | /// AtomicFunctionSkeleton::new( 49 | /// FunctionSymbol::from("battery-amount"), 50 | /// TypedList::from_iter([ 51 | /// Variable::from("r").to_typed("rover") 52 | /// ])) 53 | /// ); 54 | /// ``` 55 | /// 56 | /// ## See also 57 | /// See [`parse_atomic_function_skeleton`]. 58 | fn parse<'a, S: Into>>(input: S) -> ParseResult<'a, Self::Item> { 59 | parse_atomic_function_skeleton(input) 60 | } 61 | } 62 | 63 | #[cfg(test)] 64 | mod tests { 65 | use crate::{AtomicFunctionSkeleton, FunctionSymbol, Parser, Variable}; 66 | use crate::{ToTyped, TypedList}; 67 | 68 | #[test] 69 | fn test_parse() { 70 | let (_, value) = AtomicFunctionSkeleton::parse("(battery-amount ?r - rover)").unwrap(); 71 | assert_eq!( 72 | value, 73 | AtomicFunctionSkeleton::new( 74 | FunctionSymbol::from("battery-amount"), 75 | TypedList::from_iter([Variable::from("r").to_typed("rover")]) 76 | ) 77 | ); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/parsers/basic_function_term.rs: -------------------------------------------------------------------------------- 1 | //! Provides parsers for basic function terms. 2 | 3 | use crate::parsers::{ 4 | parens, parse_function_symbol, parse_name, space_separated_list0, ws, ParseResult, Span, 5 | }; 6 | use crate::types::BasicFunctionTerm; 7 | use nom::branch::alt; 8 | use nom::combinator::map; 9 | use nom::sequence::tuple; 10 | 11 | /// Parses a basic function term. 12 | /// 13 | /// ## Example 14 | /// ``` 15 | /// # use pddl::parsers::{parse_basic_function_term, UnwrapValue, Span}; 16 | /// # use pddl::{BasicFunctionTerm, Term}; 17 | /// assert!(parse_basic_function_term(Span::new("abcde")).is_value( 18 | /// BasicFunctionTerm::new("abcde".into(), []) 19 | /// )); 20 | /// 21 | /// assert!(parse_basic_function_term(Span::new("(abcde)")).is_value( 22 | /// BasicFunctionTerm::new("abcde".into(), []) 23 | /// )); 24 | /// 25 | /// assert!(parse_basic_function_term(Span::new("(abcde x y z)")).is_value( 26 | /// BasicFunctionTerm::new("abcde".into(), ["x".into(), "y".into(), "z".into()]) 27 | /// )); 28 | ///``` 29 | pub fn parse_basic_function_term<'a, T: Into>>( 30 | input: T, 31 | ) -> ParseResult<'a, BasicFunctionTerm> { 32 | let direct = map(parse_function_symbol, |s| BasicFunctionTerm::new(s, [])); 33 | let named = map( 34 | parens(tuple(( 35 | parse_function_symbol, 36 | ws(space_separated_list0(parse_name)), 37 | ))), 38 | |(s, ns)| BasicFunctionTerm::new(s, ns), 39 | ); 40 | alt((direct, named))(input.into()) 41 | } 42 | 43 | impl crate::parsers::Parser for BasicFunctionTerm { 44 | type Item = BasicFunctionTerm; 45 | 46 | /// Parses a basic function term. 47 | /// 48 | /// ## Example 49 | /// ``` 50 | /// # use pddl::{BasicFunctionTerm, Parser}; 51 | /// let (_, value) = BasicFunctionTerm::parse("abcde").unwrap(); 52 | /// assert_eq!(value, BasicFunctionTerm::new("abcde".into(), [])); 53 | /// 54 | /// let (_, value) = BasicFunctionTerm::parse("(abcde)").unwrap(); 55 | /// assert_eq!(value, BasicFunctionTerm::new("abcde".into(), [])); 56 | /// 57 | /// let (_, value) = BasicFunctionTerm::parse("(abcde x y z)").unwrap(); 58 | /// assert_eq!(value, BasicFunctionTerm::new("abcde".into(), [ 59 | /// "x".into(), "y".into(), "z".into()] 60 | /// )); 61 | /// ``` 62 | /// 63 | /// ## See also 64 | /// See [`parse_basic_function_term`]. 65 | fn parse<'a, S: Into>>(input: S) -> ParseResult<'a, Self::Item> { 66 | parse_basic_function_term(input) 67 | } 68 | } 69 | 70 | #[cfg(test)] 71 | mod tests { 72 | use crate::{BasicFunctionTerm, Parser}; 73 | 74 | #[test] 75 | fn test_parse() { 76 | let (_, value) = BasicFunctionTerm::parse("abcde").unwrap(); 77 | assert_eq!(value, BasicFunctionTerm::new("abcde".into(), [])); 78 | 79 | let (_, value) = BasicFunctionTerm::parse("(abcde)").unwrap(); 80 | assert_eq!(value, BasicFunctionTerm::new("abcde".into(), [])); 81 | 82 | let (_, value) = BasicFunctionTerm::parse("(abcde x y z)").unwrap(); 83 | assert_eq!( 84 | value, 85 | BasicFunctionTerm::new("abcde".into(), ["x".into(), "y".into(), "z".into()]) 86 | ); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/parsers/binary_comp.rs: -------------------------------------------------------------------------------- 1 | //! Provides parsers for binary comparison operations. 2 | 3 | use nom::branch::alt; 4 | use nom::bytes::complete::tag; 5 | use nom::combinator::map; 6 | 7 | use crate::parsers::{ParseResult, Span}; 8 | use crate::types::{binary_comp::names, BinaryComp}; 9 | 10 | /// Parses a binary comparison operation. 11 | /// 12 | /// ## Example 13 | /// ``` 14 | /// # use pddl::parsers::{parse_binary_comp, Span, UnwrapValue}; 15 | /// # use pddl::{AssignOp, BinaryComp}; 16 | /// assert!(parse_binary_comp(Span::new(">")).is_value(BinaryComp::GreaterThan)); 17 | /// assert!(parse_binary_comp(Span::new("<")).is_value(BinaryComp::LessThan)); 18 | /// assert!(parse_binary_comp(Span::new("=")).is_value(BinaryComp::Equal)); 19 | /// assert!(parse_binary_comp(Span::new(">=")).is_value(BinaryComp::GreaterOrEqual)); 20 | /// assert!(parse_binary_comp(Span::new("<=")).is_value(BinaryComp::LessThanOrEqual)); 21 | ///``` 22 | pub fn parse_binary_comp<'a, T: Into>>(input: T) -> ParseResult<'a, BinaryComp> { 23 | map( 24 | alt(( 25 | tag(names::GREATER_THAN_OR_EQUAL), 26 | tag(names::LESS_THAN_OR_EQUAL), 27 | tag(names::EQUAL), 28 | tag(names::GREATER_THAN), 29 | tag(names::LESS_THAN), 30 | )), 31 | |x: Span| BinaryComp::try_from(*x.fragment()).expect("unhandled variant"), 32 | )(input.into()) 33 | } 34 | 35 | impl crate::parsers::Parser for BinaryComp { 36 | type Item = BinaryComp; 37 | 38 | /// Parses a binary comparison operation. 39 | /// 40 | /// ## Example 41 | /// ``` 42 | /// # use pddl::{BinaryComp, Parser}; 43 | /// let (_, value) = BinaryComp::parse(">=").unwrap(); 44 | /// assert_eq!(value, BinaryComp::GreaterOrEqual); 45 | ///``` 46 | /// 47 | /// ## See also 48 | /// See [`parse_binary_comp`]. 49 | fn parse<'a, S: Into>>(input: S) -> ParseResult<'a, Self::Item> { 50 | parse_binary_comp(input) 51 | } 52 | } 53 | 54 | #[cfg(test)] 55 | mod tests { 56 | use crate::{BinaryComp, Parser}; 57 | 58 | #[test] 59 | fn test_parse() { 60 | let (_, value) = BinaryComp::parse(">=").unwrap(); 61 | assert_eq!(value, BinaryComp::GreaterOrEqual); 62 | 63 | let (_, value) = BinaryComp::parse(">").unwrap(); 64 | assert_eq!(value, BinaryComp::GreaterThan); 65 | 66 | let (_, value) = BinaryComp::parse("<=").unwrap(); 67 | assert_eq!(value, BinaryComp::LessThanOrEqual); 68 | 69 | let (_, value) = BinaryComp::parse("<").unwrap(); 70 | assert_eq!(value, BinaryComp::LessThan); 71 | 72 | let (_, value) = BinaryComp::parse("=").unwrap(); 73 | assert_eq!(value, BinaryComp::Equal); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/parsers/binary_op.rs: -------------------------------------------------------------------------------- 1 | //! Provides parsers for binary-operand operations. 2 | 3 | use nom::branch::alt; 4 | use nom::bytes::complete::tag; 5 | use nom::combinator::map; 6 | 7 | use crate::parsers::{ParseResult, Span}; 8 | use crate::types::{binary_op::names, BinaryOp}; 9 | 10 | /// Parses a two-operand operation, i.e. `* | + | - | /`. 11 | /// 12 | /// ## Example 13 | /// ``` 14 | /// # use pddl::parsers::{parse_binary_op, Span, UnwrapValue}; 15 | /// # use pddl::{BinaryOp}; 16 | /// assert!(parse_binary_op(Span::new("*")).is_value(BinaryOp::Multiplication)); 17 | /// assert!(parse_binary_op(Span::new("+")).is_value(BinaryOp::Addition)); 18 | /// assert!(parse_binary_op(Span::new("-")).is_value(BinaryOp::Subtraction)); 19 | /// assert!(parse_binary_op(Span::new("/")).is_value(BinaryOp::Division)); 20 | ///``` 21 | pub fn parse_binary_op<'a, T: Into>>(input: T) -> ParseResult<'a, BinaryOp> { 22 | map( 23 | alt(( 24 | tag(names::MULTIPLICATION), 25 | tag(names::ADDITION), 26 | tag(names::SUBTRACTION), 27 | tag(names::DIVISION), 28 | )), 29 | |x: Span| BinaryOp::try_from(*x.fragment()).expect("unhandled variant"), 30 | )(input.into()) 31 | } 32 | 33 | impl crate::parsers::Parser for BinaryOp { 34 | type Item = BinaryOp; 35 | 36 | /// Parses a two-operand operation. 37 | /// 38 | /// ## Example 39 | /// ``` 40 | /// # use pddl::{BinaryOp, Parser}; 41 | /// let (_, value) = BinaryOp::parse("*").unwrap(); 42 | /// assert_eq!(value, BinaryOp::Multiplication); 43 | ///``` 44 | /// 45 | /// ## See also. 46 | /// See [`parse_binary_op`]. 47 | fn parse<'a, S: Into>>(input: S) -> ParseResult<'a, Self::Item> { 48 | parse_binary_op(input) 49 | } 50 | } 51 | 52 | #[cfg(test)] 53 | mod tests { 54 | use crate::{BinaryOp, Parser}; 55 | 56 | #[test] 57 | fn test_parse() { 58 | let (_, value) = BinaryOp::parse("*").unwrap(); 59 | assert_eq!(value, BinaryOp::Multiplication); 60 | 61 | let (_, value) = BinaryOp::parse("/").unwrap(); 62 | assert_eq!(value, BinaryOp::Division); 63 | 64 | let (_, value) = BinaryOp::parse("+").unwrap(); 65 | assert_eq!(value, BinaryOp::Addition); 66 | 67 | let (_, value) = BinaryOp::parse("-").unwrap(); 68 | assert_eq!(value, BinaryOp::Subtraction); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/parsers/comments.rs: -------------------------------------------------------------------------------- 1 | use crate::parsers::{ParseResult, Span}; 2 | use nom::character::complete::{char, multispace0}; 3 | use nom::combinator::opt; 4 | use nom::sequence::{terminated, tuple}; 5 | use nom::{bytes::complete::is_not, combinator::value, sequence::pair}; 6 | 7 | /// Parses a comment and swallows trailing whitespace / newline. 8 | /// 9 | /// ## Example 10 | /// 11 | /// Comments are parsed and trailing whitespace is suppressed: 12 | /// 13 | /// ``` 14 | /// # use pddl::parsers::{ignore_eol_comment}; 15 | /// let input = "; nothing\n\t; and this line\n\tthen more"; 16 | /// 17 | /// let (remainder, comment) = ignore_eol_comment(input).unwrap(); 18 | /// 19 | /// assert_eq!(comment, ()); 20 | /// assert_eq!(remainder.to_ascii_lowercase().trim(), "then more"); 21 | /// ``` 22 | /// 23 | /// If no comments are found, the text parses as expected, although leading whitespace is still suppressed. 24 | /// 25 | /// ``` 26 | /// # use pddl::parsers::{ignore_eol_comment}; 27 | /// let input = "then more"; 28 | /// 29 | /// let (remainder, comment) = ignore_eol_comment(input).unwrap(); 30 | /// 31 | /// assert_eq!(comment, ()); 32 | /// assert_eq!(remainder.to_ascii_lowercase().trim(), "then more"); 33 | /// ``` 34 | pub fn ignore_eol_comment<'a, S: Into>>(input: S) -> ParseResult<'a, ()> { 35 | value( 36 | (), // Output is thrown away. 37 | opt(terminated( 38 | pair(char(';'), is_not("\r\n")), 39 | tuple((multispace0, opt(ignore_eol_comment))), 40 | )), 41 | )(input.into()) 42 | } 43 | 44 | #[cfg(test)] 45 | mod tests { 46 | use super::*; 47 | 48 | #[test] 49 | fn single_line() { 50 | let input = "; nothing"; 51 | let (remainder, comment) = ignore_eol_comment(input).unwrap(); 52 | assert_eq!(comment, ()); 53 | assert!(remainder.is_empty()); 54 | } 55 | 56 | #[test] 57 | fn precedes_text() { 58 | let input = "; nothing\n\r\tlast line"; 59 | let (remainder, comment) = ignore_eol_comment(input).unwrap(); 60 | assert_eq!(comment, ()); 61 | assert_eq!(remainder.to_ascii_lowercase(), "last line"); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/parsers/constants_def.rs: -------------------------------------------------------------------------------- 1 | //! Provides parsers for constant definitions. 2 | 3 | use nom::combinator::map; 4 | 5 | use crate::parsers::{parse_name, prefix_expr, typed_list, ParseResult, Span}; 6 | use crate::types::Constants; 7 | 8 | /// Parses constant definitions, i.e. `(:constants )`. 9 | /// 10 | /// ## Example 11 | /// ``` 12 | /// # use pddl::parsers::{parse_constants_def, preamble::*}; 13 | /// # use pddl::{Variable, AtomicFormulaSkeleton, Predicate, PredicateDefinitions, Constants, Name, ToTyped, TypedList}; 14 | /// let input = "(:constants B P D - physob)"; 15 | /// assert!(parse_constants_def(input).is_value( 16 | /// Constants::new(TypedList::from_iter([ 17 | /// Name::from("B").to_typed("physob"), 18 | /// Name::from("P").to_typed("physob"), 19 | /// Name::from("D").to_typed("physob"), 20 | /// ])) 21 | /// )); 22 | /// ``` 23 | pub fn parse_constants_def<'a, T: Into>>(input: T) -> ParseResult<'a, Constants> { 24 | map(prefix_expr(":constants", typed_list(parse_name)), |vec| { 25 | Constants::new(vec) 26 | })(input.into()) 27 | } 28 | 29 | impl crate::parsers::Parser for Constants { 30 | type Item = Constants; 31 | 32 | /// See [`parse_constants_def`]. 33 | fn parse<'a, S: Into>>(input: S) -> ParseResult<'a, Self::Item> { 34 | parse_constants_def(input) 35 | } 36 | } 37 | 38 | #[cfg(test)] 39 | mod tests { 40 | use crate::parsers::UnwrapValue; 41 | use crate::{Constants, Name, Parser, ToTyped, TypedList}; 42 | 43 | #[test] 44 | fn test_parse() { 45 | let input = "(:constants B P D - physob)"; 46 | assert!( 47 | Constants::parse(input).is_value(Constants::new(TypedList::from_iter([ 48 | Name::from("B").to_typed("physob"), 49 | Name::from("P").to_typed("physob"), 50 | Name::from("D").to_typed("physob"), 51 | ]))) 52 | ); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/parsers/d_op.rs: -------------------------------------------------------------------------------- 1 | //! Provides parsers for durative operations. 2 | 3 | use nom::branch::alt; 4 | use nom::bytes::complete::tag; 5 | use nom::combinator::map; 6 | 7 | use crate::parsers::{ParseResult, Span}; 8 | use crate::types::{d_op::names, DOp}; 9 | 10 | /// Parses a durative operation, i.e. `<= | >= | =`. 11 | /// 12 | /// ## Example 13 | /// ``` 14 | /// # use pddl::parsers::{parse_d_op, preamble::*}; 15 | /// # use pddl::{DOp}; 16 | /// assert!(parse_d_op("<=").is_value(DOp::LessThanOrEqual)); 17 | /// assert!(parse_d_op(">=").is_value(DOp::GreaterOrEqual)); 18 | /// assert!(parse_d_op("=").is_value(DOp::Equal)); 19 | ///``` 20 | pub fn parse_d_op<'a, T: Into>>(input: T) -> ParseResult<'a, DOp> { 21 | // :duration-inequalities 22 | map( 23 | alt(( 24 | tag(names::LESS_THAN_OR_EQUAL), 25 | tag(names::GREATER_OR_EQUAL), 26 | tag(names::EQUAL), 27 | )), 28 | |x: Span| DOp::try_from(*x.fragment()).expect("unhandled variant"), 29 | )(input.into()) 30 | } 31 | 32 | impl crate::parsers::Parser for DOp { 33 | type Item = DOp; 34 | 35 | /// Parses a durative operation. 36 | /// 37 | /// ## Example 38 | /// ``` 39 | /// # use pddl::{DOp, Parser}; 40 | /// let (_, value) = DOp::parse("<=").unwrap(); 41 | /// assert_eq!(value, DOp::LessThanOrEqual); 42 | ///``` 43 | /// 44 | /// ## See also. 45 | /// See [`parse_binary_op`]. 46 | /// 47 | /// ## See also 48 | /// See [`parse_d_op`]. 49 | fn parse<'a, S: Into>>(input: S) -> ParseResult<'a, Self::Item> { 50 | parse_d_op(input) 51 | } 52 | } 53 | 54 | #[cfg(test)] 55 | mod tests { 56 | use crate::parsers::UnwrapValue; 57 | use crate::{DOp, Parser}; 58 | 59 | #[test] 60 | fn test_parse() { 61 | assert!(DOp::parse("<=").is_value(DOp::LessThanOrEqual)); 62 | assert!(DOp::parse(">=").is_value(DOp::GreaterOrEqual)); 63 | assert!(DOp::parse("=").is_value(DOp::Equal)); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/parsers/d_value.rs: -------------------------------------------------------------------------------- 1 | //! Provides parsers for d-values. 2 | 3 | use nom::branch::alt; 4 | use nom::combinator::map; 5 | 6 | use crate::parsers::parse_number; 7 | use crate::parsers::{parse_f_exp, ParseResult, Span}; 8 | use crate::types::DurationValue; 9 | 10 | /// Parses a d-value. 11 | /// 12 | /// ## Example 13 | /// ``` 14 | /// # use pddl::parsers::{parse_d_value, preamble::*}; 15 | /// # use pddl::{BinaryOp, DurationValue, FExp, FHead, FunctionSymbol, MultiOp}; 16 | /// assert!(parse_d_value("1.23").is_value( 17 | /// DurationValue::new_number(1.23) 18 | /// )); 19 | /// 20 | /// assert!(parse_d_value("fun-sym").is_value( 21 | /// DurationValue::new_f_exp( 22 | /// FExp::new_function(FHead::Simple("fun-sym".into())) 23 | /// ) 24 | /// )); 25 | ///``` 26 | pub fn parse_d_value<'a, T: Into>>(input: T) -> ParseResult<'a, DurationValue> { 27 | let number = map(parse_number, DurationValue::new_number); 28 | 29 | // :numeric-fluents 30 | let f_exp = map(parse_f_exp, DurationValue::new_f_exp); 31 | 32 | alt((number, f_exp))(input.into()) 33 | } 34 | 35 | impl crate::parsers::Parser for DurationValue { 36 | type Item = DurationValue; 37 | 38 | /// See [`parse_d_value`]. 39 | fn parse<'a, S: Into>>(input: S) -> ParseResult<'a, Self::Item> { 40 | parse_d_value(input) 41 | } 42 | } 43 | 44 | #[cfg(test)] 45 | mod tests { 46 | use crate::parsers::UnwrapValue; 47 | use crate::{DurationValue, FExp, FHead, Parser}; 48 | 49 | #[test] 50 | fn test_parse() { 51 | assert!(DurationValue::parse("1.23").is_value(DurationValue::new_number(1.23))); 52 | 53 | assert!( 54 | DurationValue::parse("fun-sym").is_value(DurationValue::new_f_exp(FExp::new_function( 55 | FHead::Simple("fun-sym".into()) 56 | ))) 57 | ); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/parsers/da_symbol.rs: -------------------------------------------------------------------------------- 1 | //! Provides parsers for predicates. 2 | 3 | use crate::parsers::{parse_name, ParseResult, Span}; 4 | use crate::types::DurativeActionSymbol; 5 | use nom::combinator::map; 6 | 7 | /// Parses a durative action symbol, i.e. ``. 8 | /// 9 | /// ## Example 10 | /// ``` 11 | /// # use pddl::parsers::{parse_da_symbol, preamble::*}; 12 | /// assert!(parse_da_symbol("abcde").is_value("abcde".into())); 13 | ///``` 14 | pub fn parse_da_symbol<'a, T: Into>>(input: T) -> ParseResult<'a, DurativeActionSymbol> { 15 | map(parse_name, DurativeActionSymbol::from)(input.into()) 16 | } 17 | 18 | impl crate::parsers::Parser for DurativeActionSymbol { 19 | type Item = DurativeActionSymbol; 20 | 21 | /// Parses a durative action symbol. 22 | /// 23 | /// ## Example 24 | /// ``` 25 | /// # use pddl::{DurativeActionSymbol, Parser}; 26 | /// let (_, value) = DurativeActionSymbol::parse("abcde").unwrap(); 27 | /// assert_eq!(value, "abcde".into()); 28 | ///``` 29 | /// 30 | /// ## See also 31 | /// See [`parse_da_symbol`]. 32 | fn parse<'a, S: Into>>(input: S) -> ParseResult<'a, Self::Item> { 33 | parse_da_symbol(input) 34 | } 35 | } 36 | 37 | #[cfg(test)] 38 | mod tests { 39 | use crate::{DurativeActionSymbol, Parser}; 40 | 41 | #[test] 42 | fn test_parse() { 43 | let (_, value) = DurativeActionSymbol::parse("abcde").unwrap(); 44 | assert_eq!(value, "abcde".into()); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/parsers/derived_predicate.rs: -------------------------------------------------------------------------------- 1 | //! Provides parsers for derived predicates. 2 | 3 | use nom::character::complete::multispace1; 4 | use nom::combinator::map; 5 | use nom::sequence::{preceded, tuple}; 6 | 7 | use crate::parsers::{parse_atomic_formula_skeleton, parse_gd}; 8 | use crate::parsers::{prefix_expr, ParseResult, Span}; 9 | use crate::types::DerivedPredicate; 10 | 11 | /// Parses a derived predicate, i.e. `(:derived )`. 12 | /// 13 | /// ## Example 14 | /// ``` 15 | /// # use pddl::parsers::{parse_derived_predicate, preamble::*}; 16 | /// # use pddl::GoalDefinition; 17 | /// let input = r#"(:derived (train-usable ?t - train) 18 | /// (and 19 | /// (train-has-guard ?t) 20 | /// (train-has-driver ?t) 21 | /// ) 22 | /// )"#; 23 | /// 24 | /// let (remaining, predicate) = parse_derived_predicate(input).unwrap(); 25 | /// assert_eq!(predicate.predicate().name(), "train-usable"); 26 | /// assert!(matches!(predicate.expression(), &GoalDefinition::And(..))); 27 | ///``` 28 | pub fn parse_derived_predicate<'a, T: Into>>( 29 | input: T, 30 | ) -> ParseResult<'a, DerivedPredicate> { 31 | map( 32 | prefix_expr( 33 | ":derived", 34 | tuple(( 35 | parse_atomic_formula_skeleton, 36 | preceded(multispace1, parse_gd), 37 | )), 38 | ), 39 | DerivedPredicate::from, 40 | )(input.into()) 41 | } 42 | 43 | impl crate::parsers::Parser for DerivedPredicate { 44 | type Item = DerivedPredicate; 45 | 46 | /// See [`parse_derived_predicate`]. 47 | fn parse<'a, S: Into>>(input: S) -> ParseResult<'a, Self::Item> { 48 | parse_derived_predicate(input) 49 | } 50 | } 51 | 52 | #[cfg(test)] 53 | mod tests { 54 | use crate::{DerivedPredicate, GoalDefinition, Parser}; 55 | 56 | #[test] 57 | fn test_parse() { 58 | let input = r#"(:derived (train-usable ?t - train) 59 | (and 60 | (train-has-guard ?t) 61 | (train-has-driver ?t) 62 | ) 63 | )"#; 64 | 65 | let (_, predicate) = DerivedPredicate::parse(input).unwrap(); 66 | assert_eq!(predicate.predicate().name(), "train-usable"); 67 | assert!(matches!(predicate.expression(), &GoalDefinition::And(..))); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/parsers/domain_constraints_def.rs: -------------------------------------------------------------------------------- 1 | //! Provides parsers for domain constraint definitions. 2 | 3 | use nom::combinator::map; 4 | 5 | use crate::parsers::{parse_con_gd, prefix_expr, ParseResult, Span}; 6 | use crate::types::DomainConstraintsDef; 7 | 8 | /// Parses domain constraint definitions, i.e. `(:constraints )`. 9 | /// 10 | /// ## Example 11 | /// ``` 12 | /// # use pddl::parsers::{parse_domain_constraints_def, parse_functions_def, preamble::*}; 13 | /// # use pddl::{Variable, AtomicFormulaSkeleton, Predicate, PredicateDefinitions, FunctionTypedList, FunctionTyped, AtomicFunctionSkeleton, FunctionSymbol, Functions, ConGD, DomainConstraintsDef}; 14 | /// # use pddl::{Type, Typed, TypedList}; 15 | /// 16 | /// let input = "(:constraints (and))"; 17 | /// assert!(parse_domain_constraints_def(input).is_value( 18 | /// DomainConstraintsDef::new(ConGD::new_and([])) 19 | /// )); 20 | /// ``` 21 | pub fn parse_domain_constraints_def<'a, T: Into>>( 22 | input: T, 23 | ) -> ParseResult<'a, DomainConstraintsDef> { 24 | map( 25 | prefix_expr(":constraints", parse_con_gd), 26 | DomainConstraintsDef::new, 27 | )(input.into()) 28 | } 29 | 30 | impl crate::parsers::Parser for DomainConstraintsDef { 31 | type Item = DomainConstraintsDef; 32 | 33 | /// See [`parse_domain_constraints_def`]. 34 | fn parse<'a, S: Into>>(input: S) -> ParseResult<'a, Self::Item> { 35 | parse_domain_constraints_def(input) 36 | } 37 | } 38 | 39 | #[cfg(test)] 40 | mod tests { 41 | use crate::parsers::UnwrapValue; 42 | use crate::{ConGD, DomainConstraintsDef, Parser}; 43 | 44 | #[test] 45 | fn test_parse() { 46 | let input = "(:constraints (and))"; 47 | assert!(DomainConstraintsDef::parse(input) 48 | .is_value(DomainConstraintsDef::new(ConGD::new_and([])))); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/parsers/empty_or.rs: -------------------------------------------------------------------------------- 1 | //! Provides the [`empty_or`] parser combinator. 2 | 3 | use nom::branch::alt; 4 | use nom::bytes::complete::tag; 5 | use nom::combinator::map; 6 | use nom::error::ParseError; 7 | 8 | use crate::parsers::{ParseResult, Span}; 9 | 10 | /// Parser combinator that takes a parser `inner` and produces a parser that 11 | /// consumes `()` and returns [`None`] or the result of `inner` and produces [`Some(O)`](Some). 12 | /// 13 | /// ## Example 14 | /// ``` 15 | /// # use pddl::parsers::{parse_variable, Span, preamble::*}; 16 | /// # use pddl::parsers::empty_or; 17 | /// # use pddl::Variable; 18 | /// let mut parser = empty_or(parse_variable); 19 | /// assert!(parser(Span::new("()")).is_value(None)); 20 | /// assert!(parser(Span::new("?abc")).is_value(Some(Variable::from("abc")))); 21 | /// ``` 22 | #[allow(dead_code)] 23 | pub fn empty_or<'a, F, O, E: ParseError>>( 24 | inner: F, 25 | ) -> impl FnMut(Span<'a>) -> ParseResult<'a, Option, E> 26 | where 27 | F: FnMut(Span<'a>) -> ParseResult<'a, O, E>, 28 | { 29 | let empty_parser = map(tag("()"), |_: Span| None); 30 | let inner_parser = map(inner, |o: O| Some(o)); 31 | 32 | alt((empty_parser, inner_parser)) 33 | } 34 | 35 | #[cfg(test)] 36 | mod tests { 37 | use nom::character::complete::alpha1; 38 | 39 | use crate::parsers::Match; 40 | 41 | use super::*; 42 | 43 | #[test] 44 | fn empty_or_works() { 45 | let mut parser = empty_or(alpha1::, crate::parsers::ParseError>); 46 | assert!(parser(Span::new("()")).is_exactly(None)); 47 | assert!(parser(Span::new("abc")).is_exactly(Some("abc"))); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/parsers/f_assign_da.rs: -------------------------------------------------------------------------------- 1 | //! Provides parsers for f-assign-das. 2 | 3 | use crate::parsers::{parens, ParseResult, Span}; 4 | use crate::parsers::{parse_assign_op, parse_f_exp_da, parse_f_head}; 5 | use crate::types::FAssignDa; 6 | use nom::character::complete::multispace1; 7 | use nom::combinator::map; 8 | use nom::sequence::{preceded, tuple}; 9 | 10 | /// Parses an f-assign-da. 11 | /// 12 | /// ## Example 13 | /// ``` 14 | /// # use pddl::parsers::parse_f_assign_da; 15 | /// assert!(parse_f_assign_da("(assign fun-sym ?duration)").is_ok()); 16 | ///``` 17 | pub fn parse_f_assign_da<'a, T: Into>>(input: T) -> ParseResult<'a, FAssignDa> { 18 | map( 19 | parens(tuple(( 20 | parse_assign_op, 21 | preceded(multispace1, parse_f_head), 22 | preceded(multispace1, parse_f_exp_da), 23 | ))), 24 | FAssignDa::from, 25 | )(input.into()) 26 | } 27 | 28 | impl crate::parsers::Parser for FAssignDa { 29 | type Item = FAssignDa; 30 | 31 | /// See [`parse_f_assign_da`]. 32 | fn parse<'a, S: Into>>(input: S) -> ParseResult<'a, Self::Item> { 33 | parse_f_assign_da(input) 34 | } 35 | } 36 | 37 | #[cfg(test)] 38 | mod tests { 39 | use super::*; 40 | use crate::Parser; 41 | 42 | #[test] 43 | fn it_works() { 44 | let input = "(increase (distance-travelled) 5)"; 45 | let (_, _effect) = FAssignDa::parse(Span::new(input)).unwrap(); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/parsers/f_comp.rs: -------------------------------------------------------------------------------- 1 | //! Provides parsers for f-comps. 2 | 3 | use nom::character::complete::multispace1; 4 | use nom::combinator::map; 5 | use nom::sequence::{preceded, tuple}; 6 | 7 | use crate::parsers::{parens, ParseResult, Span}; 8 | use crate::parsers::{parse_binary_comp, parse_f_exp}; 9 | use crate::types::FComp; 10 | 11 | /// Parses an f-comp. 12 | /// 13 | /// ## Example 14 | /// ``` 15 | /// # use pddl::parsers::{parse_f_comp, preamble::*}; 16 | /// # use pddl::{FunctionTerm, Variable, FunctionSymbol, Term, FComp, BinaryComp, FExp, BinaryOp}; 17 | /// assert!(parse_f_comp("(= (+ 1.23 2.34) (+ 1.23 2.34))").is_value( 18 | /// FComp::new( 19 | /// BinaryComp::Equal, 20 | /// FExp::new_binary_op( 21 | /// BinaryOp::Addition, 22 | /// FExp::new_number(1.23), 23 | /// FExp::new_number(2.34), 24 | /// ), 25 | /// FExp::new_binary_op( 26 | /// BinaryOp::Addition, 27 | /// FExp::new_number(1.23), 28 | /// FExp::new_number(2.34), 29 | /// ) 30 | /// ) 31 | /// )); 32 | ///``` 33 | pub fn parse_f_comp<'a, T: Into>>(input: T) -> ParseResult<'a, FComp> { 34 | map( 35 | parens(tuple(( 36 | parse_binary_comp, 37 | preceded(multispace1, parse_f_exp), 38 | preceded(multispace1, parse_f_exp), 39 | ))), 40 | FComp::from, 41 | )(input.into()) 42 | } 43 | 44 | impl crate::parsers::Parser for FComp { 45 | type Item = FComp; 46 | 47 | /// See [`parse_f_comp`]. 48 | fn parse<'a, S: Into>>(input: S) -> ParseResult<'a, Self::Item> { 49 | parse_f_comp(input) 50 | } 51 | } 52 | 53 | #[cfg(test)] 54 | mod tests { 55 | use crate::parsers::UnwrapValue; 56 | use crate::{BinaryComp, BinaryOp, FComp, FExp, Parser}; 57 | 58 | #[test] 59 | fn test_parse() { 60 | assert!( 61 | FComp::parse("(= (+ 1.23 2.34) (+ 1.23 2.34))").is_value(FComp::new( 62 | BinaryComp::Equal, 63 | FExp::new_binary_op( 64 | BinaryOp::Addition, 65 | FExp::new_number(1.23), 66 | FExp::new_number(2.34), 67 | ), 68 | FExp::new_binary_op( 69 | BinaryOp::Addition, 70 | FExp::new_number(1.23), 71 | FExp::new_number(2.34), 72 | ) 73 | )) 74 | ); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/parsers/f_exp_t.rs: -------------------------------------------------------------------------------- 1 | //! Provides parsers for f-exps. 2 | 3 | use nom::branch::alt; 4 | use nom::bytes::complete::tag; 5 | use nom::character::complete::multispace1; 6 | use nom::combinator::map; 7 | use nom::sequence::{preceded, terminated, tuple}; 8 | 9 | use crate::parsers::prefix_expr; 10 | use crate::parsers::{parse_f_exp, ParseResult, Span}; 11 | use crate::types::FExpT; 12 | 13 | /// Parses an f-exp-t. 14 | /// 15 | /// ## Example 16 | /// ``` 17 | /// # use pddl::parsers::{parse_f_exp, parse_f_exp_t, preamble::*}; 18 | /// # use pddl::{BinaryOp, FExp, FExpT, FHead, FunctionSymbol, MultiOp, Term, Variable}; 19 | /// assert!(parse_f_exp_t("#t").is_value(FExpT::Now)); 20 | /// 21 | /// assert!(parse_f_exp_t("(* (fuel ?tank) #t)").is_value( 22 | /// FExpT::new_scaled( 23 | /// FExp::new_function( 24 | /// FHead::new_with_terms( 25 | /// FunctionSymbol::from_str("fuel"), 26 | /// [Term::Variable(Variable::from_str("tank"))] 27 | /// ) 28 | /// ) 29 | /// ) 30 | /// )); 31 | /// 32 | /// assert!(parse_f_exp_t("(* #t (fuel ?tank))").is_value( 33 | /// FExpT::new_scaled( 34 | /// FExp::new_function( 35 | /// FHead::new_with_terms( 36 | /// FunctionSymbol::from_str("fuel"), 37 | /// [Term::Variable(Variable::from_str("tank"))] 38 | /// ) 39 | /// ) 40 | /// ) 41 | /// )); 42 | ///``` 43 | pub fn parse_f_exp_t<'a, T: Into>>(input: T) -> ParseResult<'a, FExpT> { 44 | let now = map(tag("#t"), |_| FExpT::new()); 45 | let scaled = map( 46 | prefix_expr( 47 | "*", 48 | alt(( 49 | preceded(tuple((tag("#t"), multispace1)), parse_f_exp), 50 | terminated(parse_f_exp, tuple((multispace1, tag("#t")))), 51 | )), 52 | ), 53 | FExpT::new_scaled, 54 | ); 55 | 56 | alt((scaled, now))(input.into()) 57 | } 58 | 59 | impl crate::parsers::Parser for FExpT { 60 | type Item = FExpT; 61 | 62 | /// See [`parse_f_exp_t`]. 63 | fn parse<'a, S: Into>>(input: S) -> ParseResult<'a, Self::Item> { 64 | parse_f_exp_t(input) 65 | } 66 | } 67 | 68 | #[cfg(test)] 69 | mod tests { 70 | use crate::parsers::UnwrapValue; 71 | use crate::{FExp, FExpT, FHead, FunctionSymbol, Parser, Term, Variable}; 72 | 73 | #[test] 74 | fn test_parse() { 75 | assert!(FExpT::parse("#t").is_value(FExpT::Now)); 76 | 77 | assert!( 78 | FExpT::parse("(* (fuel ?tank) #t)").is_value(FExpT::new_scaled(FExp::new_function( 79 | FHead::new_with_terms( 80 | FunctionSymbol::from_str("fuel"), 81 | [Term::Variable(Variable::from_str("tank"))] 82 | ) 83 | ))) 84 | ); 85 | 86 | assert!( 87 | FExpT::parse("(* #t (fuel ?tank))").is_value(FExpT::new_scaled(FExp::new_function( 88 | FHead::new_with_terms( 89 | FunctionSymbol::from_str("fuel"), 90 | [Term::Variable(Variable::from_str("tank"))] 91 | ) 92 | ))) 93 | ); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/parsers/f_head.rs: -------------------------------------------------------------------------------- 1 | //! Provides parsers for f-heads. 2 | 3 | use nom::branch::alt; 4 | use nom::character::complete::multispace1; 5 | use nom::combinator::map; 6 | use nom::sequence::{preceded, tuple}; 7 | 8 | use crate::parsers::{parens, space_separated_list0, ParseResult, Span}; 9 | use crate::parsers::{parse_function_symbol, parse_term}; 10 | use crate::types::FHead; 11 | 12 | /// Parses an f-head. 13 | /// 14 | /// ## Example 15 | /// ``` 16 | /// # use pddl::parsers::{parse_f_head, preamble::*}; 17 | /// # use pddl::{FunctionTerm, Variable, FunctionSymbol, Term, FHead}; 18 | /// assert!(parse_f_head("fun-sym").is_value( 19 | /// FHead::new(FunctionSymbol::from_str("fun-sym")) 20 | /// )); 21 | /// 22 | /// assert!(parse_f_head("(fun-sym)").is_value( 23 | /// FHead::new(FunctionSymbol::from_str("fun-sym")) 24 | /// )); 25 | /// 26 | /// assert!(parse_f_head("(fun-sym term)").is_value( 27 | /// FHead::new_with_terms(FunctionSymbol::from_str("fun-sym"), [ 28 | /// Term::Name("term".into()) 29 | /// ]) 30 | /// )); 31 | ///``` 32 | pub fn parse_f_head<'a, T: Into>>(input: T) -> ParseResult<'a, FHead> { 33 | let simple = map(parse_function_symbol, FHead::new); 34 | let simple_parens = map(parens(parse_function_symbol), FHead::new); 35 | let with_terms = map( 36 | parens(tuple(( 37 | parse_function_symbol, 38 | preceded(multispace1, space_separated_list0(parse_term)), 39 | ))), 40 | |(symbol, terms)| FHead::new_with_terms(symbol, terms), 41 | ); 42 | 43 | alt((simple, simple_parens, with_terms))(input.into()) 44 | } 45 | 46 | impl crate::parsers::Parser for FHead { 47 | type Item = FHead; 48 | 49 | /// See [`parse_f_head`]. 50 | fn parse<'a, S: Into>>(input: S) -> ParseResult<'a, Self::Item> { 51 | parse_f_head(input) 52 | } 53 | } 54 | 55 | #[cfg(test)] 56 | mod tests { 57 | use crate::parsers::UnwrapValue; 58 | use crate::{FHead, FunctionSymbol, Parser, Term}; 59 | 60 | #[test] 61 | fn test_parse() { 62 | assert!(FHead::parse("fun-sym").is_value(FHead::new(FunctionSymbol::from_str("fun-sym")))); 63 | 64 | assert!(FHead::parse("(fun-sym)").is_value(FHead::new(FunctionSymbol::from_str("fun-sym")))); 65 | 66 | assert!( 67 | FHead::parse("(fun-sym term)").is_value(FHead::new_with_terms( 68 | FunctionSymbol::from_str("fun-sym"), 69 | [Term::Name("term".into())] 70 | )) 71 | ); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/parsers/function_symbol.rs: -------------------------------------------------------------------------------- 1 | //! Provides parsers for function symbols. 2 | 3 | use crate::parsers::{parse_name, ParseResult, Span}; 4 | use crate::types::FunctionSymbol; 5 | use nom::combinator::map; 6 | 7 | /// Parses a function symbol, i.e. ``. 8 | /// 9 | /// ## Example 10 | /// ``` 11 | /// # use pddl::parsers::{parse_function_symbol, preamble::*}; 12 | /// assert!(parse_function_symbol("abcde").is_value("abcde".into())); 13 | /// assert!(parse_function_symbol("a-1_2").is_value("a-1_2".into())); 14 | /// assert!(parse_function_symbol("Z01").is_value("Z01".into())); 15 | /// assert!(parse_function_symbol("x-_-_").is_value("x-_-_".into())); 16 | /// 17 | /// assert!(parse_function_symbol("").is_err()); 18 | /// assert!(parse_function_symbol(".").is_err()); 19 | /// assert!(parse_function_symbol("-abc").is_err()); 20 | /// assert!(parse_function_symbol("0124").is_err()); 21 | /// assert!(parse_function_symbol("-1").is_err()); 22 | ///``` 23 | pub fn parse_function_symbol<'a, T: Into>>(input: T) -> ParseResult<'a, FunctionSymbol> { 24 | map(parse_name, FunctionSymbol::new)(input.into()) 25 | } 26 | 27 | impl crate::parsers::Parser for FunctionSymbol { 28 | type Item = FunctionSymbol; 29 | 30 | /// Parses a function symbol. 31 | /// 32 | /// ## Example 33 | /// ``` 34 | /// # use pddl::{FunctionSymbol, Parser}; 35 | /// let (_, value) = FunctionSymbol::parse("abcde").unwrap(); 36 | /// assert_eq!(value, "abcde".into()); 37 | ///``` 38 | /// 39 | /// ## See also 40 | /// See [`parse_function_symbol`]. 41 | fn parse<'a, S: Into>>(input: S) -> ParseResult<'a, Self::Item> { 42 | parse_function_symbol(input) 43 | } 44 | } 45 | 46 | #[cfg(test)] 47 | mod tests { 48 | use crate::parsers::UnwrapValue; 49 | use crate::{FunctionSymbol, Parser}; 50 | 51 | #[test] 52 | fn test_parse() { 53 | assert!(FunctionSymbol::parse("abcde").is_value("abcde".into())); 54 | assert!(FunctionSymbol::parse("a-1_2").is_value("a-1_2".into())); 55 | assert!(FunctionSymbol::parse("Z01").is_value("Z01".into())); 56 | assert!(FunctionSymbol::parse("x-_-_").is_value("x-_-_".into())); 57 | 58 | assert!(FunctionSymbol::parse("").is_err()); 59 | assert!(FunctionSymbol::parse(".").is_err()); 60 | assert!(FunctionSymbol::parse("-abc").is_err()); 61 | assert!(FunctionSymbol::parse("0124").is_err()); 62 | assert!(FunctionSymbol::parse("-1").is_err()); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/parsers/function_term.rs: -------------------------------------------------------------------------------- 1 | //! Provides parsers for function terms. 2 | 3 | use crate::parsers::{parse_function_symbol, parse_term}; 4 | use crate::parsers::{space_separated_list0, ParseResult, Span}; 5 | use crate::types::FunctionTerm; 6 | use nom::bytes::complete::tag; 7 | use nom::combinator::map; 8 | use nom::sequence::{delimited, tuple}; 9 | 10 | /// Parses a function terms, i.e. `( *)`. 11 | /// 12 | /// ## Example 13 | /// ``` 14 | /// # use pddl::parsers::{parse_function_term, preamble::*}; 15 | /// # use pddl::{FunctionTerm, Variable, FunctionSymbol, Term}; 16 | /// assert!(parse_function_term("(fun-sym)").is_value(FunctionTerm::new("fun-sym".into(), vec![]))); 17 | /// 18 | /// let x = Term::Name("x".into()); 19 | /// assert!(parse_function_term("(fun-sym x)").is_value(FunctionTerm::new("fun-sym".into(), vec![x]))); 20 | /// 21 | /// let x = Term::Name("x".into()); 22 | /// let y = Term::Variable("y".into()); 23 | /// assert!(parse_function_term("(fun-sym ?y x)").is_value(FunctionTerm::new("fun-sym".into(), vec![y, x]))); 24 | /// 25 | /// let x = Term::Name("x".into()); 26 | /// let y = Term::Variable("y".into()); 27 | /// let a = Term::Name("a".into()); 28 | /// let ft = Term::Function(FunctionTerm::new(FunctionSymbol::from("fn"), vec![a])); 29 | /// assert!(parse_function_term("(fun-sym ?y x (fn a))").is_value(FunctionTerm::new("fun-sym".into(), vec![y, x, ft]))); 30 | ///``` 31 | pub fn parse_function_term<'a, T: Into>>(input: T) -> ParseResult<'a, FunctionTerm> { 32 | map( 33 | delimited( 34 | tag("("), 35 | tuple((parse_function_symbol, space_separated_list0(parse_term))), 36 | tag(")"), 37 | ), 38 | |(symbol, terms)| FunctionTerm::new(symbol, terms), 39 | )(input.into()) 40 | } 41 | 42 | impl crate::parsers::Parser for FunctionTerm { 43 | type Item = FunctionTerm; 44 | 45 | /// See [`parse_function_term`]. 46 | fn parse<'a, S: Into>>(input: S) -> ParseResult<'a, Self::Item> { 47 | parse_function_term(input) 48 | } 49 | } 50 | 51 | #[cfg(test)] 52 | mod tests { 53 | use crate::parsers::UnwrapValue; 54 | use crate::{FunctionSymbol, FunctionTerm, Parser, Term}; 55 | 56 | #[test] 57 | fn test_parse() { 58 | assert!( 59 | FunctionTerm::parse("(fun-sym)").is_value(FunctionTerm::new("fun-sym".into(), vec![])) 60 | ); 61 | 62 | let x = Term::Name("x".into()); 63 | assert!(FunctionTerm::parse("(fun-sym x)") 64 | .is_value(FunctionTerm::new("fun-sym".into(), vec![x]))); 65 | 66 | let x = Term::Name("x".into()); 67 | let y = Term::Variable("y".into()); 68 | assert!(FunctionTerm::parse("(fun-sym ?y x)") 69 | .is_value(FunctionTerm::new("fun-sym".into(), vec![y, x]))); 70 | 71 | let x = Term::Name("x".into()); 72 | let y = Term::Variable("y".into()); 73 | let a = Term::Name("a".into()); 74 | let ft = Term::Function(FunctionTerm::new(FunctionSymbol::from("fn"), vec![a])); 75 | assert!(FunctionTerm::parse("(fun-sym ?y x (fn a))") 76 | .is_value(FunctionTerm::new("fun-sym".into(), vec![y, x, ft]))); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/parsers/function_type.rs: -------------------------------------------------------------------------------- 1 | //! Provides parsers for function types. 2 | 3 | use crate::parsers::{parse_type, ParseResult, Span}; 4 | use crate::types::FunctionType; 5 | use nom::combinator::map; 6 | 7 | /// Parses a primitive type, i.e. `object | `. 8 | /// 9 | /// ## Example 10 | /// ``` 11 | /// # use pddl::parsers::{parse_function_type, preamble::*}; 12 | /// # use pddl::{FunctionType}; 13 | /// # use pddl::Type; 14 | /// assert!(parse_function_type("number").is_value(FunctionType::new(Type::Exactly("number".into())))); 15 | /// assert!(parse_function_type("(either object number)").is_value(FunctionType::new(Type::from_iter(["object", "number"])))); 16 | ///``` 17 | pub fn parse_function_type<'a, T: Into>>(input: T) -> ParseResult<'a, FunctionType> { 18 | map(parse_type, FunctionType::from)(input.into()) 19 | } 20 | 21 | impl crate::parsers::Parser for FunctionType { 22 | type Item = FunctionType; 23 | 24 | /// See [`parse_function_type`]. 25 | fn parse<'a, S: Into>>(input: S) -> ParseResult<'a, Self::Item> { 26 | parse_function_type(input) 27 | } 28 | } 29 | 30 | #[cfg(test)] 31 | mod tests { 32 | use crate::parsers::UnwrapValue; 33 | use crate::{FunctionType, Parser, Type}; 34 | 35 | #[test] 36 | fn test_parse() { 37 | assert!(FunctionType::parse("number") 38 | .is_value(FunctionType::new(Type::Exactly("number".into())))); 39 | assert!(FunctionType::parse("(either object number)") 40 | .is_value(FunctionType::new(Type::from_iter(["object", "number"])))); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/parsers/functions_def.rs: -------------------------------------------------------------------------------- 1 | //! Provides parsers for constant definitions. 2 | 3 | use nom::combinator::map; 4 | 5 | use crate::parsers::{function_typed_list, parse_atomic_function_skeleton}; 6 | use crate::parsers::{prefix_expr, ParseResult, Span}; 7 | use crate::types::Functions; 8 | 9 | /// Parses constant definitions, i.e. `(:constants )`. 10 | /// 11 | /// ## Example 12 | /// ``` 13 | /// # use pddl::parsers::{parse_functions_def, preamble::*}; 14 | /// # use pddl::{Variable, AtomicFormulaSkeleton, Predicate, PredicateDefinitions, FunctionTypedList, FunctionTyped, AtomicFunctionSkeleton, FunctionSymbol, Functions}; 15 | /// # use pddl::{Type, Typed, TypedList}; 16 | /// let input = "(:functions (battery-amount ?r - rover))"; 17 | /// assert!(parse_functions_def(input).is_value( 18 | /// Functions::from_iter([ 19 | /// FunctionTyped::new_number( 20 | /// AtomicFunctionSkeleton::new( 21 | /// FunctionSymbol::from_str("battery-amount"), 22 | /// TypedList::from_iter([ 23 | /// Typed::new(Variable::from("r"), Type::Exactly("rover".into())) 24 | /// ]) 25 | /// ) 26 | /// ) 27 | /// ]) 28 | /// )); 29 | /// ``` 30 | pub fn parse_functions_def<'a, T: Into>>(input: T) -> ParseResult<'a, Functions> { 31 | map( 32 | prefix_expr( 33 | ":functions", 34 | function_typed_list(parse_atomic_function_skeleton), 35 | ), 36 | Functions::new, 37 | )(input.into()) 38 | } 39 | 40 | impl crate::parsers::Parser for Functions { 41 | type Item = Functions; 42 | 43 | /// See [`parse_functions_def`]. 44 | fn parse<'a, S: Into>>(input: S) -> ParseResult<'a, Self::Item> { 45 | parse_functions_def(input) 46 | } 47 | } 48 | 49 | #[cfg(test)] 50 | mod tests { 51 | use crate::parsers::UnwrapValue; 52 | use crate::{ 53 | AtomicFunctionSkeleton, FunctionSymbol, FunctionTyped, Functions, Parser, Type, Typed, 54 | TypedList, Variable, 55 | }; 56 | 57 | #[test] 58 | fn test_parse() { 59 | let input = "(:functions (battery-amount ?r - rover))"; 60 | assert!(Functions::parse(input).is_value(Functions::from_iter([ 61 | FunctionTyped::new_number(AtomicFunctionSkeleton::new( 62 | FunctionSymbol::from_str("battery-amount"), 63 | TypedList::from_iter([Typed::new( 64 | Variable::from("r"), 65 | Type::Exactly("rover".into()) 66 | )]) 67 | )) 68 | ]))); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/parsers/goal_def.rs: -------------------------------------------------------------------------------- 1 | //! Provides parsers for pre-GD goal definitions. 2 | 3 | use crate::parsers::{parse_pre_gd, prefix_expr, ParseResult, Span}; 4 | use crate::types::GoalDef; 5 | use nom::combinator::map; 6 | 7 | /// Parses pre-GD goal definitions. 8 | /// 9 | /// ## Example 10 | /// ``` 11 | /// # use pddl::parsers::{parse_problem_goal_def, preamble::*}; 12 | /// # use pddl::{AtomicFormula, GoalDef, GoalDefinition, PreferenceGD, PreconditionGoalDefinition, Term}; 13 | /// let input = "(:goal (= x y))"; 14 | /// assert!(parse_problem_goal_def(input).is_value( 15 | /// GoalDef::from( 16 | /// PreconditionGoalDefinition::Preference( 17 | /// PreferenceGD::Goal( 18 | /// GoalDefinition::AtomicFormula( 19 | /// AtomicFormula::new_equality( 20 | /// Term::Name("x".into()), 21 | /// Term::Name("y".into()) 22 | /// ) 23 | /// ) 24 | /// ) 25 | /// ) 26 | /// ) 27 | /// )); 28 | /// ``` 29 | pub fn parse_problem_goal_def<'a, T: Into>>(input: T) -> ParseResult<'a, GoalDef> { 30 | map(prefix_expr(":goal", parse_pre_gd), GoalDef::new)(input.into()) 31 | } 32 | 33 | impl crate::parsers::Parser for GoalDef { 34 | type Item = GoalDef; 35 | 36 | /// See [`parse_problem_goal_def`]. 37 | fn parse<'a, S: Into>>(input: S) -> ParseResult<'a, Self::Item> { 38 | parse_problem_goal_def(input) 39 | } 40 | } 41 | 42 | #[cfg(test)] 43 | mod tests { 44 | use crate::parsers::UnwrapValue; 45 | use crate::{ 46 | AtomicFormula, GoalDef, GoalDefinition, Parser, PreconditionGoalDefinition, PreferenceGD, 47 | Term, 48 | }; 49 | 50 | #[test] 51 | fn test_parse() { 52 | let input = "(:goal (= x y))"; 53 | assert!(GoalDef::parse(input).is_value(GoalDef::from( 54 | PreconditionGoalDefinition::Preference(PreferenceGD::Goal( 55 | GoalDefinition::AtomicFormula(AtomicFormula::new_equality( 56 | Term::Name("x".into()), 57 | Term::Name("y".into()) 58 | )) 59 | )) 60 | ))); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/parsers/init_def.rs: -------------------------------------------------------------------------------- 1 | //! Provides parsers for goal initial state definitions. 2 | 3 | use nom::combinator::map; 4 | 5 | use crate::parsers::{parse_init_el, prefix_expr, space_separated_list0, ParseResult, Span}; 6 | use crate::types::InitElements; 7 | 8 | /// Parser for goal initial state definitions. 9 | /// 10 | /// ## Example 11 | /// ``` 12 | /// # use pddl::parsers::{parse_problem_init_def, preamble::*}; 13 | /// # use pddl::{AtomicFormula, InitElement, InitElements, NameLiteral, Number}; 14 | /// let input = "(:init (train-not-in-use train1) (at 10 (train-not-in-use train2)))"; 15 | /// assert!(parse_problem_init_def(input).is_value( 16 | /// InitElements::from_iter([ 17 | /// InitElement::new_literal( 18 | /// NameLiteral::new( 19 | /// AtomicFormula::new_predicate( 20 | /// "train-not-in-use".into(), 21 | /// ["train1".into()] 22 | /// ) 23 | /// ) 24 | /// ), 25 | /// InitElement::new_at( 26 | /// Number::from(10), 27 | /// NameLiteral::new( 28 | /// AtomicFormula::new_predicate( 29 | /// "train-not-in-use".into(), 30 | /// ["train2".into()] 31 | /// ) 32 | /// ) 33 | /// ) 34 | /// ]) 35 | /// )); 36 | /// ``` 37 | pub fn parse_problem_init_def<'a, T: Into>>(input: T) -> ParseResult<'a, InitElements> { 38 | map( 39 | prefix_expr(":init", space_separated_list0(parse_init_el)), 40 | InitElements::new, 41 | )(input.into()) 42 | } 43 | impl crate::parsers::Parser for InitElements { 44 | type Item = InitElements; 45 | 46 | /// See [`parse_problem_init_def`]. 47 | fn parse<'a, S: Into>>(input: S) -> ParseResult<'a, Self::Item> { 48 | parse_problem_init_def(input) 49 | } 50 | } 51 | 52 | #[cfg(test)] 53 | mod tests { 54 | use crate::parsers::UnwrapValue; 55 | use crate::{AtomicFormula, InitElement, InitElements, NameLiteral, Number, Parser}; 56 | 57 | #[test] 58 | fn test_parse() { 59 | let input = "(:init (train-not-in-use train1) (at 10 (train-not-in-use train2)))"; 60 | assert!( 61 | InitElements::parse(input).is_value(InitElements::from_iter([ 62 | InitElement::new_literal(NameLiteral::new(AtomicFormula::new_predicate( 63 | "train-not-in-use".into(), 64 | ["train1".into()] 65 | ))), 66 | InitElement::new_at( 67 | Number::from(10), 68 | NameLiteral::new(AtomicFormula::new_predicate( 69 | "train-not-in-use".into(), 70 | ["train2".into()] 71 | )) 72 | ) 73 | ])) 74 | ); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/parsers/interval.rs: -------------------------------------------------------------------------------- 1 | //! Provides parsers for assignment operations. 2 | 3 | use nom::bytes::complete::tag; 4 | use nom::combinator::map; 5 | 6 | use crate::parsers::{ParseResult, Span}; 7 | use crate::types::interval::names; 8 | use crate::types::Interval; 9 | 10 | /// Parses an intervals, i.e. `all`. 11 | /// 12 | /// ## Example 13 | /// ``` 14 | /// # use pddl::parsers::{parse_interval, preamble::*}; 15 | /// # use pddl::{Interval}; 16 | /// assert!(parse_interval("all").is_value(Interval::All)); 17 | ///``` 18 | pub fn parse_interval<'a, T: Into>>(input: T) -> ParseResult<'a, Interval> { 19 | map(tag(names::ALL), |x: Span| { 20 | Interval::try_from(*x.fragment()).expect("unhandled variant") 21 | })(input.into()) 22 | } 23 | 24 | impl crate::parsers::Parser for Interval { 25 | type Item = Interval; 26 | 27 | /// See [`parse_interval`]. 28 | fn parse<'a, S: Into>>(input: S) -> ParseResult<'a, Self::Item> { 29 | parse_interval(input) 30 | } 31 | } 32 | 33 | #[cfg(test)] 34 | mod tests { 35 | use crate::parsers::UnwrapValue; 36 | use crate::{Interval, Parser}; 37 | 38 | #[test] 39 | fn test_parse() { 40 | assert!(Interval::parse("all").is_value(Interval::All)); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/parsers/length_spec.rs: -------------------------------------------------------------------------------- 1 | //! Provides parsers for length specification. 2 | 3 | use nom::character::complete::multispace0; 4 | use nom::combinator::{map, opt}; 5 | use nom::sequence::{preceded, tuple}; 6 | 7 | use crate::parsers::{prefix_expr, ParseResult, Span}; 8 | use crate::types::LengthSpec; 9 | 10 | /// Parses a length specification. Deprecated since PDDL 2.1. 11 | /// 12 | /// ## Example 13 | /// ``` 14 | /// # use pddl::parsers::{parse_problem_length_spec, preamble::*}; 15 | /// # use pddl::LengthSpec; 16 | /// assert!(parse_problem_length_spec("(:length)").is_value(LengthSpec::default())); 17 | /// assert!(parse_problem_length_spec("(:length (:serial 123))").is_value(LengthSpec::new_serial(123))); 18 | /// assert!(parse_problem_length_spec("(:length (:parallel 42))").is_value(LengthSpec::new_parallel(42))); 19 | /// assert!(parse_problem_length_spec("(:length (:serial 123) (:parallel 42))").is_value(LengthSpec::new(Some(123), Some(42)))); 20 | ///``` 21 | pub fn parse_problem_length_spec<'a, T: Into>>(input: T) -> ParseResult<'a, LengthSpec> { 22 | let serial = prefix_expr(":serial", nom::character::complete::u64); 23 | let parallel = prefix_expr(":parallel", nom::character::complete::u64); 24 | let length = prefix_expr( 25 | ":length", 26 | tuple((opt(serial), opt(preceded(multispace0, parallel)))), 27 | ); 28 | 29 | map(length, |(serial, parallel)| { 30 | LengthSpec::new(serial, parallel) 31 | })(input.into()) 32 | } 33 | 34 | impl crate::parsers::Parser for LengthSpec { 35 | type Item = LengthSpec; 36 | 37 | /// See [`parse_problem_length_spec`]. 38 | fn parse<'a, S: Into>>(input: S) -> ParseResult<'a, Self::Item> { 39 | parse_problem_length_spec(input) 40 | } 41 | } 42 | 43 | #[cfg(test)] 44 | mod tests { 45 | use crate::parsers::UnwrapValue; 46 | use crate::{LengthSpec, Parser}; 47 | 48 | #[test] 49 | fn test_parse() { 50 | assert!(LengthSpec::parse("(:length)").is_value(LengthSpec::default())); 51 | assert!(LengthSpec::parse("(:length (:serial 123))").is_value(LengthSpec::new_serial(123))); 52 | assert!( 53 | LengthSpec::parse("(:length (:parallel 42))").is_value(LengthSpec::new_parallel(42)) 54 | ); 55 | assert!(LengthSpec::parse("(:length (:serial 123) (:parallel 42))") 56 | .is_value(LengthSpec::new(Some(123), Some(42)))); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/parsers/literal.rs: -------------------------------------------------------------------------------- 1 | //! Provides parsers for literals. 2 | 3 | use nom::branch::alt; 4 | use nom::combinator::map; 5 | 6 | use crate::parsers::prefix_expr; 7 | use crate::parsers::{atomic_formula, ParseResult, Span}; 8 | use crate::types::Literal; 9 | 10 | /// Parser combinator that parses a literal, i.e. ` | (not )`. 11 | /// 12 | /// ## Example 13 | /// ``` 14 | /// # use nom::character::complete::alpha1; 15 | /// # use pddl::parsers::{literal, parse_name, preamble::*}; 16 | /// # use pddl::{AtomicFormula, EqualityAtomicFormula, PredicateAtomicFormula, Predicate, Literal}; 17 | /// assert!(literal(parse_name)(Span::new("(= x y)")).is_value( 18 | /// Literal::AtomicFormula( 19 | /// AtomicFormula::Equality( 20 | /// EqualityAtomicFormula::new( 21 | /// "x".into(), 22 | /// "y".into() 23 | /// ) 24 | /// ) 25 | /// ) 26 | /// )); 27 | /// assert!(literal(parse_name)(Span::new("(not (= x y))")).is_value( 28 | /// Literal::NotAtomicFormula( 29 | /// AtomicFormula::Equality( 30 | /// EqualityAtomicFormula::new( 31 | /// "x".into(), 32 | /// "y".into() 33 | /// ) 34 | /// ) 35 | /// ) 36 | /// )); 37 | /// ``` 38 | pub fn literal<'a, F, O>(inner: F) -> impl FnMut(Span<'a>) -> ParseResult<'a, Literal> 39 | where 40 | F: Clone + FnMut(Span<'a>) -> ParseResult<'a, O>, 41 | { 42 | let is = map(atomic_formula(inner.clone()), |af| Literal::new(af)); 43 | let is_not = map(prefix_expr("not", atomic_formula(inner)), |af| { 44 | Literal::new_not(af) 45 | }); 46 | 47 | alt((is_not, is)) 48 | } 49 | 50 | #[cfg(test)] 51 | mod tests { 52 | use crate::parsers::{literal, parse_name, Span, UnwrapValue}; 53 | use crate::{AtomicFormula, EqualityAtomicFormula, Literal}; 54 | 55 | #[test] 56 | fn test_parse() { 57 | assert!( 58 | literal(parse_name)(Span::new("(= x y)")).is_value(Literal::AtomicFormula( 59 | AtomicFormula::Equality(EqualityAtomicFormula::new("x".into(), "y".into())) 60 | )) 61 | ); 62 | assert!(literal(parse_name)(Span::new("(not (= x y))")).is_value( 63 | Literal::NotAtomicFormula(AtomicFormula::Equality(EqualityAtomicFormula::new( 64 | "x".into(), 65 | "y".into() 66 | ))) 67 | )); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/parsers/metric_spec.rs: -------------------------------------------------------------------------------- 1 | //! Provides parsers for metric specification. 2 | 3 | use nom::character::complete::multispace1; 4 | use nom::combinator::map; 5 | use nom::sequence::{preceded, tuple}; 6 | 7 | use crate::parsers::{parse_metric_f_exp, parse_optimization, prefix_expr, ParseResult, Span}; 8 | use crate::types::MetricSpec; 9 | 10 | /// Parses a metric specification. 11 | /// 12 | /// ## Example 13 | /// ``` 14 | /// # use pddl::parsers::{parse_problem_metric_spec, preamble::*}; 15 | /// # use pddl::{MetricFExp, MetricSpec, Optimization}; 16 | /// assert!(parse_problem_metric_spec("(:metric minimize total-time)").is_value( 17 | /// MetricSpec::new( 18 | /// Optimization::Minimize, 19 | /// MetricFExp::TotalTime 20 | /// ) 21 | /// )); 22 | ///``` 23 | pub fn parse_problem_metric_spec<'a, T: Into>>(input: T) -> ParseResult<'a, MetricSpec> { 24 | // :numeric-fluents 25 | map( 26 | prefix_expr( 27 | ":metric", 28 | tuple(( 29 | parse_optimization, 30 | preceded(multispace1, parse_metric_f_exp), 31 | )), 32 | ), 33 | |(optimization, exp)| MetricSpec::new(optimization, exp), 34 | )(input.into()) 35 | } 36 | 37 | impl crate::parsers::Parser for MetricSpec { 38 | type Item = MetricSpec; 39 | 40 | /// See [`parse_problem_metric_spec`]. 41 | fn parse<'a, S: Into>>(input: S) -> ParseResult<'a, Self::Item> { 42 | parse_problem_metric_spec(input) 43 | } 44 | } 45 | 46 | #[cfg(test)] 47 | mod tests { 48 | use crate::parsers::UnwrapValue; 49 | use crate::{MetricFExp, MetricSpec, Optimization, Parser}; 50 | 51 | #[test] 52 | fn test_parse() { 53 | assert!( 54 | MetricSpec::parse("(:metric minimize total-time)").is_value(MetricSpec::new( 55 | Optimization::Minimize, 56 | MetricFExp::TotalTime 57 | )) 58 | ); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/parsers/multi_op.rs: -------------------------------------------------------------------------------- 1 | //! Provides parsers for multi-operand operations. 2 | 3 | use nom::branch::alt; 4 | use nom::bytes::complete::tag; 5 | use nom::combinator::map; 6 | 7 | use crate::parsers::{ParseResult, Span}; 8 | use crate::types::{multi_op::names, MultiOp}; 9 | 10 | /// Parses a multi-operand operation, i.e. `* | +`. 11 | /// 12 | /// ## Example 13 | /// ``` 14 | /// # use pddl::parsers::{parse_multi_op, preamble::*}; 15 | /// # use pddl::{MultiOp}; 16 | /// assert!(parse_multi_op("*").is_value(MultiOp::Multiplication)); 17 | /// assert!(parse_multi_op("+").is_value(MultiOp::Addition)); 18 | ///``` 19 | pub fn parse_multi_op<'a, T: Into>>(input: T) -> ParseResult<'a, MultiOp> { 20 | map( 21 | alt((tag(names::MULTIPLICATION), tag(names::ADDITION))), 22 | |x: Span| MultiOp::try_from(*x.fragment()).expect("unhandled variant"), 23 | )(input.into()) 24 | } 25 | 26 | impl crate::parsers::Parser for MultiOp { 27 | type Item = MultiOp; 28 | 29 | /// See [`parse_multi_op`]. 30 | fn parse<'a, S: Into>>(input: S) -> ParseResult<'a, Self::Item> { 31 | parse_multi_op(input) 32 | } 33 | } 34 | 35 | #[cfg(test)] 36 | mod tests { 37 | use crate::parsers::UnwrapValue; 38 | use crate::{MultiOp, Parser}; 39 | 40 | #[test] 41 | fn test_parse() { 42 | assert!(MultiOp::parse("*").is_value(MultiOp::Multiplication)); 43 | assert!(MultiOp::parse("+").is_value(MultiOp::Addition)); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/parsers/name.rs: -------------------------------------------------------------------------------- 1 | //! Provides parsers for names. 2 | 3 | use crate::parsers::{ws, ParseResult, Span}; 4 | use crate::types::Name; 5 | use nom::branch::alt; 6 | use nom::bytes::complete::tag; 7 | use nom::character::complete::{alpha1, digit1}; 8 | use nom::combinator::{map, recognize}; 9 | use nom::multi::many0; 10 | use nom::sequence::tuple; 11 | 12 | /// Parses a name, i.e. ` ⁺`. 13 | /// 14 | /// ## Example 15 | /// ``` 16 | /// # use pddl::parsers::{parse_name, preamble::*}; 17 | /// assert!(parse_name("abcde").is_value("abcde".into())); 18 | /// assert!(parse_name("a-1_2").is_value("a-1_2".into())); 19 | /// assert!(parse_name("Z01").is_value("Z01".into())); 20 | /// assert!(parse_name("x-_-_").is_value("x-_-_".into())); 21 | /// 22 | /// assert!(parse_name("").is_err()); 23 | /// assert!(parse_name(".").is_err()); 24 | /// assert!(parse_name("-abc").is_err()); 25 | /// assert!(parse_name("0124").is_err()); 26 | /// assert!(parse_name("-1").is_err()); 27 | ///``` 28 | pub fn parse_name<'a, T: Into>>(input: T) -> ParseResult<'a, Name> { 29 | map( 30 | ws(recognize(tuple((alpha1, many0(parse_any_char))))), 31 | |x: Span| Name::from(*x.fragment()), 32 | )(input.into()) 33 | } 34 | 35 | /// Parses any accepted character. 36 | pub fn parse_any_char(input: Span) -> ParseResult { 37 | recognize(alt((alpha1, digit1, tag("-"), tag("_"))))(input) 38 | } 39 | 40 | impl crate::parsers::Parser for Name { 41 | type Item = Name; 42 | 43 | /// See [`parse_name`]. 44 | fn parse<'a, S: Into>>(input: S) -> ParseResult<'a, Self::Item> { 45 | parse_name(input) 46 | } 47 | } 48 | 49 | #[cfg(test)] 50 | mod test { 51 | use super::*; 52 | use crate::parsers::Match; 53 | use crate::Parser; 54 | 55 | #[test] 56 | fn parse_name_works() { 57 | assert!(Name::parse(Span::new("abcde")).is_exactly("abcde")); 58 | } 59 | 60 | #[test] 61 | fn parse_any_char_works() { 62 | assert!(parse_any_char(Span::new("abc")).is_exactly("abc")); 63 | assert!(parse_any_char(Span::new("1")).is_exactly("1")); 64 | assert!(parse_any_char(Span::new("-.")).is_result(".", "-")); 65 | assert!(parse_any_char(Span::new("_")).is_exactly("_")); 66 | assert!(parse_any_char(Span::new(".")).is_err()); 67 | assert!(parse_any_char(Span::new(".")).is_err()); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/parsers/number.rs: -------------------------------------------------------------------------------- 1 | //! Provides parsers for numbers, decimals and digits. 2 | 3 | use nom::character::complete::{char, digit1}; 4 | use nom::combinator::{map, recognize}; 5 | use nom::multi::many_m_n; 6 | use nom::number::complete::float; 7 | use nom::sequence::tuple; 8 | use nom::Parser; 9 | 10 | use crate::parsers::{ParseResult, Span}; 11 | use crate::types::Number; 12 | 13 | /// Parses a number, i.e. `⁺[]`. 14 | /// 15 | /// ## Example 16 | /// ``` 17 | /// # use pddl::parsers::{parse_number, preamble::*}; 18 | /// assert!(parse_number("0").is_value(0.0.into())); 19 | /// assert!(parse_number("1000a").is_value(1000.0.into())); 20 | /// assert!(parse_number("012").is_value(12.0.into())); 21 | /// assert!(parse_number("1.234").is_value(1.234.into())); 22 | /// 23 | /// assert!(parse_number(".0").is_err()); 24 | /// assert!(parse_number(".").is_err()); 25 | /// assert!(parse_number("-1").is_err()); 26 | ///``` 27 | pub fn parse_number<'a, T: Into>>(input: T) -> ParseResult<'a, Number> { 28 | let pattern = recognize(tuple((digit1, many_m_n(0, 1, parse_decimal)))); 29 | let float = pattern.and_then(float); 30 | map(float, Number::new)(input.into()) 31 | } 32 | 33 | /// Parses a decimal, i.e. `.⁺`. 34 | pub fn parse_decimal(input: Span) -> ParseResult { 35 | recognize(tuple((char('.'), digit1)))(input) 36 | } 37 | 38 | impl crate::parsers::Parser for Number { 39 | type Item = Number; 40 | 41 | /// See [`parse_number`]. 42 | fn parse<'a, S: Into>>(input: S) -> ParseResult<'a, Self::Item> { 43 | parse_number(input) 44 | } 45 | } 46 | 47 | #[cfg(test)] 48 | mod tests { 49 | use crate::parsers::number::parse_decimal; 50 | use crate::parsers::{Match, Span}; 51 | use crate::{Number, Parser}; 52 | 53 | #[test] 54 | fn parse_decimal_works() { 55 | assert!(parse_decimal(Span::new(".0")).is_exactly(".0")); 56 | assert!(parse_decimal(Span::new(".012")).is_exactly(".012")); 57 | assert!(parse_decimal(Span::new(".")).is_err()); 58 | assert!(parse_decimal(Span::new("012")).is_err()); 59 | } 60 | 61 | #[test] 62 | fn test_parse() { 63 | let (_, value) = Number::parse("1.20").unwrap(); 64 | assert_eq!(value, Number::from(1.2)); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/parsers/objects_def.rs: -------------------------------------------------------------------------------- 1 | //! Provides parsers for goal object declarations. 2 | 3 | use nom::combinator::map; 4 | 5 | use crate::parsers::{parse_name, prefix_expr, typed_list, ParseResult, Span}; 6 | use crate::types::Objects; 7 | 8 | /// Parser for goal object declarations. 9 | /// 10 | /// ## Example 11 | /// ``` 12 | /// # use pddl::parsers::{parse_problem_objects_declaration, preamble::*}; 13 | /// # use pddl::{Name, Objects, ToTyped, Type}; 14 | /// let input = "(:objects train1 train2)"; 15 | /// assert!(parse_problem_objects_declaration(input).is_value( 16 | /// Objects::new([ 17 | /// Name::new("train1").to_typed(Type::OBJECT), 18 | /// Name::new("train2").to_typed(Type::OBJECT), 19 | /// ]) 20 | /// )); 21 | /// ``` 22 | pub fn parse_problem_objects_declaration<'a, T: Into>>( 23 | input: T, 24 | ) -> ParseResult<'a, Objects> { 25 | map( 26 | prefix_expr(":objects", typed_list(parse_name)), 27 | Objects::new, 28 | )(input.into()) 29 | } 30 | 31 | impl crate::parsers::Parser for Objects { 32 | type Item = Objects; 33 | 34 | /// See [`parse_problem_objects_declaration`]. 35 | fn parse<'a, S: Into>>(input: S) -> ParseResult<'a, Self::Item> { 36 | parse_problem_objects_declaration(input) 37 | } 38 | } 39 | 40 | #[cfg(test)] 41 | mod test { 42 | use crate::parsers::UnwrapValue; 43 | use crate::{Name, Parser, ToTyped, Type}; 44 | 45 | use super::*; 46 | 47 | #[test] 48 | fn test_parse() { 49 | let input = "(:objects train1 train2)"; 50 | assert!(Objects::parse(input).is_value(Objects::new([ 51 | Name::new("train1").to_typed(Type::OBJECT), 52 | Name::new("train2").to_typed(Type::OBJECT), 53 | ]))); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/parsers/optimization.rs: -------------------------------------------------------------------------------- 1 | //! Provides parsers for optimization. 2 | 3 | use crate::parsers::{ParseResult, Span}; 4 | use crate::types::{optimization::names, Optimization}; 5 | use nom::branch::alt; 6 | use nom::bytes::complete::tag; 7 | use nom::combinator::map; 8 | 9 | /// Parses an optimization goal, i.e. `minimize | maximize`. 10 | /// 11 | /// ## Example 12 | /// ``` 13 | /// # use pddl::parsers::{parse_optimization, preamble::*}; 14 | /// # use pddl::{Optimization}; 15 | /// assert!(parse_optimization("minimize").is_value(Optimization::Minimize)); 16 | /// assert!(parse_optimization("maximize").is_value(Optimization::Maximize)); 17 | ///``` 18 | pub fn parse_optimization<'a, T: Into>>(input: T) -> ParseResult<'a, Optimization> { 19 | map( 20 | alt((tag(names::MINIMIZE), tag(names::MAXIMIZE))), 21 | |x: Span| Optimization::try_from(*x.fragment()).expect("unhandled variant"), 22 | )(input.into()) 23 | } 24 | 25 | impl crate::parsers::Parser for Optimization { 26 | type Item = Optimization; 27 | 28 | /// See [`parse_optimization`]. 29 | fn parse<'a, S: Into>>(input: S) -> ParseResult<'a, Self::Item> { 30 | parse_optimization(input) 31 | } 32 | } 33 | 34 | #[cfg(test)] 35 | mod tests { 36 | use crate::parsers::preamble::*; 37 | use crate::Optimization; 38 | 39 | #[test] 40 | fn test_parse() { 41 | assert!(Optimization::parse("minimize").is_value(Optimization::Minimize)); 42 | assert!(Optimization::parse("maximize").is_value(Optimization::Maximize)); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/parsers/predicate.rs: -------------------------------------------------------------------------------- 1 | //! Provides parsers for predicates. 2 | 3 | use crate::parsers::{parse_name, ParseResult, Span}; 4 | use crate::types::Predicate; 5 | use nom::combinator::map; 6 | 7 | /// Parses a predicate, i.e. ``. 8 | /// 9 | /// ## Example 10 | /// ``` 11 | /// # use pddl::parsers::{parse_predicate, preamble::*}; 12 | /// assert!(parse_predicate(Span::new("abcde")).is_value("abcde".into())); 13 | /// assert!(parse_predicate(Span::new("a-1_2")).is_value("a-1_2".into())); 14 | /// assert!(parse_predicate(Span::new("Z01")).is_value("Z01".into())); 15 | /// assert!(parse_predicate(Span::new("x-_-_")).is_value("x-_-_".into())); 16 | /// 17 | /// assert!(parse_predicate(Span::new("")).is_err()); 18 | /// assert!(parse_predicate(Span::new(".")).is_err()); 19 | /// assert!(parse_predicate(Span::new("-abc")).is_err()); 20 | /// assert!(parse_predicate(Span::new("0124")).is_err()); 21 | /// assert!(parse_predicate(Span::new("-1")).is_err()); 22 | ///``` 23 | pub fn parse_predicate<'a, T: Into>>(input: T) -> ParseResult<'a, Predicate> { 24 | map(parse_name, Predicate::from)(input.into()) 25 | } 26 | 27 | impl crate::parsers::Parser for Predicate { 28 | type Item = Predicate; 29 | 30 | /// Parses a predicate. 31 | /// 32 | /// ## Example 33 | /// ``` 34 | /// # use pddl::{Predicate, Parser}; 35 | /// let (_, value) = Predicate::parse("abcde").unwrap(); 36 | /// assert_eq!(value, "abcde".into()); 37 | ///``` 38 | /// 39 | /// See [`parse_predicate`]. 40 | fn parse<'a, S: Into>>(input: S) -> ParseResult<'a, Self::Item> { 41 | parse_predicate(input) 42 | } 43 | } 44 | 45 | #[cfg(test)] 46 | mod tests { 47 | use crate::{Parser, Predicate}; 48 | 49 | #[test] 50 | fn test_parse() { 51 | let (_, value) = Predicate::parse("abcde").unwrap(); 52 | assert_eq!(value, "abcde".into()); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/parsers/predicates_def.rs: -------------------------------------------------------------------------------- 1 | //! Provides parsers for predicate definitions. 2 | 3 | use nom::combinator::map; 4 | 5 | use crate::parsers::{parse_atomic_formula_skeleton, ParseResult, Span}; 6 | use crate::parsers::{prefix_expr, space_separated_list1}; 7 | use crate::types::PredicateDefinitions; 8 | 9 | /// Parses predicate definitions, i.e. `(:predicates ⁺)`. 10 | /// 11 | /// ## Example 12 | /// ``` 13 | /// # use pddl::parsers::{parse_predicates_def, preamble::*}; 14 | /// # use pddl::{Variable, AtomicFormulaSkeleton, Predicate, PredicateDefinitions}; 15 | /// # use pddl::{ToTyped, TypedList}; 16 | /// let input = r#"(:predicates 17 | /// (at ?x - physob ?y - location) 18 | /// (in ?x ?y - physob) 19 | /// )"#; 20 | /// 21 | /// assert!(parse_predicates_def(input).is_value( 22 | /// PredicateDefinitions::new(vec![ 23 | /// AtomicFormulaSkeleton::new( 24 | /// Predicate::from("at"), 25 | /// TypedList::from_iter([ 26 | /// Variable::from("x").to_typed("physob"), 27 | /// Variable::from("y").to_typed("location"), 28 | /// ])), 29 | /// AtomicFormulaSkeleton::new( 30 | /// Predicate::from("in"), 31 | /// TypedList::from_iter([ 32 | /// Variable::from("x").to_typed("physob"), 33 | /// Variable::from("y").to_typed("physob"), 34 | /// ])) 35 | /// ]) 36 | /// )); 37 | /// ``` 38 | pub fn parse_predicates_def<'a, T: Into>>( 39 | input: T, 40 | ) -> ParseResult<'a, PredicateDefinitions> { 41 | map( 42 | prefix_expr( 43 | ":predicates", 44 | space_separated_list1(parse_atomic_formula_skeleton), 45 | ), 46 | PredicateDefinitions::new, 47 | )(input.into()) 48 | } 49 | 50 | impl crate::parsers::Parser for PredicateDefinitions { 51 | type Item = PredicateDefinitions; 52 | 53 | /// See [`parse_predicates_def`]. 54 | fn parse<'a, S: Into>>(input: S) -> ParseResult<'a, Self::Item> { 55 | parse_predicates_def(input) 56 | } 57 | } 58 | 59 | #[cfg(test)] 60 | mod tests { 61 | use crate::parsers::preamble::*; 62 | use crate::{ 63 | AtomicFormulaSkeleton, Predicate, PredicateDefinitions, ToTyped, TypedList, Variable, 64 | }; 65 | 66 | #[test] 67 | fn test_parse() { 68 | let input = r#"(:predicates 69 | (at ?x - physob ?y - location) 70 | (in ?x ?y - physob) 71 | )"#; 72 | 73 | assert!( 74 | PredicateDefinitions::parse(input).is_value(PredicateDefinitions::new(vec![ 75 | AtomicFormulaSkeleton::new( 76 | Predicate::from("at"), 77 | TypedList::from_iter([ 78 | Variable::from("x").to_typed("physob"), 79 | Variable::from("y").to_typed("location"), 80 | ]) 81 | ), 82 | AtomicFormulaSkeleton::new( 83 | Predicate::from("in"), 84 | TypedList::from_iter([ 85 | Variable::from("x").to_typed("physob"), 86 | Variable::from("y").to_typed("physob"), 87 | ]) 88 | ) 89 | ])) 90 | ); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/parsers/pref_name.rs: -------------------------------------------------------------------------------- 1 | //! Provides parsers for preference names. 2 | use crate::parsers::{parse_name, ParseResult, Span}; 3 | use crate::types::PreferenceName; 4 | use nom::combinator::map; 5 | 6 | /// Parses a preference name. 7 | /// 8 | /// ## Example 9 | /// ``` 10 | /// # use pddl::parsers::{parse_pref_name, preamble::*}; 11 | /// assert!(parse_pref_name("abcde").is_value("abcde".into())); 12 | ///``` 13 | pub fn parse_pref_name<'a, T: Into>>(input: T) -> ParseResult<'a, PreferenceName> { 14 | map(parse_name, PreferenceName::new)(input.into()) 15 | } 16 | 17 | impl crate::parsers::Parser for PreferenceName { 18 | type Item = PreferenceName; 19 | 20 | /// See [`parse_pref_name`]. 21 | fn parse<'a, S: Into>>(input: S) -> ParseResult<'a, Self::Item> { 22 | parse_pref_name(input) 23 | } 24 | } 25 | 26 | #[cfg(test)] 27 | mod tests { 28 | use crate::parsers::preamble::*; 29 | use crate::PreferenceName; 30 | 31 | #[test] 32 | fn test_parse() { 33 | assert!(PreferenceName::parse("abcde").is_value("abcde".into())); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/parsers/primitive_type.rs: -------------------------------------------------------------------------------- 1 | //! Provides parsers for primitive types. 2 | 3 | use nom::branch::alt; 4 | use nom::bytes::complete::tag; 5 | use nom::combinator::map; 6 | 7 | use crate::parsers::{parse_name, ParseResult, Span}; 8 | use crate::types::{Name, PrimitiveType}; 9 | 10 | /// Parses a primitive type, i.e. `object | `. 11 | /// 12 | /// ## Example 13 | /// ``` 14 | /// # use pddl::parsers::{parse_primitive_type, preamble::*}; 15 | /// assert!(parse_primitive_type(Span::new("object")).is_value("object".into())); 16 | /// assert!(parse_primitive_type(Span::new("number")).is_value("number".into())); 17 | /// assert!(parse_primitive_type(Span::new("a-1_2")).is_value("a-1_2".into())); 18 | /// assert!(parse_primitive_type(Span::new("obj!ect")).is_value("obj".into())); 19 | ///``` 20 | pub fn parse_primitive_type<'a, T: Into>>(input: T) -> ParseResult<'a, PrimitiveType> { 21 | map(alt((parse_object, parse_name)), PrimitiveType::from)(input.into()) 22 | } 23 | 24 | fn parse_object(input: Span) -> ParseResult { 25 | map(tag("object"), |x: Span| Name::from(*x.fragment()))(input) 26 | } 27 | 28 | impl crate::parsers::Parser for PrimitiveType { 29 | type Item = PrimitiveType; 30 | 31 | /// See [`parse_primitive_type`]. 32 | fn parse<'a, S: Into>>(input: S) -> ParseResult<'a, Self::Item> { 33 | parse_primitive_type(input) 34 | } 35 | } 36 | 37 | #[cfg(test)] 38 | mod tests { 39 | use crate::parsers::{Span, UnwrapValue}; 40 | use crate::{Parser, PrimitiveType}; 41 | 42 | #[test] 43 | fn test_parse() { 44 | assert!(PrimitiveType::parse(Span::new("object")).is_value("object".into())); 45 | assert!(PrimitiveType::parse(Span::new("number")).is_value("number".into())); 46 | assert!(PrimitiveType::parse(Span::new("a-1_2")).is_value("a-1_2".into())); 47 | assert!(PrimitiveType::parse(Span::new("obj!ect")).is_value("obj".into())); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/parsers/problem_constraints_def.rs: -------------------------------------------------------------------------------- 1 | //! Provides parsers for problem constraint definitions. 2 | 3 | use nom::combinator::map; 4 | 5 | use crate::parsers::{parse_pref_con_gd, prefix_expr, ParseResult, Span}; 6 | use crate::types::ProblemConstraintsDef; 7 | 8 | /// Parses problem constraint definitions, i.e. `(:constraints )`. 9 | /// 10 | /// ## Example 11 | /// ``` 12 | /// # use pddl::parsers::{parse_problem_constraints_def, preamble::*}; 13 | /// # use pddl::{ConGD, ProblemConstraintsDef, PrefConGDs}; 14 | /// let input = "(:constraints (preference test (and)))"; 15 | /// assert!(parse_problem_constraints_def(input).is_value( 16 | /// ProblemConstraintsDef::new( 17 | /// PrefConGDs::new_preference(Some("test".into()), ConGD::new_and([])) 18 | /// ) 19 | /// )); 20 | /// ``` 21 | pub fn parse_problem_constraints_def<'a, T: Into>>( 22 | input: T, 23 | ) -> ParseResult<'a, ProblemConstraintsDef> { 24 | // :constraints 25 | map( 26 | prefix_expr(":constraints", parse_pref_con_gd), 27 | ProblemConstraintsDef::new, 28 | )(input.into()) 29 | } 30 | 31 | impl crate::parsers::Parser for ProblemConstraintsDef { 32 | type Item = ProblemConstraintsDef; 33 | 34 | /// See [`parse_problem_constraints_def`]. 35 | fn parse<'a, S: Into>>(input: S) -> ParseResult<'a, Self::Item> { 36 | parse_problem_constraints_def(input) 37 | } 38 | } 39 | 40 | #[cfg(test)] 41 | mod tests { 42 | use crate::parsers::preamble::*; 43 | use crate::{ConGD, PrefConGDs, ProblemConstraintsDef}; 44 | 45 | #[test] 46 | fn test_parse() { 47 | let input = "(:constraints (preference test (and)))"; 48 | assert!( 49 | ProblemConstraintsDef::parse(input).is_value(ProblemConstraintsDef::new( 50 | PrefConGDs::new_preference(Some("test".into()), ConGD::new_and([])) 51 | )) 52 | ); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/parsers/simple_duration_constraint.rs: -------------------------------------------------------------------------------- 1 | //! Provides parsers for simple duration constraints. 2 | 3 | use nom::branch::alt; 4 | use nom::bytes::complete::tag; 5 | use nom::character::complete::multispace1; 6 | use nom::combinator::map; 7 | use nom::sequence::{preceded, tuple}; 8 | 9 | use crate::parsers::{parens, prefix_expr, ParseResult, Span}; 10 | use crate::parsers::{parse_d_op, parse_d_value, parse_time_specifier}; 11 | use crate::types::SimpleDurationConstraint; 12 | 13 | /// Parses a simple duration constraint. 14 | /// 15 | /// ## Example 16 | /// ``` 17 | /// # use pddl::parsers::{parse_simple_duration_constraint, preamble::*}; 18 | /// # use pddl::{DOp, DurationValue, FunctionType, SimpleDurationConstraint, TimeSpecifier}; 19 | /// let input = "(>= ?duration 1.23)"; 20 | /// assert!(parse_simple_duration_constraint(input).is_value( 21 | /// SimpleDurationConstraint::new_op( 22 | /// DOp::GreaterOrEqual, 23 | /// DurationValue::new_number(1.23) 24 | /// ) 25 | /// )); 26 | /// 27 | /// let input = "(at end (<= ?duration 1.23))"; 28 | /// assert!(parse_simple_duration_constraint(input).is_value( 29 | /// SimpleDurationConstraint::new_at( 30 | /// TimeSpecifier::End, 31 | /// SimpleDurationConstraint::Op( 32 | /// DOp::LessThanOrEqual, 33 | /// DurationValue::new_number(1.23) 34 | /// ) 35 | /// ) 36 | /// )); 37 | ///``` 38 | pub fn parse_simple_duration_constraint<'a, T: Into>>( 39 | input: T, 40 | ) -> ParseResult<'a, SimpleDurationConstraint> { 41 | let op = map( 42 | parens(tuple(( 43 | parse_d_op, 44 | preceded( 45 | tuple((multispace1, tag("?duration"), multispace1)), 46 | parse_d_value, 47 | ), 48 | ))), 49 | SimpleDurationConstraint::from, 50 | ); 51 | 52 | let at = map( 53 | prefix_expr( 54 | "at", 55 | tuple(( 56 | parse_time_specifier, 57 | preceded(multispace1, parse_simple_duration_constraint), 58 | )), 59 | ), 60 | SimpleDurationConstraint::from, 61 | ); 62 | 63 | alt((op, at))(input.into()) 64 | } 65 | 66 | impl crate::parsers::Parser for SimpleDurationConstraint { 67 | type Item = SimpleDurationConstraint; 68 | 69 | /// See [`parse_simple_duration_constraint`]. 70 | fn parse<'a, S: Into>>(input: S) -> ParseResult<'a, Self::Item> { 71 | parse_simple_duration_constraint(input) 72 | } 73 | } 74 | 75 | #[cfg(test)] 76 | mod tests { 77 | use crate::parsers::preamble::*; 78 | use crate::{DOp, DurationValue, SimpleDurationConstraint, TimeSpecifier}; 79 | 80 | #[test] 81 | fn test_parse() { 82 | let input = "(>= ?duration 1.23)"; 83 | assert!( 84 | SimpleDurationConstraint::parse(input).is_value(SimpleDurationConstraint::new_op( 85 | DOp::GreaterOrEqual, 86 | DurationValue::new_number(1.23) 87 | )) 88 | ); 89 | 90 | let input = "(at end (<= ?duration 1.23))"; 91 | assert!( 92 | SimpleDurationConstraint::parse(input).is_value(SimpleDurationConstraint::new_at( 93 | TimeSpecifier::End, 94 | SimpleDurationConstraint::Op(DOp::LessThanOrEqual, DurationValue::new_number(1.23)) 95 | )) 96 | ); 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/parsers/term.rs: -------------------------------------------------------------------------------- 1 | //! Provides parsers for terms. 2 | 3 | use crate::parsers::{parse_function_term, parse_variable}; 4 | use crate::parsers::{parse_name, ParseResult, Span}; 5 | use crate::types::Term; 6 | use nom::error::ErrorKind; 7 | use nom::error_position; 8 | 9 | /// Parses a term, i.e. ` | | `. 10 | /// 11 | /// ## Example 12 | /// ``` 13 | /// # use pddl::parsers::{parse_term, preamble::*}; 14 | /// # use pddl::Term; 15 | /// assert!(parse_term("abcde").is_value(Term::Name("abcde".into()))); 16 | /// assert!(parse_term("?abcde").is_value(Term::Variable("abcde".into()))); 17 | ///``` 18 | pub fn parse_term<'a, T: Into>>(input: T) -> ParseResult<'a, Term> { 19 | let input = input.into(); 20 | 21 | if let Ok((remaining, variable)) = parse_variable(input) { 22 | return Ok((remaining, Term::Variable(variable))); 23 | } 24 | 25 | if let Ok((remaining, name)) = parse_name(input) { 26 | return Ok((remaining, Term::Name(name))); 27 | } 28 | 29 | if let Ok((remaining, ft)) = parse_function_term(input) { 30 | return Ok((remaining, Term::Function(ft))); 31 | } 32 | 33 | Err(nom::Err::Error(error_position!(input, ErrorKind::Alt))) 34 | } 35 | 36 | impl crate::parsers::Parser for Term { 37 | type Item = Term; 38 | 39 | /// Parses a term. 40 | /// 41 | /// ## Example 42 | /// ``` 43 | /// # use pddl::{Term, Parser}; 44 | /// let (_, value) = Term::parse("some-name").unwrap(); 45 | /// assert_eq!(value, Term::Name("some-name".into())); 46 | /// 47 | /// let (_, value) = Term::parse("?some-var").unwrap(); 48 | /// assert_eq!(value, Term::Variable("some-var".into())); 49 | ///``` 50 | /// 51 | /// ## See also 52 | /// See [`parse_term`]. 53 | fn parse<'a, S: Into>>(input: S) -> ParseResult<'a, Self::Item> { 54 | parse_term(input) 55 | } 56 | } 57 | 58 | #[cfg(test)] 59 | mod tests { 60 | use crate::{Parser, Term}; 61 | 62 | #[test] 63 | fn test_parse() { 64 | let (_, value) = Term::parse("some-name").unwrap(); 65 | assert_eq!(value, Term::Name("some-name".into())); 66 | 67 | let (_, value) = Term::parse("?some-var").unwrap(); 68 | assert_eq!(value, Term::Variable("some-var".into())); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/parsers/time_specifier.rs: -------------------------------------------------------------------------------- 1 | //! Provides parsers for assignment operations. 2 | 3 | use nom::branch::alt; 4 | use nom::bytes::complete::tag; 5 | use nom::combinator::map; 6 | 7 | use crate::parsers::{ParseResult, Span}; 8 | use crate::types::time_specifier::names; 9 | use crate::types::TimeSpecifier; 10 | 11 | /// Parses an assignment operation, i.e. `increase | decrease`. 12 | /// 13 | /// ## Example 14 | /// ``` 15 | /// # use pddl::parsers::{parse_time_specifier, preamble::*}; 16 | /// # use pddl::{TimeSpecifier}; 17 | /// assert!(parse_time_specifier("start").is_value(TimeSpecifier::Start)); 18 | /// assert!(parse_time_specifier("end").is_value(TimeSpecifier::End)); 19 | ///``` 20 | pub fn parse_time_specifier<'a, T: Into>>(input: T) -> ParseResult<'a, TimeSpecifier> { 21 | map(alt((tag(names::START), tag(names::END))), |x: Span| { 22 | TimeSpecifier::try_from(*x.fragment()).expect("unhandled variant") 23 | })(input.into()) 24 | } 25 | 26 | impl crate::parsers::Parser for TimeSpecifier { 27 | type Item = TimeSpecifier; 28 | 29 | /// See [`parse_time_specifier`]. 30 | fn parse<'a, S: Into>>(input: S) -> ParseResult<'a, Self::Item> { 31 | parse_time_specifier(input) 32 | } 33 | } 34 | 35 | #[cfg(test)] 36 | mod tests { 37 | use crate::parsers::UnwrapValue; 38 | use crate::{Parser, TimeSpecifier}; 39 | 40 | #[test] 41 | fn test_parse() { 42 | assert!(TimeSpecifier::parse("start").is_value(TimeSpecifier::Start)); 43 | assert!(TimeSpecifier::parse("end").is_value(TimeSpecifier::End)); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/parsers/timeless_def.rs: -------------------------------------------------------------------------------- 1 | //! Provides parsers for timeless definitions. 2 | 3 | use crate::parsers::{literal, parse_name, prefix_expr, space_separated_list1, ParseResult, Span}; 4 | use crate::types::Timeless; 5 | use nom::combinator::map; 6 | 7 | /// Parser for timeless definitions. 8 | /// This is a PDDL 1.2 construct. 9 | /// 10 | /// ## Example 11 | /// ``` 12 | /// # use pddl::parsers::{parse_timeless_def, preamble::*}; 13 | /// # use pddl::{AtomicFormula, EqualityAtomicFormula, Literal, Name, Objects, Timeless, ToTyped, Type}; 14 | /// let input = "(:timeless (= x y) (= a b))"; 15 | /// assert!(parse_timeless_def(input).is_value( 16 | /// Timeless::from_iter([ 17 | /// Literal::AtomicFormula( 18 | /// AtomicFormula::Equality( 19 | /// EqualityAtomicFormula::new( 20 | /// "x".into(), 21 | /// "y".into() 22 | /// ) 23 | /// ) 24 | /// ), 25 | /// Literal::AtomicFormula( 26 | /// // ... 27 | /// # AtomicFormula::Equality( 28 | /// # EqualityAtomicFormula::new( 29 | /// # "a".into(), 30 | /// # "b".into() 31 | /// # ) 32 | /// # ) 33 | /// ) 34 | /// ]) 35 | /// )); 36 | /// ``` 37 | pub fn parse_timeless_def<'a, T: Into>>(input: T) -> ParseResult<'a, Timeless> { 38 | map( 39 | prefix_expr(":timeless", space_separated_list1(literal(parse_name))), 40 | Timeless::from_iter, 41 | )(input.into()) 42 | } 43 | 44 | impl crate::parsers::Parser for Timeless { 45 | type Item = Timeless; 46 | 47 | /// See [`parse_timeless_def`]. 48 | fn parse<'a, S: Into>>(input: S) -> ParseResult<'a, Self::Item> { 49 | parse_timeless_def(input) 50 | } 51 | } 52 | 53 | #[cfg(test)] 54 | mod tests { 55 | use crate::parsers::preamble::*; 56 | use crate::{AtomicFormula, EqualityAtomicFormula, Literal, Timeless}; 57 | 58 | #[test] 59 | fn test_parse() { 60 | let input = "(:timeless (= x y) (= a b))"; 61 | assert!(Timeless::parse(input).is_value(Timeless::from_iter([ 62 | Literal::AtomicFormula(AtomicFormula::Equality(EqualityAtomicFormula::new( 63 | "x".into(), 64 | "y".into() 65 | ))), 66 | Literal::AtomicFormula(AtomicFormula::Equality(EqualityAtomicFormula::new( 67 | "a".into(), 68 | "b".into() 69 | ))) 70 | ]))); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/parsers/type.rs: -------------------------------------------------------------------------------- 1 | //! Provides parsers for types. 2 | 3 | use crate::parsers::{parse_primitive_type, ParseResult, Span}; 4 | use crate::parsers::{prefix_expr, space_separated_list1}; 5 | use crate::types::{PrimitiveType, Type}; 6 | use nom::error::ErrorKind; 7 | use nom::error_position; 8 | 9 | /// Parses a primitive type, i.e. `object | `. 10 | /// 11 | /// ## Example 12 | /// ``` 13 | /// # use pddl::parsers::{parse_type, preamble::*}; 14 | /// # use pddl::Type; 15 | /// assert!(parse_type(Span::new("object")).is_value(Type::Exactly("object".into()))); 16 | /// assert!(parse_type(Span::new("(either object number)")).is_value(Type::from_iter(["object", "number"]))); 17 | ///``` 18 | pub fn parse_type<'a, T: Into>>(input: T) -> ParseResult<'a, Type> { 19 | let input = input.into(); 20 | 21 | if let Ok((remaining, r#type)) = parse_primitive_type(input) { 22 | return Ok((remaining, Type::Exactly(r#type))); 23 | } 24 | 25 | if let Ok((remaining, types)) = parse_either_type(input) { 26 | return Ok((remaining, Type::EitherOf(types))); 27 | } 28 | 29 | Err(nom::Err::Failure(error_position!(input, ErrorKind::Alt))) 30 | } 31 | 32 | /// Parses a either type, i.e. `(either a b c)`. 33 | fn parse_either_type<'a, T: Into>>(input: T) -> ParseResult<'a, Vec> { 34 | prefix_expr("either", space_separated_list1(parse_primitive_type))(input.into()) 35 | } 36 | 37 | impl crate::parsers::Parser for Type { 38 | type Item = Type; 39 | 40 | /// See [`parse_type`]. 41 | fn parse<'a, S: Into>>(input: S) -> ParseResult<'a, Self::Item> { 42 | parse_type(input) 43 | } 44 | } 45 | 46 | #[cfg(test)] 47 | mod tests { 48 | use super::*; 49 | use crate::parsers::Match; 50 | 51 | #[test] 52 | fn explicit_works() { 53 | assert!(parse_type(Span::new("object")).is_exactly(Type::from("object"))); 54 | } 55 | 56 | #[test] 57 | fn either_works() { 58 | assert!(parse_type(Span::new("(either object number)")) 59 | .is_exactly(Type::from_iter(["object", "number"]))); 60 | } 61 | 62 | #[test] 63 | fn either_specific_works() { 64 | assert!( 65 | parse_either_type(Span::new("(either object number)")).is_exactly(vec![ 66 | PrimitiveType::from("object"), 67 | PrimitiveType::from("number") 68 | ]) 69 | ); 70 | } 71 | 72 | #[test] 73 | fn test_invalid() { 74 | assert!(parse_type(Span::new("()")).is_err()); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/parsers/types_def.rs: -------------------------------------------------------------------------------- 1 | //! Provides parsers for constant definitions. 2 | 3 | use nom::combinator::map; 4 | 5 | use crate::parsers::{parse_name, prefix_expr, typed_list, ParseResult, Span}; 6 | use crate::types::Types; 7 | 8 | /// Parses constant definitions, i.e. `(:constants )`. 9 | /// 10 | /// ## Example 11 | /// ``` 12 | /// # use pddl::parsers::{parse_types_def, preamble::*}; 13 | /// # use pddl::{Variable, AtomicFormulaSkeleton, Predicate, PredicateDefinitions}; 14 | /// # use pddl::{Name, Type, Typed, TypedList, Types}; 15 | /// let input = "(:types location physob)"; 16 | /// assert!(parse_types_def(input).is_value( 17 | /// Types::new(TypedList::from_iter([ 18 | /// Typed::new(Name::from("location"), Type::OBJECT), 19 | /// Typed::new(Name::from("physob"), Type::OBJECT), 20 | /// ])) 21 | /// )); 22 | /// ``` 23 | pub fn parse_types_def<'a, T: Into>>(input: T) -> ParseResult<'a, Types> { 24 | map(prefix_expr(":types", typed_list(parse_name)), |vec| { 25 | Types::new(vec) 26 | })(input.into()) 27 | } 28 | 29 | impl crate::parsers::Parser for Types { 30 | type Item = Types; 31 | 32 | /// See [`parse_types_def`]. 33 | fn parse<'a, S: Into>>(input: S) -> ParseResult<'a, Self::Item> { 34 | parse_types_def(input) 35 | } 36 | } 37 | 38 | #[cfg(test)] 39 | mod tests { 40 | use crate::parsers::UnwrapValue; 41 | use crate::{Name, Parser, Type, Typed, TypedList, Types}; 42 | 43 | #[test] 44 | fn test_parse() { 45 | let input = "(:types location physob)"; 46 | assert!( 47 | Types::parse(input).is_value(Types::new(TypedList::from_iter([ 48 | Typed::new(Name::from("location"), Type::OBJECT), 49 | Typed::new(Name::from("physob"), Type::OBJECT), 50 | ]))) 51 | ); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/parsers/variable.rs: -------------------------------------------------------------------------------- 1 | //! Provides parsers for variables. 2 | 3 | use nom::bytes::complete::tag; 4 | use nom::combinator::map; 5 | use nom::sequence::preceded; 6 | 7 | use crate::parsers::{parse_name, ParseResult, Span}; 8 | use crate::types::Variable; 9 | 10 | /// Parses a variable, i.e. `?` and returns its name. 11 | /// 12 | /// ## Example 13 | /// ``` 14 | /// # use pddl::parsers::{parse_variable, preamble::*}; 15 | /// assert!(parse_variable(Span::new("?abcde")).is_value("abcde".into())); 16 | /// assert!(parse_variable(Span::new("?a-1_2")).is_value("a-1_2".into())); 17 | /// assert!(parse_variable(Span::new("?Z01")).is_value("Z01".into())); 18 | /// assert!(parse_variable(Span::new("?x-_-_")).is_value("x-_-_".into())); 19 | /// 20 | /// assert!(parse_variable(Span::new("abcde")).is_err()); 21 | /// assert!(parse_variable(Span::new("?-")).is_err()); 22 | /// assert!(parse_variable(Span::new("?1")).is_err()); 23 | ///``` 24 | pub fn parse_variable<'a, T: Into>>(input: T) -> ParseResult<'a, Variable> { 25 | map(preceded(tag("?"), parse_name), Variable::from)(input.into()) 26 | } 27 | 28 | impl crate::parsers::Parser for Variable { 29 | type Item = Variable; 30 | 31 | /// Parses a variable. 32 | /// 33 | /// ## Example 34 | /// ``` 35 | /// # use pddl::{Variable, Parser}; 36 | /// let (_, value) = Variable::parse("?abcde").unwrap(); 37 | /// assert_eq!(value, "abcde".into()); 38 | ///``` 39 | /// 40 | /// ## See also 41 | /// See [`parse_variable`]. 42 | fn parse<'a, S: Into>>(input: S) -> ParseResult<'a, Self::Item> { 43 | parse_variable(input) 44 | } 45 | } 46 | 47 | #[cfg(test)] 48 | mod tests { 49 | use crate::{Parser, Variable}; 50 | 51 | #[test] 52 | fn test_parse() { 53 | let (_, value) = Variable::parse("?abcde").unwrap(); 54 | assert_eq!(value, "abcde".into()); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/types/action_definition.rs: -------------------------------------------------------------------------------- 1 | //! Contains action definitions via the [`ActionDefinition`] type. 2 | 3 | use crate::types::TypedVariables; 4 | use crate::types::{ActionSymbol, Effects}; 5 | use crate::PreconditionGoalDefinitions; 6 | 7 | /// An action definition. 8 | /// 9 | /// ## Usage 10 | /// Used by [`StructureDef`](crate::StructureDef). 11 | #[derive(Debug, Clone, PartialEq)] 12 | pub struct ActionDefinition { 13 | symbol: ActionSymbol, 14 | parameters: TypedVariables, 15 | precondition: PreconditionGoalDefinitions, 16 | effect: Option, 17 | } 18 | 19 | impl ActionDefinition { 20 | pub const fn new( 21 | symbol: ActionSymbol, 22 | parameters: TypedVariables, 23 | precondition: PreconditionGoalDefinitions, 24 | effect: Option, 25 | ) -> Self { 26 | Self { 27 | symbol, 28 | parameters, 29 | precondition, 30 | effect, 31 | } 32 | } 33 | 34 | pub const fn symbol(&self) -> &ActionSymbol { 35 | &self.symbol 36 | } 37 | 38 | pub const fn parameters(&self) -> &TypedVariables { 39 | &self.parameters 40 | } 41 | 42 | pub const fn precondition(&self) -> &PreconditionGoalDefinitions { 43 | &self.precondition 44 | } 45 | 46 | pub const fn effect(&self) -> &Option { 47 | &self.effect 48 | } 49 | } 50 | 51 | impl AsRef for ActionDefinition { 52 | fn as_ref(&self) -> &ActionSymbol { 53 | &self.symbol 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/types/action_symbols.rs: -------------------------------------------------------------------------------- 1 | //! Contains action symbols via the [`ActionSymbol`] type. 2 | 3 | use crate::types::Name; 4 | use std::ops::Deref; 5 | 6 | /// An action symbol name. 7 | /// 8 | /// ## Usage 9 | /// Used by [`ActionDefinition`](crate::ActionDefinition). 10 | #[derive(Debug, Clone, Eq, PartialEq, Hash, Default)] 11 | pub struct ActionSymbol(Name); 12 | 13 | impl ActionSymbol { 14 | #[inline(always)] 15 | pub const fn new(name: Name) -> Self { 16 | Self(name) 17 | } 18 | 19 | #[inline(always)] 20 | pub fn from_str(name: &str) -> Self { 21 | Self(Name::new(name)) 22 | } 23 | 24 | #[inline(always)] 25 | pub const fn from_name(name: Name) -> Self { 26 | Self(name) 27 | } 28 | } 29 | 30 | impl<'a, T> From for ActionSymbol 31 | where 32 | T: Into, 33 | { 34 | #[inline(always)] 35 | fn from(value: T) -> Self { 36 | ActionSymbol::new(value.into()) 37 | } 38 | } 39 | 40 | impl AsRef for ActionSymbol { 41 | #[inline(always)] 42 | fn as_ref(&self) -> &Name { 43 | &self.0 44 | } 45 | } 46 | 47 | impl AsRef for ActionSymbol { 48 | #[inline(always)] 49 | fn as_ref(&self) -> &str { 50 | self.0.as_ref() 51 | } 52 | } 53 | 54 | impl Deref for ActionSymbol { 55 | type Target = Name; 56 | 57 | #[inline(always)] 58 | fn deref(&self) -> &Self::Target { 59 | &self.0 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/types/assign_op_t.rs: -------------------------------------------------------------------------------- 1 | //! Contains the timed effect assignment operation type [`AssignOpT`]. 2 | 3 | use std::fmt::{Display, Formatter}; 4 | 5 | /// An assignment operation. 6 | /// 7 | /// ## Usage 8 | /// Used by [`TimedEffect`](crate::TimedEffect). 9 | #[derive(Debug, Copy, Clone, Eq, PartialEq)] 10 | pub enum AssignOpT { 11 | Increase, 12 | Decrease, 13 | } 14 | 15 | pub mod names { 16 | pub const INCREASE: &str = "increase"; 17 | pub const DECREASE: &str = "decrease"; 18 | } 19 | 20 | impl Display for AssignOpT { 21 | fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { 22 | match self { 23 | AssignOpT::Increase => write!(f, "{}", names::INCREASE), 24 | AssignOpT::Decrease => write!(f, "{}", names::DECREASE), 25 | } 26 | } 27 | } 28 | 29 | impl TryFrom<&str> for AssignOpT { 30 | type Error = ParseError; 31 | 32 | fn try_from(value: &str) -> Result { 33 | match value { 34 | names::INCREASE => Ok(Self::Increase), 35 | names::DECREASE => Ok(Self::Decrease), 36 | _ => Err(ParseError::InvalidOperation), 37 | } 38 | } 39 | } 40 | 41 | #[derive(Debug, Clone, thiserror::Error)] 42 | pub enum ParseError { 43 | #[error("Invalid operation")] 44 | InvalidOperation, 45 | } 46 | -------------------------------------------------------------------------------- /src/types/atomic_formula.rs: -------------------------------------------------------------------------------- 1 | //! Contains atomic formulae via the [`AtomicFormula`] type. 2 | 3 | use crate::types::Predicate; 4 | use std::ops::Deref; 5 | 6 | /// An atomic formula. 7 | /// 8 | /// ## Usage 9 | /// Used by [`Literal`](crate::Literal), [`GoalDefinition`](crate::GoalDefinition) and 10 | /// [`PEffect`](crate::PEffect). 11 | #[derive(Debug, Clone, Eq, PartialEq)] 12 | pub enum AtomicFormula { 13 | Equality(EqualityAtomicFormula), 14 | Predicate(PredicateAtomicFormula), 15 | } 16 | 17 | impl<'a, T> AtomicFormula { 18 | pub const fn new_equality(first: T, second: T) -> Self { 19 | Self::Equality(EqualityAtomicFormula::new(first, second)) 20 | } 21 | 22 | pub fn new_predicate>(predicate: Predicate, values: V) -> Self { 23 | Self::Predicate(PredicateAtomicFormula::new( 24 | predicate, 25 | values.into_iter().collect(), 26 | )) 27 | } 28 | } 29 | 30 | #[derive(Default, Debug, Clone, Eq, PartialEq)] 31 | pub struct EqualityAtomicFormula { 32 | first: T, 33 | second: T, 34 | } 35 | 36 | #[derive(Default, Debug, Clone, Eq, PartialEq)] 37 | pub struct PredicateAtomicFormula { 38 | predicate: Predicate, 39 | values: Vec, 40 | } 41 | 42 | impl EqualityAtomicFormula { 43 | pub const fn new(first: T, second: T) -> Self { 44 | Self { first, second } 45 | } 46 | 47 | /// Gets a reference to the first element. 48 | pub const fn first(&self) -> &T { 49 | &self.first 50 | } 51 | 52 | /// Gets a reference to the second element. 53 | pub const fn second(&self) -> &T { 54 | &self.second 55 | } 56 | } 57 | 58 | impl PredicateAtomicFormula { 59 | pub const fn new(predicate: Predicate, values: Vec) -> Self { 60 | Self { predicate, values } 61 | } 62 | 63 | /// Returns the predicate. 64 | pub const fn predicate(&self) -> &Predicate { 65 | &self.predicate 66 | } 67 | 68 | /// Gets a reference to the values. 69 | pub fn values(&self) -> &[T] { 70 | self.values.as_slice() 71 | } 72 | } 73 | 74 | impl<'a, T> From> for AtomicFormula { 75 | fn from(value: EqualityAtomicFormula) -> Self { 76 | AtomicFormula::Equality(value) 77 | } 78 | } 79 | 80 | impl<'a, T> From> for AtomicFormula { 81 | fn from(value: PredicateAtomicFormula) -> Self { 82 | AtomicFormula::Predicate(value) 83 | } 84 | } 85 | 86 | impl From<(T, T)> for EqualityAtomicFormula { 87 | fn from(value: (T, T)) -> Self { 88 | EqualityAtomicFormula::new(value.0, value.1) 89 | } 90 | } 91 | 92 | impl<'a, T> From<(Predicate, Vec)> for PredicateAtomicFormula { 93 | fn from(value: (Predicate, Vec)) -> Self { 94 | PredicateAtomicFormula::new(value.0, value.1) 95 | } 96 | } 97 | 98 | impl<'a, T> Deref for PredicateAtomicFormula { 99 | type Target = [T]; 100 | 101 | fn deref(&self) -> &Self::Target { 102 | self.values() 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /src/types/atomic_formula_skeleton.rs: -------------------------------------------------------------------------------- 1 | //! Contains atomic formula skeletons via the [`AtomicFormulaSkeleton`] type. 2 | 3 | use crate::types::Predicate; 4 | use crate::types::{Name, TypedVariables}; 5 | 6 | /// An atomic formula skeleton. 7 | /// 8 | /// ## Usage 9 | /// Used by [`PredicateDefinitions`](crate::PredicateDefinitions) and [`DerivedPredicate`](crate::DerivedPredicate). 10 | #[derive(Debug, Clone, Eq, PartialEq)] 11 | pub struct AtomicFormulaSkeleton { 12 | predicate: Predicate, 13 | variables: TypedVariables, 14 | } 15 | 16 | impl AtomicFormulaSkeleton { 17 | pub const fn new(predicate: Predicate, formula: TypedVariables) -> Self { 18 | Self { 19 | predicate, 20 | variables: formula, 21 | } 22 | } 23 | 24 | pub fn name(&self) -> &Name { 25 | self.predicate.as_ref() 26 | } 27 | 28 | /// Gets a reference to the predicate. 29 | pub const fn predicate(&self) -> &Predicate { 30 | &self.predicate 31 | } 32 | 33 | /// Gets a reference to the variables. 34 | pub fn variables(&self) -> &TypedVariables { 35 | &self.variables 36 | } 37 | } 38 | 39 | impl From<(Predicate, TypedVariables)> for AtomicFormulaSkeleton { 40 | fn from(value: (Predicate, TypedVariables)) -> Self { 41 | AtomicFormulaSkeleton::new(value.0, value.1) 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/types/atomic_function_skeleton.rs: -------------------------------------------------------------------------------- 1 | //! Contains atomic function skeletons via the [`AtomicFunctionSkeleton`] type. 2 | 3 | use crate::types::Typed; 4 | use crate::types::{FunctionSymbol, TypedVariables, Variable}; 5 | 6 | /// A numeric fluent, similar to a predicate, is a variable which applies to zero or more objects 7 | /// and maintains a value throughout the duration of the plan. 8 | /// 9 | /// It is declared with a name followed by the object type to which it applies. 10 | /// For example, the function declaration 11 | /// 12 | /// ```pddl 13 | /// (battery-level ?r - rover) 14 | /// ``` 15 | /// 16 | /// means that every `rover` object in the domain has a variable which maintains a value for 17 | /// `battery-level`. A function can apply to zero or more objects, meaning we could also use it 18 | /// to represent a numeric value between two values, for example a distance. 19 | /// 20 | /// ```pddl 21 | /// (distance ?wp1 - waypoint ?wp2 - waypoint) 22 | /// ``` 23 | /// 24 | /// Numeric fluents can be altered through the effects of both actions 25 | /// ([ActionDefinition](crate::types::ActionDefinition)) and durative actions 26 | /// ([DurativeActionDefinition](crate::types::DurativeActionDefinition)). 27 | /// 28 | /// There are a number of supported effects for numeric fluents, e.g. 29 | /// [`BinaryOp`](crate::types::BinaryOp) and [`AssignOp`](crate::types::AssignOp). 30 | /// 31 | /// ## Usage 32 | /// Used by [`Functions`](crate::Functions). 33 | #[derive(Debug, Clone, Eq, PartialEq)] 34 | pub struct AtomicFunctionSkeleton { 35 | /// The name of the fluent, e.g. `battery-level`. 36 | symbol: FunctionSymbol, 37 | /// The list of parameters to the fluent, e.g. `?r - rover`. 38 | variables: TypedVariables, 39 | } 40 | 41 | impl AtomicFunctionSkeleton { 42 | pub const fn new(symbol: FunctionSymbol, variables: TypedVariables) -> Self { 43 | Self { symbol, variables } 44 | } 45 | 46 | /// Gets a reference to the function symbol. 47 | pub const fn symbol(&self) -> &FunctionSymbol { 48 | &self.symbol 49 | } 50 | 51 | /// Gets a reference to the variables. 52 | pub fn variables(&self) -> &TypedVariables { 53 | &self.variables 54 | } 55 | } 56 | 57 | impl From<(FunctionSymbol, TypedVariables)> for AtomicFunctionSkeleton { 58 | fn from(value: (FunctionSymbol, TypedVariables)) -> Self { 59 | AtomicFunctionSkeleton::new(value.0, value.1) 60 | } 61 | } 62 | 63 | impl From<(FunctionSymbol, Vec>)> for AtomicFunctionSkeleton { 64 | fn from(value: (FunctionSymbol, Vec>)) -> Self { 65 | AtomicFunctionSkeleton::new(value.0, value.1.into()) 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/types/basic_function_term.rs: -------------------------------------------------------------------------------- 1 | //! Contains the [`BasicFunctionTerm`] type. 2 | 3 | use crate::types::{FunctionSymbol, Name}; 4 | 5 | /// ## Usage 6 | /// Used by [`InitElement`](crate::InitElement). 7 | #[derive(Debug, Clone, PartialEq)] 8 | pub struct BasicFunctionTerm(FunctionSymbol, Vec); 9 | 10 | impl BasicFunctionTerm { 11 | pub fn new>(symbol: FunctionSymbol, names: N) -> Self { 12 | Self(symbol, names.into_iter().collect()) 13 | } 14 | 15 | /// Returns the function symbol. 16 | pub const fn symbol(&self) -> &FunctionSymbol { 17 | &self.0 18 | } 19 | 20 | /// Returns the associated names. 21 | pub fn names(&self) -> &[Name] { 22 | self.1.as_slice() 23 | } 24 | } 25 | 26 | impl AsRef for BasicFunctionTerm { 27 | fn as_ref(&self) -> &FunctionSymbol { 28 | self.symbol() 29 | } 30 | } 31 | 32 | impl AsRef<[Name]> for BasicFunctionTerm { 33 | fn as_ref(&self) -> &[Name] { 34 | self.names() 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/types/binary_comp.rs: -------------------------------------------------------------------------------- 1 | //! Contains binary comparison operations via the [`BinaryComp`] type. 2 | 3 | use std::fmt::{Display, Formatter}; 4 | 5 | /// A binary comparison operation. 6 | /// 7 | /// ## Usage 8 | /// Used by [`FComp`](crate::FComp). 9 | #[derive(Debug, Copy, Clone, Eq, PartialEq)] 10 | pub enum BinaryComp { 11 | GreaterThan, 12 | LessThan, 13 | Equal, 14 | GreaterOrEqual, 15 | LessThanOrEqual, 16 | } 17 | 18 | pub mod names { 19 | pub const GREATER_THAN: &str = ">"; 20 | pub const LESS_THAN: &str = "<"; 21 | pub const EQUAL: &str = "="; 22 | pub const GREATER_THAN_OR_EQUAL: &str = ">="; 23 | pub const LESS_THAN_OR_EQUAL: &str = "<="; 24 | } 25 | 26 | impl Display for BinaryComp { 27 | fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { 28 | match self { 29 | BinaryComp::GreaterThan => write!(f, "{}", names::GREATER_THAN), 30 | BinaryComp::LessThan => write!(f, "{}", names::LESS_THAN), 31 | BinaryComp::Equal => write!(f, "{}", names::EQUAL), 32 | BinaryComp::GreaterOrEqual => write!(f, "{}", names::GREATER_THAN_OR_EQUAL), 33 | BinaryComp::LessThanOrEqual => write!(f, "{}", names::LESS_THAN_OR_EQUAL), 34 | } 35 | } 36 | } 37 | 38 | impl TryFrom<&str> for BinaryComp { 39 | type Error = ParseError; 40 | 41 | fn try_from(value: &str) -> Result { 42 | match value { 43 | names::GREATER_THAN => Ok(Self::GreaterThan), 44 | names::LESS_THAN => Ok(Self::LessThan), 45 | names::EQUAL => Ok(Self::Equal), 46 | names::GREATER_THAN_OR_EQUAL => Ok(Self::GreaterOrEqual), 47 | names::LESS_THAN_OR_EQUAL => Ok(Self::LessThanOrEqual), 48 | _ => Err(ParseError::InvalidOperation), 49 | } 50 | } 51 | } 52 | 53 | #[derive(Debug, Clone, thiserror::Error)] 54 | pub enum ParseError { 55 | #[error("Invalid operation")] 56 | InvalidOperation, 57 | } 58 | -------------------------------------------------------------------------------- /src/types/binary_op.rs: -------------------------------------------------------------------------------- 1 | //! Contains binary operations via the [`BinaryOp`] type. 2 | 3 | use crate::types::MultiOp; 4 | use std::fmt::{Display, Formatter}; 5 | 6 | /// A binary operation. 7 | /// 8 | /// ## Usage 9 | /// Used by [`FExp`](crate::Fexp), [`FExpDa`](crate::FExpDa) and [`Optimization`](crate::Optimization). 10 | #[derive(Debug, Copy, Clone, Eq, PartialEq)] 11 | pub enum BinaryOp { 12 | Multiplication, 13 | Addition, 14 | Subtraction, 15 | Division, 16 | } 17 | 18 | pub mod names { 19 | pub const MULTIPLICATION: &str = "*"; 20 | pub const ADDITION: &str = "+"; 21 | pub const SUBTRACTION: &str = "-"; 22 | pub const DIVISION: &str = "/"; 23 | } 24 | 25 | impl Display for BinaryOp { 26 | fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { 27 | match self { 28 | BinaryOp::Multiplication => write!(f, "{}", names::MULTIPLICATION), 29 | BinaryOp::Addition => write!(f, "{}", names::ADDITION), 30 | BinaryOp::Subtraction => write!(f, "{}", names::SUBTRACTION), 31 | BinaryOp::Division => write!(f, "{}", names::DIVISION), 32 | } 33 | } 34 | } 35 | 36 | impl TryFrom<&str> for BinaryOp { 37 | type Error = ParseError; 38 | 39 | fn try_from(value: &str) -> Result { 40 | match value { 41 | names::MULTIPLICATION => Ok(Self::Multiplication), 42 | names::ADDITION => Ok(Self::Addition), 43 | names::SUBTRACTION => Ok(Self::Subtraction), 44 | names::DIVISION => Ok(Self::Division), 45 | _ => Err(ParseError::InvalidOperation), 46 | } 47 | } 48 | } 49 | 50 | impl From for BinaryOp { 51 | fn from(value: MultiOp) -> Self { 52 | match value { 53 | MultiOp::Multiplication => BinaryOp::Multiplication, 54 | MultiOp::Addition => BinaryOp::Addition, 55 | } 56 | } 57 | } 58 | 59 | impl TryFrom for MultiOp { 60 | type Error = TryFromError; 61 | 62 | fn try_from(value: BinaryOp) -> Result { 63 | match value { 64 | BinaryOp::Multiplication => Ok(MultiOp::Multiplication), 65 | BinaryOp::Addition => Ok(MultiOp::Addition), 66 | _ => Err(TryFromError::NotAMultiOp), 67 | } 68 | } 69 | } 70 | 71 | #[derive(Debug, Clone, thiserror::Error)] 72 | pub enum ParseError { 73 | #[error("Invalid operation")] 74 | InvalidOperation, 75 | } 76 | 77 | #[derive(Debug, Clone, thiserror::Error)] 78 | pub enum TryFromError { 79 | #[error("Operation is not a MultiOp")] 80 | NotAMultiOp, 81 | } 82 | -------------------------------------------------------------------------------- /src/types/conditional_effect.rs: -------------------------------------------------------------------------------- 1 | //! Contains conditional effects via the [`ConditionalEffect`] type. 2 | 3 | use crate::types::iterators::FlatteningIntoIterator; 4 | use crate::types::PEffect; 5 | 6 | /// A conditional effect as used by [`CEffect::When`](crate::types::CEffect::When) and [`TimedEffect::Conditional`](crate::types::TimedEffect::Conditional). 7 | /// 8 | /// ## Usage 9 | /// Used by [`CEffect`](crate::CEffect) and [`TimedEffect`](crate::types::TimedEffect). 10 | #[derive(Debug, Clone, PartialEq)] 11 | pub enum ConditionalEffect { 12 | /// Exactly the specified effect applies. 13 | Single(PEffect), // TODO: Unify with `All`; vector is allowed to be empty. 14 | /// Conjunction: All effects apply (i.e. a and b and c ..). 15 | All(Vec), 16 | } 17 | 18 | impl ConditionalEffect { 19 | pub const fn new(effect: PEffect) -> Self { 20 | Self::Single(effect) 21 | } 22 | pub const fn new_and(effect: Vec) -> Self { 23 | Self::All(effect) 24 | } 25 | } 26 | 27 | impl IntoIterator for ConditionalEffect { 28 | type Item = PEffect; 29 | type IntoIter = FlatteningIntoIterator; 30 | 31 | fn into_iter(self) -> Self::IntoIter { 32 | match self { 33 | ConditionalEffect::Single(item) => FlatteningIntoIterator::new(item), 34 | ConditionalEffect::All(vec) => FlatteningIntoIterator::new_vec(vec), 35 | } 36 | } 37 | } 38 | 39 | impl From for ConditionalEffect { 40 | fn from(value: PEffect) -> Self { 41 | ConditionalEffect::new(value) 42 | } 43 | } 44 | 45 | impl From> for ConditionalEffect { 46 | fn from(value: Vec) -> Self { 47 | ConditionalEffect::new_and(value) 48 | } 49 | } 50 | 51 | impl FromIterator for ConditionalEffect { 52 | fn from_iter>(iter: T) -> Self { 53 | ConditionalEffect::new_and(iter.into_iter().collect()) 54 | } 55 | } 56 | 57 | #[cfg(test)] 58 | mod tests { 59 | use super::*; 60 | use crate::parsers::Span; 61 | use crate::Parser; 62 | 63 | #[test] 64 | fn flatten_with_single_element_works() { 65 | let (_, effect_a) = PEffect::parse(Span::new("(= x y)")).unwrap(); 66 | 67 | let mut iter = ConditionalEffect::new(effect_a).into_iter(); 68 | assert!(iter.next().is_some()); 69 | assert!(iter.next().is_none()); 70 | } 71 | 72 | #[test] 73 | fn flatten_with_many_elements_works() { 74 | let (_, effect_a) = PEffect::parse(Span::new("(= x y)")).unwrap(); 75 | let (_, effect_b) = PEffect::parse(Span::new("(assign fun-sym 1.23)")).unwrap(); 76 | 77 | let mut iter = ConditionalEffect::from_iter([effect_a, effect_b]).into_iter(); 78 | assert!(iter.next().is_some()); 79 | assert!(iter.next().is_some()); 80 | assert!(iter.next().is_none()); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/types/constants.rs: -------------------------------------------------------------------------------- 1 | //! Provides constant definitions via the [`Constants`] type. 2 | 3 | use crate::types::{Name, Typed, TypedNames}; 4 | use std::ops::Deref; 5 | 6 | /// A set of constants. 7 | /// 8 | /// ## Usage 9 | /// Used by [`Domain`](crate::Domain). 10 | #[derive(Debug, Default, Clone, Eq, PartialEq)] 11 | pub struct Constants(TypedNames); 12 | 13 | impl Constants { 14 | pub const fn new(predicates: TypedNames) -> Self { 15 | Self(predicates) 16 | } 17 | } 18 | 19 | impl Deref for Constants { 20 | type Target = TypedNames; 21 | 22 | fn deref(&self) -> &Self::Target { 23 | &self.0 24 | } 25 | } 26 | 27 | impl From for Constants { 28 | fn from(value: TypedNames) -> Self { 29 | Constants::new(value) 30 | } 31 | } 32 | 33 | impl FromIterator> for Constants { 34 | fn from_iter>>(iter: T) -> Self { 35 | Constants::new(TypedNames::from_iter(iter)) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/types/d_op.rs: -------------------------------------------------------------------------------- 1 | //! Contains the [`DOp`] type. 2 | 3 | use std::fmt::{Display, Formatter}; 4 | 5 | /// ## Usage 6 | /// Used by [`SimpleDurationConstraint`](crate::SimpleDurationConstraint). 7 | #[derive(Debug, Copy, Clone, Eq, PartialEq)] 8 | pub enum DOp { 9 | Equal, 10 | /// ## Requirements 11 | /// Requires [Duration Inequalities](crate::Requirement::DurationInequalities); 12 | GreaterOrEqual, 13 | /// ## Requirements 14 | /// Requires [Duration Inequalities](crate::Requirement::DurationInequalities); 15 | LessThanOrEqual, 16 | } 17 | 18 | pub mod names { 19 | pub const EQUAL: &str = "="; 20 | pub const GREATER_OR_EQUAL: &str = ">="; 21 | pub const LESS_THAN_OR_EQUAL: &str = "<="; 22 | } 23 | 24 | impl Display for DOp { 25 | fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { 26 | match self { 27 | DOp::Equal => write!(f, "{}", names::EQUAL), 28 | DOp::GreaterOrEqual => write!(f, "{}", names::GREATER_OR_EQUAL), 29 | DOp::LessThanOrEqual => write!(f, "{}", names::LESS_THAN_OR_EQUAL), 30 | } 31 | } 32 | } 33 | 34 | impl TryFrom<&str> for DOp { 35 | type Error = ParseError; 36 | 37 | fn try_from(value: &str) -> Result { 38 | match value { 39 | names::EQUAL => Ok(Self::Equal), 40 | names::GREATER_OR_EQUAL => Ok(Self::GreaterOrEqual), 41 | names::LESS_THAN_OR_EQUAL => Ok(Self::LessThanOrEqual), 42 | _ => Err(ParseError::InvalidOperation), 43 | } 44 | } 45 | } 46 | 47 | #[derive(Debug, Clone, thiserror::Error)] 48 | pub enum ParseError { 49 | #[error("Invalid operation")] 50 | InvalidOperation, 51 | } 52 | -------------------------------------------------------------------------------- /src/types/d_value.rs: -------------------------------------------------------------------------------- 1 | //! Contains the [`DurationValue`] type. 2 | 3 | use crate::types::{FExp, Number}; 4 | 5 | /// A duration value, either a [`Number`] or an [`FExp`](FExp). 6 | /// 7 | /// ## Usage 8 | /// Used by [`SimpleDurationConstraint`](crate::SimpleDurationConstraint). 9 | #[derive(Debug, Clone, PartialEq)] 10 | pub enum DurationValue { 11 | /// A numerical value. 12 | Number(Number), 13 | /// A function expression that produces the duration value. 14 | /// ## Requirements 15 | /// Requires [Numeric Fluents](crate::Requirement::NumericFluents). 16 | FExp(FExp), 17 | } 18 | 19 | impl DurationValue { 20 | pub fn new_number>(number: I) -> Self { 21 | Self::Number(number.into()) 22 | } 23 | 24 | pub fn new_f_exp(exp: FExp) -> Self { 25 | Self::FExp(exp) 26 | } 27 | } 28 | 29 | impl From for DurationValue { 30 | fn from(value: Number) -> Self { 31 | Self::Number(value) 32 | } 33 | } 34 | 35 | impl From for DurationValue { 36 | fn from(value: FExp) -> Self { 37 | Self::FExp(value) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/types/da_effect.rs: -------------------------------------------------------------------------------- 1 | //! Contains durative action effects via the [`DurativeActionEffect`] type. 2 | 3 | use crate::types::TypedVariables; 4 | use crate::types::{DurativeActionGoalDefinition, TimedEffect}; 5 | 6 | /// A durative action effect used in [`DurativeActionDefinition`](crate::types::DurativeActionDefinition). 7 | /// 8 | /// ## Usage 9 | /// Used by [`DurativeActionDefinition`](crate::DurativeActionDefinition). 10 | #[derive(Debug, Clone, PartialEq)] 11 | pub enum DurativeActionEffect { 12 | Timed(TimedEffect), 13 | /// Conjunction: All effects apply (i.e. a and b and c ..). 14 | All(Vec), 15 | /// ## Requirements 16 | /// Requires [Conditional Effects](crate::Requirement::ConditionalEffects). 17 | Forall(TypedVariables, Box), 18 | /// ## Requirements 19 | /// Requires [Conditional Effects](crate::Requirement::ConditionalEffects). 20 | When(DurativeActionGoalDefinition, TimedEffect), 21 | } 22 | 23 | impl DurativeActionEffect { 24 | pub const fn new_timed(effect: TimedEffect) -> Self { 25 | Self::Timed(effect) 26 | } 27 | pub fn new_and>(effect: E) -> Self { 28 | Self::All(effect.into_iter().collect()) 29 | } 30 | pub fn new_forall(variables: TypedVariables, effect: DurativeActionEffect) -> Self { 31 | Self::Forall(variables, Box::new(effect)) 32 | } 33 | pub const fn new_when(gd: DurativeActionGoalDefinition, effect: TimedEffect) -> Self { 34 | Self::When(gd, effect) 35 | } 36 | } 37 | 38 | impl From for DurativeActionEffect { 39 | fn from(value: TimedEffect) -> Self { 40 | Self::new_timed(value) 41 | } 42 | } 43 | 44 | impl FromIterator for DurativeActionEffect { 45 | fn from_iter>(iter: T) -> Self { 46 | Self::new_and(iter) 47 | } 48 | } 49 | 50 | impl From<(TypedVariables, DurativeActionEffect)> for DurativeActionEffect { 51 | fn from(value: (TypedVariables, DurativeActionEffect)) -> Self { 52 | Self::new_forall(value.0, value.1) 53 | } 54 | } 55 | 56 | impl From<(DurativeActionGoalDefinition, TimedEffect)> for DurativeActionEffect { 57 | fn from(value: (DurativeActionGoalDefinition, TimedEffect)) -> Self { 58 | Self::new_when(value.0, value.1) 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/types/da_gd.rs: -------------------------------------------------------------------------------- 1 | //! Contains durative action goal definitions via the [`DurativeActionGoalDefinition`] type. 2 | 3 | use crate::types::PrefTimedGD; 4 | use crate::types::TypedVariables; 5 | 6 | /// A durative action goal definition. 7 | /// 8 | /// ## Usage 9 | /// Used by [`DurativeActionGoalDefinition`] itself, as well as [`DurativeActionDefinition`](crate::DurativeActionDefinition) and 10 | /// [`DurativeActionEffect`](crate::DurativeActionEffect). 11 | #[derive(Debug, Clone, PartialEq)] 12 | pub enum DurativeActionGoalDefinition { 13 | Timed(PrefTimedGD), 14 | And(Vec), 15 | /// ## Requirements 16 | /// Requires [Universal Preconditions](crate::Requirement::UniversalPreconditions). 17 | Forall(TypedVariables, Box), 18 | } 19 | 20 | impl DurativeActionGoalDefinition { 21 | pub fn new_timed(pref: PrefTimedGD) -> Self { 22 | Self::Timed(pref) 23 | } 24 | pub fn new_and>(prefs: I) -> Self { 25 | Self::And(prefs.into_iter().collect()) 26 | } 27 | pub fn new_forall(variables: TypedVariables, gd: DurativeActionGoalDefinition) -> Self { 28 | Self::Forall(variables, Box::new(gd)) 29 | } 30 | } 31 | 32 | impl From for DurativeActionGoalDefinition { 33 | fn from(value: PrefTimedGD) -> Self { 34 | DurativeActionGoalDefinition::new_timed(value) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/types/da_symbol.rs: -------------------------------------------------------------------------------- 1 | //! Contains the [`DurativeActionSymbol`] type. 2 | 3 | use crate::types::Name; 4 | use std::ops::Deref; 5 | 6 | /// A durative action symbol. 7 | /// 8 | /// ## Usage 9 | /// Used by [`DurativeActionDefinition`](crate::DurativeActionDefinition). 10 | #[derive(Debug, Clone, Eq, PartialEq, Hash, Default)] 11 | pub struct DurativeActionSymbol(Name); 12 | 13 | impl DurativeActionSymbol { 14 | #[inline(always)] 15 | pub const fn new(name: Name) -> Self { 16 | Self(name) 17 | } 18 | 19 | #[inline(always)] 20 | pub fn from_str(name: &str) -> Self { 21 | Self(Name::new(name)) 22 | } 23 | 24 | #[inline(always)] 25 | pub const fn from_name(name: Name) -> Self { 26 | Self(name) 27 | } 28 | } 29 | 30 | impl<'a, T> From for DurativeActionSymbol 31 | where 32 | T: Into, 33 | { 34 | #[inline(always)] 35 | fn from(value: T) -> Self { 36 | DurativeActionSymbol::new(value.into()) 37 | } 38 | } 39 | 40 | impl AsRef for DurativeActionSymbol { 41 | #[inline(always)] 42 | fn as_ref(&self) -> &Name { 43 | &self.0 44 | } 45 | } 46 | 47 | impl AsRef for DurativeActionSymbol { 48 | #[inline(always)] 49 | fn as_ref(&self) -> &str { 50 | self.0.as_ref() 51 | } 52 | } 53 | 54 | impl Deref for DurativeActionSymbol { 55 | type Target = Name; 56 | 57 | #[inline(always)] 58 | fn deref(&self) -> &Self::Target { 59 | &self.0 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/types/derived_predicate.rs: -------------------------------------------------------------------------------- 1 | //! Contains derived predicates via the [`DerivedPredicate`] type. 2 | 3 | use crate::types::{AtomicFormulaSkeleton, GoalDefinition}; 4 | 5 | /// A derived predicate. 6 | /// 7 | /// ## Usage 8 | /// Used by [`StructureDef`](crate::StructureDef). 9 | #[derive(Debug, Clone, PartialEq)] 10 | pub struct DerivedPredicate(AtomicFormulaSkeleton, GoalDefinition); 11 | 12 | impl DerivedPredicate { 13 | pub const fn new(formula: AtomicFormulaSkeleton, gd: GoalDefinition) -> Self { 14 | Self(formula, gd) 15 | } 16 | 17 | pub const fn predicate(&self) -> &AtomicFormulaSkeleton { 18 | &self.0 19 | } 20 | 21 | pub const fn expression(&self) -> &GoalDefinition { 22 | &self.1 23 | } 24 | } 25 | 26 | impl From<(AtomicFormulaSkeleton, GoalDefinition)> for DerivedPredicate { 27 | fn from(value: (AtomicFormulaSkeleton, GoalDefinition)) -> Self { 28 | DerivedPredicate::new(value.0, value.1) 29 | } 30 | } 31 | 32 | impl AsRef for DerivedPredicate { 33 | fn as_ref(&self) -> &AtomicFormulaSkeleton { 34 | self.predicate() 35 | } 36 | } 37 | 38 | impl AsRef for DerivedPredicate { 39 | fn as_ref(&self) -> &GoalDefinition { 40 | self.expression() 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/types/domain_constraints_def.rs: -------------------------------------------------------------------------------- 1 | //! Contains the [`DomainConstraintsDef`] type. 2 | 3 | use crate::types::ConGD; 4 | use std::ops::Deref; 5 | 6 | /// A domain constraints definition; wraps a [`ConGD`]. 7 | /// 8 | /// ## Requirements 9 | /// Requires [Constraints](crate::Requirement::Constraints). 10 | /// 11 | /// ## Usage 12 | /// Used by [`Domain`](crate::Domain). 13 | #[derive(Debug, Default, Clone, PartialEq)] 14 | pub struct DomainConstraintsDef(ConGD); 15 | 16 | impl DomainConstraintsDef { 17 | pub const fn new(gd: ConGD) -> Self { 18 | Self(gd) 19 | } 20 | 21 | /// Gets the value. 22 | pub const fn value(&self) -> &ConGD { 23 | &self.0 24 | } 25 | } 26 | 27 | impl PartialEq for DomainConstraintsDef { 28 | fn eq(&self, other: &ConGD) -> bool { 29 | self.0.eq(other) 30 | } 31 | } 32 | 33 | impl From for DomainConstraintsDef { 34 | fn from(value: ConGD) -> Self { 35 | Self::new(value) 36 | } 37 | } 38 | 39 | impl Deref for DomainConstraintsDef { 40 | type Target = ConGD; 41 | 42 | fn deref(&self) -> &Self::Target { 43 | &self.0 44 | } 45 | } 46 | 47 | impl From for ConGD { 48 | fn from(val: DomainConstraintsDef) -> Self { 49 | val.0 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/types/duration_constraint.rs: -------------------------------------------------------------------------------- 1 | //! Contains duration constraints via the [`DurationConstraint`] type. 2 | 3 | use crate::types::iterators::FlatteningIntoIterator; 4 | use crate::types::SimpleDurationConstraint; 5 | 6 | /// ## Usage 7 | /// Used by [`DurativeActionDefinition`](crate::DurativeActionDefinition). 8 | #[derive(Debug, Clone, PartialEq)] 9 | pub enum DurationConstraint { 10 | Single(SimpleDurationConstraint), 11 | /// ## Requirements 12 | /// Requires [Duration Inequalities](crate::Requirement::DurationInequalities). 13 | All(Vec), 14 | } 15 | 16 | impl IntoIterator for DurationConstraint { 17 | type Item = SimpleDurationConstraint; 18 | type IntoIter = FlatteningIntoIterator; 19 | 20 | fn into_iter(self) -> Self::IntoIter { 21 | match self { 22 | DurationConstraint::Single(item) => FlatteningIntoIterator::new(item), 23 | DurationConstraint::All(vec) => FlatteningIntoIterator::new_vec(vec), 24 | } 25 | } 26 | } 27 | 28 | impl DurationConstraint { 29 | pub const fn new(constraint: SimpleDurationConstraint) -> Self { 30 | Self::Single(constraint) 31 | } 32 | 33 | pub fn new_all>(constraints: I) -> Self { 34 | let vec: Vec<_> = constraints.into_iter().collect(); 35 | debug_assert!(!vec.is_empty()); 36 | Self::All(vec) 37 | } 38 | 39 | pub fn len(&self) -> usize { 40 | match self { 41 | DurationConstraint::Single(_) => 1, 42 | DurationConstraint::All(cs) => cs.len(), 43 | } 44 | } 45 | 46 | pub fn is_empty(&self) -> bool { 47 | match self { 48 | DurationConstraint::Single(_) => false, 49 | DurationConstraint::All(xs) => xs.is_empty(), 50 | } 51 | } 52 | } 53 | 54 | impl From for DurationConstraint { 55 | fn from(value: SimpleDurationConstraint) -> Self { 56 | DurationConstraint::new(value) 57 | } 58 | } 59 | 60 | impl FromIterator for DurationConstraint { 61 | fn from_iter>(iter: T) -> Self { 62 | DurationConstraint::new_all(iter) 63 | } 64 | } 65 | 66 | #[cfg(test)] 67 | mod tests { 68 | use super::*; 69 | use crate::parsers::Span; 70 | use crate::Parser; 71 | 72 | #[test] 73 | fn flatten_with_single_element_works() { 74 | let (_, dc_a) = SimpleDurationConstraint::parse(Span::new("(>= ?duration 1.23)")).unwrap(); 75 | 76 | let mut iter = DurationConstraint::new(dc_a).into_iter(); 77 | assert!(iter.next().is_some()); 78 | assert!(iter.next().is_none()); 79 | } 80 | 81 | #[test] 82 | fn flatten_with_many_elements_works() { 83 | let (_, dc_a) = SimpleDurationConstraint::parse(Span::new("(>= ?duration 1.23)")).unwrap(); 84 | let (_, dc_b) = 85 | SimpleDurationConstraint::parse(Span::new("(at end (<= ?duration 1.23))")).unwrap(); 86 | 87 | let mut iter = DurationConstraint::from_iter([dc_a, dc_b]).into_iter(); 88 | assert!(iter.next().is_some()); 89 | assert!(iter.next().is_some()); 90 | assert!(iter.next().is_none()); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/types/effects.rs: -------------------------------------------------------------------------------- 1 | //! Contains effects via the [`Effects`] type. 2 | 3 | use crate::types::CEffect; 4 | use std::ops::Deref; 5 | 6 | /// An effect. Occurs e.g. in a [`ActionDefinition`](crate::types::ActionDefinition). 7 | /// 8 | /// This represents the `(and ...)` variant of the PDDL definition, 9 | /// modeling cases of zero, one or many effects. 10 | /// 11 | /// ## Usage 12 | /// Used by [`ActionDefinition`](crate::ActionDefinition). 13 | #[derive(Debug, Clone, PartialEq, Default)] 14 | pub struct Effects(Vec); 15 | 16 | impl Effects { 17 | /// Constructs a new instance from the value. 18 | pub fn new(effect: CEffect) -> Self { 19 | Self(vec![effect]) 20 | } 21 | 22 | /// Constructs a new instance from the provided vector of values. 23 | pub fn new_and(effects: Vec) -> Self { 24 | Self(effects) 25 | } 26 | 27 | /// Returns `true` if the list contains no elements. 28 | pub fn is_empty(&self) -> bool { 29 | self.0.is_empty() 30 | } 31 | 32 | /// Returns the number of elements in the list, also referred to 33 | /// as its 'length'. 34 | pub fn len(&self) -> usize { 35 | self.0.len() 36 | } 37 | 38 | /// Returns an iterator over the list. 39 | /// 40 | /// The iterator yields all items from start to end. 41 | pub fn iter(&self) -> std::slice::Iter { 42 | self.0.iter() 43 | } 44 | 45 | /// Get the only element of this list if the list has 46 | /// exactly one element. Returns [`None`] in all other cases. 47 | pub fn try_get_single(self) -> Option { 48 | if self.len() == 1 { 49 | self.into_iter().next() 50 | } else { 51 | None 52 | } 53 | } 54 | } 55 | 56 | impl IntoIterator for Effects { 57 | type Item = CEffect; 58 | type IntoIter = std::vec::IntoIter; 59 | 60 | fn into_iter(self) -> Self::IntoIter { 61 | self.0.into_iter() 62 | } 63 | } 64 | 65 | impl Deref for Effects { 66 | type Target = [CEffect]; 67 | 68 | fn deref(&self) -> &Self::Target { 69 | self.0.as_slice() 70 | } 71 | } 72 | 73 | impl AsRef<[CEffect]> for Effects { 74 | fn as_ref(&self) -> &[CEffect] { 75 | self.0.as_slice() 76 | } 77 | } 78 | 79 | impl From for Effects { 80 | fn from(value: CEffect) -> Self { 81 | Effects::new(value) 82 | } 83 | } 84 | 85 | impl From> for Effects { 86 | fn from(value: Vec) -> Self { 87 | Effects::new_and(value) 88 | } 89 | } 90 | 91 | impl FromIterator for Effects { 92 | fn from_iter>(iter: T) -> Self { 93 | Effects::new_and(iter.into_iter().collect()) 94 | } 95 | } 96 | 97 | impl TryInto for Effects { 98 | type Error = (); 99 | 100 | fn try_into(self) -> Result { 101 | self.try_get_single().ok_or(()) 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/types/f_assign_da.rs: -------------------------------------------------------------------------------- 1 | //! Contains the durative action assignment expressions via the [`FAssignDa`] type. 2 | 3 | use crate::types::{AssignOp, FExpDa, FHead}; 4 | 5 | /// An timed effect assignment operation. Will perform the 6 | /// specified assignment `at` [`TimeSpecifier`](crate::TimeSpecifier) when 7 | /// [`NumericFluents`](crate::Requirement::NumericFluents) is allowed. 8 | /// 9 | /// ## Requirements 10 | /// Requires [`NumericFluents`](crate::Requirement::NumericFluents). 11 | /// 12 | /// ## Usage 13 | /// Used by [`TimedEffect`](crate::TimedEffect). 14 | #[derive(Debug, Clone, PartialEq)] 15 | pub struct FAssignDa(AssignOp, FHead, FExpDa); 16 | 17 | impl FAssignDa { 18 | pub const fn new(comp: AssignOp, head: FHead, exp: FExpDa) -> Self { 19 | Self(comp, head, exp) 20 | } 21 | 22 | /// Returns the operation. 23 | pub const fn operation(&self) -> &AssignOp { 24 | &self.0 25 | } 26 | 27 | /// Returns the function head. 28 | pub const fn function(&self) -> &FHead { 29 | &self.1 30 | } 31 | 32 | /// Returns the function expression of the durative action. 33 | pub const fn function_expr(&self) -> &FExpDa { 34 | &self.2 35 | } 36 | } 37 | 38 | impl From<(AssignOp, FHead, FExpDa)> for FAssignDa { 39 | fn from(value: (AssignOp, FHead, FExpDa)) -> Self { 40 | FAssignDa::new(value.0, value.1, value.2) 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/types/f_comp.rs: -------------------------------------------------------------------------------- 1 | //! Contains function expression comparisons via the [`FComp`] type. 2 | 3 | use crate::types::{BinaryComp, FExp}; 4 | 5 | /// An fluent comparison used as part of a [`GoalDefinition`](crate::GoalDefinition) 6 | /// when [`NumericFluents`](crate::Requirement::NumericFluents) is allowed. 7 | /// 8 | /// ## Usage 9 | /// Used by [`GoalDefinition`](crate::GoalDefinition). 10 | #[derive(Debug, Clone, PartialEq)] 11 | pub struct FComp(BinaryComp, FExp, FExp); 12 | 13 | impl FComp { 14 | pub const fn new(comp: BinaryComp, lhs: FExp, rhs: FExp) -> Self { 15 | Self(comp, lhs, rhs) 16 | } 17 | 18 | /// Returns the comparison operator. 19 | pub const fn comparison(&self) -> &BinaryComp { 20 | &self.0 21 | } 22 | 23 | /// Returns the first operand. 24 | pub const fn first(&self) -> &FExp { 25 | &self.1 26 | } 27 | 28 | /// Returns the second operand. 29 | pub const fn second(&self) -> &FExp { 30 | &self.2 31 | } 32 | } 33 | 34 | impl From<(BinaryComp, FExp, FExp)> for FComp { 35 | fn from(value: (BinaryComp, FExp, FExp)) -> Self { 36 | FComp::new(value.0, value.1, value.2) 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/types/f_exp.rs: -------------------------------------------------------------------------------- 1 | //! Contains function expressions via the [`FExp`] type. 2 | 3 | use crate::types::{BinaryOp, FHead, MultiOp, Number}; 4 | 5 | /// A function/fluent expression used e.g. in a [`DurationValue`](crate::types::DurationValue). 6 | /// 7 | /// ## Requirements 8 | /// Requires [Numeric Fluents](crate::Requirement::NumericFluents). 9 | /// 10 | /// ## Usage 11 | /// Used by [`FExp`] itself, as well as [`PEffect`](crate::PEffect), [`DurationValue`](crate::DurationValue), 12 | /// [`FExpDa`](crate::FExpDa) and [`FExpT`](crate::FExpT). 13 | #[derive(Debug, Clone, PartialEq)] 14 | pub enum FExp { 15 | /// A numerical expression. 16 | Number(Number), 17 | /// A function that derives a value. 18 | Function(FHead), 19 | /// The negative value of a function expression. 20 | Negative(Box), 21 | /// An operation applied to two function expressions. 22 | BinaryOp(BinaryOp, Box, Box), 23 | /// An operation applied to two or more function expressions. 24 | MultiOp(MultiOp, Box, Vec), 25 | } 26 | 27 | impl FExp { 28 | #[inline(always)] 29 | pub fn new_number>(number: N) -> Self { 30 | Self::Number(number.into()) 31 | } 32 | 33 | pub fn new_binary_op(op: BinaryOp, lhs: FExp, rhs: FExp) -> Self { 34 | Self::BinaryOp(op, Box::new(lhs), Box::new(rhs)) 35 | } 36 | 37 | pub fn new_multi_op>(op: MultiOp, lhs: FExp, rhs: I) -> Self { 38 | Self::MultiOp(op, Box::new(lhs), rhs.into_iter().collect()) 39 | } 40 | 41 | pub fn new_negative(value: FExp) -> Self { 42 | Self::Negative(Box::new(value)) 43 | } 44 | 45 | pub const fn new_function(f_head: FHead) -> Self { 46 | Self::Function(f_head) 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/types/f_exp_da.rs: -------------------------------------------------------------------------------- 1 | //! Contains durative function expressions via the [`FExpDa`] type. 2 | 3 | use crate::types::{AssignOp, BinaryOp, FExp, FHead, MultiOp}; 4 | 5 | /// ## Usage 6 | /// Used by [`FExpDa`] itself, as well as [`FAssignDa`](crate::FAssignDa). 7 | #[derive(Debug, Clone, PartialEq)] 8 | pub enum FExpDa { 9 | Assign(AssignOp, FHead, Box), 10 | BinaryOp(BinaryOp, Box, Box), 11 | MultiOp(MultiOp, Box, Vec), 12 | Negative(Box), 13 | /// ## Requirements 14 | /// Requires [Duration Inequalities](crate::Requirement::DurationInequalities). 15 | Duration, 16 | FExp(FExp), 17 | } 18 | 19 | impl FExpDa { 20 | pub const fn new_duration() -> Self { 21 | Self::Duration 22 | } 23 | 24 | pub fn new_binary_op(op: BinaryOp, lhs: FExpDa, rhs: FExpDa) -> Self { 25 | Self::BinaryOp(op, Box::new(lhs), Box::new(rhs)) 26 | } 27 | 28 | pub fn new_multi_op>(op: MultiOp, lhs: FExpDa, rhs: I) -> Self { 29 | Self::MultiOp(op, Box::new(lhs), rhs.into_iter().collect()) 30 | } 31 | 32 | pub fn new_negative(value: FExpDa) -> Self { 33 | Self::Negative(Box::new(value)) 34 | } 35 | 36 | pub const fn new_f_exp(f_head: FExp) -> Self { 37 | Self::FExp(f_head) 38 | } 39 | } 40 | 41 | impl From for FExpDa { 42 | fn from(value: FExp) -> Self { 43 | FExpDa::new_f_exp(value) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/types/f_exp_t.rs: -------------------------------------------------------------------------------- 1 | //! Contains timed function expressions via the [`FExpT`] type. 2 | 3 | use crate::types::FExp; 4 | 5 | /// An f-exp-t. 6 | /// 7 | /// ## Requirements 8 | /// Requires [Continuous Effects](crate::Requirement::ContinuousEffects) and 9 | /// [Numeric Fluents](crate::Requirement::NumericFluents). 10 | /// 11 | /// ## Usage 12 | /// Used by [`TimedEffect`](crate::TimedEffect). 13 | #[derive(Debug, Clone, PartialEq)] 14 | pub enum FExpT { 15 | Now, 16 | Scaled(FExp), 17 | } 18 | 19 | impl FExpT { 20 | pub const fn new() -> Self { 21 | Self::Now 22 | } 23 | 24 | pub fn new_scaled(exp: FExp) -> Self { 25 | Self::Scaled(exp) 26 | } 27 | } 28 | 29 | impl Default for FExpT { 30 | fn default() -> Self { 31 | Self::Now 32 | } 33 | } 34 | 35 | impl From for FExpT { 36 | fn from(value: FExp) -> Self { 37 | Self::Scaled(value) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/types/f_head.rs: -------------------------------------------------------------------------------- 1 | //! Contains function declarations via the [`FHead`] type. 2 | 3 | use crate::types::{FunctionSymbol, Term}; 4 | 5 | /// A function declaration. 6 | /// 7 | /// ## Requirements 8 | /// Requires [Numeric Fluents](crate::Requirement::NumericFluents). 9 | /// 10 | /// ## Usage 11 | /// Used by [`FExp`](crate::FExp), [`PEffect`](crate::PEffect), [`TimedEffect`](crate::TimedEffect) 12 | /// and [`FAssignDa`](crate::FAssignDa). 13 | #[derive(Debug, Clone, Eq, PartialEq)] 14 | pub enum FHead { 15 | Simple(FunctionSymbol), // TODO: Unify with `WithTerms`? 16 | WithTerms(FunctionSymbol, Vec), 17 | } 18 | 19 | impl FHead { 20 | pub const fn new(symbol: FunctionSymbol) -> Self { 21 | Self::Simple(symbol) 22 | } 23 | 24 | pub fn new_with_terms>(symbol: FunctionSymbol, terms: I) -> Self { 25 | Self::WithTerms(symbol, terms.into_iter().collect()) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/types/function_symbols.rs: -------------------------------------------------------------------------------- 1 | //! Contains function symbols via the [`FunctionSymbol`] type.. 2 | 3 | use crate::types::Name; 4 | use std::ops::Deref; 5 | 6 | /// A function symbol name. 7 | /// 8 | /// ## Usage 9 | /// Used by [`FunctionTerm`](crate::FunctionTerm), [`FHead`](crate::FHead), 10 | /// [`BasicFunctionTerm`](crate::BasicFunctionTerm) and [`MetricFExp`](crate::MetricFExp). 11 | #[derive(Debug, Clone, Eq, PartialEq, Hash, Default)] 12 | pub struct FunctionSymbol(Name); 13 | 14 | impl FunctionSymbol { 15 | #[inline(always)] 16 | pub fn new(name: Name) -> Self { 17 | Self(name) 18 | } 19 | 20 | #[inline(always)] 21 | pub fn from_str(name: &str) -> Self { 22 | Self(Name::new(name)) 23 | } 24 | 25 | #[inline(always)] 26 | pub const fn from_name(name: Name) -> Self { 27 | Self(name) 28 | } 29 | } 30 | 31 | impl<'a, T> From for FunctionSymbol 32 | where 33 | T: Into, 34 | { 35 | #[inline(always)] 36 | fn from(value: T) -> Self { 37 | FunctionSymbol::new(value.into()) 38 | } 39 | } 40 | 41 | impl AsRef for FunctionSymbol { 42 | #[inline(always)] 43 | fn as_ref(&self) -> &Name { 44 | &self.0 45 | } 46 | } 47 | 48 | impl AsRef for FunctionSymbol { 49 | #[inline(always)] 50 | fn as_ref(&self) -> &str { 51 | self.0.as_ref() 52 | } 53 | } 54 | 55 | impl Deref for FunctionSymbol { 56 | type Target = Name; 57 | 58 | #[inline(always)] 59 | fn deref(&self) -> &Self::Target { 60 | &self.0 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/types/function_term.rs: -------------------------------------------------------------------------------- 1 | //! Contains function terms via the [`FunctionTerm`] type. 2 | 3 | use crate::types::term::Term; 4 | use crate::types::FunctionSymbol; 5 | 6 | /// A function term. 7 | /// 8 | /// ## Requirements 9 | /// Requires [Object Fluents](crate::Requirement::ObjectFluents). 10 | /// 11 | /// ## Usage 12 | /// Used by [`Term`], and [`PEffect`](crate::PEffect). 13 | #[derive(Debug, Clone, Eq, PartialEq)] 14 | pub struct FunctionTerm(FunctionSymbol, Vec); 15 | 16 | impl FunctionTerm { 17 | pub fn new>(symbol: FunctionSymbol, terms: I) -> Self { 18 | Self(symbol, terms.into_iter().collect()) 19 | } 20 | 21 | /// Gets the function symbol. 22 | pub const fn symbol(&self) -> &FunctionSymbol { 23 | &self.0 24 | } 25 | 26 | /// Gets the function terms. 27 | pub fn terms(&self) -> &[Term] { 28 | self.1.as_ref() 29 | } 30 | } 31 | 32 | impl AsRef for FunctionTerm { 33 | fn as_ref(&self) -> &FunctionSymbol { 34 | &self.0 35 | } 36 | } 37 | 38 | impl AsRef> for FunctionTerm { 39 | fn as_ref(&self) -> &Vec { 40 | &self.1 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/types/function_type.rs: -------------------------------------------------------------------------------- 1 | //! Contains function types via the [`FunctionType`] ... type. 2 | 3 | use crate::types::{PrimitiveType, Type}; 4 | use std::ops::Deref; 5 | 6 | /// A function type. 7 | /// 8 | /// ## Requirements 9 | /// Requires [Fluents](crate::Requirement::Fluents), as well as either 10 | /// [Numeric Fluents](crate::Requirement::NumericFluents) for the default `number` type, or 11 | /// [Object Fluents](crate::Requirement::ObjectFluents) and [Typing](crate::Requirement::Typing) 12 | /// for an arbitrary type. 13 | /// 14 | /// ## Usage 15 | /// Used by [`FunctionTyped`](crate::FunctionTyped) in [`FunctionTypedList`](crate::FunctionTypedList). 16 | #[derive(Debug, Clone, Eq, PartialEq)] 17 | pub struct FunctionType(Type); 18 | 19 | impl FunctionType { 20 | pub const NUMBER: FunctionType = FunctionType::from(Type::NUMBER); 21 | 22 | pub fn new>(r#type: T) -> Self { 23 | Self(r#type.into()) 24 | } 25 | 26 | pub const fn from(r#type: Type) -> Self { 27 | Self(r#type) 28 | } 29 | } 30 | 31 | impl Default for FunctionType { 32 | fn default() -> Self { 33 | Self(Type::NUMBER) 34 | } 35 | } 36 | 37 | impl From<&str> for FunctionType { 38 | fn from(value: &str) -> Self { 39 | Self(value.into()) 40 | } 41 | } 42 | 43 | impl From> for FunctionType { 44 | fn from(value: Vec<&str>) -> Self { 45 | Self(Type::from_iter( 46 | value.iter().map(|&x| PrimitiveType::from(x)), 47 | )) 48 | } 49 | } 50 | 51 | impl From for FunctionType { 52 | fn from(value: Type) -> Self { 53 | Self(value) 54 | } 55 | } 56 | 57 | impl Deref for FunctionType { 58 | type Target = Type; 59 | 60 | fn deref(&self) -> &Self::Target { 61 | &self.0 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/types/function_typed.rs: -------------------------------------------------------------------------------- 1 | //! Contains function typed elements via the [`FunctionTyped`] type. 2 | 3 | use crate::types::FunctionType; 4 | use crate::types::Type; 5 | use std::ops::Deref; 6 | 7 | /// A typed function element. 8 | /// 9 | /// ## Requirements 10 | /// Requires [Fluents](crate::Requirement::Fluents), as well as the same requirements as [`FunctionType`]. 11 | /// 12 | /// ## Usage 13 | /// Used by [`FunctionTypedList`](crate::FunctionTypedList). 14 | #[derive(Debug, Clone, Eq, PartialEq)] 15 | pub struct FunctionTyped(O, FunctionType); 16 | 17 | impl FunctionTyped { 18 | pub const fn new(value: O, r#type: FunctionType) -> Self { 19 | Self(value, r#type) 20 | } 21 | 22 | pub const fn new_number(value: O) -> Self { 23 | Self::new(value, FunctionType::NUMBER) 24 | } 25 | 26 | pub const fn from_type(value: O, r#type: Type) -> Self { 27 | Self::new(value, FunctionType::from(r#type)) 28 | } 29 | 30 | pub const fn value_ref(&self) -> &O { 31 | &self.0 32 | } 33 | 34 | pub const fn type_ref(&self) -> &FunctionType { 35 | &self.1 36 | } 37 | } 38 | 39 | impl From for FunctionTyped { 40 | fn from(value: O) -> Self { 41 | FunctionTyped::new_number(value) 42 | } 43 | } 44 | 45 | impl Deref for FunctionTyped { 46 | type Target = O; 47 | 48 | fn deref(&self) -> &Self::Target { 49 | self.value_ref() 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/types/function_typed_list.rs: -------------------------------------------------------------------------------- 1 | //! Contains typed function elements via the [`FunctionTypedList`] type. 2 | 3 | use crate::types::function_typed::FunctionTyped; 4 | use std::ops::Deref; 5 | 6 | /// A list of typed elements. 7 | /// 8 | /// ## Example 9 | /// ``` 10 | /// # use pddl::{FunctionTypedList, FunctionTyped, FunctionType}; 11 | /// # use pddl::{TypedList, Name}; 12 | /// let tl = FunctionTypedList::from_iter([ 13 | /// FunctionTyped::new(Name::from("location"), FunctionType::NUMBER), 14 | /// FunctionTyped::new(Name::from("physob"), FunctionType::NUMBER), 15 | /// ]); 16 | /// 17 | /// assert_eq!(tl.len(), 2); 18 | /// assert_eq!(tl[0].value_ref(), &Name::from("location")); 19 | /// assert_eq!(tl[1].value_ref(), &Name::from("physob")); 20 | /// ``` 21 | /// 22 | /// ## Requirements 23 | /// Requires [Fluents](crate::Requirement::Fluents) and either 24 | /// [Numeric Fluents](crate::Requirement::NumericFluents) for the default `number` type, or 25 | /// [Object Fluents](crate::Requirement::ObjectFluents) and [Typing](crate::Requirement::Typing) 26 | /// for an arbitrary type. 27 | /// 28 | /// ## Usage 29 | /// Used by [`Functions`](crate::Functions). 30 | #[derive(Debug, Clone, Eq, PartialEq)] 31 | pub struct FunctionTypedList(Vec>); 32 | 33 | impl<'a, T> Default for FunctionTypedList { 34 | fn default() -> Self { 35 | Self(Vec::default()) 36 | } 37 | } 38 | 39 | impl<'a, T> FunctionTypedList { 40 | pub const fn new(list: Vec>) -> Self { 41 | Self(list) 42 | } 43 | 44 | /// Gets the values. 45 | pub fn values(&self) -> &[FunctionTyped] { 46 | self.0.as_slice() 47 | } 48 | } 49 | 50 | impl<'a, T> From>> for FunctionTypedList { 51 | fn from(iter: Vec>) -> Self { 52 | FunctionTypedList::new(iter) 53 | } 54 | } 55 | 56 | impl<'a, T> FromIterator> for FunctionTypedList { 57 | fn from_iter>>(iter: I) -> Self { 58 | FunctionTypedList::new(iter.into_iter().collect()) 59 | } 60 | } 61 | 62 | impl<'a, T> Deref for FunctionTypedList { 63 | type Target = [FunctionTyped]; 64 | 65 | fn deref(&self) -> &Self::Target { 66 | self.0.as_slice() 67 | } 68 | } 69 | 70 | impl<'a, T> PartialEq>> for FunctionTypedList 71 | where 72 | T: PartialEq, 73 | { 74 | fn eq(&self, other: &Vec>) -> bool { 75 | self.0.eq(other) 76 | } 77 | } 78 | 79 | impl<'a, T> PartialEq<[FunctionTyped]> for FunctionTypedList 80 | where 81 | T: PartialEq, 82 | { 83 | fn eq(&self, other: &[FunctionTyped]) -> bool { 84 | self.0.eq(other) 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/types/functions.rs: -------------------------------------------------------------------------------- 1 | //! Provides function definitions via the [`Functions`] type. 2 | 3 | use crate::types::{AtomicFunctionSkeleton, FunctionTyped, FunctionTypedList}; 4 | use std::ops::Deref; 5 | 6 | /// A set of functions. 7 | /// 8 | /// ## Requirements 9 | /// Requires [Fluents](crate::Requirement::Fluents). 10 | /// 11 | /// ## Usage 12 | /// Used by [`Domain`](crate::Domain). 13 | #[derive(Debug, Default, Clone, Eq, PartialEq)] 14 | pub struct Functions(FunctionTypedList); 15 | 16 | impl Functions { 17 | pub const fn new(functions: FunctionTypedList) -> Self { 18 | Self(functions) 19 | } 20 | 21 | /// Gets the values. 22 | pub fn values(&self) -> &FunctionTypedList { 23 | &self.0 24 | } 25 | } 26 | 27 | impl Deref for Functions { 28 | type Target = FunctionTypedList; 29 | 30 | fn deref(&self) -> &Self::Target { 31 | &self.0 32 | } 33 | } 34 | 35 | impl From> for Functions { 36 | fn from(value: FunctionTypedList) -> Self { 37 | Functions::new(value) 38 | } 39 | } 40 | 41 | impl FromIterator> for Functions { 42 | fn from_iter>>(iter: T) -> Self { 43 | Functions::new(FunctionTypedList::from_iter(iter)) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/types/goal_def.rs: -------------------------------------------------------------------------------- 1 | //! Contains the [`GoalDef`] type. 2 | 3 | use crate::types::pre_gd::PreconditionGoalDefinitions; 4 | use crate::PreconditionGoalDefinition; 5 | use std::ops::Deref; 6 | 7 | /// A problem goal definition; wraps a [`PreconditionGoalDefinitions`]. 8 | /// 9 | /// ## Usage 10 | /// Used by [`Problem`](crate::Problem). 11 | #[derive(Debug, Clone, PartialEq)] 12 | pub struct GoalDef(PreconditionGoalDefinitions); 13 | 14 | impl GoalDef { 15 | pub const fn new(gd: PreconditionGoalDefinitions) -> Self { 16 | Self(gd) 17 | } 18 | 19 | /// Gets the value. 20 | pub const fn value(&self) -> &PreconditionGoalDefinitions { 21 | &self.0 22 | } 23 | } 24 | 25 | impl PartialEq for GoalDef { 26 | fn eq(&self, other: &PreconditionGoalDefinitions) -> bool { 27 | self.0.eq(other) 28 | } 29 | } 30 | 31 | impl From for GoalDef { 32 | fn from(value: PreconditionGoalDefinitions) -> Self { 33 | Self::new(value) 34 | } 35 | } 36 | 37 | impl From for GoalDef { 38 | fn from(value: PreconditionGoalDefinition) -> Self { 39 | Self::new(PreconditionGoalDefinitions::from(value)) 40 | } 41 | } 42 | 43 | impl FromIterator for GoalDef { 44 | fn from_iter>(iter: T) -> Self { 45 | GoalDef::new(PreconditionGoalDefinitions::from_iter(iter)) 46 | } 47 | } 48 | 49 | impl Deref for GoalDef { 50 | type Target = PreconditionGoalDefinitions; 51 | 52 | fn deref(&self) -> &Self::Target { 53 | &self.0 54 | } 55 | } 56 | 57 | impl From for PreconditionGoalDefinitions { 58 | fn from(val: GoalDef) -> Self { 59 | val.0 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/types/init_el.rs: -------------------------------------------------------------------------------- 1 | //! Contains the [`InitElement`] type. 2 | 3 | use crate::types::{BasicFunctionTerm, Name, NameLiteral, Number}; 4 | 5 | /// ## Usage 6 | /// Used by [`InitElements`](crate::InitElements) in [`Problem`](crate::Problem). 7 | #[derive(Debug, Clone, PartialEq)] 8 | pub enum InitElement { 9 | Literal(NameLiteral), 10 | /// ## Requirements 11 | /// Requires [Timed Initial Literals](crate::Requirement::TimedInitialLiterals). 12 | At(Number, NameLiteral), 13 | /// ## Requirements 14 | /// Requires [Numeric Fluents](crate::Requirement::NumericFluents). 15 | IsValue(BasicFunctionTerm, Number), 16 | /// ## Requirements 17 | /// Requires [Object Fluents](crate::Requirement::ObjectFluents). 18 | IsObject(BasicFunctionTerm, Name), 19 | } 20 | 21 | impl InitElement { 22 | pub const fn new_literal(name: NameLiteral) -> Self { 23 | Self::Literal(name) 24 | } 25 | 26 | pub const fn new_at(time: Number, name: NameLiteral) -> Self { 27 | Self::At(time, name) 28 | } 29 | 30 | pub const fn new_is_value(term: BasicFunctionTerm, value: Number) -> Self { 31 | Self::IsValue(term, value) 32 | } 33 | 34 | pub const fn new_is_object(term: BasicFunctionTerm, value: Name) -> Self { 35 | Self::IsObject(term, value) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/types/init_els.rs: -------------------------------------------------------------------------------- 1 | //! Contains the [`InitElements`] type. 2 | 3 | use crate::types::InitElement; 4 | use std::ops::Deref; 5 | 6 | /// A wrapper around a list of [`InitElement`] values. 7 | /// 8 | /// ## Usage 9 | /// Used by [`Problem`](crate::Problem). 10 | #[derive(Debug, Clone, PartialEq)] 11 | pub struct InitElements(Vec); 12 | 13 | impl InitElements { 14 | pub const fn new(iter: Vec) -> Self { 15 | Self(iter) 16 | } 17 | 18 | /// Gets the values. 19 | pub fn values(&self) -> &[InitElement] { 20 | self.0.as_slice() 21 | } 22 | } 23 | 24 | impl Deref for InitElements { 25 | type Target = [InitElement]; 26 | 27 | fn deref(&self) -> &Self::Target { 28 | self.0.as_slice() 29 | } 30 | } 31 | 32 | impl FromIterator for InitElements { 33 | fn from_iter>(iter: T) -> Self { 34 | InitElements::new(iter.into_iter().collect()) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/types/interval.rs: -------------------------------------------------------------------------------- 1 | //! Contains the [`Interval`] type. 2 | 3 | use std::fmt::{Display, Formatter}; 4 | 5 | /// An interval used in [`TimedGD::Over`](crate::types::TimedGD::Over). 6 | /// 7 | /// ## Usage 8 | /// Used by [`TimedGD`](crate::TimedGD). 9 | #[derive(Debug, Copy, Clone, Eq, PartialEq)] 10 | pub enum Interval { 11 | /// The condition must be true during the entire plan. 12 | All, 13 | } 14 | 15 | pub mod names { 16 | pub const ALL: &str = "all"; 17 | } 18 | 19 | impl Display for Interval { 20 | fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { 21 | match self { 22 | Interval::All => write!(f, "{}", names::ALL), 23 | } 24 | } 25 | } 26 | 27 | impl TryFrom<&str> for Interval { 28 | type Error = ParseError; 29 | 30 | fn try_from(value: &str) -> Result { 31 | match value { 32 | names::ALL => Ok(Self::All), 33 | _ => Err(ParseError::InvalidInterval), 34 | } 35 | } 36 | } 37 | 38 | #[derive(Debug, Clone, thiserror::Error)] 39 | pub enum ParseError { 40 | #[error("Invalid interval")] 41 | InvalidInterval, 42 | } 43 | -------------------------------------------------------------------------------- /src/types/iterators.rs: -------------------------------------------------------------------------------- 1 | //! Contains iterator types. 2 | 3 | use std::iter::once; 4 | use std::vec; 5 | 6 | /// An iterator that can represent instances with either 7 | /// one or many values, such as [`ConditionalEffect`](crate::ConditionalEffect), 8 | /// [`DurationConstraint`](crate::DurationConstraint), 9 | /// [`Effect`](crate::Effects) and others. 10 | pub enum FlatteningIntoIterator { 11 | /// The iterator is already empty (similar to [`std::iter::Empty`]). 12 | Never, 13 | /// The iterator will produce exactly one value (similar to [`std::iter::Once`]). 14 | Once(std::iter::Once), 15 | /// The iterator will produce none, one or many values. 16 | Vec(vec::IntoIter), 17 | } 18 | 19 | impl FlatteningIntoIterator { 20 | /// Creates an iterator that will create exactly one item. 21 | pub fn new(item: T) -> Self { 22 | Self::Once(once(item)) 23 | } 24 | 25 | /// Creates an iterator that will create none, one or many values. 26 | pub fn new_vec(vec: Vec) -> Self { 27 | if vec.is_empty() { 28 | Self::Never 29 | } else { 30 | Self::Vec(vec.into_iter()) 31 | } 32 | } 33 | } 34 | 35 | impl Iterator for FlatteningIntoIterator { 36 | type Item = T; 37 | 38 | fn next(&mut self) -> Option { 39 | match self { 40 | Self::Never => None, 41 | Self::Once(ref mut iter) => iter.next(), 42 | Self::Vec(ref mut iter) => iter.next(), 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/types/length_spec.rs: -------------------------------------------------------------------------------- 1 | //! Contains the [`LengthSpec`] type. 2 | 3 | /// Deprecated since PDDL 2.1. 4 | /// 5 | /// ## Usage 6 | /// Used by [`Problem`](crate::Problem). 7 | #[derive(Debug, Default, Clone, Eq, PartialEq)] 8 | pub struct LengthSpec { 9 | serial: Option, 10 | parallel: Option, 11 | } 12 | 13 | impl LengthSpec { 14 | pub const fn new(serial: Option, parallel: Option) -> Self { 15 | Self { serial, parallel } 16 | } 17 | 18 | pub const fn new_serial(serial: u64) -> Self { 19 | Self::new(Some(serial), None) 20 | } 21 | 22 | pub const fn new_parallel(parallel: u64) -> Self { 23 | Self::new(None, Some(parallel)) 24 | } 25 | 26 | /// Gets the serial value. 27 | pub const fn serial(&self) -> Option { 28 | self.serial 29 | } 30 | 31 | /// Gets the parallel value. 32 | pub const fn parallel(&self) -> Option { 33 | self.parallel 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/types/literal.rs: -------------------------------------------------------------------------------- 1 | //! Contains literals via the [`Literal`] type. 2 | 3 | use crate::types::AtomicFormula; 4 | 5 | /// An [`AtomicFormula`] or its negated value. 6 | /// 7 | /// ## Usage 8 | /// Used by [`GoalDefinition`](crate::GoalDefinition) and [`InitElement`](crate::InitElement). 9 | #[derive(Debug, Clone, Eq, PartialEq)] 10 | pub enum Literal { 11 | AtomicFormula(AtomicFormula), 12 | NotAtomicFormula(AtomicFormula), 13 | } 14 | 15 | impl<'a, T> Literal { 16 | pub const fn new(atomic_formula: AtomicFormula) -> Self { 17 | Self::AtomicFormula(atomic_formula) 18 | } 19 | 20 | pub const fn new_not(atomic_formula: AtomicFormula) -> Self { 21 | Self::NotAtomicFormula(atomic_formula) 22 | } 23 | 24 | pub const fn is_negated(&self) -> bool { 25 | matches!(self, Self::NotAtomicFormula(..)) 26 | } 27 | } 28 | 29 | impl<'a, T> From> for Literal { 30 | fn from(value: AtomicFormula) -> Self { 31 | Literal::new(value) 32 | } 33 | } 34 | 35 | #[cfg(test)] 36 | mod tests { 37 | use super::*; 38 | use crate::parsers::{atomic_formula, parse_term, Span}; 39 | use crate::Term; 40 | 41 | #[test] 42 | fn from_works() { 43 | let input = "(= x y)"; 44 | let (_, effect) = atomic_formula(parse_term)(Span::new(input)).unwrap(); 45 | 46 | let literal: Literal = effect.into(); 47 | assert_eq!( 48 | literal, 49 | Literal::AtomicFormula(AtomicFormula::new_equality( 50 | Term::new_name("x".into()), 51 | Term::new_name("y".into()), 52 | )) 53 | ) 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/types/metric_f_exp.rs: -------------------------------------------------------------------------------- 1 | //! Contains the [`MetricFExp`] type. 2 | 3 | use crate::types::{BinaryOp, FunctionSymbol, MultiOp, Name, Number, PreferenceName}; 4 | 5 | /// A metric function expression. 6 | /// 7 | /// ## Requirements 8 | /// Requires [Numeric Fluents](crate::Requirement::NumericFluents). 9 | /// 10 | /// ## Usage 11 | /// Used by [`MetricSpec`](crate::MetricSpec). 12 | #[derive(Debug, Clone, PartialEq)] 13 | pub enum MetricFExp { 14 | BinaryOp(BinaryOp, Box, Box), 15 | MultiOp(MultiOp, Box, Vec), 16 | Negative(Box), 17 | Number(Number), 18 | Function(FunctionSymbol, Vec), 19 | TotalTime, 20 | /// ## Requirements 21 | /// Requires [Preferences](crate::Requirement::Preferences). 22 | IsViolated(PreferenceName), 23 | } 24 | 25 | impl MetricFExp { 26 | pub fn new_binary_op(op: BinaryOp, lhs: Self, rhs: Self) -> Self { 27 | Self::BinaryOp(op, Box::new(lhs), Box::new(rhs)) 28 | } 29 | 30 | pub fn new_multi_op>(op: MultiOp, lhs: Self, rhs: I) -> Self { 31 | let vec: Vec<_> = rhs.into_iter().collect(); 32 | debug_assert!( 33 | !vec.is_empty(), 34 | "Right-hand side requires at least one operand" 35 | ); 36 | Self::MultiOp(op, Box::new(lhs), vec) 37 | } 38 | 39 | pub fn new_negative(exp: Self) -> Self { 40 | Self::Negative(Box::new(exp)) 41 | } 42 | 43 | pub fn new_number>(number: N) -> Self { 44 | Self::Number(number.into()) 45 | } 46 | 47 | pub fn new_function>(symbol: FunctionSymbol, names: I) -> Self { 48 | Self::Function(symbol, names.into_iter().collect()) 49 | } 50 | 51 | pub const fn new_total_time() -> Self { 52 | Self::TotalTime 53 | } 54 | 55 | pub const fn new_is_violated(pref: PreferenceName) -> Self { 56 | Self::IsViolated(pref) 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/types/metric_spec.rs: -------------------------------------------------------------------------------- 1 | //! Contains the [`MetricSpec`] type. 2 | 3 | use crate::types::{MetricFExp, Optimization}; 4 | 5 | /// A metric specification. 6 | /// 7 | /// ## Requirements 8 | /// Requires [Numeric Fluents](crate::Requirement::NumericFluents). 9 | #[derive(Debug, Clone, PartialEq)] 10 | pub struct MetricSpec { 11 | optimization: Optimization, 12 | exp: MetricFExp, 13 | } 14 | 15 | impl MetricSpec { 16 | pub const fn new(optimization: Optimization, exp: MetricFExp) -> Self { 17 | Self { optimization, exp } 18 | } 19 | 20 | /// Gets the optimization instruction. 21 | pub const fn optimization(&self) -> Optimization { 22 | self.optimization 23 | } 24 | 25 | /// Gets the expression to optimize. 26 | pub const fn expression(&self) -> &MetricFExp { 27 | &self.exp 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/types/multi_op.rs: -------------------------------------------------------------------------------- 1 | //! Contains the [`MultiOp`] type. 2 | 3 | use std::fmt::{Display, Formatter}; 4 | 5 | /// An operation with multiple operands. 6 | /// 7 | /// ## Usage 8 | /// Used by [`MetricFExp`](crate::MetricFExp) and [`FExpDa`](crate::FExpDa). 9 | /// Implicitly used by [`BinaryOp`](crate::BinaryOp). 10 | #[derive(Debug, Copy, Clone, Eq, PartialEq)] 11 | pub enum MultiOp { 12 | Multiplication, 13 | Addition, 14 | } 15 | 16 | pub mod names { 17 | pub const MULTIPLICATION: &str = "*"; 18 | pub const ADDITION: &str = "+"; 19 | } 20 | 21 | impl Display for MultiOp { 22 | fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { 23 | match self { 24 | MultiOp::Multiplication => write!(f, "{}", names::MULTIPLICATION), 25 | MultiOp::Addition => write!(f, "{}", names::ADDITION), 26 | } 27 | } 28 | } 29 | 30 | impl TryFrom<&str> for MultiOp { 31 | type Error = ParseError; 32 | 33 | fn try_from(value: &str) -> Result { 34 | match value { 35 | names::MULTIPLICATION => Ok(Self::Multiplication), 36 | names::ADDITION => Ok(Self::Addition), 37 | _ => Err(ParseError::InvalidOperation), 38 | } 39 | } 40 | } 41 | 42 | #[derive(Debug, Clone, thiserror::Error)] 43 | pub enum ParseError { 44 | #[error("Invalid operation")] 45 | InvalidOperation, 46 | } 47 | -------------------------------------------------------------------------------- /src/types/objects.rs: -------------------------------------------------------------------------------- 1 | //! Contains the [`Objects`] type. 2 | 3 | use crate::types::{Name, Typed, TypedNames}; 4 | use std::ops::Deref; 5 | 6 | /// A list of objects. 7 | /// 8 | /// ## Usage 9 | /// Used by [`Problem`](crate::Problem). 10 | #[derive(Debug, Clone, Eq, PartialEq, Default)] 11 | pub struct Objects(TypedNames); 12 | 13 | impl Objects { 14 | // TODO: Convert to const again that takes `TypedNames` directly. 15 | pub fn new>>(objects: I) -> Self { 16 | Self(objects.into_iter().collect()) 17 | } 18 | 19 | pub fn values(&self) -> &TypedNames { 20 | &self.0 21 | } 22 | } 23 | 24 | impl From for Objects { 25 | fn from(value: TypedNames) -> Self { 26 | Self(value) 27 | } 28 | } 29 | 30 | impl FromIterator> for Objects { 31 | fn from_iter>>(iter: T) -> Self { 32 | Objects::new(TypedNames::from_iter(iter)) 33 | } 34 | } 35 | 36 | impl Deref for Objects { 37 | type Target = TypedNames; 38 | 39 | #[inline(always)] 40 | fn deref(&self) -> &Self::Target { 41 | &self.0 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/types/optimization.rs: -------------------------------------------------------------------------------- 1 | //! Contains the [`Optimization`] type. 2 | 3 | use std::fmt::{Display, Formatter}; 4 | 5 | /// An optimization instruction. 6 | /// 7 | /// ## Requirements 8 | /// Requires [Numeric Fluents](crate::Requirement::NumericFluents). 9 | /// 10 | /// ## Usage 11 | /// Used by [`MetricSpec`](crate::MetricSpec). 12 | #[derive(Debug, Copy, Clone, Eq, PartialEq)] 13 | pub enum Optimization { 14 | /// The associated metric should be minimized. 15 | Minimize, 16 | /// The associated metric should be maximized. 17 | Maximize, 18 | } 19 | 20 | pub mod names { 21 | pub const MINIMIZE: &str = "minimize"; 22 | pub const MAXIMIZE: &str = "maximize"; 23 | } 24 | 25 | impl Display for Optimization { 26 | fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { 27 | match self { 28 | Optimization::Minimize => write!(f, "{}", names::MINIMIZE), 29 | Optimization::Maximize => write!(f, "{}", names::MAXIMIZE), 30 | } 31 | } 32 | } 33 | 34 | impl TryFrom<&str> for Optimization { 35 | type Error = ParseError; 36 | 37 | fn try_from(value: &str) -> Result { 38 | match value { 39 | names::MINIMIZE => Ok(Self::Minimize), 40 | names::MAXIMIZE => Ok(Self::Maximize), 41 | _ => Err(ParseError::InvalidGoal), 42 | } 43 | } 44 | } 45 | 46 | #[derive(Debug, Clone, thiserror::Error)] 47 | pub enum ParseError { 48 | #[error("Invalid goal")] 49 | InvalidGoal, 50 | } 51 | -------------------------------------------------------------------------------- /src/types/p_effect.rs: -------------------------------------------------------------------------------- 1 | //! Contains p-effects. 2 | 3 | use crate::types::{AssignOp, AtomicFormula, FExp, FHead, FunctionTerm, Term}; 4 | 5 | /// A p-effect. Occurs as part of a [`CEffect`](crate::types::CEffect) (within an [`Effect`](crate::types::Effects)) 6 | /// or a [`ConditionalEffect`](crate::types::ConditionalEffect). 7 | /// 8 | /// ## Usage 9 | /// Used by [`CEffect`](crate::CEffect) and [`ConditionalEffect`](crate::ConditionalEffect). 10 | #[derive(Debug, Clone, PartialEq)] 11 | pub enum PEffect { 12 | AtomicFormula(AtomicFormula), 13 | NotAtomicFormula(AtomicFormula), 14 | /// ## Requirements 15 | /// Requires [Numeric Fluents](crate::Requirement::NumericFluents). 16 | AssignNumericFluent(AssignOp, FHead, FExp), 17 | /// ## Requirements 18 | /// Requires [Object Fluents](crate::Requirement::ObjectFluents). 19 | AssignObjectFluent(FunctionTerm, Option), 20 | } 21 | 22 | impl PEffect { 23 | pub const fn new(atomic_formula: AtomicFormula) -> Self { 24 | Self::AtomicFormula(atomic_formula) 25 | } 26 | 27 | pub const fn new_not(atomic_formula: AtomicFormula) -> Self { 28 | Self::NotAtomicFormula(atomic_formula) 29 | } 30 | 31 | pub const fn new_numeric_fluent(op: AssignOp, head: FHead, exp: FExp) -> Self { 32 | Self::AssignNumericFluent(op, head, exp) 33 | } 34 | 35 | pub const fn new_object_fluent(f_term: FunctionTerm, term: Option) -> Self { 36 | Self::AssignObjectFluent(f_term, term) 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/types/predicate.rs: -------------------------------------------------------------------------------- 1 | //! Contains predicates via the [`Predicate`] type. 2 | 3 | use crate::types::Name; 4 | use std::ops::Deref; 5 | 6 | /// A predicate name. 7 | /// 8 | /// ## Usage 9 | /// Used by [`AtomicFormulaSkeleton`](crate::AtomicFormulaSkeleton) and [`AtomicFormula`](crate::AtomicFormula). 10 | #[derive(Debug, Clone, Eq, PartialEq, Hash, Default)] 11 | pub struct Predicate(Name); 12 | 13 | impl Predicate { 14 | #[inline(always)] 15 | pub const fn new(name: Name) -> Self { 16 | Self(name) 17 | } 18 | 19 | #[inline(always)] 20 | pub fn from_str(name: &str) -> Self { 21 | Self(Name::new(name)) 22 | } 23 | 24 | #[inline(always)] 25 | pub const fn from_static(name: &'static str) -> Self { 26 | Self(Name::new_static(name)) 27 | } 28 | 29 | #[inline(always)] 30 | pub const fn from_name(name: Name) -> Self { 31 | Self(name) 32 | } 33 | } 34 | 35 | impl<'a, T> From for Predicate 36 | where 37 | T: Into, 38 | { 39 | #[inline(always)] 40 | fn from(value: T) -> Self { 41 | Predicate::new(value.into()) 42 | } 43 | } 44 | 45 | impl AsRef for Predicate { 46 | #[inline(always)] 47 | fn as_ref(&self) -> &Name { 48 | &self.0 49 | } 50 | } 51 | 52 | impl AsRef for Predicate { 53 | #[inline(always)] 54 | fn as_ref(&self) -> &str { 55 | self.0.as_ref() 56 | } 57 | } 58 | 59 | impl Deref for Predicate { 60 | type Target = Name; 61 | 62 | #[inline(always)] 63 | fn deref(&self) -> &Self::Target { 64 | &self.0 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/types/predicate_definitions.rs: -------------------------------------------------------------------------------- 1 | //! Provides predicate definitions. 2 | 3 | use crate::types::AtomicFormulaSkeleton; 4 | use std::ops::Deref; 5 | 6 | /// A set of predicate definitions. 7 | /// 8 | /// ## Usage 9 | /// Used by [`Domain`](crate::Domain). 10 | #[derive(Debug, Default, Clone, Eq, PartialEq)] 11 | pub struct PredicateDefinitions(Vec); 12 | 13 | impl PredicateDefinitions { 14 | pub fn new>(predicates: I) -> Self { 15 | Self::from(predicates.into_iter().collect()) 16 | } 17 | 18 | pub const fn from(predicates: Vec) -> Self { 19 | Self(predicates) 20 | } 21 | 22 | /// Gets the values. 23 | pub fn values(&self) -> &[AtomicFormulaSkeleton] { 24 | self.0.as_slice() 25 | } 26 | } 27 | 28 | impl Deref for PredicateDefinitions { 29 | type Target = [AtomicFormulaSkeleton]; 30 | 31 | fn deref(&self) -> &Self::Target { 32 | self.0.as_slice() 33 | } 34 | } 35 | 36 | impl From> for PredicateDefinitions { 37 | fn from(value: Vec) -> Self { 38 | PredicateDefinitions::new(value) 39 | } 40 | } 41 | 42 | impl FromIterator for PredicateDefinitions { 43 | fn from_iter>(iter: T) -> Self { 44 | PredicateDefinitions::new(iter) 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/types/pref_gd.rs: -------------------------------------------------------------------------------- 1 | //! Contains preference goal definitions. 2 | 3 | use crate::types::{GoalDefinition, Preference}; 4 | 5 | /// A preferred goal definition. 6 | /// 7 | /// ## Usage 8 | /// Used by [`PreconditionGoalDefinition`](crate::PreconditionGoalDefinition). 9 | #[derive(Debug, Clone, PartialEq)] 10 | pub enum PreferenceGD { 11 | Goal(GoalDefinition), 12 | /// ## Requirements 13 | /// Requires [Preferences](crate::Requirement::Preferences). 14 | Preference(Preference), 15 | } 16 | 17 | impl PreferenceGD { 18 | pub const fn from_gd(gd: GoalDefinition) -> Self { 19 | Self::Goal(gd) 20 | } 21 | 22 | pub fn from_preference(pref: Preference) -> Self { 23 | Self::Preference(pref) 24 | } 25 | } 26 | 27 | impl From for PreferenceGD { 28 | fn from(value: GoalDefinition) -> Self { 29 | PreferenceGD::from_gd(value) 30 | } 31 | } 32 | 33 | impl From for PreferenceGD { 34 | fn from(value: Preference) -> Self { 35 | PreferenceGD::from_preference(value) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/types/pref_name.rs: -------------------------------------------------------------------------------- 1 | //! Provides names for preferences. 2 | 3 | use crate::types::Name; 4 | use std::ops::Deref; 5 | 6 | /// A name of a preference. 7 | /// 8 | /// ## Usage 9 | /// Used by [`PrefGD`](crate::PreferenceGD), [`PrefTimedGD`](crate::PrefTimedGD), 10 | /// [`PrefConGD`](crate::PrefConGD) and [`MetricFExp`](crate::MetricFExp). 11 | #[derive(Debug, Clone, Eq, PartialEq)] 12 | pub struct PreferenceName(Name); 13 | 14 | impl PreferenceName { 15 | #[inline(always)] 16 | pub fn new>(name: N) -> Self { 17 | Self(name.into()) 18 | } 19 | 20 | #[inline(always)] 21 | pub fn from_str(name: &str) -> Self { 22 | Self(Name::new(name)) 23 | } 24 | 25 | #[inline(always)] 26 | pub const fn from_static(name: &'static str) -> Self { 27 | Self(Name::new_static(name)) 28 | } 29 | 30 | #[inline(always)] 31 | pub const fn from_name(name: Name) -> Self { 32 | Self(name) 33 | } 34 | } 35 | 36 | impl Deref for PreferenceName { 37 | type Target = Name; 38 | 39 | fn deref(&self) -> &Self::Target { 40 | &self.0 41 | } 42 | } 43 | 44 | impl<'a, T> From for PreferenceName 45 | where 46 | T: Into, 47 | { 48 | fn from(value: T) -> Self { 49 | PreferenceName::new(value.into()) 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/types/pref_timed_gd.rs: -------------------------------------------------------------------------------- 1 | //! Contains the [`PrefTimedGD`] type. 2 | 3 | use crate::types::{PreferenceName, TimedGD}; 4 | 5 | /// A (preferred) timed goal definition. 6 | /// 7 | /// ## Usage 8 | /// Used by [`DurativeActionGoalDefinition`](crate::DurativeActionGoalDefinition). 9 | #[derive(Debug, Clone, PartialEq)] 10 | pub enum PrefTimedGD { 11 | Required(TimedGD), 12 | /// ## Requirements 13 | /// Requires [Preferences](crate::Requirement::Preferences). 14 | Preference(Option, TimedGD), 15 | } 16 | 17 | impl PrefTimedGD { 18 | pub const fn new_required(gd: TimedGD) -> Self { 19 | Self::Required(gd) 20 | } 21 | 22 | pub const fn new_preference(name: Option, gd: TimedGD) -> Self { 23 | Self::Preference(name, gd) 24 | } 25 | } 26 | 27 | impl From for PrefTimedGD { 28 | fn from(value: TimedGD) -> Self { 29 | PrefTimedGD::Required(value) 30 | } 31 | } 32 | 33 | impl From<(Option, TimedGD)> for PrefTimedGD { 34 | fn from(value: (Option, TimedGD)) -> Self { 35 | PrefTimedGD::Preference(value.0, value.1) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/types/preference.rs: -------------------------------------------------------------------------------- 1 | //! Contains preferences. 2 | 3 | use crate::types::{GoalDefinition, PreferenceName}; 4 | 5 | /// A preference. 6 | /// 7 | /// ## Requirements 8 | /// Requires [Preferences](crate::Requirement::Preferences). 9 | /// 10 | /// ## Usage 11 | /// Used by [`PreferenceGD`](crate::PreferenceGD). 12 | #[derive(Debug, Clone, PartialEq)] 13 | pub struct Preference(Option, GoalDefinition); // TODO: A similar type is used for PrefConGD 14 | 15 | impl Preference { 16 | pub const fn new(name: Option, gd: GoalDefinition) -> Self { 17 | Self(name, gd) 18 | } 19 | 20 | /// Gets the optional preference name. 21 | pub fn name(&self) -> &Option { 22 | &self.0 23 | } 24 | 25 | /// Gets the goal definition. 26 | pub fn goal(&self) -> &GoalDefinition { 27 | &self.1 28 | } 29 | 30 | pub fn is_empty(&self) -> bool { 31 | self.1.is_empty() 32 | } 33 | } 34 | 35 | impl From<(Option, GoalDefinition)> for Preference { 36 | fn from(value: (Option, GoalDefinition)) -> Self { 37 | Self::new(value.0, value.1) 38 | } 39 | } 40 | 41 | impl From<(PreferenceName, GoalDefinition)> for Preference { 42 | fn from(value: (PreferenceName, GoalDefinition)) -> Self { 43 | Self::new(Some(value.0), value.1) 44 | } 45 | } 46 | 47 | impl From for Preference { 48 | fn from(value: GoalDefinition) -> Self { 49 | Self::new(None, value) 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/types/problem_constraints_def.rs: -------------------------------------------------------------------------------- 1 | //! Contains the [`ProblemConstraintsDef`] type. 2 | 3 | use crate::PrefConGDs; 4 | use std::ops::Deref; 5 | 6 | /// A problem constraints definition; wraps a [`PrefConGD`]. 7 | /// 8 | /// ## Requirements 9 | /// Requires [Constraints](crate::Requirement::Constraints). 10 | #[derive(Debug, Default, Clone, PartialEq)] 11 | pub struct ProblemConstraintsDef(PrefConGDs); 12 | 13 | impl ProblemConstraintsDef { 14 | pub const fn new(gd: PrefConGDs) -> Self { 15 | Self(gd) 16 | } 17 | 18 | /// Gets the value. 19 | pub const fn value(&self) -> &PrefConGDs { 20 | &self.0 21 | } 22 | } 23 | 24 | impl PartialEq for ProblemConstraintsDef { 25 | fn eq(&self, other: &PrefConGDs) -> bool { 26 | self.0.eq(other) 27 | } 28 | } 29 | 30 | impl From for ProblemConstraintsDef { 31 | fn from(value: PrefConGDs) -> Self { 32 | Self::new(value) 33 | } 34 | } 35 | 36 | impl Deref for ProblemConstraintsDef { 37 | type Target = PrefConGDs; 38 | 39 | fn deref(&self) -> &Self::Target { 40 | &self.0 41 | } 42 | } 43 | 44 | impl From for PrefConGDs { 45 | fn from(val: ProblemConstraintsDef) -> Self { 46 | val.0 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/types/simple_duration_constraint.rs: -------------------------------------------------------------------------------- 1 | //! Contains the [`SimpleDurationConstraint`] type. 2 | 3 | use crate::types::{DOp, DurationValue, TimeSpecifier}; 4 | 5 | /// A simple duration constraint. 6 | /// 7 | /// ## Usage 8 | /// Used by [`SimpleDurationConstraint`] itself, as well as [`DurationConstraint`](crate::DurationConstraint). 9 | #[derive(Debug, Clone, PartialEq)] 10 | pub enum SimpleDurationConstraint { 11 | /// A comparison operation against a duration value. 12 | Op(DOp, DurationValue), 13 | /// A specific time at or after which a constraint applies. 14 | At(TimeSpecifier, Box), 15 | } 16 | 17 | impl SimpleDurationConstraint { 18 | pub const fn new_op(op: DOp, value: DurationValue) -> Self { 19 | Self::Op(op, value) 20 | } 21 | 22 | pub fn new_at(time: TimeSpecifier, constraint: SimpleDurationConstraint) -> Self { 23 | Self::At(time, Box::new(constraint)) 24 | } 25 | } 26 | 27 | impl From<(DOp, DurationValue)> for SimpleDurationConstraint { 28 | fn from(value: (DOp, DurationValue)) -> Self { 29 | SimpleDurationConstraint::new_op(value.0, value.1) 30 | } 31 | } 32 | 33 | impl From<(TimeSpecifier, SimpleDurationConstraint)> for SimpleDurationConstraint { 34 | fn from(value: (TimeSpecifier, SimpleDurationConstraint)) -> Self { 35 | SimpleDurationConstraint::new_at(value.0, value.1) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/types/structure_def.rs: -------------------------------------------------------------------------------- 1 | //! Contains definitions for domain structure definitions. 2 | 3 | use crate::types::{ActionDefinition, DerivedPredicate, DurativeActionDefinition}; 4 | 5 | /// A domain structure definition. 6 | /// 7 | /// ## Usage 8 | /// Used by [`StructureDefs`](crate::StructureDefs) in [`Domain`](crate::Domain). 9 | #[derive(Debug, Clone, PartialEq)] 10 | pub enum StructureDef { 11 | Action(ActionDefinition), 12 | /// ## Requirements 13 | /// Requires [Durative Actions](crate::Requirement::DurativeActions). 14 | DurativeAction(DurativeActionDefinition), 15 | /// ## Requirements 16 | /// Requires [Derived Predicates](crate::Requirement::DerivedPredicates). 17 | Derived(DerivedPredicate), 18 | } 19 | 20 | impl StructureDef { 21 | pub const fn new_action(action: ActionDefinition) -> Self { 22 | Self::Action(action) 23 | } 24 | pub const fn new_durative_action(action: DurativeActionDefinition) -> Self { 25 | Self::DurativeAction(action) 26 | } 27 | pub const fn new_derived(predicate: DerivedPredicate) -> Self { 28 | Self::Derived(predicate) 29 | } 30 | } 31 | 32 | impl From for StructureDef { 33 | fn from(value: ActionDefinition) -> Self { 34 | StructureDef::new_action(value) 35 | } 36 | } 37 | 38 | impl From for StructureDef { 39 | fn from(value: DurativeActionDefinition) -> Self { 40 | StructureDef::new_durative_action(value) 41 | } 42 | } 43 | 44 | impl From for StructureDef { 45 | fn from(value: DerivedPredicate) -> Self { 46 | StructureDef::new_derived(value) 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/types/structure_defs.rs: -------------------------------------------------------------------------------- 1 | //! Provides structure definitions. 2 | 3 | use crate::types::StructureDef; 4 | use std::ops::Deref; 5 | 6 | /// A set of structure definitions. 7 | /// 8 | /// ## Usage 9 | /// Used by [`Domain`](crate::Domain). 10 | #[derive(Debug, Default, Clone, PartialEq)] 11 | pub struct StructureDefs(Vec); 12 | 13 | impl StructureDefs { 14 | pub fn new>(defs: I) -> Self { 15 | Self(defs.into_iter().collect()) 16 | } 17 | 18 | /// Gets the values. 19 | pub fn values(&self) -> &[StructureDef] { 20 | self.0.as_slice() 21 | } 22 | } 23 | 24 | impl Deref for StructureDefs { 25 | type Target = [StructureDef]; 26 | 27 | fn deref(&self) -> &Self::Target { 28 | &self.0 29 | } 30 | } 31 | 32 | impl From> for StructureDefs { 33 | fn from(value: Vec) -> Self { 34 | StructureDefs::new(value) 35 | } 36 | } 37 | 38 | impl FromIterator for StructureDefs { 39 | fn from_iter>(iter: T) -> Self { 40 | StructureDefs::new(iter) 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/types/term.rs: -------------------------------------------------------------------------------- 1 | use crate::types::function_term::FunctionTerm; 2 | use crate::types::Name; 3 | use crate::types::Variable; 4 | 5 | /// A term, i.e. a [`Name`], [`Variable`] or [`FunctionTerm`]. 6 | /// 7 | /// ## Usage 8 | /// Used by [`GoalDefinition`](crate::GoalDefinition), [`FunctionTerm`](FunctionTerm), 9 | /// [`FHead`](crate::FHead), [`PEffect`](crate::PEffect) and [`InitElement`](crate::InitElement). 10 | #[derive(Debug, Clone, Eq, PartialEq)] 11 | pub enum Term { 12 | Name(Name), 13 | Variable(Variable), 14 | Function(FunctionTerm), 15 | } 16 | 17 | impl Term { 18 | pub const fn new_name(name: Name) -> Self { 19 | Self::Name(name) 20 | } 21 | 22 | pub const fn new_variable(var: Variable) -> Self { 23 | Self::Variable(var) 24 | } 25 | 26 | pub const fn new_function(fun: FunctionTerm) -> Self { 27 | Self::Function(fun) 28 | } 29 | } 30 | 31 | impl From for Term { 32 | fn from(value: Name) -> Self { 33 | Self::Name(value) 34 | } 35 | } 36 | 37 | impl From for Term { 38 | fn from(value: Variable) -> Self { 39 | Self::Variable(value) 40 | } 41 | } 42 | 43 | impl From for Term { 44 | fn from(value: FunctionTerm) -> Self { 45 | Self::Function(value) 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/types/time_specifier.rs: -------------------------------------------------------------------------------- 1 | //! Contains the [`TimeSpecifier`] type. 2 | 3 | use std::fmt::{Display, Formatter}; 4 | 5 | /// A time specifier used in e.g. [`TimedGD::At`](crate::types::TimedGD::At) and [`TimedEffect`](crate::types::TimedEffect). 6 | /// 7 | /// ## Usage 8 | /// Used by [`TimedGD`](crate::TimedGD) and [`TimedEffect`](crate::TimedEffect). 9 | #[derive(Debug, Copy, Clone, Eq, PartialEq)] 10 | pub enum TimeSpecifier { 11 | /// The condition or effect holds or applies at the beginning of a plan. 12 | Start, 13 | /// The condition or effect must hold or apply at the end of a plan. 14 | End, 15 | } 16 | 17 | pub mod names { 18 | pub const START: &str = "start"; 19 | pub const END: &str = "end"; 20 | } 21 | 22 | impl Display for TimeSpecifier { 23 | fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { 24 | match self { 25 | TimeSpecifier::Start => write!(f, "{}", names::START), 26 | TimeSpecifier::End => write!(f, "{}", names::END), 27 | } 28 | } 29 | } 30 | 31 | impl TryFrom<&str> for TimeSpecifier { 32 | type Error = ParseError; 33 | 34 | fn try_from(value: &str) -> Result { 35 | match value { 36 | names::START => Ok(Self::Start), 37 | names::END => Ok(Self::End), 38 | _ => Err(ParseError::InvalidSpecifier), 39 | } 40 | } 41 | } 42 | 43 | #[derive(Debug, Clone, thiserror::Error)] 44 | pub enum ParseError { 45 | #[error("Invalid specifier")] 46 | InvalidSpecifier, 47 | } 48 | -------------------------------------------------------------------------------- /src/types/timed_effect.rs: -------------------------------------------------------------------------------- 1 | //! Contains the [`TimedEffect`] type. 2 | 3 | use crate::types::{AssignOpT, ConditionalEffect, FAssignDa, FExpT, FHead, TimeSpecifier}; 4 | 5 | /// A timed effect, either conditional, continuous or derived from a fluent, e.g. [`DurativeActionEffect`](crate::types::DurativeActionEffect). 6 | /// 7 | /// An effect is a condition which is made true when an action is applied. 8 | /// Note that the effect is always more restrictive than an action and typically only 9 | /// allows `and` and `not` as logical expressions. 10 | /// 11 | /// ## Notes 12 | /// 13 | /// Temporal expressions, such as `at start` and `at end` are available, however, `over all` 14 | /// is typically not used because it’s not common to express a boolean effect which is true 15 | /// over the duration of the action. 16 | /// 17 | /// Instead you would set it to true at the start, using an `at start` and set it to false at 18 | /// the end using `at end`. 19 | /// 20 | /// ## Usage 21 | /// Used by [`DurativeActionEffect`](crate::DurativeActionEffect). 22 | #[derive(Debug, Clone, PartialEq)] 23 | pub enum TimedEffect { 24 | Conditional(TimeSpecifier, ConditionalEffect), 25 | /// ## Requirements 26 | /// Requires [Numeric Fluents](crate::Requirement::NumericFluents). 27 | NumericFluent(TimeSpecifier, FAssignDa), 28 | /// ## Requirements 29 | /// Requires [Continuous Effects](crate::Requirement::ContinuousEffects) and 30 | /// [Numeric Fluents](crate::Requirement::NumericFluents). 31 | ContinuousEffect(AssignOpT, FHead, FExpT), 32 | } 33 | 34 | impl TimedEffect { 35 | pub const fn new_conditional(at: TimeSpecifier, effect: ConditionalEffect) -> Self { 36 | Self::Conditional(at, effect) 37 | } 38 | 39 | pub const fn new_fluent(at: TimeSpecifier, action: FAssignDa) -> Self { 40 | Self::NumericFluent(at, action) 41 | } 42 | 43 | pub const fn new_continuous(operation: AssignOpT, f_head: FHead, f_exp_t: FExpT) -> Self { 44 | Self::ContinuousEffect(operation, f_head, f_exp_t) 45 | } 46 | } 47 | 48 | impl From<(TimeSpecifier, ConditionalEffect)> for TimedEffect { 49 | fn from(value: (TimeSpecifier, ConditionalEffect)) -> Self { 50 | TimedEffect::Conditional(value.0, value.1) 51 | } 52 | } 53 | 54 | impl From<(TimeSpecifier, FAssignDa)> for TimedEffect { 55 | fn from(value: (TimeSpecifier, FAssignDa)) -> Self { 56 | TimedEffect::NumericFluent(value.0, value.1) 57 | } 58 | } 59 | 60 | impl From<(AssignOpT, FHead, FExpT)> for TimedEffect { 61 | fn from(value: (AssignOpT, FHead, FExpT)) -> Self { 62 | TimedEffect::ContinuousEffect(value.0, value.1, value.2) 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/types/timed_gd.rs: -------------------------------------------------------------------------------- 1 | use crate::types::{GoalDefinition, Interval, TimeSpecifier}; 2 | 3 | /// A timed goal definition. 4 | /// 5 | /// ## Usage 6 | /// Used by [`PrefTimedGD`](crate::PrefTimedGD). 7 | #[derive(Debug, Clone, PartialEq)] 8 | pub enum TimedGD { 9 | /// ## `at start` 10 | /// An expression or predicate with `at start` prefixed to it means that the condition 11 | /// must be true at the start of the action in order for the action to be applied. e.g. 12 | /// 13 | /// ```pddl 14 | /// (at start (at ?rover ?from-waypoint)) 15 | /// ``` 16 | /// 17 | /// expresses that `at start` the given rover is `at` the `from-waypoint`. 18 | /// Confusingly in this particular domain, the `at` is a predicate representing the 19 | /// location of an object `at` a point, whilst `at start` is a keyword. 20 | /// 21 | /// `at start` is usually applied per predicate. 22 | /// 23 | /// ## `at end` 24 | /// An expression or predicate with `at end` prefixed to it means that the condition 25 | /// must be true at the end of the action in order for the action to be applied e.g. 26 | /// 27 | /// ```pddl 28 | /// (at end (>= (battery-amount ?rover) 0)) 29 | /// ``` 30 | /// 31 | /// expresses that whilst this fact doesn't have to be true at the start or during the action, 32 | /// it must be true at the end. In this case, we're expressing that the battery amount at the 33 | /// end of the action must be greater than zero. 34 | At(TimeSpecifier, GoalDefinition), 35 | /// ## `over all` 36 | /// An expression or predicate with an overall prefixed to it, means that the condition 37 | /// must be true throughout the action, including at the start and end. e.g. 38 | /// 39 | /// ```pddl 40 | /// (over all (can-move ?from-waypoint ?to-waypoint)) 41 | /// ``` 42 | /// 43 | /// At all points in the execution of the action the given expression must evaluate to true. 44 | /// In the case above, we are expressing that it must be possible to move from the from 45 | /// waypoint to the to waypoint all the way through the action. I.e. we don't want to get 46 | /// half way through the action to find that after a certain point a path has become blocked. 47 | Over(Interval, GoalDefinition), 48 | } 49 | 50 | impl TimedGD { 51 | pub const fn new_at(time: TimeSpecifier, gd: GoalDefinition) -> Self { 52 | Self::At(time, gd) 53 | } 54 | 55 | pub const fn new_over(interval: Interval, gd: GoalDefinition) -> Self { 56 | Self::Over(interval, gd) 57 | } 58 | } 59 | 60 | impl From<(TimeSpecifier, GoalDefinition)> for TimedGD { 61 | fn from(value: (TimeSpecifier, GoalDefinition)) -> Self { 62 | TimedGD::At(value.0, value.1) 63 | } 64 | } 65 | 66 | impl From<(Interval, GoalDefinition)> for TimedGD { 67 | fn from(value: (Interval, GoalDefinition)) -> Self { 68 | TimedGD::Over(value.0, value.1) 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/types/timeless.rs: -------------------------------------------------------------------------------- 1 | //! Contains the [`Timeless`] type. 2 | 3 | use crate::types::NameLiteral; 4 | use std::ops::Deref; 5 | 6 | /// A timeless predicate. 7 | /// 8 | /// A timeless predicate is a predicate which is always true and cannot be changed by any action 9 | /// in the domain. Under the “closed world” assumption, anything not specified as true 10 | /// is considered false and timeless predicates are one possibility of addressing this. 11 | /// 12 | /// ## PDDL Version 13 | /// This is a PDDL 1.2 construct. It was removed in later versions of PDDL. 14 | /// 15 | /// ## Usage 16 | /// Used by [`Domain`](crate::Domain). 17 | #[derive(Debug, Clone, Eq, PartialEq, Default)] 18 | pub struct Timeless(Vec); 19 | 20 | impl Timeless { 21 | pub fn new(literal: Vec) -> Self { 22 | Self(literal) 23 | } 24 | 25 | /// Gets the literals. 26 | pub fn values(&self) -> &[NameLiteral] { 27 | self.0.as_slice() 28 | } 29 | } 30 | 31 | impl FromIterator for Timeless { 32 | fn from_iter>(iter: T) -> Self { 33 | Timeless::new(iter.into_iter().collect()) 34 | } 35 | } 36 | 37 | impl Deref for Timeless { 38 | type Target = [NameLiteral]; 39 | 40 | #[inline(always)] 41 | fn deref(&self) -> &Self::Target { 42 | &self.0 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/types/typed.rs: -------------------------------------------------------------------------------- 1 | //! Contains typed elements. 2 | 3 | use crate::types::{PrimitiveType, Type}; 4 | use std::ops::Deref; 5 | 6 | /// A typed element. 7 | /// 8 | /// ## Usage 9 | /// Used by [`TypedList`](crate::TypedList). 10 | #[derive(Debug, Clone, Eq, PartialEq)] 11 | pub struct Typed(O, Type); 12 | 13 | impl Typed { 14 | pub const fn new(value: O, r#type: Type) -> Self { 15 | Self(value, r#type) 16 | } 17 | 18 | pub const fn new_object(value: O) -> Self { 19 | Self::new(value, Type::OBJECT) 20 | } 21 | 22 | /// Gets the value. 23 | pub const fn value(&self) -> &O { 24 | &self.0 25 | } 26 | 27 | /// Gets the assigned type. 28 | pub const fn type_(&self) -> &Type { 29 | &self.1 30 | } 31 | } 32 | 33 | pub trait ToTyped { 34 | /// Wraps the value into a [`Typed`] as [`Type::Exactly`] the specified type. 35 | /// 36 | /// ## Example 37 | /// ``` 38 | /// # use pddl::{Name, PrimitiveType, ToTyped, Type, Typed}; 39 | /// assert_eq!( 40 | /// Name::from("kitchen").to_typed("room"), 41 | /// Typed::new(Name::from("kitchen"), Type::Exactly(PrimitiveType::from("room"))) 42 | /// ); 43 | /// ``` 44 | fn to_typed>(self, r#type: I) -> Typed; 45 | 46 | /// Wraps the value into a [`Typed`] as [`Type::EitherOf`] the specified types. 47 | /// 48 | /// ## Example 49 | /// ``` 50 | /// # use pddl::{Name, PrimitiveType, ToTyped, Type, Typed}; 51 | /// assert_eq!( 52 | /// Name::from("georgia").to_typed_either(["country", "state"]), 53 | /// Typed::new(Name::from("georgia"), Type::EitherOf( 54 | /// vec![ 55 | /// PrimitiveType::from("country"), 56 | /// PrimitiveType::from("state") 57 | /// ]) 58 | /// ) 59 | /// ); 60 | /// ``` 61 | fn to_typed_either, P: Into>( 62 | self, 63 | r#type: I, 64 | ) -> Typed; 65 | } 66 | 67 | impl<'a, O> From for Typed { 68 | fn from(value: O) -> Self { 69 | Typed::new_object(value) 70 | } 71 | } 72 | 73 | impl<'a, O> Deref for Typed { 74 | type Target = O; 75 | 76 | fn deref(&self) -> &Self::Target { 77 | self.value() 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/types/typed_list.rs: -------------------------------------------------------------------------------- 1 | use crate::types::Typed; 2 | use std::ops::Deref; 3 | 4 | /// A list of typed elements. 5 | /// 6 | /// ## Example 7 | /// ``` 8 | /// # use pddl::{Name, TypedList, Typed, Type}; 9 | /// let tl = TypedList::from_iter([ 10 | /// Typed::new(Name::from("location"), Type::OBJECT), 11 | /// Typed::new(Name::from("physob"), Type::OBJECT), 12 | /// ]); 13 | /// 14 | /// assert_eq!(tl.len(), 2); 15 | /// assert_eq!(tl[0].value(), &Name::from("location")); 16 | /// assert_eq!(tl[1].value(), &Name::from("physob")); 17 | /// ``` 18 | /// 19 | /// ## Usage 20 | /// Used by [`Types`](crate::Types) and [`Constants`](crate::Constants) in [`Domain`](crate::Domain), 21 | /// [`AtomicFormulaSkeleton`](crate::AtomicFormulaSkeleton), [`AtomicFunctionSkeleton`](crate::AtomicFunctionSkeleton), 22 | /// [`ActionDefinition`](crate::ActionDefinition), [`PreconditionGoalDefinition`](crate::PreconditionGoalDefinition), 23 | /// [`GoalDefinition`](crate::GoalDefinition), [`CEffect`](crate::CEffect), 24 | /// [`DurativeActionDefinition`](crate::DurativeActionDefinition), [`DurativeActionEffect`](crate::DurativeActionEffect), 25 | /// [`Objects`](crate::Objects) in [`Problem`](crate::Problem), [`PrefConGD`](crate::PrefConGD) and 26 | /// [`ConGD`](crate::ConGD). 27 | #[derive(Debug, Default, Clone, Eq, PartialEq)] 28 | pub struct TypedList(Vec>); 29 | 30 | impl TypedList { 31 | pub const fn new(list: Vec>) -> Self { 32 | Self(list) 33 | } 34 | 35 | /// Gets the values. 36 | pub fn value(&self) -> &[Typed] { 37 | self.0.as_slice() 38 | } 39 | } 40 | 41 | impl From>> for TypedList { 42 | fn from(iter: Vec>) -> Self { 43 | TypedList::new(iter) 44 | } 45 | } 46 | 47 | impl FromIterator> for TypedList { 48 | fn from_iter>>(iter: I) -> Self { 49 | TypedList::new(iter.into_iter().collect()) 50 | } 51 | } 52 | 53 | impl Deref for TypedList { 54 | type Target = [Typed]; 55 | 56 | fn deref(&self) -> &Self::Target { 57 | self.0.as_slice() 58 | } 59 | } 60 | 61 | impl PartialEq>> for TypedList 62 | where 63 | T: PartialEq, 64 | { 65 | fn eq(&self, other: &Vec>) -> bool { 66 | self.0.eq(other) 67 | } 68 | } 69 | 70 | impl PartialEq<[Typed]> for TypedList 71 | where 72 | T: PartialEq, 73 | { 74 | fn eq(&self, other: &[Typed]) -> bool { 75 | self.0.eq(other) 76 | } 77 | } 78 | 79 | impl IntoIterator for TypedList { 80 | type Item = Typed; 81 | type IntoIter = std::vec::IntoIter>; 82 | 83 | fn into_iter(self) -> Self::IntoIter { 84 | self.0.into_iter() 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/types/types.rs: -------------------------------------------------------------------------------- 1 | //! Provides type definitions; 2 | 3 | use crate::types::TypedNames; 4 | use std::ops::Deref; 5 | 6 | /// A set of types. 7 | /// 8 | /// ## Usage 9 | /// Used by [`Domain`](crate::Domain). 10 | #[derive(Debug, Default, Clone, Eq, PartialEq)] 11 | pub struct Types(TypedNames); 12 | 13 | impl Types { 14 | pub const fn new(predicates: TypedNames) -> Self { 15 | Self(predicates) 16 | } 17 | 18 | /// Gets the values. 19 | pub fn values(&self) -> &TypedNames { 20 | &self.0 21 | } 22 | } 23 | 24 | impl Deref for Types { 25 | type Target = TypedNames; 26 | 27 | fn deref(&self) -> &Self::Target { 28 | &self.0 29 | } 30 | } 31 | 32 | impl From for Types { 33 | fn from(value: TypedNames) -> Self { 34 | Types::new(value) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/types/variable.rs: -------------------------------------------------------------------------------- 1 | //! Contains variables. 2 | 3 | use crate::types::{Name, PrimitiveType, ToTyped, Type, Typed}; 4 | use std::ops::Deref; 5 | 6 | /// A variable name. 7 | /// 8 | /// ## Usage 9 | /// Used by [`AtomicFormulaSkeleton`](crate::AtomicFormulaSkeleton), 10 | /// [`AtomicFunctionSkeleton`](crate::AtomicFunctionSkeleton), [`ActionDefinition`](crate::ActionDefinition), 11 | /// [`PreconditionGoalDefinition`](crate::PreconditionGoalDefinition), [`GoalDefinition`](crate::GoalDefinition), 12 | /// [`Term`](crate::Term), [`CEffect`](crate::CEffect), [`DurativeActionDefinition`](crate::DurativeActionDefinition), 13 | /// [`DurativeActionGoalDefinition`](crate::DurativeActionGoalDefinition), [`DurativeActionEffect`](crate::DurativeActionEffect), 14 | /// [`PrefConGD`](crate::PrefConGD) and [`ConGD`](crate::ConGD). 15 | #[derive(Debug, Clone, Eq, PartialEq, Hash, Default)] 16 | pub struct Variable(Name); 17 | 18 | impl Variable { 19 | #[inline(always)] 20 | pub const fn new(name: Name) -> Self { 21 | Self(name) 22 | } 23 | 24 | #[inline(always)] 25 | pub fn from_str(name: &str) -> Self { 26 | Self(Name::new(name)) 27 | } 28 | 29 | #[inline(always)] 30 | pub const fn from_static(name: &'static str) -> Self { 31 | Self(Name::new_static(name)) 32 | } 33 | 34 | #[inline(always)] 35 | pub const fn from_name(name: Name) -> Self { 36 | Self(name) 37 | } 38 | } 39 | 40 | impl ToTyped for Variable { 41 | fn to_typed>(self, r#type: I) -> Typed { 42 | Typed::new(self, r#type.into()) 43 | } 44 | fn to_typed_either, P: Into>( 45 | self, 46 | types: I, 47 | ) -> Typed { 48 | Typed::new(self, Type::from_iter(types)) 49 | } 50 | } 51 | 52 | impl<'a, T> From for Variable 53 | where 54 | T: Into, 55 | { 56 | #[inline(always)] 57 | fn from(value: T) -> Self { 58 | Variable::new(value.into()) 59 | } 60 | } 61 | 62 | impl AsRef for Variable { 63 | #[inline(always)] 64 | fn as_ref(&self) -> &Name { 65 | &self.0 66 | } 67 | } 68 | 69 | impl AsRef for Variable { 70 | #[inline(always)] 71 | fn as_ref(&self) -> &str { 72 | self.0.as_ref() 73 | } 74 | } 75 | 76 | impl Deref for Variable { 77 | type Target = Name; 78 | 79 | #[inline(always)] 80 | fn deref(&self) -> &Self::Target { 81 | &self.0 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/visitor.rs: -------------------------------------------------------------------------------- 1 | /// A visitor. 2 | pub trait Visitor { 3 | fn visit(&self, value: &T) -> O; 4 | } 5 | 6 | /// A mutable visitor. 7 | pub trait VisitorMut { 8 | fn visit_mut(&mut self, value: &T) -> O; 9 | } 10 | 11 | /// Trait to accept immutable visitors. 12 | pub trait Accept, T, O> { 13 | fn accept(&self, v: &V) -> O; 14 | } 15 | 16 | /// Trait to accept mutable visitors. 17 | pub trait AcceptMut, T, O> { 18 | fn accept_mut(&self, v: &mut V) -> O; 19 | } 20 | 21 | /// Automatic implementation for accepting immutable visitors 22 | /// if the visitor recognizes the target type. 23 | impl Accept for T 24 | where 25 | V: Visitor, 26 | { 27 | fn accept(&self, v: &V) -> O { 28 | v.visit(self) 29 | } 30 | } 31 | 32 | /// Automatic implementation for accepting mutable visitors 33 | /// if the visitor recognizes the target type. 34 | impl AcceptMut for T 35 | where 36 | V: VisitorMut, 37 | { 38 | fn accept_mut(&self, v: &mut V) -> O { 39 | v.visit_mut(self) 40 | } 41 | } 42 | 43 | #[cfg(test)] 44 | mod tests { 45 | use super::*; 46 | 47 | struct Visi(isize); 48 | struct Item(i32); 49 | 50 | impl VisitorMut for Visi { 51 | fn visit_mut(&mut self, value: &Item) { 52 | self.0 += value.0 as isize; 53 | } 54 | } 55 | 56 | #[test] 57 | fn it_works() { 58 | let a = Item(10); 59 | let b = Item(7); 60 | let mut v = Visi(20); 61 | 62 | a.accept_mut(&mut v); 63 | b.accept_mut(&mut v); 64 | 65 | assert_eq!(v.0, 37); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /tea.yaml: -------------------------------------------------------------------------------- 1 | # https://tea.xyz/what-is-this-file 2 | --- 3 | version: 1.0.0 4 | codeOwners: 5 | - '0xfB0cb2c716Ceb7A207C18c540c8EfdDf71B64689' 6 | quorum: 1 7 | 8 | --------------------------------------------------------------------------------