Skip to content

Commit

Permalink
feat: interrupting xml reader for better debug
Browse files Browse the repository at this point in the history
  • Loading branch information
Lukáš Chudíček committed Oct 7, 2023
1 parent ef38578 commit 529f57d
Show file tree
Hide file tree
Showing 4 changed files with 132 additions and 100 deletions.
82 changes: 14 additions & 68 deletions src/prototype/expression.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use std::{io::BufRead, str::FromStr};
use thiserror::Error;
use xml::reader::{EventReader, XmlEvent};
use xml::reader::XmlEvent;

use crate::{expect_closure_of, expect_opening, expect_opening_of, XmlReader};

#[derive(Debug)]
pub enum Expression<T> {
Expand Down Expand Up @@ -46,8 +48,8 @@ impl LogicOp {
// todo there should be constraint on the type of T: FromStr
impl<T: FromStr> Expression<T> {
// todo consider iterative approach instead of recursive?
pub fn try_from_xml<BR: BufRead>(
xml: &mut EventReader<BR>,
pub fn try_from_xml<XR: XmlReader<BR>, BR: BufRead>(
xml: &mut XR,
) -> Result<Self, Box<dyn std::error::Error>> {
loop {
match xml.next() {
Expand Down Expand Up @@ -77,21 +79,22 @@ impl<T: FromStr> Expression<T> {
}
}

fn terminal_from_xml<T: FromStr>(
fn terminal_from_xml<T: FromStr, XR: XmlReader<BR>, BR: BufRead>(
op: CmpOp,
xml: &mut EventReader<impl BufRead>,
xml: &mut XR,
) -> Result<Expression<T>, Box<dyn std::error::Error>> {
expect_closure_of(&op.its_string(), xml)?; // close the cmp op tag
let prp = parse_terminal_ops(xml)?;
expect_closure_of("apply", xml)?;
Ok(Expression::Terminal(Proposition::new(op, prp)))
}

fn logical_from_xml<T: FromStr, BR: BufRead>(
fn logical_from_xml<T: FromStr, XR: XmlReader<BR>, BR: BufRead>(
op: LogicOp,
xml: &mut EventReader<BR>,
xml: &mut XR,
) -> Result<Expression<T>, Box<dyn std::error::Error>> {
expect_closure_of(&op.its_string(), xml)?; // self closing tag must be "closed"
// expect_closure_of(&op.its_string(), xml)?; // self closing tag must be "closed"
expect_closure_of(&op.its_string(), xml)?;
match op {
LogicOp::Not => {
expect_opening_of("apply", xml)?;
Expand Down Expand Up @@ -119,59 +122,17 @@ fn logical_from_xml<T: FromStr, BR: BufRead>(
}
}

fn expect_opening_of<T: BufRead>(
expected: &str,
xml: &mut EventReader<T>,
) -> Result<(), Box<dyn std::error::Error>> {
loop {
match xml.next() {
Ok(XmlEvent::Whitespace(_)) => { /* whitespace is the reason we want to loop */ }
Ok(XmlEvent::StartElement { name, .. }) => {
return if name.local_name == expected {
Ok(())
} else {
Err(format!(
"expected opening element {}, got {}",
expected, name.local_name
)
.into())
}
}
any => return Err(format!("expected opening of {}, got {:?}", expected, any).into()),
}
}
}

fn expect_closure_of<T: BufRead>(
expected: &str,
xml: &mut EventReader<T>,
) -> Result<(), Box<dyn std::error::Error>> {
loop {
match xml.next() {
Ok(XmlEvent::Whitespace(_)) => { /* whitespace is the reason we want to loop */ }
Ok(XmlEvent::EndElement { name, .. }) => {
return if name.local_name == expected {
Ok(())
} else {
Err(format!("expected closing of {}, got {}", expected, name.local_name).into())
}
}
any => return Err(format!("expected closing of {}, got {:?}", expected, any).into()),
}
}
}

pub enum TerminalOps<T> {
Standard(String, T),
Flipped(T, String),
}

/// expects input xml to be in such state that the next two xml nodes are either
/// ci and then cn, or cn and then ci
pub fn parse_terminal_ops<T: FromStr, BR: BufRead>(
xml: &mut EventReader<BR>,
pub fn parse_terminal_ops<T: FromStr, XR: XmlReader<BR>, BR: BufRead>(
xml: &mut XR,
) -> Result<TerminalOps<T>, Box<dyn std::error::Error>> {
let elem = expect_opening(xml)?;
let elem = expect_opening(xml)?.name.local_name;
if elem == "ci" {
let ci;

Expand Down Expand Up @@ -237,21 +198,6 @@ pub fn parse_terminal_ops<T: FromStr, BR: BufRead>(
Err("expected ci or cn".into())
}

/// get the name of the opening tag
/// if the next event is not a start element, returns an error
/// if the next event is a start element, returns its name
fn expect_opening<T: BufRead>(
xml: &mut EventReader<T>,
) -> Result<String, Box<dyn std::error::Error>> {
loop {
match xml.next() {
Ok(XmlEvent::Whitespace(_)) => { /* whitespace is the reason we want to loop */ }
Ok(XmlEvent::StartElement { name, .. }) => return Ok(name.local_name),
any => return Err(format!("expected an opening, got {:?}", any).into()),
}
}
}

#[derive(Debug, Clone)]
pub enum CmpOp {
Eq,
Expand Down
19 changes: 11 additions & 8 deletions src/prototype/system_update_fn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@ use std::{collections::HashMap, io::BufRead};

use xml::EventReader;

use crate::{UnaryIntegerDomain, UpdateFn, VariableUpdateFnCompiled};
use crate::{UnaryIntegerDomain, UpdateFn, VariableUpdateFnCompiled, XmlReader};

struct SystemUpdateFn {
pub update_fns: HashMap<String, VariableUpdateFnCompiled<UnaryIntegerDomain, u8>>,
}

impl SystemUpdateFn {
/// expects the xml reader to be at the start of the <listOfTransitions> element
pub fn try_from_xml<BR: BufRead>(
_xml: &mut EventReader<BR>,
pub fn try_from_xml<XR: XmlReader<BR>, BR: BufRead>(
_xml: &mut XR,
) -> Result<Self, Box<dyn std::error::Error>> {
let var_names_and_upd_fns = load_all_update_fns(_xml)?;
println!("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
Expand All @@ -30,8 +30,8 @@ impl SystemUpdateFn {

#[allow(dead_code)]
/// expects the xml reader to be at the start of the <listOfTransitions> element
fn load_all_update_fns<BR: BufRead>(
xml: &mut EventReader<BR>,
fn load_all_update_fns<XR: XmlReader<BR>, BR: BufRead>(
xml: &mut XR,
// todo generic
) -> Result<HashMap<String, UpdateFn<u8>>, Box<dyn std::error::Error>> {
Ok(crate::process_list(
Expand Down Expand Up @@ -85,13 +85,16 @@ fn compile_update_fns(

#[cfg(test)]
mod tests {
use crate::LoudReader;

#[test]
fn test() {
let file = std::fs::File::open("data/dataset.sbml").expect("cannot open file");
let br = std::io::BufReader::new(file);
let mut xml = xml::reader::EventReader::new(br);
let event_reader = xml::reader::EventReader::new(br);
let mut loud = LoudReader::new(event_reader);

crate::find_start_of(&mut xml, "listOfTransitions").expect("cannot find start of list");
let _system_update_fn = super::SystemUpdateFn::try_from_xml(&mut xml).unwrap();
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();
}
}
43 changes: 31 additions & 12 deletions src/prototype/update_fn.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{expect_closure_of, expect_opening_of, process_list, StartElementWrapper};
use crate::{expect_closure_of, expect_opening_of, process_list, StartElementWrapper, XmlReader};

use super::expression::Expression;
use super::utils::expect_opening;
Expand Down Expand Up @@ -38,8 +38,8 @@ impl<T> UpdateFn<T> {

/// expects the xml reader to be at the start of the <transition> element
impl<T: FromStr> UpdateFn<T> {
pub fn try_from_xml<BR: BufRead>(
xml: &mut EventReader<BR>,
pub fn try_from_xml<XR: XmlReader<BR>, BR: BufRead>(
xml: &mut XR,
) -> Result<Self, Box<dyn std::error::Error>> {
let some_start_element = expect_opening(xml)?;
if !matches!(
Expand All @@ -53,7 +53,7 @@ impl<T: FromStr> UpdateFn<T> {
.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
Expand Down Expand Up @@ -83,8 +83,8 @@ impl<T: FromStr> UpdateFn<T> {
}
}

fn process_input_var_name_item<BR: BufRead>(
xml: &mut EventReader<BR>,
fn process_input_var_name_item<XR: XmlReader<BR>, BR: BufRead>(
xml: &mut XR,
current: StartElementWrapper,
) -> Result<String, Box<dyn std::error::Error>> {
let mut qualitative_species = current.attributes.iter().filter_map(|att| {
Expand All @@ -104,8 +104,8 @@ fn process_input_var_name_item<BR: BufRead>(
Ok(item)
}

fn process_output_var_name_item<BR: BufRead>(
xml: &mut EventReader<BR>,
fn process_output_var_name_item<XR: XmlReader<BR>, BR: BufRead>(
xml: &mut XR,
current: StartElementWrapper,
) -> Result<String, Box<dyn std::error::Error>> {
let mut qualitative_species = current.attributes.iter().filter_map(|att| {
Expand Down Expand Up @@ -137,8 +137,8 @@ fn get_target_var_name<BR: BufRead>(
unimplemented!();
}

fn get_default_and_list_of_terms<T: FromStr, BR: BufRead>(
xml: &mut EventReader<BR>,
fn get_default_and_list_of_terms<T: FromStr, XR: XmlReader<BR>, BR: BufRead>(
xml: &mut XR,
) -> Result<(T, Vec<(T, Expression<T>)>), Box<dyn std::error::Error>> {
// firs should be the default
let default_element = expect_opening_of("defaultTerm", xml)?;
Expand All @@ -155,11 +155,30 @@ fn get_default_and_list_of_terms<T: FromStr, BR: BufRead>(
xml,
)?;

// let xd = other_process_list(
// "listOfFunctionTerms",
// "functionTerm",
// process_function_term_item,
// xml,
// );

Ok((default_val, values_and_expressions))
}

fn process_function_term_item<T: FromStr, BR: BufRead>(
xml: &mut EventReader<BR>,
// fn process_list<XR: XmlReader<BR>, BR: BufRead, Fun, Res>(
// list_name: &str,
// item_name: &str,
// processing_fn: Fun,
// xml: &mut XR,
// ) -> Result<Vec<Res>, Box<dyn std::error::Error>>
// where
// Fun: Fn(&mut XR, StartElementWrapper) -> Result<Res, Box<dyn std::error::Error>>,
// {
// unimplemented!();
// }

fn process_function_term_item<T: FromStr, XR: XmlReader<BR>, BR: BufRead>(
xml: &mut XR,
current: StartElementWrapper,
) -> Result<(T, Expression<T>), Box<dyn std::error::Error>> {
let res_lvl = result_level_from_attributes(&current)
Expand Down
Loading

0 comments on commit 529f57d

Please sign in to comment.