use std::collections::HashMap;
use super::NonTerminal;
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct SegmentKey {
pub text: String,
pub is_partial_special: bool,
}
pub fn is_prefix(prefix: &[SegmentKey], full: &[SegmentKey]) -> bool {
if prefix.len() > full.len() {
return false;
}
prefix.iter().zip(full.iter()).all(|(a, b)| a == b)
}
#[derive(Default, Debug, Clone)]
struct SpanCacheDepth {
by_nt: HashMap<String, HashMap<usize, HashMap<usize, Vec<NonTerminal>>>>,
}
#[derive(Default, Debug, Clone)]
pub(crate) struct SpanCache {
by_depth: HashMap<usize, SpanCacheDepth>,
}
impl SpanCache {
pub fn clear(&mut self) {
self.by_depth.clear();
}
pub fn collect(
&self,
depth: usize,
nt: &str,
start: usize,
max_len: usize,
) -> Option<Vec<NonTerminal>> {
let d = self.by_depth.get(&depth)?;
let starts = d.by_nt.get(nt)?;
let by_searched = starts.get(&start)?;
by_searched.get(&max_len).cloned()
}
pub fn store_span(
&mut self,
depth: usize,
nt: &str,
start: usize,
searched_max_len: usize,
trees: Vec<NonTerminal>,
) {
let d = self.by_depth.entry(depth).or_default();
let starts = d.by_nt.entry(nt.to_string()).or_default();
let by_searched = starts.entry(start).or_default();
let existing = by_searched.entry(searched_max_len).or_default();
for tree in trees {
if !existing.contains(&tree) {
existing.push(tree);
}
}
}
}