Skip to main content

chumsky/
private.rs

1use super::*;
2
3#[derive(Clone)]
4pub(crate) struct Located<T, E> {
5    pub(crate) pos: T,
6    pub(crate) err: E,
7}
8
9impl<T, E> Located<T, E> {
10    #[inline]
11    pub fn at(pos: T, err: E) -> Self {
12        Self { pos, err }
13    }
14}
15
16/// The result of calling [`Parser::go`]
17pub(crate) type PResult<M, O> = Result<<M as Mode>::Output<O>, ()>;
18/// The result of calling [`IterParser::next`]
19pub(crate) type IPResult<M, O> = Result<Option<<M as Mode>::Output<O>>, ()>;
20
21/// An abstract parse mode - can be [`Emit`] or [`Check`] in practice, and represents the
22/// common interface for handling both in the same method.
23pub trait Mode {
24    /// The output of this mode for a given type
25    type Output<T>;
26
27    /// Bind the result of a closure into an output
28    fn bind<T, F: FnOnce() -> T>(f: F) -> Self::Output<T>;
29
30    /// Given an [`Output`](Self::Output), takes its value and return a newly generated output
31    fn map<T, U, F: FnOnce(T) -> U>(x: Self::Output<T>, f: F) -> Self::Output<U>;
32
33    /// Choose between two fallible functions to execute depending on the mode.
34    fn choose<A, T, E, F: FnOnce(A) -> Result<T, E>, G: FnOnce(A) -> Result<(), E>>(
35        arg: A,
36        f: F,
37        g: G,
38    ) -> Result<Self::Output<T>, E>;
39
40    /// Given two [`Output`](Self::Output)s, take their values and combine them into a new
41    /// output value
42    fn combine<T, U, V, F: FnOnce(T, U) -> V>(
43        x: Self::Output<T>,
44        y: Self::Output<U>,
45        f: F,
46    ) -> Self::Output<V>;
47    /// By-reference version of [`Mode::combine`].
48    fn combine_mut<T, U, F: FnOnce(&mut T, U)>(x: &mut Self::Output<T>, y: Self::Output<U>, f: F);
49
50    /// Given an array of outputs, bind them into an output of arrays
51    fn array<T, const N: usize>(x: [Self::Output<T>; N]) -> Self::Output<[T; N]>;
52
53    /// Given an iterator of outputs, collect them into a container. The iterator will always be
54    /// consumed.
55    fn from_iter<T, C: FromIterator<T>>(
56        iter: impl Iterator<Item = Self::Output<T>>,
57    ) -> Self::Output<C>;
58
59    fn from_mut<T>(r: &mut Self::Output<T>) -> Self::Output<&mut T>;
60
61    fn get_or<T, F: FnOnce() -> T>(r: Self::Output<T>, f: F) -> T;
62
63    /// Invoke a parser user the current mode. This is normally equivalent to
64    /// [`parser.go::<M>(inp)`](Parser::go), but it can be called on unsized values such as
65    /// `dyn Parser`.
66    fn invoke<'a, I, O, E, P>(parser: &P, inp: &mut InputRef<'a, '_, I, E>) -> PResult<Self, O>
67    where
68        I: Input<'a>,
69        E: ParserExtra<'a, I>,
70        P: Parser<'a, I, O, E> + ?Sized;
71
72    /// Invoke a parser with configuration using the current mode. This is normally equivalent
73    /// to [`parser.go::<M>(inp)`](ConfigParser::go_cfg), but it can be called on unsized values
74    /// such as `dyn Parser`.
75    fn invoke_cfg<'a, I, O, E, P>(
76        parser: &P,
77        inp: &mut InputRef<'a, '_, I, E>,
78        cfg: P::Config,
79    ) -> PResult<Self, O>
80    where
81        I: Input<'a>,
82        E: ParserExtra<'a, I>,
83        P: ConfigParser<'a, I, O, E> + ?Sized;
84
85    #[cfg(feature = "pratt")]
86    fn invoke_pratt_op_prefix<'src, 'parse, Op, I, O, E>(
87        op: &Op,
88        inp: &mut InputRef<'src, 'parse, I, E>,
89        pre_expr: &input::Checkpoint<'src, 'parse, I, <E::State as Inspector<'src, I>>::Checkpoint>,
90        f: &impl Fn(&mut InputRef<'src, 'parse, I, E>, i32) -> PResult<Self, O>,
91    ) -> pratt::OperatorResult<Self::Output<O>, ()>
92    where
93        Op: pratt::Operator<'src, I, O, E>,
94        I: Input<'src>,
95        E: ParserExtra<'src, I>;
96    #[cfg(feature = "pratt")]
97    fn invoke_pratt_op_postfix<'src, 'parse, Op, I, O, E>(
98        op: &Op,
99        inp: &mut InputRef<'src, 'parse, I, E>,
100        pre_expr: &input::Cursor<'src, 'parse, I>,
101        pre_op: &input::Checkpoint<'src, 'parse, I, <E::State as Inspector<'src, I>>::Checkpoint>,
102        lhs: Self::Output<O>,
103        min_power: i32,
104    ) -> pratt::OperatorResult<Self::Output<O>, Self::Output<O>>
105    where
106        Op: pratt::Operator<'src, I, O, E>,
107        I: Input<'src>,
108        E: ParserExtra<'src, I>;
109    #[cfg(feature = "pratt")]
110    fn invoke_pratt_op_infix<'src, 'parse, Op, I, O, E>(
111        op: &Op,
112        inp: &mut InputRef<'src, 'parse, I, E>,
113        pre_expr: &input::Cursor<'src, 'parse, I>,
114        pre_op: &input::Checkpoint<'src, 'parse, I, <E::State as Inspector<'src, I>>::Checkpoint>,
115        lhs: Self::Output<O>,
116        min_power: i32,
117        f: &impl Fn(&mut InputRef<'src, 'parse, I, E>, i32) -> PResult<Self, O>,
118    ) -> pratt::OperatorResult<Self::Output<O>, Self::Output<O>>
119    where
120        Op: pratt::Operator<'src, I, O, E>,
121        I: Input<'src>,
122        E: ParserExtra<'src, I>;
123}
124
125/// Emit mode - generates parser output
126pub struct Emit;
127
128impl Mode for Emit {
129    type Output<T> = T;
130    #[inline(always)]
131    fn bind<T, F: FnOnce() -> T>(f: F) -> Self::Output<T> {
132        f()
133    }
134    #[inline(always)]
135    fn map<T, U, F: FnOnce(T) -> U>(x: Self::Output<T>, f: F) -> Self::Output<U> {
136        f(x)
137    }
138    #[inline(always)]
139    fn choose<A, T, E, F: FnOnce(A) -> Result<T, E>, G: FnOnce(A) -> Result<(), E>>(
140        arg: A,
141        f: F,
142        _: G,
143    ) -> Result<Self::Output<T>, E> {
144        f(arg)
145    }
146    #[inline(always)]
147    fn combine<T, U, V, F: FnOnce(T, U) -> V>(
148        x: Self::Output<T>,
149        y: Self::Output<U>,
150        f: F,
151    ) -> Self::Output<V> {
152        f(x, y)
153    }
154    #[inline(always)]
155    fn combine_mut<T, U, F: FnOnce(&mut T, U)>(x: &mut Self::Output<T>, y: Self::Output<U>, f: F) {
156        f(x, y)
157    }
158    #[inline(always)]
159    fn array<T, const N: usize>(x: [Self::Output<T>; N]) -> Self::Output<[T; N]> {
160        x
161    }
162    #[inline(always)]
163    fn from_iter<T, C: FromIterator<T>>(
164        iter: impl Iterator<Item = Self::Output<T>>,
165    ) -> Self::Output<C> {
166        iter.collect()
167    }
168
169    #[inline(always)]
170    fn from_mut<T>(r: &mut Self::Output<T>) -> Self::Output<&mut T> {
171        r
172    }
173    #[inline(always)]
174    fn get_or<T, F: FnOnce() -> T>(r: Self::Output<T>, _f: F) -> T {
175        r
176    }
177
178    #[inline(always)]
179    fn invoke<'a, I, O, E, P>(parser: &P, inp: &mut InputRef<'a, '_, I, E>) -> PResult<Self, O>
180    where
181        I: Input<'a>,
182        E: ParserExtra<'a, I>,
183        P: Parser<'a, I, O, E> + ?Sized,
184    {
185        parser.go_emit(inp)
186    }
187
188    #[inline(always)]
189    fn invoke_cfg<'a, I, O, E, P>(
190        parser: &P,
191        inp: &mut InputRef<'a, '_, I, E>,
192        cfg: P::Config,
193    ) -> PResult<Self, O>
194    where
195        I: Input<'a>,
196        E: ParserExtra<'a, I>,
197        P: ConfigParser<'a, I, O, E> + ?Sized,
198    {
199        parser.go_emit_cfg(inp, cfg)
200    }
201
202    #[cfg(feature = "pratt")]
203    #[inline(always)]
204    fn invoke_pratt_op_prefix<'src, 'parse, Op, I, O, E>(
205        op: &Op,
206        inp: &mut InputRef<'src, 'parse, I, E>,
207        pre_expr: &input::Checkpoint<'src, 'parse, I, <E::State as Inspector<'src, I>>::Checkpoint>,
208        f: &impl Fn(&mut InputRef<'src, 'parse, I, E>, i32) -> PResult<Self, O>,
209    ) -> pratt::OperatorResult<Self::Output<O>, ()>
210    where
211        Op: pratt::Operator<'src, I, O, E>,
212        I: Input<'src>,
213        E: ParserExtra<'src, I>,
214    {
215        op.do_parse_prefix_emit(inp, pre_expr, &f)
216    }
217    #[cfg(feature = "pratt")]
218    #[inline(always)]
219    fn invoke_pratt_op_postfix<'src, 'parse, Op, I, O, E>(
220        op: &Op,
221        inp: &mut InputRef<'src, 'parse, I, E>,
222        pre_expr: &input::Cursor<'src, 'parse, I>,
223        pre_op: &input::Checkpoint<'src, 'parse, I, <E::State as Inspector<'src, I>>::Checkpoint>,
224        lhs: Self::Output<O>,
225        min_power: i32,
226    ) -> pratt::OperatorResult<Self::Output<O>, Self::Output<O>>
227    where
228        Op: pratt::Operator<'src, I, O, E>,
229        I: Input<'src>,
230        E: ParserExtra<'src, I>,
231    {
232        op.do_parse_postfix_emit(inp, pre_expr, pre_op, lhs, min_power)
233    }
234    #[cfg(feature = "pratt")]
235    #[inline(always)]
236    fn invoke_pratt_op_infix<'src, 'parse, Op, I, O, E>(
237        op: &Op,
238        inp: &mut InputRef<'src, 'parse, I, E>,
239        pre_expr: &input::Cursor<'src, 'parse, I>,
240        pre_op: &input::Checkpoint<'src, 'parse, I, <E::State as Inspector<'src, I>>::Checkpoint>,
241        lhs: Self::Output<O>,
242        min_power: i32,
243        f: &impl Fn(&mut InputRef<'src, 'parse, I, E>, i32) -> PResult<Self, O>,
244    ) -> pratt::OperatorResult<Self::Output<O>, Self::Output<O>>
245    where
246        Op: pratt::Operator<'src, I, O, E>,
247        I: Input<'src>,
248        E: ParserExtra<'src, I>,
249    {
250        op.do_parse_infix_emit(inp, pre_expr, pre_op, lhs, min_power, &f)
251    }
252}
253
254/// Check mode - all output is discarded, and only uses parsers to check validity
255pub struct Check;
256
257impl Mode for Check {
258    type Output<T> = ();
259    #[inline(always)]
260    fn bind<T, F: FnOnce() -> T>(_: F) -> Self::Output<T> {}
261    #[inline(always)]
262    fn map<T, U, F: FnOnce(T) -> U>(_: Self::Output<T>, _: F) -> Self::Output<U> {}
263    #[inline(always)]
264    fn choose<A, T, E, F: FnOnce(A) -> Result<T, E>, G: FnOnce(A) -> Result<(), E>>(
265        arg: A,
266        _: F,
267        g: G,
268    ) -> Result<Self::Output<T>, E> {
269        g(arg)
270    }
271    #[inline(always)]
272    fn combine<T, U, V, F: FnOnce(T, U) -> V>(
273        _: Self::Output<T>,
274        _: Self::Output<U>,
275        _: F,
276    ) -> Self::Output<V> {
277    }
278    #[inline(always)]
279    fn combine_mut<T, U, F: FnOnce(&mut T, U)>(_: &mut Self::Output<T>, _: Self::Output<U>, _: F) {}
280    #[inline(always)]
281    fn array<T, const N: usize>(_: [Self::Output<T>; N]) -> Self::Output<[T; N]> {}
282    #[inline(always)]
283    fn from_iter<T, C: FromIterator<T>>(
284        iter: impl Iterator<Item = Self::Output<T>>,
285    ) -> Self::Output<C> {
286        iter.for_each(drop);
287    }
288    #[inline(always)]
289    fn from_mut<T>(_r: &mut Self::Output<T>) -> Self::Output<&mut T> {}
290    #[inline(always)]
291    fn get_or<T, F: FnOnce() -> T>(_r: Self::Output<T>, f: F) -> T {
292        f()
293    }
294
295    #[inline(always)]
296    fn invoke<'a, I, O, E, P>(parser: &P, inp: &mut InputRef<'a, '_, I, E>) -> PResult<Self, O>
297    where
298        I: Input<'a>,
299        E: ParserExtra<'a, I>,
300        P: Parser<'a, I, O, E> + ?Sized,
301    {
302        parser.go_check(inp)
303    }
304
305    #[inline(always)]
306    fn invoke_cfg<'a, I, O, E, P>(
307        parser: &P,
308        inp: &mut InputRef<'a, '_, I, E>,
309        cfg: P::Config,
310    ) -> PResult<Self, O>
311    where
312        I: Input<'a>,
313        E: ParserExtra<'a, I>,
314        P: ConfigParser<'a, I, O, E> + ?Sized,
315    {
316        parser.go_check_cfg(inp, cfg)
317    }
318
319    #[cfg(feature = "pratt")]
320    #[inline(always)]
321    fn invoke_pratt_op_prefix<'src, 'parse, Op, I, O, E>(
322        op: &Op,
323        inp: &mut InputRef<'src, 'parse, I, E>,
324        pre_expr: &input::Checkpoint<'src, 'parse, I, <E::State as Inspector<'src, I>>::Checkpoint>,
325        f: &impl Fn(&mut InputRef<'src, 'parse, I, E>, i32) -> PResult<Self, O>,
326    ) -> pratt::OperatorResult<Self::Output<O>, ()>
327    where
328        Op: pratt::Operator<'src, I, O, E>,
329        I: Input<'src>,
330        E: ParserExtra<'src, I>,
331    {
332        op.do_parse_prefix_check(inp, pre_expr, &f)
333    }
334    #[cfg(feature = "pratt")]
335    #[inline(always)]
336    fn invoke_pratt_op_postfix<'src, 'parse, Op, I, O, E>(
337        op: &Op,
338        inp: &mut InputRef<'src, 'parse, I, E>,
339        pre_expr: &input::Cursor<'src, 'parse, I>,
340        pre_op: &input::Checkpoint<'src, 'parse, I, <E::State as Inspector<'src, I>>::Checkpoint>,
341        lhs: Self::Output<O>,
342        min_power: i32,
343    ) -> pratt::OperatorResult<Self::Output<O>, Self::Output<O>>
344    where
345        Op: pratt::Operator<'src, I, O, E>,
346        I: Input<'src>,
347        E: ParserExtra<'src, I>,
348    {
349        op.do_parse_postfix_check(inp, pre_expr, pre_op, lhs, min_power)
350    }
351    #[cfg(feature = "pratt")]
352    #[inline(always)]
353    fn invoke_pratt_op_infix<'src, 'parse, Op, I, O, E>(
354        op: &Op,
355        inp: &mut InputRef<'src, 'parse, I, E>,
356        pre_expr: &input::Cursor<'src, 'parse, I>,
357        pre_op: &input::Checkpoint<'src, 'parse, I, <E::State as Inspector<'src, I>>::Checkpoint>,
358        lhs: Self::Output<O>,
359        min_power: i32,
360        f: &impl Fn(&mut InputRef<'src, 'parse, I, E>, i32) -> PResult<Self, O>,
361    ) -> pratt::OperatorResult<Self::Output<O>, Self::Output<O>>
362    where
363        Op: pratt::Operator<'src, I, O, E>,
364        I: Input<'src>,
365        E: ParserExtra<'src, I>,
366    {
367        op.do_parse_infix_check(inp, pre_expr, pre_op, lhs, min_power, &f)
368    }
369}
370
371// TODO: Remove this when MaybeUninit transforms to/from arrays stabilize in any form
372pub(crate) trait MaybeUninitExt<T>: Sized {
373    /// Identical to the unstable [`MaybeUninit::uninit_array`]
374    fn uninit_array<const N: usize>() -> [Self; N];
375
376    /// Identical to the unstable [`MaybeUninit::array_assume_init`]
377    unsafe fn array_assume_init<const N: usize>(uninit: [Self; N]) -> [T; N];
378}
379
380impl<T> MaybeUninitExt<T> for MaybeUninit<T> {
381    #[allow(clippy::uninit_assumed_init)]
382    fn uninit_array<const N: usize>() -> [Self; N] {
383        // SAFETY: Output type is entirely uninhabited - IE, it's made up entirely of `MaybeUninit`
384        unsafe { MaybeUninit::uninit().assume_init() }
385    }
386
387    unsafe fn array_assume_init<const N: usize>(uninit: [Self; N]) -> [T; N] {
388        (&uninit as *const [Self; N] as *const [T; N]).read()
389    }
390}
391
392pub trait Sealed {}