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)),
)
}