Parse rewrite using recursion #4

Merged
FrogWithACoolHat merged 2 commits from blizzardfinnegan/wacp_xml_parser:main into main 2023-08-08 13:28:33 -04:00

View file

@ -1,6 +1,6 @@
mod oop;
use std::{thread::{self, JoinHandle}, io::Write};
use roxmltree::{self, Document, Node};
use roxmltree;
fn main() {
let args: Vec<String> = std::env::args().collect();
@ -28,7 +28,8 @@ fn main() {
match doc {
Ok(doc_good) => {
//output(parse(&doc_good));
parse(&doc_good);
#[allow(unused_variables)]
let output:oop::Family = new_parse(&doc_good).unwrap();
},
Err(doc_bad) => {
println!("{:?}", doc_bad);
@ -43,80 +44,158 @@ fn main() {
handle.join().expect("Couldn't close thread.");
}
}
fn parse(doc: &Document) -> oop::Family {
let mut family: Option<oop::Family> = None;
let mut family_name: String;
fn new_parse(doc:&roxmltree::Document) -> Result<oop::Family,core::fmt::Error>{
let mut wrapped_family:Option<oop::Family> = None;
let mut messages: oop::Messages = oop::Messages::new(Vec::new(), Vec::new(), Vec::new(), Vec::new(), Vec::new());
for child1 in doc.root_element().first_children() {
if child1.is_element() && child1.tag_name().name() == "FAMILY" {
for attr in child1.attributes() {
if attr.name() == "name" {
family_name = attr.value().to_string();
family = Some(oop::Family::new(family_name, Vec::new(), Vec::new()));
} else {
panic!("No family name found in file. Failed to initialize data structure.")
if let Some(root) = doc.root_element().first_child(){
match root.tag_name().name() {
"FAMILY" => {
if let Some(attribute) = root.attributes().filter(|attribute| attribute.name() == "name" ).next(){
wrapped_family = Some(oop::Family::new(attribute.value().to_string(), Vec::new(), Vec::new()));
}
}
if let Some(ref mut real_family) = family {
for child2 in child1.children() {
if child2.is_element() {
if child2.tag_name().name() == "SPECIES_KEY" {
for child3 in child2.children() {
if child3.is_element() && child3.tag_name().name() == "GENUS" {
for attr in child3.attributes() {
if attr.name() == "name" {
real_family.push_genus(oop::Genus::new(attr.value().to_string(), Vec::new()));
}
}
for child4 in child3.children() {
if child4.is_element() && child4.tag_name().name() == "SPECIES" {
real_family.get_genera().last_mut().unwrap().push_species(oop::Species::new(child4.attribute_node("name").unwrap().value().to_string(), child4.attribute_node("defaultvalue").unwrap().value().to_string(), Vec::new()));
}
}
}
}
} else if child2.tag_name().name() == "DEFINITION" {
push_object(child2, real_family);
for child3 in child2.children() {
if child3.is_element() {
if child3.tag_name().name() == "MEMBERS" {
for child4 in child3.children() {
if child4.is_element() && child4.tag_name().name() == "MEMBER"{
push_member(child2, child4, real_family);
}
}
} else if child3.tag_name().name() == "ENUMERATION" {
for child4 in child3.children() {
if child4.is_element() && child4.tag_name().name() == "ENUM"{
push_enum(child2, child3, child4, real_family);
}
}
}
}
}
} else if child2.tag_name().name() == "MESSAGES" {
for child3 in child2.children() {
if child3.is_element() && child3.tag_name().name() == "MSG" {
messages.push(child3);
}
}
}
}
}
}
},
_ => {}
}
if let Some(ref mut family) = wrapped_family{
root.children().for_each(|child| nested_parse(family, child));
}
root.children().filter(|outer_child| outer_child.tag_name().name() == "MESSAGES" )
.for_each(|message_group| {
message_group.children().filter(|inner_child| inner_child.tag_name().name() == "MSG")
.for_each(|message| {
messages.push(message);
});
});
if let Some(family) = wrapped_family{
return Ok(family);
}
}
return Err(core::fmt::Error);
}
if let Some(ref mut real_family) = family {
real_family.push_messages(messages);
println!("{:?}",real_family);
return family.unwrap();
} else {
panic!("Family is uninitialized.")
fn nested_parse(input_family:&mut oop::Family, node: roxmltree::Node) {
match node.tag_name().name() {
"SPECIES_KEY" => {
node.children().for_each(|child| nested_parse(input_family, child));
},
"GENUS" => {
node.attributes()
.filter(|attr| attr.name() != "comment")
.for_each(|attr| {
if attr.name() == "name" {
input_family.push_genus(oop::Genus::new(attr.value().to_string(), Vec::new()));
};
});
node.children().for_each(|child| nested_parse(input_family, child));
},
"SPECIES" => {
input_family.get_genera().last_mut().unwrap()
.push_species(oop::Species::new(
node.attribute("name").unwrap().to_string(),
node.attribute("defaultvalue").unwrap().to_string(),
Vec::new()
));
},
"DEFINITION" => {
let Some(attr_family) = node.attribute("family")
else { todo!() };
let Some(attr_genus) = node.attribute("genus")
else { todo!() };
let Some(attr_species) = node.attribute("species")
else { todo!() };
if attr_family != input_family.get_name() {
println!("Inconsistent family naming scheme. Check XML file.");
panic!();
}
input_family.get_genera().as_mut_slice().iter_mut().filter(|genus| genus.get_name().as_str() == attr_genus)
.for_each(|genus| {
genus.get_species().as_mut_slice().iter_mut().filter(|species| species.get_name().as_str() == attr_species)
.for_each(|species|{
species.push_object(oop::Object::new(
node.attribute("class").unwrap().to_string(),
node.attribute("abrv").unwrap().to_string(),
node.attribute("version").unwrap().to_string(),
Vec::new()
));
});
}
);
node.children().for_each(|child| nested_parse(input_family, child));
},
"MEMBERS" => {
node.children().for_each(|child| nested_parse(input_family, child));
},
"MEMBER" => {
let Some(attr_family) = node.attribute("family")
else { todo!() };
let Some(attr_genus) = node.attribute("genus")
else { todo!() };
let Some(attr_species) = node.attribute("species")
else { todo!() };
if attr_family != input_family.get_name() {
println!("Inconsistent family naming scheme. Check XML file.");
panic!();
}
input_family.get_genera().as_mut_slice().iter_mut().filter(|genus| genus.get_name().as_str() == attr_genus)
.for_each(|genus| {
genus.get_species().as_mut_slice().iter_mut().filter(|species| species.get_name().as_str() == attr_species)
.for_each(|species|{
species.get_objects().as_mut_slice().iter_mut()
.for_each(|object| {
object.push_object_member(oop::ObjectMember::new(
node.attribute("type").unwrap().to_string(),
node.attribute("name").unwrap().to_string(),
node.attribute("minversion").unwrap().to_string(),
node.attribute("maxversion").unwrap().to_string(),
Vec::new(),
node.attribute("format").unwrap_or("").to_string()
));
});
});
}
);
},
"ENUMERATION" => {
node.children().for_each(|child| nested_parse(input_family, child));
},
"ENUM" => {
let Some(attr_family) = node.attribute("family")
else { todo!() };
let Some(attr_genus) = node.attribute("genus")
else { todo!() };
let Some(attr_species) = node.attribute("species")
else { todo!() };
let Some(attr_name) = node.attribute("name")
else { todo!() };
if attr_family != input_family.get_name() {
println!("Inconsistent family naming scheme. Check XML file.");
}
input_family.get_genera().as_mut_slice().iter_mut().filter(|genus| genus.get_name().as_str() == attr_genus)
.for_each(|genus| {
genus.get_species().as_mut_slice().iter_mut().filter(|species| species.get_name().as_str() == attr_species)
.for_each(|species|{
species.get_objects().as_mut_slice().iter_mut()
.for_each(|object| {
object.get_members().as_mut_slice().iter_mut().filter(|member| member.get_name().as_str() == attr_name)
.for_each(|member| {
member.get_enumerations().push(
oop::MemberEnumeration::new(
node.attribute("name").unwrap().to_string(),
node.attribute("defaultvalue").unwrap_or("").to_string(),
)
);
});
});
});
}
);
},
"MESSAGES" => {},
"MSG" => {},
_ => {}
}
}
@ -159,91 +238,3 @@ fn output(family: oop::Family) {
}
}
fn push_object(child2: Node, real_family: &mut oop::Family) {
if let Some(f) = child2.attribute_node("family") {
if f.value() ==real_family.get_name() {
for genus in real_family.get_genera().as_mut_slice() {
if let Some(g) = child2.attribute_node("genus") {
if g.value() == genus.get_name() {
for species in genus.get_species().as_mut_slice() {
if let Some(s) = child2.attribute_node("species") {
if s.value() == species.get_name() {
species.push_object(oop::Object::new(child2.attribute_node("class").unwrap().value().to_string(), child2.attribute_node("abrv").unwrap().value().to_string(), child2.attribute_node("version").unwrap().value().to_string(), Vec::new()))
}
}
}
}
}
}
}
}
}
fn push_member(child2: Node, child4: Node, real_family: &mut oop::Family) {
if let Some(s) = child2.attribute_node("family") {
if s.value() ==real_family.get_name() {
for genus in real_family.get_genera().as_mut_slice() {
if let Some(g) = child2.attribute_node("genus") {
if g.value() == genus.get_name() {
for species in genus.get_species().as_mut_slice() {
if let Some(s) = child2.attribute_node("species") {
if s.value() == species.get_name() {
for object in species.get_objects().as_mut_slice() {
object.push_object_member(oop::ObjectMember::new(
child4.attribute_node("type").unwrap().value().to_string(),
child4.attribute_node("name").unwrap().value().to_string(),
child4.attribute_node("minversion").unwrap().value().to_string(),
child4.attribute_node("maxversion").unwrap().value().to_string(),
Vec::new(),
if child4.has_attribute("format") {
child4.attribute_node("format").unwrap().value().to_string()
} else {
String::new()
}));
}
}
}
}
}
}
}
}
}
}
fn push_enum(child2: Node, child3: Node, child4: Node, real_family: &mut oop::Family) {
if let Some(f) = child2.attribute_node("family") {
if f.value() ==real_family.get_name() {
for genus in real_family.get_genera().as_mut_slice() {
if let Some(g) = child2.attribute_node("genus") {
if g.value() == genus.get_name() {
for species in genus.get_species().as_mut_slice() {
if let Some(s) = child2.attribute_node("species") {
if s.value() == species.get_name() {
for object in species.get_objects().as_mut_slice() {
for member in object.get_members().as_mut_slice() {
if let Some(m) = child3.attribute_node("name") {
if m.value() == member.get_name() {
if child4.has_attribute("defaultvalue") {
member.get_enumerations().push(oop::MemberEnumeration::new(
child4.attribute_node("name").unwrap().value().to_string(),
child4.attribute_node("defaultvalue").unwrap().value().to_string()));
} else {
member.get_enumerations().push(oop::MemberEnumeration::new(
child4.attribute_node("name").unwrap().value().to_string(),
String::new()));
}
}
}
}
}
}
}
}
}
}
}
}
}
}