use idata::cont::IVec;
use std::result::Result;
pub mod flat;
#[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) {
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 passthrow_except(&self, nodes2keep: &[&str]) -> Self {
fn pthr_vn(vnodes: &[Node], nodes2keep: &[&str]) -> Vec<Node> {
let nname2keep = |nname: &str| nodes2keep.iter().find(|n| *n == &nname);
let node2keep = |node: &Node| match node {
Node::Rule((nname, _)) => nname2keep(nname).is_some(),
_ => true,
};
vnodes.iter().fold(vec![], |acc, n| {
if node2keep(n) {
acc.ipush(n.passthrow_except(nodes2keep))
} else {
match n {
Node::Rule((_, new_nodes)) => acc.iappend(pthr_vn(new_nodes, nodes2keep)),
_ => acc.ipush(n.passthrow_except(nodes2keep)),
}
}
})
};
match self {
Node::EOF => Node::EOF,
Node::Val(v) => Node::Val(v.clone()),
Node::Rule((n, vn)) => Node::Rule((n.clone(), pthr_vn(vn, nodes2keep))),
}
}
pub fn compact(&self) -> Self {
fn concat_nodes(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.ipush(Node::EOF),
(Node::Val(ref v), ref prev_v) => match concat_v(v, prev_v) {
Some(c) => {
let (_, nodes) = nodes.ipop();
nodes.ipush(Node::Val(c.clone()))
}
_ => nodes.ipush(Node::Val(v.clone())),
},
(Node::Rule((ref n, ref vn)), _) => {
nodes.ipush(Node::Rule((n.clone(), compact_nodes(vn))))
}
}
};
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(node: &Node) -> Result<(&str, &[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_else(|| 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)?;
if nv == v {
Ok(nodes)
} else {
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> {
if nodes.is_empty() {
Ok(())
} else {
Err(error("not consumed full nodes", None))
}
}
pub fn peek_first_node(nodes: &[Node]) -> Result<&Node, Error> {
if nodes.is_empty() {
Err(error("exptected node on peek_first_node", None))
} else {
Ok(&nodes[0])
}
}