use nom::branch::alt;
use nom::character::complete::multispace1;
use nom::combinator::map;
use nom::sequence::preceded;
use nom::Parser;
use crate::parsers::{parens, prefix_expr, typed_list, ParseResult, Span};
use crate::parsers::{
parse_effect, parse_effect_condition, parse_gd, parse_p_effect, parse_variable,
};
use crate::types::ConditionalEffect;
use crate::{ForallConditionalEffect, WhenConditionalEffect};
#[allow(deprecated)]
pub fn parse_c_effect<'a, T: Into<Span<'a>>>(input: T) -> ParseResult<'a, ConditionalEffect> {
let p_effect = map(parse_p_effect, ConditionalEffect::from);
let forall = map(parse_forall_c_effect, ConditionalEffect::from);
let when = map(parse_when_c_effect, ConditionalEffect::from);
alt((forall, when, p_effect)).parse(input.into())
}
pub fn parse_forall_c_effect<'a, T: Into<Span<'a>>>(
input: T,
) -> ParseResult<'a, ForallConditionalEffect> {
map(
prefix_expr(
"forall",
(
parens(typed_list(parse_variable)),
preceded(multispace1, parse_effect),
),
),
ForallConditionalEffect::from,
)
.parse(input.into())
}
#[allow(deprecated)]
pub fn parse_when_c_effect<'a, T: Into<Span<'a>>>(
input: T,
) -> ParseResult<'a, WhenConditionalEffect> {
map(
prefix_expr(
"when",
(parse_gd, preceded(multispace1, parse_effect_condition)),
),
WhenConditionalEffect::from,
)
.parse(input.into())
}
#[allow(deprecated)]
impl crate::parsers::Parser for ConditionalEffect {
type Item = ConditionalEffect;
fn parse<'a, S: Into<Span<'a>>>(input: S) -> ParseResult<'a, Self::Item> {
parse_c_effect(input.into())
}
}
impl crate::parsers::Parser for ForallConditionalEffect {
type Item = ForallConditionalEffect;
fn parse<'a, S: Into<Span<'a>>>(input: S) -> ParseResult<'a, Self::Item> {
parse_forall_c_effect(input)
}
}
#[allow(deprecated)]
impl crate::parsers::Parser for WhenConditionalEffect {
type Item = WhenConditionalEffect;
fn parse<'a, S: Into<Span<'a>>>(input: S) -> ParseResult<'a, Self::Item> {
parse_when_c_effect(input)
}
}
#[cfg(test)]
#[allow(deprecated)]
mod tests {
use crate::{
ConditionalEffect, EffectCondition, Effects, ForallConditionalEffect, GoalDefinition,
Parser, PrimitiveEffect, Typed, TypedList, Variable, WhenConditionalEffect,
};
#[test]
fn test_parse() {
let (_, value) = ConditionalEffect::parse("(= x y)").unwrap();
assert_eq!(
value,
ConditionalEffect::new_primitive_effect(PrimitiveEffect::from_str("(= x y)").unwrap())
);
let (_, value) = ConditionalEffect::parse("(not (= ?a B))").unwrap();
assert_eq!(
value,
ConditionalEffect::new_primitive_effect(
PrimitiveEffect::from_str("(not (= ?a B))").unwrap()
)
);
let (_, value) = ConditionalEffect::parse("(forall (?a ?b) (= ?a ?b))").unwrap();
assert_eq!(
value,
ConditionalEffect::new_forall(
TypedList::from_iter([
Typed::new_object(Variable::new_string("a")),
Typed::new_object(Variable::new_string("b")),
]),
Effects::from_str("(= ?a ?b)").unwrap()
)
);
let input = r#"(when
(and (has-hot-chocolate ?p ?c) (has-marshmallows ?c))
(and (person-is-happy ?p)))"#;
let (_, value) = ConditionalEffect::parse(input).unwrap();
assert_eq!(
value,
ConditionalEffect::new_when(
GoalDefinition::from_str("(and (has-hot-chocolate ?p ?c) (has-marshmallows ?c))")
.unwrap(),
EffectCondition::from_str("(and (person-is-happy ?p))").unwrap()
)
);
}
#[test]
fn test_parse_forall() {
let (_, value) = ForallConditionalEffect::parse("(forall (?a ?b) (= ?a ?b))").unwrap();
assert_eq!(
value,
ForallConditionalEffect::new(
TypedList::from_iter([
Typed::new_object(Variable::new_string("a")),
Typed::new_object(Variable::new_string("b")),
]),
Effects::from_str("(= ?a ?b)").unwrap()
)
);
}
#[test]
fn test_parse_when() {
let input = r#"(when
(and (has-hot-chocolate ?p ?c) (has-marshmallows ?c))
(and (person-is-happy ?p)))"#;
let (_, value) = WhenConditionalEffect::parse(input).unwrap();
assert_eq!(
value,
WhenConditionalEffect::new(
GoalDefinition::from_str("(and (has-hot-chocolate ?p ?c) (has-marshmallows ?c))")
.unwrap(),
EffectCondition::from_str("(and (person-is-happy ?p))").unwrap()
)
);
}
}