1use crate::nfa::{Graph as Nfa, State};
10
11#[non_exhaustive]
13#[allow(clippy::ref_option_ref)]
14#[derive(Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
15pub enum Lazy<I: Clone + Ord> {
16 Immediate(Nfa<I>),
18 Postponed,
20 PostponedReference(*const Self),
22 Or(Box<Self>, Box<Self>),
24 ShrEps(Box<Self>, Box<Self>),
26 ShrNonEps(Box<Self>, (I, Option<&'static str>, Box<Self>)),
28 Repeat(Box<Self>),
30}
31
32impl<I: Clone + Ord> Clone for Lazy<I> {
33 #[inline]
34 fn clone(&self) -> Self {
35 match *self {
36 Self::Immediate(ref lhs) => Self::Immediate(lhs.clone()),
37 Self::Postponed => Self::PostponedReference(self), Self::PostponedReference(ptr) => Self::PostponedReference(ptr),
39 Self::Or(ref lhs, ref rhs) => Self::Or(lhs.clone(), rhs.clone()),
40 Self::ShrEps(ref lhs, ref rhs) => Self::ShrEps(lhs.clone(), rhs.clone()),
41 Self::ShrNonEps(ref lhs, ref rhs) => Self::ShrNonEps(lhs.clone(), rhs.clone()),
42 Self::Repeat(ref lhs) => Self::Repeat(lhs.clone()),
43 }
44 }
45}
46
47impl<I: Clone + Ord> Lazy<I> {
48 #[inline]
52 #[allow(clippy::manual_assert, clippy::panic)]
53 pub fn finally(&mut self, value: Self) {
54 if *self != Self::Postponed {
55 panic!("Called `finally` on a value that was already defined");
56 }
57 if value == Self::Postponed {
58 panic!("Called `finally` with a definition that is itself postponed");
59 }
60 *self = value;
61 }
62
63 #[inline]
65 #[must_use]
66 #[allow(clippy::missing_assert_message)]
67 pub fn compile(self) -> crate::dfa::Graph<I> {
68 self.evaluate().compile()
69 }
70
71 #[inline]
74 #[must_use]
75 pub fn repeat(self) -> Self {
76 Lazy::Repeat(Box::new(self))
77 }
78
79 #[inline]
81 #[must_use]
82 pub fn optional(self) -> Self {
83 crate::empty() | self
84 }
85
86 #[inline]
88 #[must_use]
89 pub fn star(self) -> Self {
90 self.repeat().optional()
91 }
92
93 #[inline]
98 #[allow(
99 clippy::arithmetic_side_effects,
100 clippy::panic,
101 clippy::shadow_reuse,
102 clippy::suspicious_arithmetic_impl,
103 unsafe_code
104 )]
105 pub fn evaluate(self) -> Nfa<I> {
106 match self {
107 Self::Immediate(nfa) => nfa,
108 Self::Postponed => panic!("Needed a postponed value that had not been initialized"),
109 Self::PostponedReference(ptr) => unsafe { &*ptr }.clone().evaluate(),
111 Self::Or(lhs, rhs) => {
112 let mut lhs = lhs.evaluate();
113 let mut rhs = rhs.evaluate();
114 let index = lhs.states.len();
115 for state in &mut rhs.states {
116 *state += index;
117 }
118 lhs.states.extend(rhs.states);
119 lhs.initial.extend(
120 rhs.initial
121 .into_iter()
122 .map(|x| x.checked_add(index).expect("Huge number of states")),
123 );
124 lhs
125 }
126 Self::ShrEps(lhs, rhs) => {
127 let mut lhs = lhs.evaluate();
128 let mut rhs = rhs.evaluate();
129 let index = lhs.states.len();
130 for state in &mut rhs.states {
131 *state += index;
132 }
133 let incr_initial = rhs
134 .initial
135 .iter()
136 .map(|x| x.checked_add(index).expect("Huge number of states"));
137 for state in &mut lhs.states {
138 if state.accepting {
139 state.accepting = false;
140 state.epsilon.extend(incr_initial.clone());
141 }
142 }
143 lhs.states.extend(rhs.states);
144 lhs
145 }
146 Self::ShrNonEps(lhs, (token, fn_name, rhs)) => {
147 let mut lhs = lhs.evaluate();
148 let mut rhs = rhs.evaluate();
149 let index = lhs.states.len();
150 for state in &mut rhs.states {
151 *state += index;
152 }
153 let incr_initial = rhs
154 .initial
155 .iter()
156 .map(|x| x.checked_add(index).expect("Huge number of states"));
157 for state in &mut lhs.states {
158 if state.accepting {
159 state.accepting = false;
160 state.non_epsilon.extend(
161 incr_initial
162 .clone()
163 .map(|i| (token.clone(), (core::iter::once(i).collect(), fn_name)))
164 .clone(),
165 );
166 }
167 }
168 lhs.states.extend(rhs.states);
169 lhs
170 }
171 Self::Repeat(lhs) => {
172 let mut eval = lhs.evaluate();
173 for state in &mut eval.states {
174 if state.accepting {
175 state.epsilon.extend(eval.initial.iter());
176 }
177 }
178 eval
179 }
180 }
181 }
182}
183
184impl<I: Clone + Ord> core::ops::AddAssign<usize> for State<I> {
185 #[inline]
186 fn add_assign(&mut self, rhs: usize) {
187 self.epsilon = self
189 .epsilon
190 .iter()
191 .map(|x| x.checked_add(rhs).expect("Huge number of states"))
192 .collect();
193 for &mut (ref mut set, _fn_name) in &mut self.non_epsilon.values_mut() {
194 *set = set
195 .iter()
196 .map(|&x| x.checked_add(rhs).expect("Huge number of states"))
197 .collect();
198 }
199 }
200}
201
202impl<I: Clone + Ord> core::ops::BitOr for Lazy<I> {
203 type Output = Self;
204 #[inline]
205 #[allow(clippy::arithmetic_side_effects, clippy::suspicious_arithmetic_impl)]
206 fn bitor(self, rhs: Self) -> Self::Output {
207 Lazy::Or(Box::new(self), Box::new(rhs))
208 }
209}
210
211impl<I: Clone + Ord> core::ops::Shr<(I, Option<&'static str>, Lazy<I>)> for Lazy<I> {
212 type Output = Self;
213 #[inline]
214 #[allow(clippy::arithmetic_side_effects, clippy::suspicious_arithmetic_impl)]
215 fn shr(self, (token, fn_name, rhs): (I, Option<&'static str>, Self)) -> Self::Output {
216 Lazy::ShrNonEps(Box::new(self), (token, fn_name, Box::new(rhs)))
217 }
218}
219
220impl<I: Clone + Ord> core::ops::Shr for Lazy<I> {
221 type Output = Self;
222 #[inline]
223 #[allow(clippy::arithmetic_side_effects, clippy::suspicious_arithmetic_impl)]
224 fn shr(self, rhs: Self) -> Self::Output {
225 Lazy::ShrEps(Box::new(self), Box::new(rhs))
226 }
227}
228
229impl core::ops::Add for Lazy<char> {
230 type Output = Self;
231 #[inline]
232 #[allow(clippy::arithmetic_side_effects, clippy::suspicious_arithmetic_impl)]
233 fn add(self, rhs: Self) -> Self::Output {
234 self >> crate::space() >> rhs
235 }
236}