regast-core 0.1.0

Parse-tree matching backends for regast
Documentation
use crate::{IrId, IrKind, IrPool, Value, mkeps::mkeps_at};

#[cfg(test)]
pub fn inj(pool: &mut IrPool, root: IrId, c: char, value: Value) -> Value {
    inj_at(pool, root, c, value, 1, 2)
}

pub fn inj_at(
    pool: &mut IrPool,
    root: IrId,
    c: char,
    value: Value,
    position: usize,
    input_len: usize,
) -> Value {
    match (pool.kind(root).clone(), value) {
        (IrKind::Class(..), Value::Empty) => Value::Char(c),
        (IrKind::Alt(left, _, _, _), Value::Left(value)) => {
            Value::Left(Box::new(inj_at(pool, left, c, *value, position, input_len)))
        }
        (IrKind::Alt(_, right, _, _), Value::Right(value)) => Value::Right(Box::new(inj_at(
            pool, right, c, *value, position, input_len,
        ))),
        (IrKind::Seq(left, _, _), Value::Seq(first, second)) => Value::Seq(
            Box::new(inj_at(pool, left, c, *first, position, input_len)),
            second,
        ),
        (IrKind::Seq(left, right, _), Value::Left(value)) => {
            if pool.prefers_empty(left) {
                Value::Seq(
                    Box::new(mkeps_at(pool, left, position, input_len)),
                    Box::new(inj_at(pool, right, c, *value, position, input_len)),
                )
            } else {
                let Value::Seq(first, second) = *value else {
                    unreachable!("left sequence derivative must contain Seq")
                };
                Value::Seq(
                    Box::new(inj_at(pool, left, c, *first, position, input_len)),
                    second,
                )
            }
        }
        (IrKind::Seq(left, right, _), Value::Right(value)) => {
            inject_right_sequence(pool, left, right, c, *value, position, input_len)
        }
        (IrKind::Star(inner, _, _), Value::Seq(first, rest)) => {
            let Value::Stars(mut values) = *rest else {
                unreachable!("star derivative must end in Stars")
            };
            values.insert(0, inj_at(pool, inner, c, *first, position, input_len));
            Value::Stars(values)
        }
        _ => unreachable!("value is not typed by derivative"),
    }
}

#[allow(clippy::too_many_arguments)]
fn inject_right_sequence(
    pool: &mut IrPool,
    left: IrId,
    right: IrId,
    c: char,
    value: Value,
    position: usize,
    input_len: usize,
) -> Value {
    if pool.prefers_empty(left) {
        let Value::Seq(first, second) = value else {
            unreachable!("empty-preferred continuation must contain Seq")
        };
        return Value::Seq(
            Box::new(inj_at(pool, left, c, *first, position, input_len)),
            second,
        );
    }
    Value::Seq(
        Box::new(mkeps_at(pool, left, position, input_len)),
        Box::new(inj_at(pool, right, c, value, position, input_len)),
    )
}