From 8c172dca5b6f522c537868710fcdf555899a27af Mon Sep 17 00:00:00 2001 From: Sven Thiele Date: Fri, 22 May 2020 08:50:17 +0200 Subject: [PATCH] Refactor (#6) * refactor ParDeclItem, VarDeclItem, Expr * remove ArrayLiteral * remove Domain * remove BasicExpr * remove ParArrayLiteral * remove BasicLiteralExpr * remove ParExpr * add tests --- Cargo.toml | 2 +- src/lib.rs | 1346 +++++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 1123 insertions(+), 225 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index b12dd9a..10a49c0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "flatzinc" -version = "0.2.2" +version = "0.3.0" publish = true authors = ["Sven Thiele "] description = "A FlatZinc parser" diff --git a/src/lib.rs b/src/lib.rs index ee07de2..63d164a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -145,7 +145,10 @@ fn bpt_set_of_int<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str } #[derive(PartialEq, Clone, Debug)] pub enum ParType { - Basic(BasicParType), + Bool, + Int, + Float, + SetOfInt, Array { ix: IndexSet, par_type: BasicParType, @@ -166,12 +169,30 @@ fn test_par_type() { ); } fn par_type<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, ParType, E> { - let (input, par_type) = alt((pt_basic_par_type, array_par_type))(input)?; + let (input, par_type) = alt((pt_bool, pt_int, pt_float, pt_set_of_int, array_par_type))(input)?; Ok((input, par_type)) } -fn pt_basic_par_type<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, ParType, E> { - let (input, pt) = basic_par_type(input)?; - Ok((input, ParType::Basic(pt))) + +fn pt_bool<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, ParType, E> { + let (input, _tag) = tag("bool")(input)?; + Ok((input, ParType::Bool)) +} +fn pt_int<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, ParType, E> { + let (input, _tag) = tag("int")(input)?; + Ok((input, ParType::Int)) +} +fn pt_float<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, ParType, E> { + let (input, _tag) = tag("float")(input)?; + Ok((input, ParType::Float)) +} +// "var" "set" "of" "int" +fn pt_set_of_int<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, ParType, E> { + let (input, _tag) = tag("set")(input)?; + let (input, _) = space1(input)?; + let (input, _tag) = tag("of")(input)?; + let (input, _) = space1(input)?; + let (input, _tag) = tag("int")(input)?; + Ok((input, ParType::SetOfInt)) } fn array_par_type<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, ParType, E> { let (input, _) = tag("array")(input)?; @@ -198,14 +219,26 @@ pub enum BasicVarType { Bool, Int, Float, - Domain(Domain), - SetOfInt, // added var_set_of_int from basic_pred_par_type + IntInRange(i128, i128), + IntInSet(Vec), // possibly empty + FloatInRange(f64, f64), + SetOfIntInSet(Vec), + SetOfIntInRange(i128, i128), + + SetOfInt, // added var_set_of_int from basic_pred_par_type TODO: move back } fn basic_var_type<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, BasicVarType, E> { let (input, _) = space0(input)?; let (input, _tag) = tag("var")(input)?; let (input, _) = space1(input)?; - let (input, bvt) = alt((bvt_basic_par_type, bvt_domain))(input)?; + let (input, bvt) = alt(( + bvt_basic_par_type, + bvt_int_in_range, + bvt_int_in_set, + bvt_float_in_range, + bvt_subset_of_int_in_set, + bvt_subset_of_int_in_range, + ))(input)?; Ok((input, bvt)) } fn bvt_basic_par_type<'a, E: ParseError<&'a str>>( @@ -219,47 +252,54 @@ fn bvt_basic_par_type<'a, E: ParseError<&'a str>>( BasicParType::SetOfInt => Ok((input, BasicVarType::SetOfInt)), } } -fn bvt_domain<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, BasicVarType, E> { - let (input, domain) = domain(input)?; - Ok((input, BasicVarType::Domain(domain))) +fn bvt_int_in_range<'a, E: ParseError<&'a str>>( + input: &'a str, +) -> IResult<&'a str, BasicVarType, E> { + let (input, (lb, ub)) = int_in_range(input)?; + Ok((input, BasicVarType::IntInRange(lb, ub))) } -// introduced by me used in basic-var-type and basic-pred-param-type -#[derive(PartialEq, Clone, Debug)] -pub enum Domain { - IntRange(i128, i128), - FloatRange(f64, f64), - SetIntNonEmpty(Vec), - SetIntRange(i128, i128), - SetInt(Vec), // possibly empty -} -fn domain<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, Domain, E> { - let (input, domain) = alt(( - int_range, - float_range, - set_of_int_range, - set_of_ints, - set_of_ints_non_empty, - ))(input)?; - Ok((input, domain)) +fn bvt_int_in_set<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, BasicVarType, E> { + let (input, set) = int_in_set(input)?; + Ok((input, BasicVarType::IntInSet(set))) +} +fn bvt_float_in_range<'a, E: ParseError<&'a str>>( + input: &'a str, +) -> IResult<&'a str, BasicVarType, E> { + let (input, (lb, ub)) = float_in_range(input)?; + Ok((input, BasicVarType::FloatInRange(lb, ub))) +} +fn bvt_subset_of_int_in_range<'a, E: ParseError<&'a str>>( + input: &'a str, +) -> IResult<&'a str, BasicVarType, E> { + let (input, (lb, ub)) = subset_of_int_in_range(input)?; + Ok((input, BasicVarType::SetOfIntInRange(lb, ub))) } -fn int_range<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, Domain, E> { +fn bvt_subset_of_int_in_set<'a, E: ParseError<&'a str>>( + input: &'a str, +) -> IResult<&'a str, BasicVarType, E> { + let (input, set) = subset_of_int_in_set(input)?; + Ok((input, BasicVarType::SetOfIntInSet(set))) +} +fn int_in_range<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, (i128, i128), E> { let (input, lb) = int_literal(input)?; let (input, _) = space0(input)?; let (input, _tag) = tag("..")(input)?; let (input, _) = space0(input)?; let (input, ub) = int_literal(input)?; - Ok((input, Domain::IntRange(lb, ub))) + Ok((input, (lb, ub))) } -fn float_range<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, Domain, E> { +fn float_in_range<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, (f64, f64), E> { let (input, lb) = float_literal(input)?; let (input, _) = space0(input)?; let (input, _tag) = tag("..")(input)?; let (input, _) = space0(input)?; let (input, ub) = float_literal(input)?; - Ok((input, Domain::FloatRange(lb, ub))) + Ok((input, (lb, ub))) } // "set" "of" ".." -fn set_of_int_range<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, Domain, E> { +fn subset_of_int_in_range<'a, E: ParseError<&'a str>>( + input: &'a str, +) -> IResult<&'a str, (i128, i128), E> { let (input, _tag) = tag("set")(input)?; let (input, _) = space1(input)?; let (input, _tag) = tag("of")(input)?; @@ -269,27 +309,27 @@ fn set_of_int_range<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a s let (input, _tag) = tag("..")(input)?; let (input, _) = space0(input)?; let (input, ub) = int_literal(input)?; - Ok((input, Domain::SetIntRange(lb, ub))) + Ok((input, (lb, ub))) } // "set" "of" "{" [ "," ... ] "}" -fn set_of_ints<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, Domain, E> { +fn subset_of_int_in_set<'a, E: ParseError<&'a str>>( + input: &'a str, +) -> IResult<&'a str, Vec, E> { let (input, _tag) = tag("set of {")(input)?; let (input, _) = space0(input)?; let (input, v) = separated_list(char(','), int_literal)(input)?; let (input, _) = space0(input)?; let (input, _tag) = tag("}")(input)?; - Ok((input, Domain::SetInt(v))) + Ok((input, v)) } // "{" "," ... "}" -fn set_of_ints_non_empty<'a, E: ParseError<&'a str>>( - input: &'a str, -) -> IResult<&'a str, Domain, E> { +fn int_in_set<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, Vec, E> { let (input, _) = char('{')(input)?; let (input, _) = space0(input)?; let (input, v) = separated_list(char(','), int_literal)(input)?; let (input, _) = space0(input)?; let (input, _) = char('}')(input)?; - Ok((input, Domain::SetIntNonEmpty(v))) + Ok((input, v)) } #[derive(PartialEq, Clone, Debug)] pub struct IndexSet(pub i128); @@ -303,12 +343,24 @@ fn index_set<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, i12 pub enum BasicPredParType { BasicParType(BasicParType), BasicVarType(BasicVarType), - Domain(Domain), + IntInRange(i128, i128), + IntInSet(Vec), // possibly empty + FloatInRange(f64, f64), + SetOfIntInSet(Vec), + SetOfIntInRange(i128, i128), } fn basic_pred_par_type<'a, E: ParseError<&'a str>>( input: &'a str, ) -> IResult<&'a str, BasicPredParType, E> { - let (input, bppt) = alt((bppt_basic_par_type, bppt_basic_var_type, bppt_domain))(input)?; + let (input, bppt) = alt(( + bppt_basic_par_type, + bppt_basic_var_type, + bppt_int_in_range, + bppt_int_in_set, + bppt_float_in_range, + bppt_subset_of_int_in_set, + bppt_subset_of_int_in_range, + ))(input)?; Ok((input, bppt)) } fn bppt_basic_par_type<'a, E: ParseError<&'a str>>( @@ -323,11 +375,35 @@ fn bppt_basic_var_type<'a, E: ParseError<&'a str>>( let (input, bvt) = basic_var_type(input)?; Ok((input, BasicPredParType::BasicVarType(bvt))) } -fn bppt_domain<'a, E: ParseError<&'a str>>( +fn bppt_int_in_range<'a, E: ParseError<&'a str>>( + input: &'a str, +) -> IResult<&'a str, BasicPredParType, E> { + let (input, (lb, ub)) = int_in_range(input)?; + Ok((input, BasicPredParType::IntInRange(lb, ub))) +} +fn bppt_int_in_set<'a, E: ParseError<&'a str>>( + input: &'a str, +) -> IResult<&'a str, BasicPredParType, E> { + let (input, set) = int_in_set(input)?; + Ok((input, BasicPredParType::IntInSet(set))) +} +fn bppt_float_in_range<'a, E: ParseError<&'a str>>( input: &'a str, ) -> IResult<&'a str, BasicPredParType, E> { - let (input, domain) = domain(input)?; - Ok((input, BasicPredParType::Domain(domain))) + let (input, (lb, ub)) = float_in_range(input)?; + Ok((input, BasicPredParType::FloatInRange(lb, ub))) +} +fn bppt_subset_of_int_in_range<'a, E: ParseError<&'a str>>( + input: &'a str, +) -> IResult<&'a str, BasicPredParType, E> { + let (input, (lb, ub)) = subset_of_int_in_range(input)?; + Ok((input, BasicPredParType::SetOfIntInRange(lb, ub))) +} +fn bppt_subset_of_int_in_set<'a, E: ParseError<&'a str>>( + input: &'a str, +) -> IResult<&'a str, BasicPredParType, E> { + let (input, set) = subset_of_int_in_set(input)?; + Ok((input, BasicPredParType::SetOfIntInSet(set))) } #[derive(PartialEq, Clone, Debug)] pub enum PredParType { @@ -382,121 +458,190 @@ fn pis_index_set<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, Ok((input, PredIndexSet::IndexSet(int))) } #[derive(PartialEq, Clone, Debug)] -pub enum BasicLiteralExpr { +pub enum BoolExpr { Bool(bool), - Int(i128), - Float(f64), - Set(SetLiteral), + VarParIdentifier(String), } -fn basic_literal_expr<'a, E: ParseError<&'a str>>( - input: &'a str, -) -> IResult<&'a str, BasicLiteralExpr, E> { - let (input, ble) = alt(( - ble_bool_literal, - ble_set_literal, - ble_float_literal, - ble_int_literal, - ))(input)?; - Ok((input, ble)) +fn bool_expr<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, BoolExpr, E> { + let (input, expr) = alt((be_bool_literal, be_var_par_identifier))(input)?; + Ok((input, expr)) } -fn ble_bool_literal<'a, E: ParseError<&'a str>>( - input: &'a str, -) -> IResult<&'a str, BasicLiteralExpr, E> { - let (input, bl) = bool_literal(input)?; - Ok((input, BasicLiteralExpr::Bool(bl))) +fn be_bool_literal<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, BoolExpr, E> { + let (input, expr) = bool_literal(input)?; + Ok((input, BoolExpr::Bool(expr))) } -fn ble_int_literal<'a, E: ParseError<&'a str>>( +fn be_var_par_identifier<'a, E: ParseError<&'a str>>( input: &'a str, -) -> IResult<&'a str, BasicLiteralExpr, E> { - let (input, int) = int_literal(input)?; - Ok((input, BasicLiteralExpr::Int(int))) +) -> IResult<&'a str, BoolExpr, E> { + let (input, id) = var_par_identifier(input)?; + Ok((input, BoolExpr::VarParIdentifier(id))) } -fn ble_float_literal<'a, E: ParseError<&'a str>>( - input: &'a str, -) -> IResult<&'a str, BasicLiteralExpr, E> { - let (input, float) = float_literal(input)?; - Ok((input, BasicLiteralExpr::Float(float))) +#[derive(PartialEq, Clone, Debug)] +pub enum IntExpr { + Int(i128), + VarParIdentifier(String), +} +fn int_expr<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, IntExpr, E> { + let (input, _) = space0(input)?; + let (input, expr) = alt((ie_int_literal, ie_var_par_identifier))(input)?; + Ok((input, expr)) } -fn ble_set_literal<'a, E: ParseError<&'a str>>( +fn ie_int_literal<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, IntExpr, E> { + let (input, expr) = int_literal(input)?; + Ok((input, IntExpr::Int(expr))) +} +fn ie_var_par_identifier<'a, E: ParseError<&'a str>>( input: &'a str, -) -> IResult<&'a str, BasicLiteralExpr, E> { - let (input, sl) = set_literal(input)?; - Ok((input, BasicLiteralExpr::Set(sl))) +) -> IResult<&'a str, IntExpr, E> { + let (input, id) = var_par_identifier(input)?; + Ok((input, IntExpr::VarParIdentifier(id))) } - #[derive(PartialEq, Clone, Debug)] -pub enum BasicExpr { - BasicLiteralExpr(BasicLiteralExpr), +pub enum FloatExpr { + Float(f64), VarParIdentifier(String), } -fn basic_expr<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, BasicExpr, E> { - let (input, expr) = alt((be_basic_literal_expr, be_var_par_identifier))(input)?; +fn float_expr<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, FloatExpr, E> { + let (input, expr) = alt((fe_float_literal, fe_var_par_identifier))(input)?; Ok((input, expr)) } -fn be_basic_literal_expr<'a, E: ParseError<&'a str>>( +fn fe_float_literal<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, FloatExpr, E> { + let (input, expr) = float_literal(input)?; + Ok((input, FloatExpr::Float(expr))) +} +fn fe_var_par_identifier<'a, E: ParseError<&'a str>>( input: &'a str, -) -> IResult<&'a str, BasicExpr, E> { - let (input, expr) = basic_literal_expr(input)?; - Ok((input, BasicExpr::BasicLiteralExpr(expr))) +) -> IResult<&'a str, FloatExpr, E> { + let (input, id) = var_par_identifier(input)?; + Ok((input, FloatExpr::VarParIdentifier(id))) } -fn be_var_par_identifier<'a, E: ParseError<&'a str>>( +#[derive(PartialEq, Clone, Debug)] +pub enum SetExpr { + Set(SetLiteral), + VarParIdentifier(String), +} +fn set_expr<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, SetExpr, E> { + let (input, expr) = alt((se_set_literal, se_var_par_identifier))(input)?; + Ok((input, expr)) +} +fn se_set_literal<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, SetExpr, E> { + let (input, expr) = set_literal(input)?; + Ok((input, SetExpr::Set(expr))) +} +fn se_var_par_identifier<'a, E: ParseError<&'a str>>( input: &'a str, -) -> IResult<&'a str, BasicExpr, E> { +) -> IResult<&'a str, SetExpr, E> { let (input, id) = var_par_identifier(input)?; - Ok((input, BasicExpr::VarParIdentifier(id))) + Ok((input, SetExpr::VarParIdentifier(id))) +} +#[test] +fn test_expr() { + use nom::error::VerboseError; + assert_eq!( + expr::>("1..2"), + Ok(("", Expr::Set(SetLiteral::IntRange(1, 2)))) + ); } - #[derive(PartialEq, Clone, Debug)] pub enum Expr { - BasicExpr(BasicExpr), - ArrayLiteral(ArrayLiteral), + VarParIdentifier(String), + Bool(bool), + Int(i128), + Float(f64), + Set(SetLiteral), + ArrayOfBool(Vec), + ArrayOfInt(Vec), + ArrayOfFloat(Vec), + ArrayOfSet(Vec), } fn expr<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, Expr, E> { - let (input, expr) = alt((e_basic_expr, e_array_literal))(input)?; + let (input, _) = space0(input)?; + let (input, expr) = alt(( + e_var_par_identifier, + e_bool_literal, + e_set_literal, + e_float_literal, + e_int_literal, + e_array_of_bool_expr, + e_array_of_int_expr, + e_array_of_float_expr, + e_array_of_set_expr, + ))(input)?; Ok((input, expr)) } -fn e_basic_expr<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, Expr, E> { - let (input, basic_expr) = basic_expr(input)?; - Ok((input, Expr::BasicExpr(basic_expr))) +fn e_var_par_identifier<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, Expr, E> { + let (input, id) = var_par_identifier(input)?; + Ok((input, Expr::VarParIdentifier(id))) } -fn e_array_literal<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, Expr, E> { - let (input, array_literal) = array_literal(input)?; - Ok((input, Expr::ArrayLiteral(array_literal))) +fn e_bool_literal<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, Expr, E> { + let (input, b) = bool_literal(input)?; + Ok((input, Expr::Bool(b))) } -#[derive(PartialEq, Clone, Debug)] -pub enum ParExpr { - BasicLiteralExpr(BasicLiteralExpr), - ParArrayLiteral(ParArrayLiteral), +fn e_int_literal<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, Expr, E> { + let (input, int) = int_literal(input)?; + Ok((input, Expr::Int(int))) } -fn par_expr<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, ParExpr, E> { - let (input, expr) = alt((pe_basic_literal_expr, pe_par_array_literal))(input)?; - Ok((input, expr)) +fn e_float_literal<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, Expr, E> { + let (input, float) = float_literal(input)?; + Ok((input, Expr::Float(float))) } -fn pe_basic_literal_expr<'a, E: ParseError<&'a str>>( - input: &'a str, -) -> IResult<&'a str, ParExpr, E> { - let (input, expr) = basic_literal_expr(input)?; - Ok((input, ParExpr::BasicLiteralExpr(expr))) +fn e_set_literal<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, Expr, E> { + let (input, sl) = set_literal(input)?; + Ok((input, Expr::Set(sl))) } -fn pe_par_array_literal<'a, E: ParseError<&'a str>>( - input: &'a str, -) -> IResult<&'a str, ParExpr, E> { - let (input, expr) = par_array_literal(input)?; - Ok((input, ParExpr::ParArrayLiteral(expr))) +fn e_array_of_bool_expr<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, Expr, E> { + let (input, array_literal) = array_of_bool_expr(input)?; + Ok((input, Expr::ArrayOfBool(array_literal))) +} +fn e_array_of_int_expr<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, Expr, E> { + let (input, array_literal) = array_of_int_expr(input)?; + Ok((input, Expr::ArrayOfInt(array_literal))) +} +fn e_array_of_float_expr<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, Expr, E> { + let (input, array_literal) = array_of_float_expr(input)?; + Ok((input, Expr::ArrayOfFloat(array_literal))) +} +fn e_array_of_set_expr<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, Expr, E> { + let (input, array_literal) = array_of_set_expr(input)?; + Ok((input, Expr::ArrayOfSet(array_literal))) } - #[derive(PartialEq, Clone, Debug)] pub enum ParDeclItem { - Basic { - par_type: BasicParType, + Bool { id: String, - expr: ParExpr, + bool: bool, }, - Array { + Int { + id: String, + int: i128, + }, + Float { + id: String, + float: f64, + }, + SetOfInt { + id: String, + set_literal: SetLiteral, + }, + ArrayOfBool { ix: IndexSet, - par_type: BasicParType, id: String, - expr: ParExpr, + expr: Vec, + }, + ArrayOfInt { + ix: IndexSet, + id: String, + expr: Vec, + }, + ArrayOfFloat { + ix: IndexSet, + id: String, + expr: Vec, + }, + ArrayOfSet { + ix: IndexSet, + id: String, + expr: Vec, }, } #[test] @@ -506,15 +651,10 @@ fn test_par_decl_item() { par_decl_item::>("array [1..3] of float: X_139 = [1.0,1.0,1.0];"), Ok(( "", - ParDeclItem::Array { + ParDeclItem::ArrayOfFloat { ix: IndexSet(3), - par_type: BasicParType::Float, id: "X_139".to_string(), - expr: ParExpr::ParArrayLiteral(vec![ - BasicLiteralExpr::Float(1.0), - BasicLiteralExpr::Float(1.0), - BasicLiteralExpr::Float(1.0) - ]) + expr: vec![1.0, 1.0, 1.0] } )) ); @@ -537,38 +677,59 @@ pub fn par_decl_item<'a, E: ParseError<&'a str>>( let (input, _) = space0(input)?; let (input, _) = char('=')(input)?; let (input, _) = space0(input)?; - let (input, expr) = par_expr(input)?; - let (input, _) = space0(input)?; - let (input, _) = char(';')(input)?; match ptype { - ParType::Array { ix, par_type } => Ok(( - input, - ParDeclItem::Array { - ix, - par_type, - id, - expr, - }, - )), - ParType::Basic(par_type) => Ok((input, ParDeclItem::Basic { par_type, id, expr })), + ParType::Array { ix, par_type } => match par_type { + BasicParType::Bool => { + let (input, expr) = array_of_bool_literal(input)?; + let (input, _) = space0(input)?; + let (input, _) = char(';')(input)?; + Ok((input, ParDeclItem::ArrayOfBool { ix, id, expr })) + } + BasicParType::Int => { + let (input, expr) = array_of_int_literal(input)?; + let (input, _) = space0(input)?; + let (input, _) = char(';')(input)?; + Ok((input, ParDeclItem::ArrayOfInt { ix, id, expr })) + } + BasicParType::Float => { + let (input, expr) = array_of_float_literal(input)?; + let (input, _) = space0(input)?; + let (input, _) = char(';')(input)?; + Ok((input, ParDeclItem::ArrayOfFloat { ix, id, expr })) + } + BasicParType::SetOfInt => { + let (input, expr) = array_of_set_literal(input)?; + let (input, _) = space0(input)?; + let (input, _) = char(';')(input)?; + Ok((input, ParDeclItem::ArrayOfSet { ix, id, expr })) + } + }, + ParType::Bool => { + let (input, bool) = bool_literal(input)?; + let (input, _) = space0(input)?; + let (input, _) = char(';')(input)?; + Ok((input, ParDeclItem::Bool { id, bool })) + } + ParType::Int => { + let (input, int) = int_literal(input)?; + let (input, _) = space0(input)?; + let (input, _) = char(';')(input)?; + Ok((input, ParDeclItem::Int { id, int })) + } + ParType::Float => { + let (input, float) = float_literal(input)?; + let (input, _) = space0(input)?; + let (input, _) = char(';')(input)?; + Ok((input, ParDeclItem::Float { id, float })) + } + ParType::SetOfInt => { + let (input, set_literal) = set_literal(input)?; + let (input, _) = space0(input)?; + let (input, _) = char(';')(input)?; + Ok((input, ParDeclItem::SetOfInt { id, set_literal })) + } } } -#[derive(PartialEq, Clone, Debug)] -pub enum VarDeclItem { - Basic { - var_type: BasicVarType, - id: String, - annos: Annotations, - expr: Option, - }, - Array { - ix: IndexSet, - var_type: BasicVarType, - id: String, - annos: Annotations, - array_literal: ArrayLiteral, - }, -} #[test] fn test_var_decl_item() { use nom::error::VerboseError; @@ -578,19 +739,16 @@ fn test_var_decl_item() { ), Ok(( "", - VarDeclItem::Array { + VarDeclItem::ArrayOfSet { ix: IndexSet(1), - var_type: BasicVarType::SetOfInt, id: "sets".to_string(), annos: vec![Annotation::Id { id: "output_array".to_string(), - expressions: vec![AnnExpr::Expr(Expr::ArrayLiteral(vec![ - BasicExpr::BasicLiteralExpr(BasicLiteralExpr::Set(SetLiteral::IntRange( - 1, 1 - ))) - ]))] + expressions: vec![AnnExpr::Expr(Expr::ArrayOfSet(vec![SetExpr::Set( + SetLiteral::IntRange(1, 1) + )]))] }], - array_literal: vec![BasicExpr::VarParIdentifier("X_0".to_owned())] + array_literal: vec![SetExpr::VarParIdentifier("X_0".to_owned())] } )) ); @@ -598,16 +756,148 @@ fn test_var_decl_item() { var_decl_item::>("array[1..5] of var 0..3: w;"), Ok(( "", - VarDeclItem::Array { - ix: IndexSet(5), - var_type: BasicVarType::Domain(Domain::IntRange(0, 3)), + VarDeclItem::ArrayOfIntInRange { id: "w".to_string(), + ix: IndexSet(5), + lb: 0, + ub: 3, + array_literal: vec![], + annos: vec![], + } + )) + ); + assert_eq!( + var_decl_item::>("var 1..101: objective = X_2586;"), + Ok(( + "", + VarDeclItem::IntInRange { + id: "objective".to_string(), + lb: 1, + ub: 101, + int: Some(IntExpr::VarParIdentifier("X_2586".to_string())), annos: vec![], - array_literal: vec![] } )) ); } +#[derive(PartialEq, Clone, Debug)] +pub enum VarDeclItem { + Bool { + id: String, + expr: Option, + annos: Annotations, + }, + Int { + id: String, + expr: Option, + annos: Annotations, + }, + Float { + id: String, + expr: Option, + annos: Annotations, + }, + IntInRange { + id: String, + lb: i128, + ub: i128, + int: Option, + annos: Annotations, + }, + IntInSet { + id: String, + set: Vec, // possibly empty + int: Option, + annos: Annotations, + }, + FloatInRange { + id: String, + lb: f64, + ub: f64, + float: Option, + annos: Annotations, + }, + SetOfInt { + id: String, + expr: Option, + annos: Annotations, + }, + SetOfIntInSet { + id: String, + set: Vec, + expr: Option, + annos: Annotations, + }, + SetOfIntInRange { + id: String, + lb: i128, + ub: i128, + expr: Option, + annos: Annotations, + }, + ArrayOfBool { + ix: IndexSet, + id: String, + annos: Annotations, + array_literal: Vec, + }, + ArrayOfInt { + ix: IndexSet, + id: String, + annos: Annotations, + array_literal: Vec, + }, + ArrayOfIntInRange { + lb: i128, + ub: i128, + ix: IndexSet, + id: String, + annos: Annotations, + array_literal: Vec, + }, + ArrayOfIntInSet { + set: Vec, + ix: IndexSet, + id: String, + annos: Annotations, + array_literal: Vec, + }, + ArrayOfFloat { + ix: IndexSet, + id: String, + annos: Annotations, + array_literal: Vec, + }, + ArrayOfFloatInRange { + lb: f64, + ub: f64, + ix: IndexSet, + id: String, + annos: Annotations, + array_literal: Vec, + }, + ArrayOfSet { + ix: IndexSet, + id: String, + annos: Annotations, + array_literal: Vec, + }, + ArrayOfSetOfIntInRange { + ub: i128, + lb: i128, + ix: IndexSet, + id: String, + annos: Annotations, + array_literal: Vec, + }, + ArrayOfSetOfIntInSet { + set: Vec, + ix: IndexSet, + id: String, + annos: Annotations, + array_literal: Vec, + }, +} fn var_decl_item_ln<'a, E: ParseError<&'a str>>( input: &'a str, ) -> IResult<&'a str, VarDeclItem, E> { @@ -619,12 +909,19 @@ fn var_decl_item_ln<'a, E: ParseError<&'a str>>( pub fn var_decl_item<'a, E: ParseError<&'a str>>( input: &'a str, ) -> IResult<&'a str, VarDeclItem, E> { - let (input, item) = alt((vdi_basic_var, vdi_array))(input)?; + let (input, item) = alt(( + vdi_basic_var_with_assignment, + vdi_basic_var_without_assignment, + vdi_array_with_assignment, + vdi_array_without_assignment, + ))(input)?; let (input, _tag) = space0(input)?; let (input, _) = char(';')(input)?; Ok((input, item)) } -fn vdi_basic_var<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, VarDeclItem, E> { +fn vdi_basic_var_with_assignment<'a, E: ParseError<&'a str>>( + input: &'a str, +) -> IResult<&'a str, VarDeclItem, E> { let (input, var_type) = basic_var_type(input)?; let (input, _) = space0(input)?; let (input, _) = char(':')(input)?; @@ -633,32 +930,216 @@ fn vdi_basic_var<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, let (input, _) = space0(input)?; let (input, annos) = annotations(input)?; let (input, _) = space0(input)?; - let (input, assign) = opt(char('='))(input)?; - if assign.is_some() { - let (input, _) = space0(input)?; - let (input, expr) = opt(basic_expr)(input)?; - Ok(( + let (input, _) = char('=')(input)?; + let (input, _) = space0(input)?; + match var_type { + BasicVarType::Bool => { + let (input, bool) = bool_expr(input)?; + Ok(( + input, + VarDeclItem::Bool { + id, + annos, + expr: Some(bool), + }, + )) + } + BasicVarType::Int => { + let (input, int) = int_expr(input)?; + Ok(( + input, + VarDeclItem::Int { + id, + annos, + expr: Some(int), + }, + )) + } + BasicVarType::Float => { + let (input, float) = float_expr(input)?; + Ok(( + input, + VarDeclItem::Float { + id, + annos, + expr: Some(float), + }, + )) + } + BasicVarType::SetOfInt => { + let (input, sl) = set_expr(input)?; + Ok(( + input, + VarDeclItem::SetOfInt { + id, + annos, + expr: Some(sl), + }, + )) + } + BasicVarType::IntInRange(lb, ub) => { + let (input, int) = int_expr(input)?; + Ok(( + input, + VarDeclItem::IntInRange { + id, + lb, + ub, + int: Some(int), + annos, + }, + )) + } + BasicVarType::IntInSet(set) => { + let (input, int) = int_expr(input)?; + Ok(( + input, + VarDeclItem::IntInSet { + id, + set, + int: Some(int), + annos, + }, + )) + } + BasicVarType::FloatInRange(lb, ub) => { + let (input, float) = float_expr(input)?; + Ok(( + input, + VarDeclItem::FloatInRange { + id, + lb, + ub, + float: Some(float), + annos, + }, + )) + } + BasicVarType::SetOfIntInRange(lb, ub) => { + let (input, sl) = set_expr(input)?; + Ok(( + input, + VarDeclItem::SetOfIntInRange { + id, + lb, + ub, + expr: Some(sl), + annos, + }, + )) + } + BasicVarType::SetOfIntInSet(set) => { + let (input, sl) = set_expr(input)?; + Ok(( + input, + VarDeclItem::SetOfIntInSet { + id, + set, + expr: Some(sl), + annos, + }, + )) + } + } +} +fn vdi_basic_var_without_assignment<'a, E: ParseError<&'a str>>( + input: &'a str, +) -> IResult<&'a str, VarDeclItem, E> { + let (input, var_type) = basic_var_type(input)?; + let (input, _) = space0(input)?; + let (input, _) = char(':')(input)?; + let (input, _) = space0(input)?; + let (input, id) = var_par_identifier(input)?; + let (input, _) = space0(input)?; + let (input, annos) = annotations(input)?; + let (input, _) = space0(input)?; + match var_type { + BasicVarType::Bool => Ok(( input, - VarDeclItem::Basic { - var_type, + VarDeclItem::Bool { id, annos, - expr, + expr: None, }, - )) - } else { - Ok(( + )), + BasicVarType::Int => Ok(( input, - VarDeclItem::Basic { - var_type, + VarDeclItem::Int { id, annos, expr: None, }, - )) + )), + BasicVarType::Float => Ok(( + input, + VarDeclItem::Float { + id, + annos, + expr: None, + }, + )), + BasicVarType::SetOfInt => Ok(( + input, + VarDeclItem::SetOfInt { + id, + expr: None, + annos, + }, + )), + BasicVarType::IntInRange(lb, ub) => Ok(( + input, + VarDeclItem::IntInRange { + id, + lb, + ub, + int: None, + annos, + }, + )), + BasicVarType::IntInSet(set) => Ok(( + input, + VarDeclItem::IntInSet { + id, + set, + int: None, + annos, + }, + )), + BasicVarType::FloatInRange(lb, ub) => Ok(( + input, + VarDeclItem::FloatInRange { + id, + lb, + ub, + float: None, + annos, + }, + )), + BasicVarType::SetOfIntInRange(lb, ub) => Ok(( + input, + VarDeclItem::SetOfIntInRange { + id, + lb, + ub, + expr: None, + annos, + }, + )), + BasicVarType::SetOfIntInSet(set) => Ok(( + input, + VarDeclItem::SetOfIntInSet { + id, + set, + expr: None, + annos, + }, + )), } } -fn vdi_array<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, VarDeclItem, E> { + +fn vdi_array_with_assignment<'a, E: ParseError<&'a str>>( + input: &'a str, +) -> IResult<&'a str, VarDeclItem, E> { // let (input, avt) = array_var_type(input)?; let (input, _tag) = tag("array")(input)?; @@ -680,33 +1161,329 @@ fn vdi_array<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, Var let (input, _) = space0(input)?; let (input, annos) = annotations(input)?; let (input, _) = space0(input)?; - let (input, assign) = opt(char('='))(input)?; - if assign.is_some() { - let (input, _) = space0(input)?; - let (input, array_literal) = array_literal(input)?; - Ok(( + let (input, _) = char('=')(input)?; + let (input, _) = space0(input)?; + match var_type { + BasicVarType::Bool => { + let (input, array_literal) = array_of_bool_expr(input)?; + Ok(( + input, + VarDeclItem::ArrayOfBool { + ix: IndexSet(int), + id, + annos, + array_literal, + }, + )) + } + BasicVarType::Int => { + let (input, array_literal) = array_of_int_expr(input)?; + Ok(( + input, + VarDeclItem::ArrayOfInt { + ix: IndexSet(int), + id, + annos, + array_literal, + }, + )) + } + BasicVarType::Float => { + let (input, array_literal) = array_of_float_expr(input)?; + Ok(( + input, + VarDeclItem::ArrayOfFloat { + ix: IndexSet(int), + id, + annos, + array_literal, + }, + )) + } + BasicVarType::SetOfInt => { + let (input, array_literal) = array_of_set_expr(input)?; + Ok(( + input, + VarDeclItem::ArrayOfSet { + ix: IndexSet(int), + id, + annos, + array_literal, + }, + )) + } + BasicVarType::IntInRange(lb, ub) => { + let (input, array_literal) = array_of_int_expr(input)?; + Ok(( + input, + VarDeclItem::ArrayOfIntInRange { + lb, + ub, + ix: IndexSet(int), + id, + annos, + array_literal, + }, + )) + } + BasicVarType::IntInSet(set) => { + let (input, array_literal) = array_of_int_expr(input)?; + Ok(( + input, + VarDeclItem::ArrayOfIntInSet { + set, + ix: IndexSet(int), + id, + annos, + array_literal, + }, + )) + } + BasicVarType::FloatInRange(lb, ub) => { + let (input, array_literal) = array_of_float_expr(input)?; + Ok(( + input, + VarDeclItem::ArrayOfFloatInRange { + lb, + ub, + ix: IndexSet(int), + id, + annos, + array_literal, + }, + )) + } + BasicVarType::SetOfIntInRange(lb, ub) => { + let (input, array_literal) = array_of_set_expr(input)?; + Ok(( + input, + VarDeclItem::ArrayOfSetOfIntInRange { + lb, + ub, + ix: IndexSet(int), + id, + annos, + array_literal, + }, + )) + } + BasicVarType::SetOfIntInSet(set) => { + let (input, array_literal) = array_of_set_expr(input)?; + Ok(( + input, + VarDeclItem::ArrayOfSetOfIntInSet { + set, + ix: IndexSet(int), + id, + annos, + array_literal, + }, + )) + } + } +} +fn vdi_array_without_assignment<'a, E: ParseError<&'a str>>( + input: &'a str, +) -> IResult<&'a str, VarDeclItem, E> { + // let (input, avt) = array_var_type(input)?; + + let (input, _tag) = tag("array")(input)?; + let (input, _) = space0(input)?; + let (input, _) = char('[')(input)?; + let (input, _) = space0(input)?; + let (input, int) = index_set(input)?; + let (input, _) = space0(input)?; + let (input, _) = char(']')(input)?; + let (input, _) = space1(input)?; + let (input, _tag) = tag("of")(input)?; + let (input, _) = space1(input)?; + let (input, var_type) = basic_var_type(input)?; + + let (input, _) = space0(input)?; + let (input, _) = char(':')(input)?; + let (input, _) = space0(input)?; + let (input, id) = var_par_identifier(input)?; + let (input, _) = space0(input)?; + let (input, annos) = annotations(input)?; + let (input, _) = space0(input)?; + match var_type { + BasicVarType::Bool => Ok(( input, - VarDeclItem::Array { + VarDeclItem::ArrayOfBool { ix: IndexSet(int), - var_type, id, annos, - array_literal, + array_literal: vec![], }, - )) - } else { - Ok(( + )), + BasicVarType::Int => Ok(( input, - VarDeclItem::Array { + VarDeclItem::ArrayOfInt { ix: IndexSet(int), - var_type, id, annos, array_literal: vec![], }, - )) + )), + BasicVarType::Float => Ok(( + input, + VarDeclItem::ArrayOfFloat { + ix: IndexSet(int), + id, + annos, + array_literal: vec![], + }, + )), + BasicVarType::SetOfInt => Ok(( + input, + VarDeclItem::ArrayOfSet { + ix: IndexSet(int), + id, + annos, + array_literal: vec![], + }, + )), + BasicVarType::IntInRange(lb, ub) => Ok(( + input, + VarDeclItem::ArrayOfIntInRange { + lb, + ub, + ix: IndexSet(int), + id, + annos, + array_literal: vec![], + }, + )), + BasicVarType::IntInSet(set) => Ok(( + input, + VarDeclItem::ArrayOfIntInSet { + set, + ix: IndexSet(int), + id, + annos, + array_literal: vec![], + }, + )), + BasicVarType::FloatInRange(lb, ub) => Ok(( + input, + VarDeclItem::ArrayOfFloatInRange { + lb, + ub, + ix: IndexSet(int), + id, + annos, + array_literal: vec![], + }, + )), + BasicVarType::SetOfIntInRange(lb, ub) => Ok(( + input, + VarDeclItem::ArrayOfSetOfIntInRange { + lb, + ub, + ix: IndexSet(int), + id, + annos, + array_literal: vec![], + }, + )), + BasicVarType::SetOfIntInSet(set) => Ok(( + input, + VarDeclItem::ArrayOfSetOfIntInSet { + set, + ix: IndexSet(int), + id, + annos, + array_literal: vec![], + }, + )), } } +#[test] +fn test_constraint_item() { + use nom::error::VerboseError; + assert_eq!( + constraint_item::>( + "constraint set_in_reif(X_26,1..2,X_52):: defines_var(X_52);" + ), + Ok(( + "", + ConstraintItem { + id: "set_in_reif".to_string(), + exprs: vec![ + Expr::VarParIdentifier("X_26".to_string()), + Expr::Set(SetLiteral::IntRange(1, 2)), + Expr::VarParIdentifier("X_52".to_string()) + ], + annos: vec![Annotation::Id { + id: "defines_var".to_string(), + expressions: vec![AnnExpr::Expr(Expr::VarParIdentifier("X_52".to_string()))] + }] + } + )) + ); + assert_eq!( + constraint_item::>("constraint array_var_int_element(INT01, w, 2);"), + Ok(( + "", + ConstraintItem { + id: "array_var_int_element".to_string(), + exprs: vec![ + Expr::VarParIdentifier("INT01".to_string()), + Expr::VarParIdentifier("w".to_string()), + Expr::Float(2.0) + ], + annos: vec![] + } + )) + ); +} +#[test] +fn test_constraint_item_2() { + use nom::error::VerboseError; + assert_eq!( + constraint_item::>("constraint int_lin_eq([-1, 1], [INT01, p], -3);"), + Ok(( + "", + ConstraintItem { + id: "int_lin_eq".to_string(), + exprs: vec![ + Expr::ArrayOfInt(vec![IntExpr::Int(-1), IntExpr::Int(1)]), + Expr::ArrayOfInt(vec![ + IntExpr::VarParIdentifier("INT01".to_string()), + IntExpr::VarParIdentifier("p".to_string()) + ]), + Expr::Float(-3.0) + ], + annos: vec![] + } + )) + ); +} +#[test] +fn test_constraint_item_3() { + use nom::error::VerboseError; + assert_eq!( + constraint_item::>( + "constraint float_lin_eq(X_139,[X_27,X_28,X_29],1.0);" + ), + Ok(( + "", + ConstraintItem { + id: "float_lin_eq".to_string(), + exprs: vec![ + Expr::VarParIdentifier("X_139".to_string()), + Expr::ArrayOfBool(vec![ + BoolExpr::VarParIdentifier("X_27".to_string()), + BoolExpr::VarParIdentifier("X_28".to_string()), + BoolExpr::VarParIdentifier("X_29".to_string()), + ]), + Expr::Float(1.0) + ], + annos: vec![] + } + )) + ); +} #[derive(PartialEq, Clone, Debug)] pub struct ConstraintItem { pub id: String, @@ -738,10 +1515,37 @@ pub fn constraint_item<'a, E: ParseError<&'a str>>( let (input, _) = char(';')(input)?; Ok((input, ConstraintItem { id, exprs, annos })) } +#[test] +fn test_solve_item() { + use nom::error::VerboseError; + assert_eq!( + solve_item::>( + "solve :: int_search(X_59,input_order,indomain_min,complete) minimize X_24;" + ), + Ok(( + "", + SolveItem { + goal: Goal::OptimizeBool( + OptimizationType::Minimize, + BoolExpr::VarParIdentifier("X_24".to_string()) + ), + annotations: vec![Annotation::Id { + id: "int_search".to_string(), + expressions: vec![ + AnnExpr::Expr(Expr::VarParIdentifier("X_59".to_string())), + AnnExpr::Expr(Expr::VarParIdentifier("input_order".to_string())), + AnnExpr::Expr(Expr::VarParIdentifier("indomain_min".to_string())), + AnnExpr::Expr(Expr::VarParIdentifier("complete".to_string())) + ] + }] + } + )) + ); +} #[derive(PartialEq, Clone, Debug)] pub struct SolveItem { - pub annotations: Annotations, pub goal: Goal, + pub annotations: Annotations, } fn solve_item_ln<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, SolveItem, E> { let (input, item) = solve_item(input)?; @@ -754,7 +1558,13 @@ pub fn solve_item<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str let (input, _) = space1(input)?; let (input, annotations) = annotations(input)?; let (input, _) = space0(input)?; - let (input, goal) = alt((satisfy, maximize, minimize))(input)?; + let (input, goal) = alt(( + satisfy, + optimize_bool, + optimize_int, + optimize_float, + optimize_set, + ))(input)?; let (input, _) = space0(input)?; let (input, _) = char(';')(input)?; Ok((input, SolveItem { annotations, goal })) @@ -762,24 +1572,54 @@ pub fn solve_item<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str #[derive(PartialEq, Clone, Debug)] pub enum Goal { Satisfy, - Minimize(BasicExpr), - Maximize(BasicExpr), + OptimizeBool(OptimizationType, BoolExpr), + OptimizeInt(OptimizationType, IntExpr), + OptimizeFloat(OptimizationType, FloatExpr), + OptimizeSet(OptimizationType, SetExpr), +} +#[derive(PartialEq, Clone, Debug)] +pub enum OptimizationType { + Minimize, + Maximize, } fn satisfy<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, Goal, E> { let (input, _) = tag("satisfy")(input)?; Ok((input, Goal::Satisfy)) } -fn maximize<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, Goal, E> { +fn opt_type<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, OptimizationType, E> { + alt((minimize, maximize))(input) +} +fn minimize<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, OptimizationType, E> { + let (input, _) = tag("minimize")(input)?; + Ok((input, OptimizationType::Minimize)) +} +fn maximize<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, OptimizationType, E> { let (input, _) = tag("maximize")(input)?; + Ok((input, OptimizationType::Maximize)) +} +fn optimize_bool<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, Goal, E> { + let (input, opt_type) = opt_type(input)?; let (input, _) = space1(input)?; - let (input, be) = basic_expr(input)?; - Ok((input, Goal::Maximize(be))) + let (input, be) = bool_expr(input)?; + Ok((input, Goal::OptimizeBool(opt_type, be))) } -fn minimize<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, Goal, E> { - let (input, _) = tag("minimize")(input)?; +fn optimize_int<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, Goal, E> { + let (input, opt_type) = opt_type(input)?; + let (input, _) = space1(input)?; + let (input, be) = int_expr(input)?; + Ok((input, Goal::OptimizeInt(opt_type, be))) +} +fn optimize_float<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, Goal, E> { + let (input, opt_type) = opt_type(input)?; + let (input, _) = space1(input)?; + let (input, be) = float_expr(input)?; + Ok((input, Goal::OptimizeFloat(opt_type, be))) +} +fn optimize_set<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, Goal, E> { + let (input, opt_type) = opt_type(input)?; let (input, _) = space1(input)?; - let (input, be) = basic_expr(input)?; - Ok((input, Goal::Minimize(be))) + let (input, be) = set_expr(input)?; + Ok((input, Goal::OptimizeSet(opt_type, be))) } type Annotations = Vec; fn annotations<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, Annotations, E> { @@ -824,8 +1664,6 @@ fn annotation<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, An )) } } -// := | -// better // ::= // | // | "[" "," ... "]" @@ -934,25 +1772,85 @@ fn sl_set_of_floats<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a s let (input, _) = char('}')(input)?; Ok((input, SetLiteral::SetFloats(v))) } -type ArrayLiteral = Vec; -fn array_literal<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, ArrayLiteral, E> { +fn array_of_bool_expr<'a, E: ParseError<&'a str>>( + input: &'a str, +) -> IResult<&'a str, Vec, E> { let (input, _) = char('[')(input)?; let (input, _) = space0(input)?; - let (input, al) = separated_list(char(','), basic_expr)(input)?; + let (input, al) = separated_list(char(','), bool_expr)(input)?; let (input, _) = space0(input)?; let (input, _) = char(']')(input)?; Ok((input, al)) } -type ParArrayLiteral = Vec; -fn par_array_literal<'a, E: ParseError<&'a str>>( +fn array_of_bool_literal<'a, E: ParseError<&'a str>>( input: &'a str, -) -> IResult<&'a str, ParArrayLiteral, E> { +) -> IResult<&'a str, Vec, E> { let (input, _) = char('[')(input)?; let (input, _) = space0(input)?; - let (input, v) = separated_list(char(','), basic_literal_expr)(input)?; + let (input, al) = separated_list(char(','), bool_literal)(input)?; let (input, _) = space0(input)?; let (input, _) = char(']')(input)?; - Ok((input, v)) + Ok((input, al)) +} +fn array_of_int_expr<'a, E: ParseError<&'a str>>( + input: &'a str, +) -> IResult<&'a str, Vec, E> { + let (input, _) = char('[')(input)?; + let (input, _) = space0(input)?; + let (input, al) = separated_list(char(','), int_expr)(input)?; + let (input, _) = space0(input)?; + let (input, _) = char(']')(input)?; + Ok((input, al)) +} +fn array_of_int_literal<'a, E: ParseError<&'a str>>( + input: &'a str, +) -> IResult<&'a str, Vec, E> { + let (input, _) = char('[')(input)?; + let (input, _) = space0(input)?; + let (input, al) = separated_list(char(','), int_literal)(input)?; + let (input, _) = space0(input)?; + let (input, _) = char(']')(input)?; + Ok((input, al)) +} +fn array_of_float_expr<'a, E: ParseError<&'a str>>( + input: &'a str, +) -> IResult<&'a str, Vec, E> { + let (input, _) = char('[')(input)?; + let (input, _) = space0(input)?; + let (input, al) = separated_list(char(','), float_expr)(input)?; + let (input, _) = space0(input)?; + let (input, _) = char(']')(input)?; + Ok((input, al)) +} +fn array_of_float_literal<'a, E: ParseError<&'a str>>( + input: &'a str, +) -> IResult<&'a str, Vec, E> { + let (input, _) = char('[')(input)?; + let (input, _) = space0(input)?; + let (input, al) = separated_list(char(','), float_literal)(input)?; + let (input, _) = space0(input)?; + let (input, _) = char(']')(input)?; + Ok((input, al)) +} +fn array_of_set_expr<'a, E: ParseError<&'a str>>( + input: &'a str, +) -> IResult<&'a str, Vec, E> { + let (input, _) = char('[')(input)?; + let (input, _) = space0(input)?; + let (input, al) = separated_list(char(','), set_expr)(input)?; + let (input, _) = space0(input)?; + let (input, _) = char(']')(input)?; + Ok((input, al)) +} +fn array_of_set_literal<'a, E: ParseError<&'a str>>( + input: &'a str, +) -> IResult<&'a str, Vec, E> { + let (input, _) = char('[')(input)?; + let (input, _) = space0(input)?; + let (input, al) = separated_list(char(','), set_literal)(input)?; + let (input, _) = space0(input)?; + let (input, _) = char(']')(input)?; + Ok((input, al)) } fn identifier<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, String, E> { let (input, first) = one_of("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")(input)?;