regast-core 0.1.0

Parse-tree matching backends for regast
Documentation
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
}