1use crate::*;
6use ::std::marker::PhantomData;
7
8#[derive(Clone)]
9pub struct Group<'code, Capture, const NUM: usize> {
19 buffer: Option<Buffer<'code>>,
20 _captured: PhantomData<Capture>,
21}
22
23impl<'code, Capture, const NUM: usize> std::fmt::Debug
24 for Group<'code, Capture, NUM>
25{
26 fn fmt(
27 &self,
28 f: &mut std::fmt::Formatter<'_>,
29 ) -> std::fmt::Result {
30 f.debug_tuple("Group").field(&self.buffer).finish()
31 }
32}
33
34impl<'code, Capture, const NUM: usize> Token<'code>
35 for Group<'code, Capture, NUM>
36where
37 Capture: Token<'code>,
38{
39 const NAME: &'static str = <Capture as Token>::NAME;
40
41 fn buffer(&self) -> Option<Buffer<'code>> {
42 self.buffer.clone()
43 }
44}
45
46impl<'code, Capture, const NUM: usize> Lexer<'code>
47 for Group<'code, Capture, NUM>
48where
49 Capture: Lexer<'code>,
50{
51 fn lex(
52 buffer: &mut Buffer<'code>,
53 ) -> Result<Self, Error<'code>> {
54 let mut local_buffer = buffer.clone();
56
57 let mut return_buffer = None::<Buffer<'code>>;
58 let mut matched = 0usize;
59
60 loop {
62 match <Capture as Lexer>::lex(&mut local_buffer)
63 {
64 Ok(captured) => {
65 return_buffer = match return_buffer {
66 Some(return_buffer) => Some(
67 match <Capture as Token>::buffer(
68 &captured,
69 ) {
70 Some(captured_buffer) => {
71 return_buffer
72 + captured_buffer
73 }
74 None => return_buffer,
75 },
76 ),
77 None => <Capture as Token>::buffer(
78 &captured,
79 )
80 .clone(),
81 };
82 matched += 1;
83 }
84 Err(mut err) => {
85 if NUM > 0 && matched < NUM {
87 err.matched = matched;
89 Err(err)?
90 }
91 break;
93 }
94 }
95 }
96
97 *buffer = local_buffer;
98
99 Ok(Self {
100 buffer: return_buffer,
101 _captured: PhantomData,
102 })
103 }
104}
105
106#[derive(Clone)]
107pub struct GroupUntil<'code, Capture, End, const NUM: usize>
115{
116 buffer: Option<Buffer<'code>>,
117 _captured: PhantomData<Capture>,
118 _end: PhantomData<End>,
119}
120
121impl<'code, Capture, End, const NUM: usize> std::fmt::Debug
122 for GroupUntil<'code, Capture, End, NUM>
123{
124 fn fmt(
125 &self,
126 f: &mut std::fmt::Formatter<'_>,
127 ) -> std::fmt::Result {
128 f.debug_tuple("Group").field(&self.buffer).finish()
129 }
130}
131
132impl<'code, Capture, End, const NUM: usize> Token<'code>
133 for GroupUntil<'code, Capture, End, NUM>
134where
135 Capture: Token<'code>,
136 End: Token<'code>,
137{
138 const NAME: &'static str = <Capture as Token>::NAME;
139
140 fn buffer(&self) -> Option<Buffer<'code>> {
141 self.buffer.clone()
142 }
143}
144
145impl<'code, Capture, End, const NUM: usize> Lexer<'code>
146 for GroupUntil<'code, Capture, End, NUM>
147where
148 Capture: Lexer<'code>,
149 End: Lexer<'code>,
150{
151 fn lex(
152 buffer: &mut Buffer<'code>,
153 ) -> Result<Self, Error<'code>> {
154 let mut local_buffer = buffer.clone();
156
157 let mut return_buffer = None::<Buffer<'code>>;
158 let mut matched = 0usize;
159
160 while <End as Lexer>::lex(&mut local_buffer.clone())
164 .is_err()
165 {
166 let captured =
168 <Capture as Lexer>::lex(&mut local_buffer)
169 .map_err(|mut err| {
170 err.matched = matched;
171 if let Kind::NotFound(syntax) =
172 &mut err.kind
173 {
174 *syntax = <End as Token>::NAME
175 }
176 err
177 })?;
178
179 return_buffer = match return_buffer {
181 Some(return_buffer) => Some(
182 match <Capture as Token>::buffer(
183 &captured,
184 ) {
185 Some(captured_buffer) => {
186 return_buffer + captured_buffer
187 }
188 None => return_buffer,
189 },
190 ),
191 None => {
192 <Capture as Token>::buffer(&captured)
193 .clone()
194 }
195 };
196 matched += 1;
197 }
198
199 if NUM > 0 && matched < NUM {
201 Err(Error {
202 buffer: local_buffer.clone(),
203 matched,
204 kind: Kind::NotFound(<Self as Token>::NAME),
205 })?
206 }
207
208 *buffer = local_buffer;
209
210 Ok(Self {
211 buffer: return_buffer,
212 _captured: PhantomData,
213 _end: PhantomData,
214 })
215 }
216}
217
218#[derive(Debug, Clone)]
219pub struct GroupBookEnd<
228 'code,
229 Start,
230 Capture,
231 End,
232 const NUM: usize,
233> {
234 start: Start,
235 group: GroupUntil<'code, Capture, End, NUM>,
236 end: End,
237}
238
239impl<'code, Start, Capture, End, const NUM: usize>
240 Token<'code>
241 for GroupBookEnd<'code, Start, Capture, End, NUM>
242where
243 Start: Token<'code>,
244 Capture: Token<'code>,
245 End: Token<'code>,
246{
247 const NAME: &'static str = <Capture as Token>::NAME;
248
249 fn buffer(&self) -> Option<Buffer<'code>> {
250 let buffers = [
251 <Start as Token>::buffer(&self.start),
252 <GroupUntil<'code, Capture, End, NUM> as Token>::buffer(&self.group),
253 <End as Token>::buffer(&self.end),
254 ]
255 .into_iter();
256
257 buffers
258 .flatten()
259 .reduce(|acc, current| acc + current)
260 }
261}
262
263impl<'code, Start, Capture, End, const NUM: usize>
264 Lexer<'code>
265 for GroupBookEnd<'code, Start, Capture, End, NUM>
266where
267 Start: Lexer<'code>,
268 Capture: Lexer<'code>,
269 End: Lexer<'code>,
270{
271 fn lex(
272 buffer: &mut Buffer<'code>,
273 ) -> Result<Self, Error<'code>> {
274 let mut local_buffer = buffer.clone();
275 let mut matched = 0usize;
276
277 let start =
279 <Start as Lexer>::lex(&mut local_buffer)?;
280 matched += 1;
281
282 let group =
284 <GroupUntil<Capture, End, NUM> as Lexer>::lex(
285 &mut local_buffer,
286 )
287 .map_err(|mut err| {
288 matched += err.matched;
289 err.matched = matched;
290 err
291 })?;
292
293 let end = <End as Lexer>::lex(&mut local_buffer)
295 .map_err(|mut err| {
296 matched += err.matched;
297 err.matched = matched;
298 err
299 })?;
300
301 *buffer = local_buffer;
303
304 Ok(Self { start, group, end })
305 }
306}