flatzinc 0.3.21

A FlatZinc parser
Documentation
use winnow::{
    combinator::{cut_err, separated},
    error::{AddContext, FromExternalError, ParserError, StrContext},
    PResult, Parser,
};

use crate::{
    comments::{separator, space_or_comment0, space_or_comment1},
    predicates::types::{pred_par_type, PredParType},
    primitive_literals::identifier,
};

#[derive(PartialEq, Clone, Debug)]
pub struct PredicateItem {
    pub id: String,
    pub parameters: Vec<(PredParType, String)>,
}

pub fn predicate_item<'a, E>(input: &mut &'a str) -> PResult<PredicateItem, E>
where
    E: ParserError<&'a str>
        + FromExternalError<&'a str, std::num::ParseIntError>
        + FromExternalError<&'a str, std::num::ParseFloatError>
        + AddContext<&'a str, StrContext>,
{
    space_or_comment0(input)?;
    "predicate".parse_next(input)?;
    cut_err(predicate_item_tail.context(StrContext::Label("Error while parsing solve statement")))
        .parse_next(input)
}
pub fn predicate_item_tail<'a, E>(input: &mut &'a str) -> PResult<PredicateItem, E>
where
    E: ParserError<&'a str>
        + FromExternalError<&'a str, std::num::ParseIntError>
        + FromExternalError<&'a str, std::num::ParseFloatError>,
{
    space_or_comment1(input)?;
    let id = identifier(input)?;
    '('.parse_next(input)?;
    let parameters = separated(1.., pred_par_type_ident_pair, separator).parse_next(input)?;
    ')'.parse_next(input)?;
    space_or_comment0(input)?;
    ';'.parse_next(input)?;
    space_or_comment0(input)?;
    Ok(PredicateItem { id, parameters })
}
#[test]
fn test_predicate_item() {
    use crate::predicates::types::BasicPredParType;
    use winnow::error::ContextError;
    let mut input = "predicate float_03({1.0,3.3}:c);";
    assert_eq!(
        predicate_item::<ContextError>(&mut input),
        Ok(PredicateItem {
            id: "float_03".to_string(),
            parameters: vec![(
                PredParType::Basic(BasicPredParType::FloatInSet(vec![1.0, 3.3])),
                "c".to_string()
            )]
        })
    );
}
#[test]
fn test_predicate_item2() {
    use crate::predicates::types::BasicPredParType;
    use winnow::error::ContextError;
    let mut input = "predicate my_pred({1.0,3.3}:c);";
    assert_eq!(
        predicate_item::<ContextError>(&mut input),
        Ok(PredicateItem {
            id: "my_pred".to_string(),
            parameters: vec![(
                PredParType::Basic(BasicPredParType::FloatInSet(vec![1.0, 3.3])),
                "c".to_string()
            )]
        })
    );
}
#[test]
#[should_panic]
fn test_predicate_item_3() {
    use winnow::error::ContextError;
    let mut input = "predicate float_01(set of float:c);";
    predicate_item::<ContextError>(&mut input).unwrap();
}

pub fn pred_par_type_ident_pair<'a, E>(input: &mut &'a str) -> PResult<(PredParType, String), E>
where
    E: ParserError<&'a str>
        + FromExternalError<&'a str, std::num::ParseIntError>
        + FromExternalError<&'a str, std::num::ParseFloatError>,
{
    space_or_comment0(input)?;
    let pred_par_type = pred_par_type(input)?;
    space_or_comment0(input)?;
    ':'.parse_next(input)?;
    space_or_comment0(input)?;
    let ident = identifier(input)?;
    space_or_comment0(input)?;
    Ok((pred_par_type, ident))
}
#[test]
fn test_pred_par_type_ident_pair() {
    use crate::predicates::declarations;
    use crate::predicates::types;
    use winnow::error::ContextError;
    let mut input = "var set of int: g";
    assert_eq!(
        declarations::pred_par_type_ident_pair::<ContextError>(&mut input),
        Ok((
            types::PredParType::Basic(types::BasicPredParType::VarSetOfInt),
            "g".to_string()
        ))
    );
}