Skip to main content

regast_core/
value.rs

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}