use idata::IVec;
use std::result::Result;
#[derive(Debug, PartialEq)]
pub struct Error(pub String, pub Option<String>);
pub fn error(desc: &str, ast_context: Option<&str>) -> Error {
Error(
desc.to_string(),
ast_context.and_then(|a| Some(a.to_string())),
)
}
#[derive(Debug, PartialEq)]
pub enum Node {
Val(String),
Rule((String, Vec<Node>)),
EOF,
}
impl Node {
pub fn prune(&self, nodes2prune: &[&str]) -> Self {
let nname2prune = |nname: &str| nodes2prune.iter().find(|n| *n == &nname);
let node2prune = |node: &Node| match node {
Node::Rule((nname, _)) => nname2prune(nname).is_some(),
_ => false,
};
let prune_vn = |vnodes: &[Node]| {
vnodes.iter().fold(vec![], |acc, n| {
if node2prune(n) == false {
acc.ipush(n.prune(nodes2prune))
} else {
acc
}
})
};
match self {
Node::EOF => Node::EOF,
Node::Val(v) => Node::Val(v.clone()),
Node::Rule((n, vn)) => Node::Rule((n.clone(), prune_vn(vn))),
}
}
pub fn compact(&self) -> Self {
fn concat_nodes(mut nodes: Vec<Node>, n: &Node) -> Vec<Node> {
let get_val = |nodes: &Vec<Node>| match nodes.last() {
Some(Node::Val(ref v)) => Some(v.to_string()),
_ => None,
};
let concat_v = |v: &String, prev_v: &Option<String>| match (v, prev_v) {
(v, Some(pv)) => Some(format!("{}{}", pv, v)),
_ => None,
};
match (n, get_val(&nodes)) {
(Node::EOF, _) => nodes.push(Node::EOF),
(Node::Val(ref v), ref prev_v) => match concat_v(v, prev_v) {
Some(c) => {
nodes.pop();
nodes.push(Node::Val(c.clone()));
}
_ => nodes.push(Node::Val(v.clone())),
},
(Node::Rule((ref n, ref vn)), _) => {
nodes.push(Node::Rule((n.clone(), compact_nodes(vn))))
}
};
nodes
};
fn compact_nodes(nodes: &[Node]) -> Vec<Node> {
nodes
.iter()
.fold(vec![], |acc: Vec<Node>, n| (concat_nodes(acc, n)))
};
match self {
Node::EOF => Node::EOF,
Node::Val(v) => Node::Val(v.clone()),
Node::Rule((n, vn)) => Node::Rule((n.clone(), compact_nodes(vn))),
}
}
}
pub fn get_nodename_and_nodes<'a>(node: &'a Node) -> Result<(&'a str, &'a [Node]), Error> {
match node {
Node::Rule((nname, nodes)) => Ok((nname, nodes)),
_ => Err(error("expected node::Rule", None)),
}
}
pub fn get_node_val(node: &Node) -> Result<&str, Error> {
match node {
Node::Val(v) => Ok(v),
_ => Err(error("expected node::Val", None)),
}
}
pub fn get_nodes_unique_val(nodes: &[Node]) -> Result<&str, Error> {
match (nodes.first(), nodes.len()) {
(Some(n), 1) => get_node_val(n),
_ => Err(error("expected only one value in nodes", None)),
}
}
pub fn consume_val(nodes: &[Node]) -> Result<(&str, &[Node]), Error> {
let (node, nodes) = split_first_nodes(nodes)?;
match node {
Node::Val(v) => Ok((&v, nodes)),
_ => Err(error("expected Val node", None)),
}
}
pub fn split_first_nodes(nodes: &[Node]) -> Result<(&Node, &[Node]), Error> {
nodes.split_first().ok_or(error(
"trying get first element from nodes on empty slice",
None,
))
}
pub fn consume_this_value<'a>(v: &str, nodes: &'a [Node]) -> Result<&'a [Node], Error> {
let (node, nodes) = split_first_nodes(nodes)?;
let nv = get_node_val(node)?;
match nv == v {
true => Ok(nodes),
false => Err(error(
"trying get first element from nodes on empty slice",
None,
)),
}
}
pub fn consume_node_get_subnodes_for_rule_name_is<'a>(
name: &str,
nodes: &'a [Node],
) -> Result<(&'a [Node], &'a [Node]), Error> {
let (node, nodes) = split_first_nodes(nodes)?;
match node {
Node::Rule((n, sub_nodes)) => if n == name {
Ok((nodes, sub_nodes))
} else {
Err(error(
&format!("expected {} node, received {}", name, n),
None,
))
},
unknown => Err(error(
&format!("expected {} Node::Rule, received {:?}", name, unknown),
None,
)),
}
}
pub fn check_empty_nodes(nodes: &[Node]) -> Result<(), Error> {
match nodes.is_empty() {
true => Ok(()),
false => Err(error("not consumed full nodes", None)),
}
}