pddl/parsers/
f_exp_t.rs

1//! Provides parsers for f-exps.
2
3use nom::branch::alt;
4use nom::bytes::complete::tag;
5use nom::character::complete::multispace1;
6use nom::combinator::map;
7use nom::sequence::{preceded, terminated, tuple};
8
9use crate::parsers::prefix_expr;
10use crate::parsers::{parse_f_exp, ParseResult, Span};
11use 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///```
43pub fn parse_f_exp_t<'a, T: Into<Span<'a>>>(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
59impl crate::parsers::Parser for FExpT {
60    type Item = FExpT;
61
62    /// See [`parse_f_exp_t`].
63    fn parse<'a, S: Into<Span<'a>>>(input: S) -> ParseResult<'a, Self::Item> {
64        parse_f_exp_t(input)
65    }
66}
67
68#[cfg(test)]
69mod 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}