diff --git a/src/prototype/expression.rs b/src/prototype/expression.rs index 87aa708..b61dca8 100644 --- a/src/prototype/expression.rs +++ b/src/prototype/expression.rs @@ -8,8 +8,10 @@ use crate::{expect_closure_of, expect_opening, expect_opening_of, XmlReader}; pub enum Expression { Terminal(Proposition), Not(Box>), - And(Box>, Box>), - Or(Box>, Box>), + // And(Box>, Box>), + // Or(Box>, Box>), + And(Vec>), // cnf + Or(Vec>), // dnf Xor(Box>, Box>), Implies(Box>, Box>), } @@ -102,21 +104,80 @@ fn logical_from_xml, BR: BufRead>( expect_closure_of("apply", xml)?; // close *this* apply tag ie the one wrapping the op Ok(Expression::Not(Box::new(inner))) } - LogicOp::And | LogicOp::Or | LogicOp::Xor | LogicOp::Implies => { + LogicOp::Xor => { expect_opening_of("apply", xml)?; let inner_lhs = Expression::try_from_xml(xml)?; expect_opening_of("apply", xml)?; let inner_rhs = Expression::try_from_xml(xml)?; expect_closure_of("apply", xml)?; // close *this* apply tag ie the one wrapping the op - match op { - LogicOp::And => Ok(Expression::And(Box::new(inner_lhs), Box::new(inner_rhs))), - LogicOp::Or => Ok(Expression::Or(Box::new(inner_lhs), Box::new(inner_rhs))), - LogicOp::Xor => Ok(Expression::Xor(Box::new(inner_lhs), Box::new(inner_rhs))), - LogicOp::Implies => Ok(Expression::Implies( - Box::new(inner_lhs), - Box::new(inner_rhs), - )), - _ => unreachable!(), // because of the not + Ok(Expression::Xor(Box::new(inner_lhs), Box::new(inner_rhs))) + } + LogicOp::Implies => { + expect_opening_of("apply", xml)?; + let inner_lhs = Expression::try_from_xml(xml)?; + expect_opening_of("apply", xml)?; + let inner_rhs = Expression::try_from_xml(xml)?; + expect_closure_of("apply", xml)?; // close *this* apply tag ie the one wrapping the op + Ok(Expression::Implies( + Box::new(inner_lhs), + Box::new(inner_rhs), + )) + } + LogicOp::And => { + let cnf_items = get_cnf_or_dnf_items::(xml)?; + Ok(Expression::And(cnf_items)) + } + LogicOp::Or => { + let dnf_items = get_cnf_or_dnf_items::(xml)?; + Ok(Expression::Or(dnf_items)) + } + } +} + +// this could be probably done using process_list, but scuffed so better new fn +/// expects the xml reader to be set so that calling `next()` should encounter +/// either opening of `apply` (encountering the first element), or end of +/// `apply` (signaling the end of the cnf/dnf arguments (so empty cnf/dnf)) +fn get_cnf_or_dnf_items, BR: BufRead>( + xml: &mut XR, +) -> Result>, Box> { + let mut acc = Vec::>::new(); + + loop { + match xml.next() { + Ok(XmlEvent::Whitespace(_)) => { /* ignore */ } + Ok(XmlEvent::StartElement { name, .. }) => { + if name.local_name == "apply" { + acc.push(Expression::try_from_xml(xml)?); + continue; + } + + return Err(format!( + "expected opening of indented apply or closing of this cnf/dnf apply, got opening of {}", + name.local_name + ) + .into()); + } + Ok(XmlEvent::EndElement { name, .. }) => { + if name.local_name == "apply" { + return Ok(acc); + } + + return Err(format!( + "expected opening of indented apply or closing of this cnf/dnf apply, got closing of {}", + name.local_name + ) + .into()); + } + Ok(XmlEvent::EndDocument) => { + return Err("unexpected end of document".into()); + } + other => { + return Err(format!( + "expected either opening of indented apply or closing of this cnf/dnf apply, got {:?}", + other + ) + .into()); } } } diff --git a/src/prototype/system_update_fn.rs b/src/prototype/system_update_fn.rs index 6adbee4..f3e3c1e 100644 --- a/src/prototype/system_update_fn.rs +++ b/src/prototype/system_update_fn.rs @@ -16,7 +16,6 @@ impl SystemUpdateFn { _xml: &mut XR, ) -> Result> { let var_names_and_upd_fns = load_all_update_fns(_xml)?; - println!("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); let ctx = vars_and_their_max_values(&var_names_and_upd_fns); var_names_and_upd_fns.iter().for_each(|(var_name, upd_fn)| { @@ -91,10 +90,10 @@ mod tests { fn test() { let file = std::fs::File::open("data/dataset.sbml").expect("cannot open file"); let br = std::io::BufReader::new(file); - let event_reader = xml::reader::EventReader::new(br); - let mut loud = LoudReader::new(event_reader); + let mut reader = xml::reader::EventReader::new(br); + // let mut reader = LoudReader::new(reader); // uncomment to see how xml is loaded - crate::find_start_of(&mut loud, "listOfTransitions").expect("cannot find start of list"); - let _system_update_fn = super::SystemUpdateFn::try_from_xml(&mut loud).unwrap(); + crate::find_start_of(&mut reader, "listOfTransitions").expect("cannot find start of list"); + let _system_update_fn = super::SystemUpdateFn::try_from_xml(&mut reader).unwrap(); } } diff --git a/src/prototype/update_fn.rs b/src/prototype/update_fn.rs index 9aef349..b1a4bf5 100644 --- a/src/prototype/update_fn.rs +++ b/src/prototype/update_fn.rs @@ -53,7 +53,7 @@ impl UpdateFn { .into()); } - // // listOfInputs might not be present at all + // listOfInputs might not be present at all let input_vars_names = if some_start_element.name.local_name == "listOfInputs" { let aux = process_list("listOfInputs", "input", process_input_var_name_item, xml)?; expect_opening_of("listOfOutputs", xml)?; // must be followed by listOfOutputs diff --git a/src/prototype/update_fn_bdd.rs b/src/prototype/update_fn_bdd.rs index 161752e..c4c182e 100644 --- a/src/prototype/update_fn_bdd.rs +++ b/src/prototype/update_fn_bdd.rs @@ -107,16 +107,12 @@ fn bdd_from_expr>( let bdd = bdd_from_expr(expr, symbolic_domains, bdd_variable_set); bdd.not() } - Expression::And(lhs, rhs) => { - let lhs = bdd_from_expr(lhs, symbolic_domains, bdd_variable_set); - let rhs = bdd_from_expr(rhs, symbolic_domains, bdd_variable_set); - lhs.and(&rhs) - } - Expression::Or(lhs, rhs) => { - let lhs = bdd_from_expr(lhs, symbolic_domains, bdd_variable_set); - let rhs = bdd_from_expr(rhs, symbolic_domains, bdd_variable_set); - lhs.or(&rhs) - } + Expression::And(clauses) => clauses.iter().fold(bdd_variable_set.mk_true(), |acc, it| { + acc.and(&bdd_from_expr(it, symbolic_domains, bdd_variable_set)) + }), + Expression::Or(clauses) => clauses.iter().fold(bdd_variable_set.mk_false(), |acc, it| { + acc.or(&bdd_from_expr(it, symbolic_domains, bdd_variable_set)) + }), Expression::Xor(lhs, rhs) => { let lhs = bdd_from_expr(lhs, symbolic_domains, bdd_variable_set); let rhs = bdd_from_expr(rhs, symbolic_domains, bdd_variable_set); diff --git a/src/prototype/utils.rs b/src/prototype/utils.rs index 9ab631c..d83b439 100644 --- a/src/prototype/utils.rs +++ b/src/prototype/utils.rs @@ -117,8 +117,6 @@ where loop { let elem = xml.next(); - println!("elem: {:?}", elem); - match elem { Ok(XmlEvent::Whitespace(_)) => { /* ignore */ } Ok(XmlEvent::StartElement {