use std::cmp::Ordering;
use std::collections::HashMap;
use std::hash::Hasher;
use crate::dom::*;
use crate::errors::*;
#[derive(Debug, Default)]
pub struct ParseTree{
data: HashMap<usize, ParseTreeNode>,
pos: Option<usize>
}
impl ParseTree {
pub fn new() -> Self {
Self::default()
}
pub fn empty_stack(&self) -> bool {
match self.pos {
None => true,
Some(_) => false
}
}
pub fn push(&mut self, new_element: Element) {
if self.pos.is_none() {
self.data.insert(0, ParseTreeNode{
id: 0,
value: Box::new(new_element),
parent_id: None,
child_ids: Vec::new(),
});
self.pos = Some(0);
} else {
let old_pos = self.pos.unwrap();
let new_pos = self.data.len();
self.data.get_mut(&old_pos).expect("logic error")
.child_ids.push(new_pos);
self.data.insert(new_pos, ParseTreeNode{
id: new_pos,
value: Box::new(new_element),
parent_id: Some(old_pos),
child_ids: Vec::new(),
});
self.pos = Some(new_pos);
}
}
pub fn pop(&mut self) -> Result<(), KissXmlError> {
if self.pos.is_none() {
return Err(ParsingError::new("closing tag without corresponding open tag").into());
}
let pos = self.pos.unwrap();
let new_pos = self.data
.get(&pos).expect("logic error").parent_id;
self.pos = new_pos;
Ok(())
}
pub fn append(&mut self, n: impl Node + 'static) -> Result<(), KissXmlError> {
if self.pos.is_none() {
return Err(ParsingError::new("no root element").into());
}
let pos = self.pos.unwrap();
let new_id = self.data.len();
self.data.get_mut(&pos).expect("logic error")
.child_ids.push(new_id);
self.data.insert(new_id, ParseTreeNode{
id: new_id,
value: Box::new(n),
parent_id: Some(pos),
child_ids: Vec::new(),
});
Ok(())
}
pub fn top_element(&self) -> Option<&Element> {
match self.pos {
None => None,
Some(pos) => Some(
self.data.get(&pos).expect("logic error")
.value.as_element().expect("logic error")
)
}
}
pub fn to_dom(mut self) -> Result<Element, KissXmlError> {
if self.data.is_empty() {
return Err(ParsingError::new("no root element").into());
}
for i in (1..self.data.len()).rev() {
let mut node = self.data.remove(&i).expect("logic error: missing index");
if node.value.is_element() {
node.value.as_element_mut().unwrap().reverse_children()
}
let parent_index = node.parent_id.expect("logic error: non-root node with no parent");
self.data.get_mut(&parent_index).expect("logic error: parent is missing")
.value.as_element_mut().expect("logic error: parent is not an Element")
.append_boxed(node.value);
}
let root_node = self.data.remove(&0).expect("logic error: no root element");
let mut root = root_node.destruct();
let e = root.as_element_mut().expect("logic error: root is not an element");
e.reverse_children();
return Ok(std::mem::take(e));
}
}
#[derive(Debug)]
pub struct ParseTreeNode{
id: usize,
value: Box<dyn Node>,
parent_id: Option<usize>,
child_ids: Vec<usize>
}
impl ParseTreeNode {
fn destruct(self) -> Box<dyn Node>{self.value}
}
impl PartialEq for ParseTreeNode {
fn eq(&self, other: &Self) -> bool {
self.id == other.id
}
}
impl Eq for ParseTreeNode{}
impl std::hash::Hash for ParseTreeNode {
fn hash<H: Hasher>(&self, state: &mut H) {
self.id.hash(state)
}
}
impl PartialOrd for ParseTreeNode {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.id.cmp(&other.id))
}
}
impl Ord for ParseTreeNode{
fn cmp(&self, other: &Self) -> Ordering {
self.partial_cmp(other).unwrap()
}
}