use nom::branch::alt;
use nom::combinator::{map, opt};
use nom::multi::many0;
use nom::sequence::{delimited, preceded};
use nom::IResult;
use serde::{Deserialize, Serialize};
use crate::error::ParserError;
use crate::lexer::{Token, TokenStream};
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum Requirement {
Strips,
Typing,
DisjunctivePreconditions,
Equality,
ExistentialPreconditions,
UniversalPreconditions,
QuantifiedPreconditions,
ConditionalEffects,
ActionExpansions,
ForeachExpansions,
DagExpansions,
DomainAxioms,
SubgoalsThroughAxioms,
SafetyConstraints,
ExpressionEvaluation,
Fluents,
OpenWorld,
TrueNegation,
Adl,
Ucpop,
NumericFluents,
DurativeActions,
DurativeInequalities,
ContinuousEffects,
NegativePreconditions,
DerivedPredicates,
TimedInitialLiterals,
Preferences,
Constraints,
ActionCosts,
GoalUtilities,
Time,
}
impl Requirement {
fn parse_requirement(input: TokenStream) -> IResult<TokenStream, Requirement, ParserError> {
alt((
alt((
map(Token::Strips, |_| Requirement::Strips),
map(Token::Typing, |_| Requirement::Typing),
map(Token::DisjunctivePreconditions, |_| {
Requirement::DisjunctivePreconditions
}),
map(Token::Equality, |_| Requirement::Equality),
map(Token::ExistentialPreconditions, |_| {
Requirement::ExistentialPreconditions
}),
map(Token::UniversalPreconditions, |_| Requirement::UniversalPreconditions),
map(Token::QuantifiedPreconditions, |_| Requirement::QuantifiedPreconditions),
map(Token::ConditionalEffects, |_| Requirement::ConditionalEffects),
map(Token::ActionExpansions, |_| Requirement::ActionExpansions),
map(Token::ForeachExpansions, |_| Requirement::ForeachExpansions),
map(Token::DagExpansions, |_| Requirement::DagExpansions),
map(Token::DomainAxioms, |_| Requirement::DomainAxioms),
map(Token::SubgoalsThroughAxioms, |_| Requirement::SubgoalsThroughAxioms),
map(Token::SafetyConstraints, |_| Requirement::SafetyConstraints),
map(Token::ExpressionEvaluation, |_| Requirement::ExpressionEvaluation),
map(Token::Fluents, |_| Requirement::Fluents),
map(Token::OpenWorld, |_| Requirement::OpenWorld),
map(Token::TrueNegation, |_| Requirement::TrueNegation),
map(Token::Adl, |_| Requirement::Adl),
map(Token::Ucpop, |_| Requirement::Ucpop),
)),
alt((
map(Token::NumericFluents, |_| Requirement::NumericFluents),
map(Token::DurativeActions, |_| Requirement::DurativeActions),
map(Token::DurativeInequalities, |_| Requirement::DurativeInequalities),
map(Token::ContinuousEffects, |_| Requirement::ContinuousEffects),
map(Token::NegativePreconditions, |_| Requirement::NegativePreconditions),
)),
alt((
map(Token::DerivedPredicates, |_| Requirement::DerivedPredicates),
map(Token::TimedInitialLiterals, |_| Requirement::TimedInitialLiterals),
)),
alt((
map(Token::Preferences, |_| Requirement::Preferences),
map(Token::Constraints, |_| Requirement::Constraints),
)),
alt((
map(Token::ActionCosts, |_| Requirement::ActionCosts),
map(Token::GoalUtilities, |_| Requirement::GoalUtilities),
)),
map(Token::Time, |_| Requirement::Time),
))(input)
}
const fn is_supported(&self) -> bool {
matches!(
self,
Requirement::Strips | Requirement::Typing | Requirement::DurativeActions | Requirement::NumericFluents
)
}
pub fn parse_requirements(input: TokenStream) -> IResult<TokenStream, Vec<Requirement>, ParserError> {
log::debug!("BEGIN > parse_requirements {:?}", input.span());
let (output, requirements) = opt(delimited(
Token::OpenParen,
preceded(Token::Requirements, many0(Requirement::parse_requirement)),
Token::CloseParen,
))(input)?;
if let Some(requirements) = &requirements {
for requirement in requirements {
if !requirement.is_supported() {
return Err(nom::Err::Error(ParserError::UnsupportedRequirement(
requirement.clone(),
)));
}
}
}
log::debug!("Requirements: {requirements:?}");
log::debug!("END < parse_requirements {:?}", output.span());
Ok((output, requirements.unwrap_or_default()))
}
pub fn to_pddl(&self) -> String {
match self {
Requirement::Strips => ":strips".to_string(),
Requirement::Typing => ":typing".to_string(),
Requirement::DisjunctivePreconditions => ":disjunctive-preconditions".to_string(),
Requirement::Equality => ":equality".to_string(),
Requirement::ExistentialPreconditions => ":existential-preconditions".to_string(),
Requirement::UniversalPreconditions => ":universal-preconditions".to_string(),
Requirement::QuantifiedPreconditions => ":quantified-preconditions".to_string(),
Requirement::ConditionalEffects => ":conditional-effects".to_string(),
Requirement::ActionExpansions => ":action-expansions".to_string(),
Requirement::ForeachExpansions => ":foreach-expansions".to_string(),
Requirement::DagExpansions => ":dag-expansions".to_string(),
Requirement::DomainAxioms => ":domain-axioms".to_string(),
Requirement::SubgoalsThroughAxioms => ":subgoals-through-axioms".to_string(),
Requirement::SafetyConstraints => ":safety-constraints".to_string(),
Requirement::ExpressionEvaluation => ":expression-evaluation".to_string(),
Requirement::Fluents => ":fluents".to_string(),
Requirement::OpenWorld => ":open-world".to_string(),
Requirement::TrueNegation => ":true-negation".to_string(),
Requirement::Adl => ":adl".to_string(),
Requirement::Ucpop => ":ucpop".to_string(),
Requirement::NumericFluents => ":numeric-fluents".to_string(),
Requirement::DurativeActions => ":durative-actions".to_string(),
Requirement::DurativeInequalities => ":durative-inequalities".to_string(),
Requirement::ContinuousEffects => ":continuous-effects".to_string(),
Requirement::NegativePreconditions => ":negative-preconditions".to_string(),
Requirement::DerivedPredicates => ":derived-predicates".to_string(),
Requirement::TimedInitialLiterals => ":timed-initial-literals".to_string(),
Requirement::Preferences => ":preferences".to_string(),
Requirement::Constraints => ":constraints".to_string(),
Requirement::ActionCosts => ":action-costs".to_string(),
Requirement::GoalUtilities => ":goal-utilities".to_string(),
Requirement::Time => ":time".to_string(),
}
}
}