1use crate::{IrId, IrKind, IrPool};
2
3#[derive(Clone, Debug, PartialEq, Eq)]
4pub enum Value {
5 Empty,
6 Char(char),
7 Seq(Box<Self>, Box<Self>),
8 Left(Box<Self>),
9 Right(Box<Self>),
10 Stars(Vec<Self>),
11}
12
13impl Value {
14 #[must_use]
15 pub(crate) fn byte_len(&self) -> usize {
16 match self {
17 Self::Empty => 0,
18 Self::Char(c) => c.len_utf8(),
19 Self::Seq(left, right) => left.byte_len() + right.byte_len(),
20 Self::Left(value) | Self::Right(value) => value.byte_len(),
21 Self::Stars(values) => values.iter().map(Self::byte_len).sum(),
22 }
23 }
24
25 #[must_use]
26 pub fn flatten(&self) -> String {
27 let mut output = String::new();
28 self.flatten_into(&mut output);
29 output
30 }
31
32 pub fn flatten_into(&self, output: &mut String) {
33 match self {
34 Self::Empty => {}
35 Self::Char(c) => output.push(*c),
36 Self::Seq(left, right) => {
37 left.flatten_into(output);
38 right.flatten_into(output);
39 }
40 Self::Left(value) | Self::Right(value) => value.flatten_into(output),
41 Self::Stars(values) => {
42 for value in values {
43 value.flatten_into(output);
44 }
45 }
46 }
47 }
48
49 #[must_use]
50 pub fn typed_by(&self, pool: &IrPool, root: IrId) -> bool {
51 match (self, pool.kind(root)) {
52 (Self::Empty, IrKind::One | IrKind::Anchor(..)) => true,
53 (Self::Char(c), IrKind::Class(set, _)) => pool.get_class_set(*set).contains(*c),
54 (Self::Seq(left_value, right_value), IrKind::Seq(left, right, _)) => {
55 left_value.typed_by(pool, *left) && right_value.typed_by(pool, *right)
56 }
57 (Self::Left(value), IrKind::Alt(left, _, _, _)) => value.typed_by(pool, *left),
58 (Self::Right(value), IrKind::Alt(_, right, _, _)) => value.typed_by(pool, *right),
59 (Self::Stars(values), IrKind::Star(inner, _, _)) => {
60 values.iter().all(|value| value.typed_by(pool, *inner))
61 }
62 _ => false,
63 }
64 }
65}