use crate::parsers::{
parens, parse_con_gd, parse_pref_name, parse_variable, prefix_expr, space_separated_list0,
typed_list, ParseResult, Span,
};
use crate::PreferenceConstraintGoalDefinitions;
use nom::branch::alt;
use nom::character::complete::multispace1;
use nom::combinator::map;
use nom::sequence::preceded;
use nom::Parser;
pub fn parse_pref_con_gd<'a, T: Into<Span<'a>>>(
input: T,
) -> ParseResult<'a, PreferenceConstraintGoalDefinitions> {
let and = map(
prefix_expr("and", space_separated_list0(parse_pref_con_gd)),
|x| PreferenceConstraintGoalDefinitions::from_iter(x.into_iter().flatten()),
);
let forall = map(
prefix_expr(
"forall",
(
parens(typed_list(parse_variable)),
preceded(multispace1, parse_pref_con_gd),
),
),
|(vars, gd)| PreferenceConstraintGoalDefinitions::forall(vars, gd),
);
let named_preference = map(
prefix_expr(
"preference",
(parse_pref_name, preceded(multispace1, parse_con_gd)),
),
|(name, gd)| PreferenceConstraintGoalDefinitions::preference(Some(name), gd),
);
let unnamed_preference = map(prefix_expr("preference", parse_con_gd), |gd| {
PreferenceConstraintGoalDefinitions::preference(None, gd)
});
let goal = map(parse_con_gd, PreferenceConstraintGoalDefinitions::new_goal);
alt((and, forall, named_preference, unnamed_preference, goal)).parse(input.into())
}
impl crate::parsers::Parser for PreferenceConstraintGoalDefinitions {
type Item = PreferenceConstraintGoalDefinitions;
fn parse<'a, S: Into<Span<'a>>>(input: S) -> ParseResult<'a, Self::Item> {
parse_pref_con_gd(input)
}
}
#[cfg(test)]
mod tests {
use crate::parsers::preamble::*;
use crate::{
AtomicFormula, ConstraintGoalDefinition, ConstraintGoalDefinitionInner, GoalDefinition,
PreferenceConstraintGoalDefinition, PreferenceConstraintGoalDefinitions, Term, ToTyped,
Type, TypedList, Variable,
};
#[test]
fn test_parse() {
let gd_a = GoalDefinition::atomic_formula(AtomicFormula::equality(
Term::Name("x".into()),
Term::Name("y".into()),
));
let gd_b = GoalDefinition::not(GoalDefinition::atomic_formula(AtomicFormula::equality(
Term::Name("x".into()),
Term::Name("z".into()),
)));
assert!(PreferenceConstraintGoalDefinitions::parse("(and)")
.is_value(PreferenceConstraintGoalDefinitions::default()));
assert!(PreferenceConstraintGoalDefinitions::parse(
"(and (at end (= x y)) (at end (not (= x z))))"
)
.is_value(PreferenceConstraintGoalDefinitions::from_iter([
PreferenceConstraintGoalDefinition::goal(ConstraintGoalDefinition::at_end(
gd_a.clone()
)),
PreferenceConstraintGoalDefinition::goal(ConstraintGoalDefinition::at_end(
gd_b.clone()
)),
])));
assert!(PreferenceConstraintGoalDefinitions::parse(
"(forall (?x ?z) (sometime (= ?x ?z)))"
)
.is_value(PreferenceConstraintGoalDefinitions::forall(
TypedList::from_iter([
Variable::from("x").to_typed(Type::OBJECT),
Variable::from("z").to_typed(Type::OBJECT),
]),
PreferenceConstraintGoalDefinitions::goal(ConstraintGoalDefinition::sometime(
ConstraintGoalDefinitionInner::Goal(GoalDefinition::atomic_formula(
AtomicFormula::equality(Term::Variable("x".into()), Term::Variable("z".into()))
))
))
)));
assert!(
PreferenceConstraintGoalDefinitions::parse("(at end (= x y))").is_value(
PreferenceConstraintGoalDefinitions::goal(ConstraintGoalDefinition::AtEnd(
gd_a.clone()
))
)
);
assert!(
PreferenceConstraintGoalDefinitions::parse("(preference (at end (= x y)))").is_value(
PreferenceConstraintGoalDefinitions::preference(
None,
ConstraintGoalDefinition::AtEnd(gd_a.clone())
)
)
);
assert!(
PreferenceConstraintGoalDefinitions::parse("(preference name (at end (= x y)))")
.is_value(PreferenceConstraintGoalDefinitions::preference(
Some("name".into()),
ConstraintGoalDefinition::AtEnd(gd_a.clone())
))
);
}
}