brzozowski_regex/
builder.rs

1// Copyright 2024 Hendrik van Antwerpen
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Regular expression data type and builders.
16
17use std::fmt::Debug;
18use std::hash::Hash;
19
20use crate::Alphabet;
21
22mod pure;
23mod similarity;
24
25#[doc(inline)]
26pub use pure::Pure;
27#[doc(inline)]
28pub use similarity::ApproximatelySimilarCanonical;
29
30/// The recommended regular expression builder.
31pub type Default<S> = ApproximatelySimilarCanonical<S>;
32
33/// Constructor methods for regular expressions.
34pub trait Builder: Eq + Hash + Sized {
35    type Symbol: Alphabet;
36
37    fn empty_set() -> Regex<Self>;
38    fn empty_string() -> Regex<Self>;
39    fn symbol(value: Self::Symbol) -> Regex<Self>;
40    fn closure(inner: Regex<Self>) -> Regex<Self>;
41    fn concat(left: Regex<Self>, right: Regex<Self>) -> Regex<Self>;
42    fn or(left: Regex<Self>, right: Regex<Self>) -> Regex<Self>;
43    fn and(left: Regex<Self>, right: Regex<Self>) -> Regex<Self>;
44    fn complement(inner: Regex<Self>) -> Regex<Self>;
45}
46
47/// Data type describing regular expressions.
48#[derive(Debug, Eq, Hash, PartialEq)]
49pub enum Regex<B: Builder> {
50    /// The empty set `∅`
51    EmptySet,
52    /// The empty string `ε`
53    EmptyString,
54    /// A symbol _s_
55    Symbol(B::Symbol),
56    /// Concatenation `R S`
57    Concat(Box<Self>, Box<Self>),
58    /// Closure `R*`
59    Closure(Box<Self>),
60    /// Disjunction `R | S`
61    Or(Box<Self>, Box<Self>),
62    /// Conjunction `R & R`
63    And(Box<Self>, Box<Self>),
64    /// Complement `¬R`
65    Complement(Box<Self>),
66}
67
68impl<B: Builder> Regex<B> {
69    #[inline]
70    pub fn empty_set() -> Self {
71        B::empty_set()
72    }
73
74    #[inline]
75    pub fn empty_string() -> Self {
76        B::empty_string()
77    }
78
79    #[inline]
80    pub fn symbol(value: B::Symbol) -> Self {
81        B::symbol(value)
82    }
83
84    #[inline]
85    pub fn closure(inner: Self) -> Self {
86        B::closure(inner)
87    }
88
89    #[inline]
90    pub fn concat(left: Self, right: Self) -> Self {
91        B::concat(left, right)
92    }
93
94    #[inline]
95    pub fn or(left: Self, right: Self) -> Self {
96        B::or(left, right)
97    }
98
99    #[inline]
100    pub fn and(left: Self, right: Self) -> Self {
101        B::and(left, right)
102    }
103
104    #[inline]
105    pub fn complement(inner: Self) -> Self {
106        B::complement(inner)
107    }
108}
109
110impl<B: Builder> Regex<B> {
111    /// Rebuild this regular expression using a different builder over the same symbol type.
112    pub fn rebuild<X: Builder<Symbol = B::Symbol>>(&self) -> Regex<X> {
113        match self {
114            Regex::EmptySet => X::empty_set(),
115            Regex::EmptyString => X::empty_string(),
116            Regex::Symbol(value) => X::symbol(value.clone()),
117            Regex::Concat(left, right) => X::concat(left.rebuild(), right.rebuild()),
118            Regex::Closure(inner) => X::closure(inner.rebuild()),
119            Regex::Or(left, right) => X::or(left.rebuild(), right.rebuild()),
120            Regex::And(left, right) => X::and(left.rebuild(), right.rebuild()),
121            Regex::Complement(inner) => X::complement(inner.rebuild()),
122        }
123    }
124}
125
126impl<B: Builder> Clone for Regex<B> {
127    fn clone(&self) -> Self {
128        self.rebuild()
129    }
130}