use std::borrow::Borrow; use std::collections::BTreeMap; use std::fmt; use std::mem; use cfg::Symbol; use earley_omnitool::forest::compact_bocage::traverse::{LeafHandle, NullingHandle, SumHandle, Traverse}; use earley_omnitool::forest::node_handle::NodeHandle; use earley_omnitool::grammar::InternalGrammar; use super::cartesian_product::CartesianProduct; pub struct SimpleCompactEvaluator { values: Vec, evaluated: BTreeMap>, leaf: F, rule: G, null: H, } impl SimpleCompactEvaluator where FLeaf: FnMut(Symbol) -> V, FRule: FnMut(u32, &[&V]) -> V, FNull: for<'r> FnMut(Symbol, &'r mut Vec), V: fmt::Debug + Clone, { pub fn new(leaf: FLeaf, rule: FRule, null: FNull) -> Self { SimpleCompactEvaluator { values: vec![], evaluated: BTreeMap::new(), leaf, rule, null, } } pub fn traverse<'f, G>(&mut self, traverse: &mut Traverse<'f, G>, root: NodeHandle) -> Vec where G: Borrow, { while let Some(mut item) = traverse.next_node() { match &mut item.item { &mut SumHandle(ref mut products) => { while let Some(product) = products.next_product() { let mut cartesian_product = CartesianProduct::new(); for &(_sym, handle) in product.factors { cartesian_product.push(&self.evaluated[&handle][..]); } loop { let v = (self.rule)(product.action, cartesian_product.as_slice()); self.values.push(v); if !cartesian_product.advance() { break; } } } } &mut NullingHandle => { (self.null)(item.symbol, &mut self.values); } &mut LeafHandle => { let v = (self.leaf)(item.symbol); self.values.push(v); } } self.evaluated .insert(item.handle(), mem::replace(&mut self.values, vec![])); item.end_evaluation(); } self.evaluated[&root].clone() } }