1use crate::intervals::{Interval, Intervals};
10use std::fmt::{Display, Formatter};
11use std::ops::RangeInclusive;
12use std::rc::Rc;
13
14#[derive(Ord, PartialOrd, Eq, PartialEq, Debug, Clone, Hash)]
15pub enum RegexTree {
16 Top,
17 Bottom,
19 Set(Intervals),
21 Epsilon,
22 Concat(Rc<RegexTree>, Rc<RegexTree>),
23 KleeneClosure(Rc<RegexTree>),
24 Union(Rc<RegexTree>, Rc<RegexTree>),
25 Intersection(Rc<RegexTree>, Rc<RegexTree>),
26 Complement(Rc<RegexTree>),
27}
28
29impl Display for RegexTree {
30 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
31 match self {
32 RegexTree::Top => {
33 write!(f, "⊤")
34 }
35 RegexTree::Bottom => {
36 write!(f, "⊥")
37 }
38 RegexTree::Set(x) => {
39 write!(f, "{}", x)
40 }
41 RegexTree::Epsilon => {
42 write!(f, "ε")
43 }
44 RegexTree::Concat(x, y) => {
45 write!(f, "({} ~ {})", x, y)
46 }
47 RegexTree::KleeneClosure(x) => {
48 write!(f, "{}*", x)
49 }
50 RegexTree::Union(x, y) => {
51 write!(f, "({} ∪ {})", x, y)
52 }
53 RegexTree::Intersection(x, y) => {
54 write!(f, "({} ∩ {})", x, y)
55 }
56 RegexTree::Complement(x) => {
57 write!(f, "¬({})", x)
58 }
59 }
60 }
61}
62
63impl RegexTree {
64 pub fn single(x: u8) -> Self {
65 unsafe { RegexTree::Set(Intervals::new([Interval(x, x)]).unwrap_unchecked()) }
66 }
67 pub fn range(x: RangeInclusive<u8>) -> Self {
68 if x.is_empty() {
69 return RegexTree::Bottom;
70 }
71 match Intervals::new([Interval(*x.start(), *x.end())]) {
72 Some(set) => RegexTree::Set(set),
73 None => RegexTree::Bottom,
74 }
75 }
76 pub fn mangle(&self) -> String {
77 match self {
78 RegexTree::Top => "T".to_string(),
79 RegexTree::Bottom => "B".to_string(),
80 RegexTree::Set(x) => x.mangle(),
81 RegexTree::Epsilon => "E".to_string(),
82 RegexTree::Concat(x, y) => {
83 let x = x.mangle();
84 let y = y.mangle();
85 format!("C{}{}{}{}", x.len(), x, y.len(), y)
86 }
87 RegexTree::KleeneClosure(x) => {
88 let x = x.mangle();
89 format!("K{}{}", x.len(), x)
90 }
91 RegexTree::Union(x, y) => {
92 let x = x.mangle();
93 let y = y.mangle();
94 format!("U{}{}{}{}", x.len(), x, y.len(), y)
95 }
96 RegexTree::Intersection(x, y) => {
97 let x = x.mangle();
98 let y = y.mangle();
99 format!("I{}{}{}{}", x.len(), x, y.len(), y)
100 }
101 RegexTree::Complement(x) => {
102 let x = x.mangle();
103 format!("N{}{}", x.len(), x)
104 }
105 }
106 }
107 pub fn is_nullable(&self) -> bool {
108 match self {
109 RegexTree::Top => false,
110 RegexTree::Bottom => false,
111 RegexTree::Set(_) => false,
112 RegexTree::Epsilon => true,
113 RegexTree::Concat(left, right) => left.is_nullable() && right.is_nullable(),
114 RegexTree::KleeneClosure(_) => true,
115 RegexTree::Union(left, right) => left.is_nullable() || right.is_nullable(),
116 RegexTree::Intersection(left, right) => left.is_nullable() && right.is_nullable(),
117 RegexTree::Complement(r) => !r.is_nullable(),
118 }
119 }
120}