use winnow::{
combinator::alt,
error::{FromExternalError, ParserError},
PResult, Parser,
};
use crate::{
comments::{space_or_comment0, space_or_comment1},
parameters::types::{basic_par_type, BasicParType},
primitive_literals::index_set,
variables::types::{
basic_var_type, bounded_float, float_in_set, int_in_range, int_in_set, subset_of_int_range,
subset_of_int_set, BasicVarType,
},
};
#[derive(PartialEq, Clone, Debug)]
pub enum BasicPredParType {
BasicParType(BasicParType),
BasicVarType(BasicVarType),
VarSetOfInt,
IntInRange(i128, i128),
IntInSet(Vec<i128>),
BoundedFloat(f64, f64),
FloatInSet(Vec<f64>),
SubSetOfIntSet(Vec<i128>),
SubSetOfIntRange(i128, i128),
}
pub fn basic_pred_par_type<'a, E>(input: &mut &'a str) -> PResult<BasicPredParType, E>
where
E: ParserError<&'a str>
+ FromExternalError<&'a str, std::num::ParseIntError>
+ FromExternalError<&'a str, std::num::ParseFloatError>,
{
alt((
bppt_basic_par_type,
bppt_basic_var_type,
bppt_var_set_of_int,
bppt_int_in_range,
bppt_int_in_set,
bppt_bounded_float,
bppt_float_in_set,
bppt_subset_of_int_set,
bppt_subset_of_int_range,
))
.parse_next(input)
}
#[test]
fn test_basic_pred_par_type() {
use crate::predicates::types;
use crate::predicates::types::BasicPredParType;
use winnow::error::ContextError;
let mut input = "var set of int";
assert_eq!(
types::basic_pred_par_type::<ContextError>(&mut input),
Ok(BasicPredParType::VarSetOfInt)
);
}
fn bppt_basic_par_type<'a, E: ParserError<&'a str>>(
input: &mut &'a str,
) -> PResult<BasicPredParType, E> {
let bpt = basic_par_type(input)?;
Ok(BasicPredParType::BasicParType(bpt))
}
fn bppt_basic_var_type<'a, E>(input: &mut &'a str) -> PResult<BasicPredParType, E>
where
E: ParserError<&'a str>
+ FromExternalError<&'a str, std::num::ParseIntError>
+ FromExternalError<&'a str, std::num::ParseFloatError>,
{
let bvt = basic_var_type(input)?;
Ok(BasicPredParType::BasicVarType(bvt))
}
fn bppt_var_set_of_int<'a, E: ParserError<&'a str>>(
input: &mut &'a str,
) -> PResult<BasicPredParType, E> {
space_or_comment0(input)?;
"var".parse_next(input)?;
space_or_comment1(input)?;
"set".parse_next(input)?;
space_or_comment1(input)?;
"of".parse_next(input)?;
space_or_comment1(input)?;
"int".parse_next(input)?;
space_or_comment0(input)?;
Ok(BasicPredParType::VarSetOfInt)
}
fn bppt_int_in_range<'a, E>(input: &mut &'a str) -> PResult<BasicPredParType, E>
where
E: ParserError<&'a str> + FromExternalError<&'a str, std::num::ParseIntError>,
{
let (lb, ub) = int_in_range(input)?;
Ok(BasicPredParType::IntInRange(lb, ub))
}
fn bppt_int_in_set<'a, E>(input: &mut &'a str) -> PResult<BasicPredParType, E>
where
E: ParserError<&'a str> + FromExternalError<&'a str, std::num::ParseIntError>,
{
let set = int_in_set(input)?;
Ok(BasicPredParType::IntInSet(set))
}
fn bppt_bounded_float<'a, E>(input: &mut &'a str) -> PResult<BasicPredParType, E>
where
E: ParserError<&'a str> + FromExternalError<&'a str, std::num::ParseFloatError>,
{
let (lb, ub) = bounded_float(input)?;
Ok(BasicPredParType::BoundedFloat(lb, ub))
}
fn bppt_float_in_set<'a, E>(input: &mut &'a str) -> PResult<BasicPredParType, E>
where
E: ParserError<&'a str> + FromExternalError<&'a str, std::num::ParseFloatError>,
{
let set = float_in_set(input)?;
Ok(BasicPredParType::FloatInSet(set))
}
fn bppt_subset_of_int_range<'a, E>(input: &mut &'a str) -> PResult<BasicPredParType, E>
where
E: ParserError<&'a str> + FromExternalError<&'a str, std::num::ParseIntError>,
{
let (lb, ub) = subset_of_int_range(input)?;
Ok(BasicPredParType::SubSetOfIntRange(lb, ub))
}
fn bppt_subset_of_int_set<'a, E>(input: &mut &'a str) -> PResult<BasicPredParType, E>
where
E: ParserError<&'a str> + FromExternalError<&'a str, std::num::ParseIntError>,
{
let set = subset_of_int_set(input)?;
Ok(BasicPredParType::SubSetOfIntSet(set))
}
#[derive(PartialEq, Clone, Debug)]
pub enum PredParType {
Basic(BasicPredParType),
Array {
ix: PredIndexSet,
par_type: BasicPredParType,
},
}
pub fn pred_par_type<'a, E>(input: &mut &'a str) -> PResult<PredParType, E>
where
E: ParserError<&'a str>
+ FromExternalError<&'a str, std::num::ParseIntError>
+ FromExternalError<&'a str, std::num::ParseFloatError>,
{
alt((ppt_basic_pred_par_type, array_of_pred_index_set)).parse_next(input)
}
#[test]
fn test_pred_par_type_range() {
use crate::predicates::types;
use winnow::error::ContextError;
let mut input = "1..3";
assert_eq!(
types::pred_par_type::<ContextError>(&mut input),
Ok(types::PredParType::Basic(
types::BasicPredParType::IntInRange(1, 3)
))
);
}
#[test]
fn test_pred_par_type_2() {
use crate::predicates::types;
use winnow::error::ContextError;
let mut input = "array [1..1] of var set of int";
assert_eq!(
pred_par_type::<ContextError>(&mut input),
Ok(PredParType::Array {
ix: types::PredIndexSet::IndexSet(1),
par_type: types::BasicPredParType::VarSetOfInt,
},)
);
}
#[test]
fn test_pred_par_type_3() {
use crate::predicates::types;
use winnow::error::ContextError;
let mut input = "var set of int";
assert_eq!(
types::pred_par_type::<ContextError>(&mut input),
Ok(types::PredParType::Basic(
types::BasicPredParType::VarSetOfInt
))
);
}
fn ppt_basic_pred_par_type<'a, E>(input: &mut &'a str) -> PResult<PredParType, E>
where
E: ParserError<&'a str>
+ FromExternalError<&'a str, std::num::ParseIntError>
+ FromExternalError<&'a str, std::num::ParseFloatError>,
{
let bppt = basic_pred_par_type(input)?;
Ok(PredParType::Basic(bppt))
}
fn array_of_pred_index_set<'a, E>(input: &mut &'a str) -> PResult<PredParType, E>
where
E: ParserError<&'a str>
+ FromExternalError<&'a str, std::num::ParseIntError>
+ FromExternalError<&'a str, std::num::ParseFloatError>,
{
space_or_comment0(input)?;
"array".parse_next(input)?;
space_or_comment1(input)?;
'['.parse_next(input)?;
space_or_comment0(input)?;
let ix = pred_index_set(input)?;
space_or_comment0(input)?;
']'.parse_next(input)?;
space_or_comment1(input)?;
"of".parse_next(input)?;
space_or_comment1(input)?;
let par_type = basic_pred_par_type(input)?;
Ok(PredParType::Array { ix, par_type })
}
#[derive(PartialEq, Clone, Debug)]
pub enum PredIndexSet {
IndexSet(i128),
Int,
}
fn pred_index_set<'a, E>(input: &mut &'a str) -> PResult<PredIndexSet, E>
where
E: ParserError<&'a str> + FromExternalError<&'a str, std::num::ParseIntError>,
{
alt((pis_int, pis_index_set)).parse_next(input)
}
fn pis_int<'a, E: ParserError<&'a str>>(input: &mut &'a str) -> PResult<PredIndexSet, E> {
"int".parse_next(input)?;
Ok(PredIndexSet::Int)
}
fn pis_index_set<'a, E>(input: &mut &'a str) -> PResult<PredIndexSet, E>
where
E: ParserError<&'a str> + FromExternalError<&'a str, std::num::ParseIntError>,
{
let ix = index_set(input)?;
Ok(PredIndexSet::IndexSet(ix.0))
}