pddl_parser/domain/
expression.rs

1use nom::branch::alt;
2use nom::combinator::map;
3use nom::multi::many0;
4use nom::sequence::{delimited, pair, preceded, tuple};
5use nom::IResult;
6use serde::{Deserialize, Serialize};
7
8use super::parameter::Parameter;
9use crate::domain::typed_parameter::TypedParameter;
10use crate::error::ParserError;
11use crate::lexer::{Token, TokenStream};
12use crate::tokens::{id, integer, var};
13
14/// An enumeration of binary operations that can be used in expressions.
15#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
16pub enum BinaryOp {
17    /// Addition operation.
18    Add,
19    /// Subtraction operation.
20    Subtract,
21    /// Multiplication operation.
22    Multiply,
23    /// Division operation.
24    Divide,
25    /// Equality operation.
26    Equal,
27}
28
29/// An enumeration of duration instants that can be used in expressions. The duration instant can be one of `at start`, `at end`, or `over all`.
30#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
31pub enum DurationInstant {
32    /// The duration instant `at start` represents the start of the action.
33    Start,
34    /// The duration instant `at end` represents the end of the action.
35    End,
36    /// The duration instant `over all` represents the entire duration of the action.
37    All,
38}
39
40/// An enumeration of expressions that can be used in PDDL planning domains and problems.
41#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
42pub enum Expression {
43    /// An atomic expression consisting of a name and an optional list of parameters.
44    Atom {
45        /// The name of the atom.
46        name: String,
47        /// The parameters of the atom.
48        #[serde(default)]
49        parameters: Vec<Parameter>,
50    },
51    /// A logical "and" expression that takes a list of sub-expressions as arguments.
52    And(Vec<Expression>),
53    /// A logical "not" expression that takes a single sub-expression as an argument.
54    Not(Box<Expression>),
55
56    // Assign operator
57    /// An assignment expression that assigns the value of the second sub-expression to the first sub-expression.
58    Assign(Box<Expression>, Box<Expression>),
59    /// An increase expression that increases the value of the first sub-expression by the value of the second sub-expression.
60    Increase(Box<Expression>, Box<Expression>),
61    /// A decrease expression that decreases the value of the first sub-expression by the value of the second sub-expression.
62    Decrease(Box<Expression>, Box<Expression>),
63    /// A scale-up expression that multiplies the value of the first sub-expression by the value of the second sub-expression.
64    ScaleUp(Box<Expression>, Box<Expression>),
65    /// A scale-down expression that divides the value of the first sub-expression by the value of the second sub-expression.
66    ScaleDown(Box<Expression>, Box<Expression>),
67    /// A binary operation expression that applies a binary operation to two sub-expressions.
68    BinaryOp(BinaryOp, Box<Expression>, Box<Expression>),
69    /// A numeric constant expression.
70    Number(i64),
71
72    // Forall
73    /// A forall expression that takes a list of typed parameters and a sub-expression as arguments.
74    Forall(Vec<TypedParameter>, Box<Expression>),
75
76    // Duration
77    /// A duration expression that takes a duration instant and a sub-expression as arguments. The duration instant can be one of `at start`, `at end`, or `over all`.
78    Duration(DurationInstant, Box<Expression>),
79}
80
81impl Expression {
82    /// Parse an expression from a token stream.
83    pub fn parse_expression(input: TokenStream) -> IResult<TokenStream, Expression, ParserError> {
84        log::debug!("BEGIN > parse_expression {:?}", input.span());
85        let (output, expression) = alt((
86            Self::parse_and,
87            Self::parse_not,
88            Self::parse_atom,
89            // Assign op
90            alt((
91                Self::parse_assign,
92                Self::parse_scale_up,
93                Self::parse_scale_down,
94                Self::parse_increase,
95                Self::parse_decrease,
96            )),
97            Self::parse_duration,
98            Self::parse_forall,
99            Self::parse_comparison,
100        ))(input)?;
101        log::debug!("END < parse_expression {:?}", output.span());
102        Ok((output, expression))
103    }
104
105    /// Convert the expression to PDDL.
106    pub fn to_pddl(&self) -> String {
107        match self {
108            Expression::Atom { name, parameters } => format!(
109                "({} {})",
110                name,
111                parameters.iter().map(Parameter::to_pddl).collect::<Vec<_>>().join(" ")
112            ),
113            Expression::And(expressions) => format!(
114                "(and {})",
115                expressions
116                    .iter()
117                    .map(Expression::to_pddl)
118                    .collect::<Vec<_>>()
119                    .join(" ")
120            ),
121            Expression::Not(expression) => format!("(not {})", expression.to_pddl()),
122            Expression::Assign(exp1, exp2) => format!("(assign {} {})", exp1.to_pddl(), exp2.to_pddl()),
123            Expression::Increase(exp1, exp2) => {
124                format!("(increase {} {})", exp1.to_pddl(), exp2.to_pddl())
125            },
126            Expression::Decrease(exp1, exp2) => {
127                format!("(decrease {} {})", exp1.to_pddl(), exp2.to_pddl())
128            },
129            Expression::ScaleUp(exp1, exp2) => {
130                format!("(scale-up {} {})", exp1.to_pddl(), exp2.to_pddl())
131            },
132            Expression::ScaleDown(exp1, exp2) => {
133                format!("(scale-down {} {})", exp1.to_pddl(), exp2.to_pddl())
134            },
135            Expression::BinaryOp(op, exp1, exp2) => format!(
136                "({} {} {})",
137                match op {
138                    BinaryOp::Add => "+",
139                    BinaryOp::Subtract => "-",
140                    BinaryOp::Multiply => "*",
141                    BinaryOp::Divide => "/",
142                    BinaryOp::Equal => "=",
143                },
144                exp1.to_pddl(),
145                exp2.to_pddl()
146            ),
147            Expression::Number(n) => n.to_string(),
148            Expression::Duration(instant, exp) => format!(
149                "({} {})",
150                match instant {
151                    DurationInstant::Start => "at start",
152                    DurationInstant::End => "at end",
153                    DurationInstant::All => "over all",
154                },
155                exp.to_pddl()
156            ),
157            Expression::Forall(parameters, expression) => format!(
158                "(forall ({}) {})",
159                parameters
160                    .iter()
161                    .map(TypedParameter::to_pddl)
162                    .collect::<Vec<_>>()
163                    .join(" "),
164                expression.to_pddl()
165            ),
166        }
167    }
168
169    fn parse_and(input: TokenStream) -> IResult<TokenStream, Expression, ParserError> {
170        log::debug!("BEGIN > parse_and {:?}", input.span());
171        let (output, expressions) = delimited(
172            Token::OpenParen,
173            preceded(Token::And, many0(Expression::parse_expression)),
174            Token::CloseParen,
175        )(input)?;
176        log::debug!("END < parse_and {:?}", output.span());
177        Ok((output, Expression::And(expressions)))
178    }
179
180    fn parse_not(input: TokenStream) -> IResult<TokenStream, Expression, ParserError> {
181        log::debug!("BEGIN > parse_not {:?}", input.span());
182        let (output, expression) = delimited(
183            Token::OpenParen,
184            preceded(Token::Not, Expression::parse_expression),
185            Token::CloseParen,
186        )(input)?;
187        log::debug!("END < parse_not {:?}", output.span());
188        Ok((output, Expression::Not(Box::new(expression))))
189    }
190
191    fn parse_atom(input: TokenStream) -> IResult<TokenStream, Expression, ParserError> {
192        log::debug!("BEGIN > parse_atom {:?}", input.span());
193        let (output, expression) = map(
194            delimited(
195                Token::OpenParen,
196                pair(id, Parameter::parse_parameters),
197                Token::CloseParen,
198            ),
199            |(name, parameters)| Expression::Atom { name, parameters },
200        )(input)?;
201        log::debug!("END < parse_atom {:?}", output.span());
202        Ok((output, expression))
203    }
204
205    fn parse_var(input: TokenStream) -> IResult<TokenStream, Expression, ParserError> {
206        log::debug!("BEGIN > parse_var {:?}", input.span());
207        let (output, expression) = map(var, |name| Expression::Atom {
208            name,
209            parameters: Vec::new(),
210        })(input)?;
211        log::debug!("END < parse_var {:?}", output.span());
212        Ok((output, expression))
213    }
214
215    fn parse_assign(input: TokenStream) -> IResult<TokenStream, Expression, ParserError> {
216        log::debug!("BEGIN > parse_assign {:?}", input.span());
217        let (output, expression) = map(
218            delimited(
219                Token::OpenParen,
220                preceded(
221                    Token::Assign,
222                    tuple((
223                        alt((Self::parse_number, Self::parse_comparison, Self::parse_atom)),
224                        alt((Self::parse_number, Self::parse_comparison, Self::parse_atom)),
225                    )),
226                ),
227                Token::CloseParen,
228            ),
229            |(exp1, exp2)| Expression::Assign(Box::new(exp1), Box::new(exp2)),
230        )(input)?;
231        log::debug!("END < parse_assign {:?}", output.span());
232        Ok((output, expression))
233    }
234
235    fn parse_binary_operator(input: TokenStream) -> IResult<TokenStream, BinaryOp, ParserError> {
236        log::debug!("BEGIN > parse_binary_operator {:?}", input.span());
237        let (output, op) = alt((
238            map(Token::Plus, |_| BinaryOp::Add),
239            map(Token::Dash, |_| BinaryOp::Subtract),
240            map(Token::Times, |_| BinaryOp::Multiply),
241            map(Token::Divide, |_| BinaryOp::Divide),
242            map(Token::Equal, |_| BinaryOp::Equal),
243        ))(input)?;
244        log::debug!("END < parse_binary_operator {:?}", output.span());
245        Ok((output, op))
246    }
247
248    fn parse_comparison(input: TokenStream) -> IResult<TokenStream, Expression, ParserError> {
249        log::debug!("BEGIN > parse_comparison {:?}", input.span());
250        let (output, expression) = map(
251            delimited(
252                Token::OpenParen,
253                tuple((
254                    Self::parse_binary_operator,
255                    alt((
256                        Self::parse_number,
257                        Self::parse_comparison,
258                        Self::parse_atom,
259                        Self::parse_var,
260                    )),
261                    alt((
262                        Self::parse_number,
263                        Self::parse_comparison,
264                        Self::parse_atom,
265                        Self::parse_var,
266                    )),
267                )),
268                Token::CloseParen,
269            ),
270            |(name, parameters, value)| Expression::BinaryOp(name, Box::new(parameters), Box::new(value)),
271        )(input)?;
272        log::debug!("END < parse_comparison {:?}", output.span());
273        Ok((output, expression))
274    }
275
276    fn parse_number(input: TokenStream) -> IResult<TokenStream, Expression, ParserError> {
277        log::debug!("BEGIN > parse_number {:?}", input.span());
278        let (output, number) = integer(input)?;
279        log::debug!("END < parse_number {:?}", output.span());
280        Ok((output, Expression::Number(number)))
281    }
282
283    fn parse_scale_up(input: TokenStream) -> IResult<TokenStream, Expression, ParserError> {
284        log::debug!("BEGIN > parse_scale_up {:?}", input.span());
285        let (output, expression) = map(
286            delimited(
287                Token::OpenParen,
288                preceded(
289                    Token::ScaleUp,
290                    tuple((
291                        alt((Self::parse_number, Self::parse_comparison, Self::parse_atom)),
292                        alt((Self::parse_number, Self::parse_comparison, Self::parse_atom)),
293                    )),
294                ),
295                Token::CloseParen,
296            ),
297            |(exp1, exp2)| Expression::ScaleUp(Box::new(exp1), Box::new(exp2)),
298        )(input)?;
299        log::debug!("END < parse_scale_up {:?}", output.span());
300        Ok((output, expression))
301    }
302
303    fn parse_scale_down(input: TokenStream) -> IResult<TokenStream, Expression, ParserError> {
304        log::debug!("BEGIN > parse_scale_down {:?}", input.span());
305        let (output, expression) = map(
306            delimited(
307                Token::OpenParen,
308                preceded(
309                    Token::ScaleDown,
310                    tuple((
311                        alt((Self::parse_number, Self::parse_comparison, Self::parse_atom)),
312                        alt((Self::parse_number, Self::parse_comparison, Self::parse_atom)),
313                    )),
314                ),
315                Token::CloseParen,
316            ),
317            |(exp1, exp2)| Expression::ScaleDown(Box::new(exp1), Box::new(exp2)),
318        )(input)?;
319        log::debug!("END < parse_scale_down {:?}", output.span());
320        Ok((output, expression))
321    }
322
323    fn parse_increase(input: TokenStream) -> IResult<TokenStream, Expression, ParserError> {
324        log::debug!("BEGIN > parse_increase {:?}", input.span());
325        let (output, expression) = map(
326            delimited(
327                Token::OpenParen,
328                preceded(
329                    Token::Increase,
330                    tuple((
331                        alt((Self::parse_number, Self::parse_comparison, Self::parse_atom)),
332                        alt((Self::parse_number, Self::parse_comparison, Self::parse_atom)),
333                    )),
334                ),
335                Token::CloseParen,
336            ),
337            |(exp1, exp2)| Expression::Increase(Box::new(exp1), Box::new(exp2)),
338        )(input)?;
339        log::debug!("END < parse_increase {:?}", output.span());
340        Ok((output, expression))
341    }
342
343    fn parse_decrease(input: TokenStream) -> IResult<TokenStream, Expression, ParserError> {
344        log::debug!("BEGIN > parse_decrease {:?}", input.span());
345        let (output, expression) = map(
346            delimited(
347                Token::OpenParen,
348                preceded(
349                    Token::Decrease,
350                    tuple((
351                        alt((Self::parse_number, Self::parse_comparison, Self::parse_atom)),
352                        alt((Self::parse_number, Self::parse_comparison, Self::parse_atom)),
353                    )),
354                ),
355                Token::CloseParen,
356            ),
357            |(exp1, exp2)| Expression::Decrease(Box::new(exp1), Box::new(exp2)),
358        )(input)?;
359        log::debug!("END < parse_decrease {:?}", output.span());
360        Ok((output, expression))
361    }
362
363    fn parse_forall(input: TokenStream) -> IResult<TokenStream, Expression, ParserError> {
364        log::debug!("BEGIN > parse_forall {:?}", input.span());
365        let (output, expression) = map(
366            delimited(
367                Token::OpenParen,
368                preceded(
369                    Token::Forall,
370                    tuple((
371                        delimited(
372                            Token::OpenParen,
373                            TypedParameter::parse_typed_parameters,
374                            Token::CloseParen,
375                        ),
376                        Expression::parse_expression,
377                    )),
378                ),
379                Token::CloseParen,
380            ),
381            |(parameters, expression)| Expression::Forall(parameters, Box::new(expression)),
382        )(input)?;
383        log::debug!("END < parse_forall {:?}", output.span());
384        Ok((output, expression))
385    }
386
387    fn parse_duration(input: TokenStream) -> IResult<TokenStream, Expression, ParserError> {
388        log::debug!("BEGIN > parse_duration {:?}", input.span());
389        let (output, expression) = delimited(
390            Token::OpenParen,
391            alt((
392                map(
393                    tuple((Token::At, Token::Start, Expression::parse_expression)),
394                    |(_, _, expression)| Expression::Duration(DurationInstant::Start, Box::new(expression)),
395                ),
396                map(
397                    tuple((Token::At, Token::End, Expression::parse_expression)),
398                    |(_, _, expression)| Expression::Duration(DurationInstant::End, Box::new(expression)),
399                ),
400                map(
401                    tuple((Token::Over, Token::All, Expression::parse_expression)),
402                    |(_, _, expression)| Expression::Duration(DurationInstant::All, Box::new(expression)),
403                ),
404            )),
405            Token::CloseParen,
406        )(input)?;
407        log::debug!("END < parse_duration {:?}", output.span());
408        Ok((output, expression))
409    }
410}