Skip to main content

parse_that/combinators/
macros.rs

1// ── seq!: flat N-ary sequential combinator ────────────────────
2// Creates a single Box<dyn ParserFn> instead of N-1 intermediate boxes.
3// Usage: seq!(p1, p2) → Parser<(O1, O2)>, seq!(p1, p2, p3) → Parser<(O1, O2, O3)>, etc.
4
5#[macro_export]
6macro_rules! seq {
7    ($p1:expr, $p2:expr) => {
8        $crate::Parser::new(move |state| {
9            let v1 = $p1.call(state)?;
10            let v2 = $p2.call(state)?;
11            Some((v1, v2))
12        })
13    };
14    ($p1:expr, $p2:expr, $p3:expr) => {
15        $crate::Parser::new(move |state| {
16            let v1 = $p1.call(state)?;
17            let v2 = $p2.call(state)?;
18            let v3 = $p3.call(state)?;
19            Some((v1, v2, v3))
20        })
21    };
22    ($p1:expr, $p2:expr, $p3:expr, $p4:expr) => {
23        $crate::Parser::new(move |state| {
24            let v1 = $p1.call(state)?;
25            let v2 = $p2.call(state)?;
26            let v3 = $p3.call(state)?;
27            let v4 = $p4.call(state)?;
28            Some((v1, v2, v3, v4))
29        })
30    };
31    ($p1:expr, $p2:expr, $p3:expr, $p4:expr, $p5:expr) => {
32        $crate::Parser::new(move |state| {
33            let v1 = $p1.call(state)?;
34            let v2 = $p2.call(state)?;
35            let v3 = $p3.call(state)?;
36            let v4 = $p4.call(state)?;
37            let v5 = $p5.call(state)?;
38            Some((v1, v2, v3, v4, v5))
39        })
40    };
41    ($p1:expr, $p2:expr, $p3:expr, $p4:expr, $p5:expr, $p6:expr) => {
42        $crate::Parser::new(move |state| {
43            let v1 = $p1.call(state)?;
44            let v2 = $p2.call(state)?;
45            let v3 = $p3.call(state)?;
46            let v4 = $p4.call(state)?;
47            let v5 = $p5.call(state)?;
48            let v6 = $p6.call(state)?;
49            Some((v1, v2, v3, v4, v5, v6))
50        })
51    };
52    ($p1:expr, $p2:expr, $p3:expr, $p4:expr, $p5:expr, $p6:expr, $p7:expr) => {
53        $crate::Parser::new(move |state| {
54            let v1 = $p1.call(state)?;
55            let v2 = $p2.call(state)?;
56            let v3 = $p3.call(state)?;
57            let v4 = $p4.call(state)?;
58            let v5 = $p5.call(state)?;
59            let v6 = $p6.call(state)?;
60            let v7 = $p7.call(state)?;
61            Some((v1, v2, v3, v4, v5, v6, v7))
62        })
63    };
64    ($p1:expr, $p2:expr, $p3:expr, $p4:expr, $p5:expr, $p6:expr, $p7:expr, $p8:expr) => {
65        $crate::Parser::new(move |state| {
66            let v1 = $p1.call(state)?;
67            let v2 = $p2.call(state)?;
68            let v3 = $p3.call(state)?;
69            let v4 = $p4.call(state)?;
70            let v5 = $p5.call(state)?;
71            let v6 = $p6.call(state)?;
72            let v7 = $p7.call(state)?;
73            let v8 = $p8.call(state)?;
74            Some((v1, v2, v3, v4, v5, v6, v7, v8))
75        })
76    };
77}
78
79// ── alt!: flat N-ary alternation combinator ───────────────────
80// Creates a single Box<dyn ParserFn> instead of N-1 intermediate boxes.
81// Usage: alt!(p1, p2) → Parser<O>, alt!(p1, p2, p3) → Parser<O>, etc.
82
83#[macro_export]
84macro_rules! alt {
85    ($p1:expr, $p2:expr) => {
86        $crate::Parser::new(move |state| {
87            let cp = state.offset;
88            if let Some(v) = $p1.call(state) {
89                return Some(v);
90            }
91            state.furthest_offset = state.furthest_offset.max(state.offset);
92            state.offset = cp;
93            if let Some(v) = $p2.call(state) {
94                return Some(v);
95            }
96            state.furthest_offset = state.furthest_offset.max(state.offset);
97            state.offset = cp;
98            None
99        })
100    };
101    ($p1:expr, $p2:expr, $p3:expr) => {
102        $crate::Parser::new(move |state| {
103            let cp = state.offset;
104            if let Some(v) = $p1.call(state) {
105                return Some(v);
106            }
107            state.furthest_offset = state.furthest_offset.max(state.offset);
108            state.offset = cp;
109            if let Some(v) = $p2.call(state) {
110                return Some(v);
111            }
112            state.furthest_offset = state.furthest_offset.max(state.offset);
113            state.offset = cp;
114            if let Some(v) = $p3.call(state) {
115                return Some(v);
116            }
117            state.furthest_offset = state.furthest_offset.max(state.offset);
118            state.offset = cp;
119            None
120        })
121    };
122    ($p1:expr, $p2:expr, $p3:expr, $p4:expr) => {
123        $crate::Parser::new(move |state| {
124            let cp = state.offset;
125            if let Some(v) = $p1.call(state) {
126                return Some(v);
127            }
128            state.furthest_offset = state.furthest_offset.max(state.offset);
129            state.offset = cp;
130            if let Some(v) = $p2.call(state) {
131                return Some(v);
132            }
133            state.furthest_offset = state.furthest_offset.max(state.offset);
134            state.offset = cp;
135            if let Some(v) = $p3.call(state) {
136                return Some(v);
137            }
138            state.furthest_offset = state.furthest_offset.max(state.offset);
139            state.offset = cp;
140            if let Some(v) = $p4.call(state) {
141                return Some(v);
142            }
143            state.furthest_offset = state.furthest_offset.max(state.offset);
144            state.offset = cp;
145            None
146        })
147    };
148    ($p1:expr, $p2:expr, $p3:expr, $p4:expr, $p5:expr) => {
149        $crate::Parser::new(move |state| {
150            let cp = state.offset;
151            if let Some(v) = $p1.call(state) {
152                return Some(v);
153            }
154            state.furthest_offset = state.furthest_offset.max(state.offset);
155            state.offset = cp;
156            if let Some(v) = $p2.call(state) {
157                return Some(v);
158            }
159            state.furthest_offset = state.furthest_offset.max(state.offset);
160            state.offset = cp;
161            if let Some(v) = $p3.call(state) {
162                return Some(v);
163            }
164            state.furthest_offset = state.furthest_offset.max(state.offset);
165            state.offset = cp;
166            if let Some(v) = $p4.call(state) {
167                return Some(v);
168            }
169            state.furthest_offset = state.furthest_offset.max(state.offset);
170            state.offset = cp;
171            if let Some(v) = $p5.call(state) {
172                return Some(v);
173            }
174            state.furthest_offset = state.furthest_offset.max(state.offset);
175            state.offset = cp;
176            None
177        })
178    };
179    ($p1:expr, $p2:expr, $p3:expr, $p4:expr, $p5:expr, $p6:expr) => {
180        $crate::Parser::new(move |state| {
181            let cp = state.offset;
182            if let Some(v) = $p1.call(state) {
183                return Some(v);
184            }
185            state.furthest_offset = state.furthest_offset.max(state.offset);
186            state.offset = cp;
187            if let Some(v) = $p2.call(state) {
188                return Some(v);
189            }
190            state.furthest_offset = state.furthest_offset.max(state.offset);
191            state.offset = cp;
192            if let Some(v) = $p3.call(state) {
193                return Some(v);
194            }
195            state.furthest_offset = state.furthest_offset.max(state.offset);
196            state.offset = cp;
197            if let Some(v) = $p4.call(state) {
198                return Some(v);
199            }
200            state.furthest_offset = state.furthest_offset.max(state.offset);
201            state.offset = cp;
202            if let Some(v) = $p5.call(state) {
203                return Some(v);
204            }
205            state.furthest_offset = state.furthest_offset.max(state.offset);
206            state.offset = cp;
207            if let Some(v) = $p6.call(state) {
208                return Some(v);
209            }
210            state.furthest_offset = state.furthest_offset.max(state.offset);
211            state.offset = cp;
212            None
213        })
214    };
215    ($p1:expr, $p2:expr, $p3:expr, $p4:expr, $p5:expr, $p6:expr, $p7:expr) => {
216        $crate::Parser::new(move |state| {
217            let cp = state.offset;
218            if let Some(v) = $p1.call(state) {
219                return Some(v);
220            }
221            state.furthest_offset = state.furthest_offset.max(state.offset);
222            state.offset = cp;
223            if let Some(v) = $p2.call(state) {
224                return Some(v);
225            }
226            state.furthest_offset = state.furthest_offset.max(state.offset);
227            state.offset = cp;
228            if let Some(v) = $p3.call(state) {
229                return Some(v);
230            }
231            state.furthest_offset = state.furthest_offset.max(state.offset);
232            state.offset = cp;
233            if let Some(v) = $p4.call(state) {
234                return Some(v);
235            }
236            state.furthest_offset = state.furthest_offset.max(state.offset);
237            state.offset = cp;
238            if let Some(v) = $p5.call(state) {
239                return Some(v);
240            }
241            state.furthest_offset = state.furthest_offset.max(state.offset);
242            state.offset = cp;
243            if let Some(v) = $p6.call(state) {
244                return Some(v);
245            }
246            state.furthest_offset = state.furthest_offset.max(state.offset);
247            state.offset = cp;
248            if let Some(v) = $p7.call(state) {
249                return Some(v);
250            }
251            state.furthest_offset = state.furthest_offset.max(state.offset);
252            state.offset = cp;
253            None
254        })
255    };
256    ($p1:expr, $p2:expr, $p3:expr, $p4:expr, $p5:expr, $p6:expr, $p7:expr, $p8:expr) => {
257        $crate::Parser::new(move |state| {
258            let cp = state.offset;
259            if let Some(v) = $p1.call(state) {
260                return Some(v);
261            }
262            state.furthest_offset = state.furthest_offset.max(state.offset);
263            state.offset = cp;
264            if let Some(v) = $p2.call(state) {
265                return Some(v);
266            }
267            state.furthest_offset = state.furthest_offset.max(state.offset);
268            state.offset = cp;
269            if let Some(v) = $p3.call(state) {
270                return Some(v);
271            }
272            state.furthest_offset = state.furthest_offset.max(state.offset);
273            state.offset = cp;
274            if let Some(v) = $p4.call(state) {
275                return Some(v);
276            }
277            state.furthest_offset = state.furthest_offset.max(state.offset);
278            state.offset = cp;
279            if let Some(v) = $p5.call(state) {
280                return Some(v);
281            }
282            state.furthest_offset = state.furthest_offset.max(state.offset);
283            state.offset = cp;
284            if let Some(v) = $p6.call(state) {
285                return Some(v);
286            }
287            state.furthest_offset = state.furthest_offset.max(state.offset);
288            state.offset = cp;
289            if let Some(v) = $p7.call(state) {
290                return Some(v);
291            }
292            state.furthest_offset = state.furthest_offset.max(state.offset);
293            state.offset = cp;
294            if let Some(v) = $p8.call(state) {
295                return Some(v);
296            }
297            state.furthest_offset = state.furthest_offset.max(state.offset);
298            state.offset = cp;
299            None
300        })
301    };
302}