use nom::combinator::{map, opt};
use nom::sequence::{delimited, preceded, tuple};
use nom::IResult;
use serde::{Deserialize, Serialize};
use super::expression::Expression;
use super::typed_parameter::TypedParameter;
use crate::error::ParserError;
use crate::lexer::{Token, TokenStream};
use crate::tokens::id;
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct SimpleAction {
pub name: String,
#[serde(default)]
pub parameters: Vec<TypedParameter>,
pub precondition: Option<Expression>,
pub effect: Expression,
}
impl SimpleAction {
pub fn parse(input: TokenStream) -> IResult<TokenStream, SimpleAction, ParserError> {
log::debug!("BEGIN > parse_action {:?}", input.span());
log::debug!("Parsing action: {:?}", input.peek_n(10));
let (output, action) = map(
delimited(
Token::OpenParen,
preceded(
Token::Action,
tuple((
id,
preceded(
Token::Parameters,
delimited(
Token::OpenParen,
TypedParameter::parse_typed_parameters,
Token::CloseParen,
),
),
opt(preceded(Token::Precondition, Expression::parse_expression)),
preceded(Token::Effect, Expression::parse_expression),
)),
),
Token::CloseParen,
),
|(name, parameters, precondition, effect)| SimpleAction {
name,
parameters,
precondition,
effect,
},
)(input)?;
log::debug!("END < parse_action {:?}", output.span());
Ok((output, action))
}
pub fn to_pddl(&self) -> String {
let mut pddl = String::new();
pddl.push_str(&format!("(:action {}\n", self.name));
pddl.push_str(&format!(
":parameters ({})\n",
self.parameters
.iter()
.map(TypedParameter::to_pddl)
.collect::<Vec<_>>()
.join(" ")
));
if let Some(precondition) = &self.precondition {
pddl.push_str(&format!(":precondition {}\n", precondition.to_pddl()));
}
pddl.push_str(&format!(":effect \n{}\n", self.effect.to_pddl()));
pddl.push(')');
pddl
}
}