use std::collections::HashSet;
use crate::{IrId, IrKind, IrPool, deriv::nullable_at, simp::simp};
pub fn partial_derivative_at(
pool: &mut IrPool,
root: IrId,
c: char,
position: usize,
input_len: usize,
) -> Vec<IrId> {
let raw = match pool.kind(root).clone() {
IrKind::Class(set, _) if pool.get_class_set(set).contains(c) => vec![pool.one()],
IrKind::Zero | IrKind::One | IrKind::Anchor(..) | IrKind::Class(..) => Vec::new(),
IrKind::Alt(left, right, _, _) => {
let mut result = partial_derivative_at(pool, left, c, position, input_len);
result.extend(partial_derivative_at(pool, right, c, position, input_len));
result
}
IrKind::Seq(left, right, prov) => {
let mut result: Vec<_> = partial_derivative_at(pool, left, c, position, input_len)
.into_iter()
.map(|derivative| pool.seq(derivative, right, prov))
.collect();
if nullable_at(pool, left, position, input_len) {
result.extend(partial_derivative_at(pool, right, c, position, input_len));
}
result
}
IrKind::Star(inner, prov, _) => partial_derivative_at(pool, inner, c, position, input_len)
.into_iter()
.map(|derivative| pool.seq(derivative, root, prov))
.collect(),
};
normalize(pool, raw)
}
fn normalize(pool: &mut IrPool, expressions: Vec<IrId>) -> Vec<IrId> {
let mut seen = HashSet::new();
let mut result = Vec::new();
for expression in expressions {
let simple = simp(pool, expression).0;
if simple != pool.zero() && seen.insert(simple) {
result.push(simple);
}
}
result
}