Skip to content

Commit

Permalink
refactor: xml parsing works
Browse files Browse the repository at this point in the history
  • Loading branch information
Lukáš Chudíček committed Dec 9, 2023
1 parent 722e57e commit 0e0eced
Show file tree
Hide file tree
Showing 5 changed files with 351 additions and 17 deletions.
219 changes: 219 additions & 0 deletions src/update/update_fn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -798,3 +798,222 @@ pub mod variable_update_fn {
}
}
}

#[cfg(test)]
mod tests {
use std::str::FromStr;

use crate::{
symbolic_domains::symbolic_domain::UnaryIntegerDomain,
system::variable_update_function::UnprocessedVariableUpdateFn,
update::update_fn::{SmartSystemUpdateFn, SystemUpdateFn},
xml_parsing::{self, variable_update_fn_parser::load_from_sbml_buf_reader},
};

#[test]
fn basic_variable_update_fn() {
let xd = get_test_update_fn::<u8>();
let xdd = xd.target_var_name;
println!("xdd = {:?}", xdd);
}

/// get the update fn from "data/update_fn_test.sbml"
/// used in tests / to play around with the code
#[allow(dead_code)]
pub fn get_test_update_fn<T: FromStr>() -> UnprocessedVariableUpdateFn<T> {
use std::fs::File;
use std::io::BufReader;

let file = File::open("data/update_fn_test.sbml").expect("cannot open file");
let file = BufReader::new(file);

let xml = xml::reader::EventReader::new(file);
let mut xml = xml_parsing::xml_reader::LoudReader {
xml,
curr_indent: 0,
};

loop {
// match xml.next() {
match xml_parsing::xml_reader::XmlReader::next(&mut xml) {
Ok(xml::reader::XmlEvent::StartElement { name, .. }) => {
if name.local_name == "transition" {
let update_fn = UnprocessedVariableUpdateFn::try_from_xml(&mut xml);
return update_fn.unwrap();
}
}
Ok(xml::reader::XmlEvent::EndElement { .. }) => continue,
Ok(xml::reader::XmlEvent::EndDocument) => panic!(),
Err(_) => panic!(),
_ => continue,
}
}
}

#[test]
fn test_all_bigger() {
std::fs::read_dir("data/large")
.expect("could not read dir")
.skip(1)
.take(1)
.for_each(|dirent| {
println!("dirent = {:?}", dirent);
let dirent = dirent.expect("could not read file");

let (
smart_empty_succs_dot,
smart_whole_succs_dot,
smart_empty_succs,
smart_whole_succs,
) = {
// let mut xml = xml::reader::EventReader::new(std::io::BufReader::new(
// std::fs::File::open(dirent.path()).unwrap(),
// ));

// let mut xml =
// std::io::BufReader::new(std::fs::File::open(dirent.path()).unwrap());

// let system_update_fns = load_from_sbml_buf_reader::<
// xml::reader::EventReader<std::io::BufReader<std::fs::File>>,
// std::io::BufReader<std::fs::File>,
// u8,
// >(&mut xml)
// .expect("should be able to load");

let xml = xml::reader::EventReader::new(std::io::BufReader::new(
std::fs::File::open(dirent.path()).unwrap(),
));

let xml = xml_parsing::xml_reader::LoudReader {
xml,
curr_indent: 0,
};

let system_update_fns =
load_from_sbml_buf_reader(xml).expect("should be able to load");

let smart_system =
SmartSystemUpdateFn::<UnaryIntegerDomain, u8>::from_update_fns(
system_update_fns,
);

smart_system.get_transition_relation_and_domain("this will fail");

// let smart_system: SmartSystemUpdateFn<UnaryIntegerDomain, u8> =
// SmartSystemUpdateFn::from_update_fns(smart_system_update_fns);

// println!(
// "smart const false: {}",
// smart_system_update_fn.get_empty_state_subset()
// );
// println!(
// "smart const true: {}",
// smart_system_update_fn.get_whole_state_space_subset()
// );

// let empty_subset = smart_system_update_fn.get_empty_state_subset();
// let whole_subset = smart_system_update_fn.get_whole_state_space_subset();

// let empty_succs = smart_system_update_fn
// .transition_under_variable("BCat_exp_id99", &empty_subset);
// let whole_succs = smart_system_update_fn
// .transition_under_variable("BCat_exp_id99", &whole_subset);

// (
// smart_system_update_fn.bdd_to_dot_string(&empty_succs),
// smart_system_update_fn.bdd_to_dot_string(&whole_succs),
// empty_succs,
// whole_succs,
// )
((), (), (), ())
};

let (
force_empty_succs_dot,
force_whole_succs_dot,
force_empty_succs,
force_whole_succs,
) = {
// let mut xml = xml::reader::EventReader::new(std::io::BufReader::new(
// std::fs::File::open(dirent.path()).unwrap(),
// ));

// let mut xml =
// std::io::BufReader::new(std::fs::File::open(dirent.path()).unwrap());

// let system_update_fns =
// load_from_sbml_buf_reader(&mut xml).expect("should be able to load");

let xml = xml::reader::EventReader::new(std::io::BufReader::new(
std::fs::File::open(dirent.path()).unwrap(),
));

let system_update_fns =
load_from_sbml_buf_reader(xml).expect("should be able to load");

let system = SystemUpdateFn::<UnaryIntegerDomain, u8>::from_update_fns(
system_update_fns,
);

system.get_update_fn_and_domain_of("BCat_exp_id99");

// let mut xml = xml::reader::EventReader::new(std::io::BufReader::new(
// std::fs::File::open(dirent.path()).unwrap(),
// ));

// find_start_of(&mut xml, "listOfTransitions").expect("cannot find list");

// let force_system_update_fn: SystemUpdateFn<BinaryIntegerDomain<u8>, u8> =
// SystemUpdateFn::try_from_xml(&mut xml)
// .expect("cannot load smart system update fn");

// println!(
// "force const false: {}",
// force_system_update_fn.get_empty_state_subset()
// );
// println!(
// "force const true: {}",
// force_system_update_fn.get_whole_state_space_subset()
// );

// let empty_subset = force_system_update_fn.get_empty_state_subset();
// let whole_subset = force_system_update_fn.get_whole_state_space_subset();

// let empty_succs = force_system_update_fn
// .transition_under_variable("BCat_exp_id99", &empty_subset);
// let whole_succs = force_system_update_fn
// .transition_under_variable("BCat_exp_id99", &whole_subset);

// (
// force_system_update_fn.bdd_to_dot_string(&empty_succs),
// force_system_update_fn.bdd_to_dot_string(&whole_succs),
// empty_succs,
// whole_succs,
// )

((), (), (), ())
};

// assert_eq!(smart_empty_succs, force_empty_succs);
// assert_eq!(smart_whole_succs, force_whole_succs);

// assert_eq!(smart_empty_succs_dot, force_empty_succs_dot);

// println!("smart_empty_succs_dot = {:?}", smart_empty_succs_dot);
// println!("force_empty_succs_dot = {:?}", force_empty_succs_dot);

// print!("smart_whole_succs_dot = {}", smart_whole_succs_dot);
// print!("force_whole_succs_dot = {}", force_whole_succs_dot);

// assert_eq!(smart_whole_succs_dot, force_whole_succs_dot); // todo this is the problematic one

// assert!(smart_empty_succs.iff(&force_empty_succs).is_true());
// assert!(smart_whole_succs.iff(&force_whole_succs).is_true());

println!("smart_empty_succs = {:?}", smart_empty_succs);
println!("smart_whole_succs = {:?}", smart_whole_succs);
println!("force_empty_succs = {:?}", force_empty_succs);
println!("force_whole_succs = {:?}", force_whole_succs);
})
}
}
125 changes: 118 additions & 7 deletions src/xml_parsing/expression_parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use crate::{
};

use super::{
utils::{expect_opening_of, XmlReadingError},
utils::{expect_opening_of, ExpectedXmlEvent, XmlReadingError},
xml_reader::XmlReader,
};

Expand Down Expand Up @@ -69,14 +69,15 @@ impl<T: FromStr> Expression<T> {
received_operator.parse::<LogicalOperator>()
{
return logical_from_xml(xml, received_logical_operator);
// todo likely forgor to close the apply tag
}

if let Ok(comparison_operator) = received_operator.parse::<ComparisonOperator>()
{
return Ok(Expression::Terminal(proposition_from_xml(
xml,
comparison_operator,
)?));
expect_closure_of(xml, &comparison_operator.to_string())?;
let proposition = proposition_from_xml(xml, comparison_operator)?;
expect_closure_of(xml, "apply")?;
return Ok(Expression::Terminal(proposition));
}
}
other => {
Expand Down Expand Up @@ -110,8 +111,14 @@ where
expect_closure_of(xml, "apply")?; // "close" the *this* apply tag
Ok(inner_expression)
}
LogicalOperator::And => unimplemented!(),
LogicalOperator::Or => unimplemented!(),
LogicalOperator::And => {
let cnf_items = get_cnf_or_dnf_items(xml)?;
Ok(Expression::And(cnf_items))
}
LogicalOperator::Or => {
let dnf_items = get_cnf_or_dnf_items(xml)?;
Ok(Expression::Or(dnf_items))
}
LogicalOperator::Xor => {
expect_opening_of(xml, "apply")?; // "open" the first inner apply tag
let lhs = Expression::try_from_xml(xml)?;
Expand All @@ -131,6 +138,108 @@ where
}
}

// 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<T: FromStr, XR: XmlReader<BR>, BR: BufRead>(
// xml: &mut XR,
// ) -> Result<Vec<Expression<T>>, XmlReadingError> {
// let mut acc = Vec::<Expression<T>>::new();

// loop {
// match xml.next() {
// Ok(XmlEvent::Whitespace(_)) => { /* ignore */ }
// Ok(ref actual @ XmlEvent::StartElement { ref name, .. }) => {
// if name.local_name == "apply" {
// acc.push(Expression::try_from_xml(xml)?);
// continue;
// }

// return Err(XmlReadingError::UnexpectedEvent {
// expected: crate::xml_parsing::utils::ExpectedXmlEvent::AnyOf(vec![
// crate::xml_parsing::utils::ExpectedXmlEvent::Start(
// "apply (indented one)".to_string(),
// ),
// crate::xml_parsing::utils::ExpectedXmlEvent::End(
// "apply (this one)".to_string(),
// ),
// ]),
// got: actual.to_owned(),
// });
// }
// Ok(ref actual @ XmlEvent::EndElement { ref name, .. }) => {
// if name.local_name == "apply" {
// return Ok(acc);
// }

// return Err(XmlReadingError::UnexpectedEvent {
// expected: crate::xml_parsing::utils::ExpectedXmlEvent::AnyOf(vec![
// crate::xml_parsing::utils::ExpectedXmlEvent::Start(
// "apply (indented one)".to_string(),
// ),
// crate::xml_parsing::utils::ExpectedXmlEvent::End(
// "apply (this one)".to_string(),
// ),
// ]),
// got: actual.to_owned(),
// });
// }
// Ok(XmlEvent::EndDocument) => {
// // return Err("unexpected end of document".into());
// todo!()
// }
// other => {
// todo!()
// // return Err(format!(
// // "expected either opening of indented apply or closing of this cnf/dnf apply, got {:?}",
// // other
// // )
// // .into());
// }
// }
// }
// }

fn get_cnf_or_dnf_items<T: FromStr, XR: XmlReader<BR>, BR: BufRead>(
xml: &mut XR,
) -> Result<Vec<Expression<T>>, XmlReadingError> {
let mut acc = Vec::<Expression<T>>::new();

loop {
match xml.next()? {
XmlEvent::Whitespace(_) => { /* ignore */ }
XmlEvent::StartElement { name, .. } if name.local_name == "apply" => {
acc.push(Expression::try_from_xml(xml)?);
}
actual_start @ XmlEvent::StartElement { .. } => {
return Err(XmlReadingError::UnexpectedEvent {
expected: ExpectedXmlEvent::Start("apply (indented one)".to_string()),
got: actual_start,
});
}
XmlEvent::EndElement { ref name, .. } if name.local_name == "apply" => {
return Ok(acc);
}
actual_end @ XmlEvent::EndElement { .. } => {
return Err(XmlReadingError::UnexpectedEvent {
expected: ExpectedXmlEvent::End("apply (this one)".to_string()),
got: actual_end,
});
}
other => {
return Err(XmlReadingError::UnexpectedEvent {
expected: ExpectedXmlEvent::AnyOf(vec![
ExpectedXmlEvent::Start("apply [inner one]".into()),
ExpectedXmlEvent::End("apply [this one]".into()),
]),
got: other,
});
}
}
}
}

// todo maybe try to rewrite this using the `prcess_list` function
fn get_clausule_items<XR, BR, T>(xml: &mut XR) -> Result<Vec<Expression<T>>, XmlReadingError>
where
Expand Down Expand Up @@ -174,6 +283,7 @@ where
}
}

/// Expects xml to be at the end of the comparison operator tag (ie next is either value or variable name)
fn proposition_from_xml<XR, BR, T>(
xml: &mut XR,
comparison_operator: ComparisonOperator,
Expand Down Expand Up @@ -249,6 +359,7 @@ where
{
let constant_value = match xml.next()? {
XmlEvent::Characters(constant_value) => constant_value
.trim()
.parse::<T>()
.map_err(|_| XmlReadingError::ParsingError(constant_value))?,
other => {
Expand Down
Loading

0 comments on commit 0e0eced

Please sign in to comment.