use rvs_parser::ast;
use std::collections::HashMap;
use std::collections::hash_map::Entry;
pub struct Ast {
variable_indexes: HashMap<String, usize>,
nodes: Vec<Box<ast::Node>>,
}
impl Ast {
pub fn new() -> Ast {
Ast {
variable_indexes: HashMap::new(),
nodes: Vec::new(),
}
}
pub fn add_nodes(&mut self, mut nodes: Vec<Box<ast::Node>>) {
for node in nodes.drain(..) {
self.add_node(node);
}
}
fn add_node(&mut self, node: Box<ast::Node>) {
let is_variable = if let ast::Node::Variable(_, _) = *node {
true
} else {
false
};
if is_variable {
let name = if let ast::Node::Variable(ref name, _) = *node {
name.to_owned()
} else {
"".to_owned()
};
let nodes = &mut self.nodes;
match self.variable_indexes.entry(name) {
Entry::Occupied(entry) => {
let index = *entry.get();
nodes[index] = node;
}
Entry::Vacant(entry) => {
nodes.push(node);
entry.insert(nodes.len() - 1);
}
}
} else {
self.nodes.push(node);
}
}
pub fn get(&self) -> &[Box<ast::Node>] {
&self.nodes
}
}