Skip to main content

chumsky/
pratt.rs

1//! Utilities for parsing expressions using
2//! [Pratt parsing](https://en.wikipedia.org/wiki/Operator-precedence_parser#Pratt_parsing).
3//!
4//! *“Who am I? What is my purpose in life? Does it really, cosmically speaking, matter if I don’t get up and go to work?”*
5//!
6//! Pratt parsing is a powerful technique for defining and parsing operators of varying arity, precedence, and
7//! associativity. Unlike [precedence climbing](https://en.wikipedia.org/wiki/Operator-precedence_parser), which
8//! defines operator precedence by structurally composing parsers of decreasing precedence, Pratt parsing defines
9//! precedence through a numerical
10//! ['binding power'](https://matklad.github.io/2020/04/13/simple-but-powerful-pratt-parsing.html#From-Precedence-to-Binding-Power)
11//! that determines how strongly operators should bind to the operands around them.
12//!
13//! Pratt parsers are defined with the [`Parser::pratt`] method.
14//!
15//! When writing pratt parsers, it is necessary to first define an 'atomic' operand used by the parser for building up
16//! expressions. In most languages, atoms are simple, self-delimiting patterns such as numeric and string literals,
17//! identifiers, or parenthesised expressions. Once an atom has been defined, operators can also be defined that
18//! operate upon said atoms.
19//!
20//! # Fold functions
21//!
22//! Because operators bind atoms together, pratt parsers require you to specify, for each operator, a function that
23//! combines its operands together into a syntax tree. These functions are given as the last arguments of [`infix`],
24//! [`prefix`], and [`postfix`].
25//!
26//! # Examples
27//!
28//! ```
29//! use chumsky::prelude::*;
30//! use chumsky::pratt::*;
31//! use chumsky::extra;
32//!
33//! enum Expr {
34//!     Add(Box<Self>, Box<Self>),
35//!     Sub(Box<Self>, Box<Self>),
36//!     Pow(Box<Self>, Box<Self>),
37//!     Neg(Box<Self>),
38//!     Factorial(Box<Self>),
39//!     Deref(Box<Self>),
40//!     Literal(i32),
41//! }
42//!
43//! impl std::fmt::Display for Expr {
44//!     fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
45//!         match self {
46//!             Self::Literal(literal) => write!(f, "{literal}"),
47//!             Self::Factorial(left) => write!(f, "({left}!)"),
48//!             Self::Deref(left) => write!(f, "(*{left})"),
49//!             Self::Neg(right) => write!(f, "(-{right})"),
50//!             Self::Add(left, right) => write!(f, "({left} + {right})"),
51//!             Self::Sub(left, right) => write!(f, "({left} - {right})"),
52//!             Self::Pow(left, right) => write!(f, "({left} ^ {right})"),
53//!         }
54//!     }
55//! }
56//!
57//! let atom = text::int::<_, extra::Err<Simple<char>>>(10)
58//!     .from_str()
59//!     .unwrapped()
60//!     .map(Expr::Literal)
61//!     .padded();
62//!
63//! let op = |c| just(c).padded();
64//!
65//! let expr = atom.pratt((
66//!     // We want factorial to happen before any negation, so we
67//!     // need its precedence to be higher than `Expr::Neg`.
68//!     postfix(4, op('!'), |lhs, _, _| Expr::Factorial(Box::new(lhs))),
69//!     // Just like in math, we want that if we write -x^2, our parser
70//!     // parses that as -(x^2), so we need it to have exponents bind
71//!     // tighter than our prefix operators.
72//!     infix(right(3), op('^'), |l, _, r, _| Expr::Pow(Box::new(l), Box::new(r))),
73//!     // Notice the conflict with our `Expr::Sub`. This will still
74//!     // parse correctly. We want negation to happen before `+` and
75//!     // `-`, so we set its precedence higher.
76//!     prefix(2, op('-'), |_, rhs, _| Expr::Neg(Box::new(rhs))),
77//!     prefix(2, op('*'), |_, rhs, _| Expr::Deref(Box::new(rhs))),
78//!     // Our `-` and `+` bind the weakest, meaning that even if they
79//!     // occur first in an expression, they will be the last executed.
80//!     infix(left(1), op('+'), |l, _, r, _| Expr::Add(Box::new(l), Box::new(r))),
81//!     infix(left(1), op('-'), |l, _, r, _| Expr::Sub(Box::new(l), Box::new(r))),
82//! ))
83//!     .map(|x| x.to_string());
84//!
85//! assert_eq!(
86//!     expr.parse("*1 + -2! - -3^2").into_result(),
87//!     Ok("(((*1) + (-(2!))) - (-(3 ^ 2)))".to_string()),
88//! );
89//! ```
90//!
91//! `left`, `right` and `none` are shorthand versions of `Associativity` variants.
92
93use super::*;
94
95/// The result of calling [`Operator::do_parse_prefix`], [`Operator::do_parse_postfix`] or [`Operator::do_parse_infix`]
96pub enum OperatorResult<T, E> {
97    /// Input was parsed
98    Ok(T),
99    /// Input could not be parsed, not fatal
100    NoMatch(E),
101    /// Input could not be parsed, fatal error
102    Err(E),
103}
104
105macro_rules! op_check_and_emit {
106    () => {
107        #[inline(always)]
108        fn do_parse_prefix_check<'parse>(
109            &self,
110            inp: &mut InputRef<'src, 'parse, I, E>,
111            pre_expr: &input::Checkpoint<
112                'src,
113                'parse,
114                I,
115                <E::State as Inspector<'src, I>>::Checkpoint,
116            >,
117            f: &dyn Fn(&mut InputRef<'src, 'parse, I, E>, i32) -> PResult<Check, O>,
118        ) -> OperatorResult<<Check as Mode>::Output<O>, ()> {
119            self.do_parse_prefix::<Check>(inp, pre_expr, &f)
120        }
121        #[inline(always)]
122        fn do_parse_prefix_emit<'parse>(
123            &self,
124            inp: &mut InputRef<'src, 'parse, I, E>,
125            pre_expr: &input::Checkpoint<
126                'src,
127                'parse,
128                I,
129                <E::State as Inspector<'src, I>>::Checkpoint,
130            >,
131            f: &dyn Fn(&mut InputRef<'src, 'parse, I, E>, i32) -> PResult<Emit, O>,
132        ) -> OperatorResult<<Emit as Mode>::Output<O>, ()> {
133            self.do_parse_prefix::<Emit>(inp, pre_expr, &f)
134        }
135        #[inline(always)]
136        fn do_parse_postfix_check<'parse>(
137            &self,
138            inp: &mut InputRef<'src, 'parse, I, E>,
139            pre_expr: &input::Cursor<'src, 'parse, I>,
140            pre_op: &input::Checkpoint<
141                'src,
142                'parse,
143                I,
144                <E::State as Inspector<'src, I>>::Checkpoint,
145            >,
146            lhs: (),
147            min_power: i32,
148        ) -> OperatorResult<(), ()> {
149            self.do_parse_postfix::<Check>(inp, pre_expr, pre_op, lhs, min_power)
150        }
151        #[inline(always)]
152        fn do_parse_postfix_emit<'parse>(
153            &self,
154            inp: &mut InputRef<'src, 'parse, I, E>,
155            pre_expr: &input::Cursor<'src, 'parse, I>,
156            pre_op: &input::Checkpoint<
157                'src,
158                'parse,
159                I,
160                <E::State as Inspector<'src, I>>::Checkpoint,
161            >,
162            lhs: O,
163            min_power: i32,
164        ) -> OperatorResult<O, O> {
165            self.do_parse_postfix::<Emit>(inp, pre_expr, pre_op, lhs, min_power)
166        }
167        #[inline(always)]
168        fn do_parse_infix_check<'parse>(
169            &self,
170            inp: &mut InputRef<'src, 'parse, I, E>,
171            pre_expr: &input::Cursor<'src, 'parse, I>,
172            pre_op: &input::Checkpoint<
173                'src,
174                'parse,
175                I,
176                <E::State as Inspector<'src, I>>::Checkpoint,
177            >,
178            lhs: (),
179            min_power: i32,
180            f: &dyn Fn(&mut InputRef<'src, 'parse, I, E>, i32) -> PResult<Check, O>,
181        ) -> OperatorResult<(), ()> {
182            self.do_parse_infix::<Check>(inp, pre_expr, pre_op, lhs, min_power, &f)
183        }
184        #[inline(always)]
185        fn do_parse_infix_emit<'parse>(
186            &self,
187            inp: &mut InputRef<'src, 'parse, I, E>,
188            pre_expr: &input::Cursor<'src, 'parse, I>,
189            pre_op: &input::Checkpoint<
190                'src,
191                'parse,
192                I,
193                <E::State as Inspector<'src, I>>::Checkpoint,
194            >,
195            lhs: O,
196            min_power: i32,
197            f: &dyn Fn(&mut InputRef<'src, 'parse, I, E>, i32) -> PResult<Emit, O>,
198        ) -> OperatorResult<O, O> {
199            self.do_parse_infix::<Emit>(inp, pre_expr, pre_op, lhs, min_power, &f)
200        }
201    };
202}
203
204/// A type implemented by pratt parser operators.
205pub trait Operator<'src, I, O, E>
206where
207    I: Input<'src>,
208    E: ParserExtra<'src, I>,
209{
210    /// Box this operator, allowing it to be used via dynamic dispatch.
211    fn boxed<'a>(self) -> Boxed<'src, 'a, I, O, E>
212    where
213        Self: Sized + 'a,
214    {
215        Boxed(Rc::new(self))
216    }
217
218    #[doc(hidden)]
219    #[inline(always)]
220    fn do_parse_prefix<'parse, M: Mode>(
221        &self,
222        _inp: &mut InputRef<'src, 'parse, I, E>,
223        _pre_expr: &input::Checkpoint<
224            'src,
225            'parse,
226            I,
227            <E::State as Inspector<'src, I>>::Checkpoint,
228        >,
229        _f: &impl Fn(&mut InputRef<'src, 'parse, I, E>, i32) -> PResult<M, O>,
230    ) -> OperatorResult<M::Output<O>, ()>
231    where
232        Self: Sized,
233    {
234        OperatorResult::NoMatch(())
235    }
236
237    #[doc(hidden)]
238    #[inline(always)]
239    fn do_parse_postfix<'parse, M: Mode>(
240        &self,
241        _inp: &mut InputRef<'src, 'parse, I, E>,
242        _pre_expr: &input::Cursor<'src, 'parse, I>,
243        _pre_op: &input::Checkpoint<'src, 'parse, I, <E::State as Inspector<'src, I>>::Checkpoint>,
244        lhs: M::Output<O>,
245        _min_power: i32,
246    ) -> OperatorResult<M::Output<O>, M::Output<O>>
247    where
248        Self: Sized,
249    {
250        OperatorResult::NoMatch(lhs)
251    }
252
253    #[doc(hidden)]
254    #[inline(always)]
255    fn do_parse_infix<'parse, M: Mode>(
256        &self,
257        _inp: &mut InputRef<'src, 'parse, I, E>,
258        _pre_expr: &input::Cursor<'src, 'parse, I>,
259        _pre_op: &input::Checkpoint<'src, 'parse, I, <E::State as Inspector<'src, I>>::Checkpoint>,
260        lhs: M::Output<O>,
261        _min_power: i32,
262        _f: &impl Fn(&mut InputRef<'src, 'parse, I, E>, i32) -> PResult<M, O>,
263    ) -> OperatorResult<M::Output<O>, M::Output<O>>
264    where
265        Self: Sized,
266    {
267        OperatorResult::NoMatch(lhs)
268    }
269
270    #[doc(hidden)]
271    fn do_parse_prefix_check<'parse>(
272        &self,
273        inp: &mut InputRef<'src, 'parse, I, E>,
274        pre_expr: &input::Checkpoint<'src, 'parse, I, <E::State as Inspector<'src, I>>::Checkpoint>,
275        f: &dyn Fn(&mut InputRef<'src, 'parse, I, E>, i32) -> PResult<Check, O>,
276    ) -> OperatorResult<<Check as Mode>::Output<O>, ()>;
277    #[doc(hidden)]
278    fn do_parse_prefix_emit<'parse>(
279        &self,
280        inp: &mut InputRef<'src, 'parse, I, E>,
281        pre_expr: &input::Checkpoint<'src, 'parse, I, <E::State as Inspector<'src, I>>::Checkpoint>,
282        f: &dyn Fn(&mut InputRef<'src, 'parse, I, E>, i32) -> PResult<Emit, O>,
283    ) -> OperatorResult<<Emit as Mode>::Output<O>, ()>;
284    #[doc(hidden)]
285    fn do_parse_postfix_check<'parse>(
286        &self,
287        inp: &mut InputRef<'src, 'parse, I, E>,
288        pre_expr: &input::Cursor<'src, 'parse, I>,
289        pre_op: &input::Checkpoint<'src, 'parse, I, <E::State as Inspector<'src, I>>::Checkpoint>,
290        lhs: (),
291        min_power: i32,
292    ) -> OperatorResult<(), ()>;
293    #[doc(hidden)]
294    fn do_parse_postfix_emit<'parse>(
295        &self,
296        inp: &mut InputRef<'src, 'parse, I, E>,
297        pre_expr: &input::Cursor<'src, 'parse, I>,
298        pre_op: &input::Checkpoint<'src, 'parse, I, <E::State as Inspector<'src, I>>::Checkpoint>,
299        lhs: O,
300        min_power: i32,
301    ) -> OperatorResult<O, O>;
302    #[doc(hidden)]
303    fn do_parse_infix_check<'parse>(
304        &self,
305        inp: &mut InputRef<'src, 'parse, I, E>,
306        pre_expr: &input::Cursor<'src, 'parse, I>,
307        pre_op: &input::Checkpoint<'src, 'parse, I, <E::State as Inspector<'src, I>>::Checkpoint>,
308        lhs: (),
309        min_power: i32,
310        f: &dyn Fn(&mut InputRef<'src, 'parse, I, E>, i32) -> PResult<Check, O>,
311    ) -> OperatorResult<(), ()>;
312    #[doc(hidden)]
313    fn do_parse_infix_emit<'parse>(
314        &self,
315        inp: &mut InputRef<'src, 'parse, I, E>,
316        pre_expr: &input::Cursor<'src, 'parse, I>,
317        pre_op: &input::Checkpoint<'src, 'parse, I, <E::State as Inspector<'src, I>>::Checkpoint>,
318        lhs: O,
319        min_power: i32,
320        f: &dyn Fn(&mut InputRef<'src, 'parse, I, E>, i32) -> PResult<Emit, O>,
321    ) -> OperatorResult<O, O>;
322}
323
324/// A boxed pratt parser operator. See [`Operator`].
325pub struct Boxed<'src, 'a, I, O, E = extra::Default>(Rc<DynOperator<'src, 'a, I, O, E>>);
326
327impl<I, O, E> Clone for Boxed<'_, '_, I, O, E> {
328    fn clone(&self) -> Self {
329        Self(self.0.clone())
330    }
331}
332
333impl<'src, I, O, E> Operator<'src, I, O, E> for Boxed<'src, '_, I, O, E>
334where
335    I: Input<'src>,
336    E: ParserExtra<'src, I>,
337{
338    #[inline(always)]
339    fn do_parse_prefix<'parse, M: Mode>(
340        &self,
341        inp: &mut InputRef<'src, 'parse, I, E>,
342        pre_expr: &input::Checkpoint<'src, 'parse, I, <E::State as Inspector<'src, I>>::Checkpoint>,
343        f: &impl Fn(&mut InputRef<'src, 'parse, I, E>, i32) -> PResult<M, O>,
344    ) -> OperatorResult<M::Output<O>, ()>
345    where
346        Self: Sized,
347    {
348        M::invoke_pratt_op_prefix(self, inp, pre_expr, f)
349    }
350
351    #[inline(always)]
352    fn do_parse_postfix<'parse, M: Mode>(
353        &self,
354        inp: &mut InputRef<'src, 'parse, I, E>,
355        pre_expr: &input::Cursor<'src, 'parse, I>,
356        pre_op: &input::Checkpoint<'src, 'parse, I, <E::State as Inspector<'src, I>>::Checkpoint>,
357        lhs: M::Output<O>,
358        min_power: i32,
359    ) -> OperatorResult<M::Output<O>, M::Output<O>>
360    where
361        Self: Sized,
362    {
363        M::invoke_pratt_op_postfix(self, inp, pre_expr, pre_op, lhs, min_power)
364    }
365
366    #[inline(always)]
367    fn do_parse_infix<'parse, M: Mode>(
368        &self,
369        inp: &mut InputRef<'src, 'parse, I, E>,
370        pre_expr: &input::Cursor<'src, 'parse, I>,
371        pre_op: &input::Checkpoint<'src, 'parse, I, <E::State as Inspector<'src, I>>::Checkpoint>,
372        lhs: M::Output<O>,
373        min_power: i32,
374        f: &impl Fn(&mut InputRef<'src, 'parse, I, E>, i32) -> PResult<M, O>,
375    ) -> OperatorResult<M::Output<O>, M::Output<O>>
376    where
377        Self: Sized,
378    {
379        M::invoke_pratt_op_infix(self, inp, pre_expr, pre_op, lhs, min_power, f)
380    }
381
382    #[inline(always)]
383    fn do_parse_prefix_check<'parse>(
384        &self,
385        inp: &mut InputRef<'src, 'parse, I, E>,
386        pre_expr: &input::Checkpoint<'src, 'parse, I, <E::State as Inspector<'src, I>>::Checkpoint>,
387        f: &dyn Fn(&mut InputRef<'src, 'parse, I, E>, i32) -> PResult<Check, O>,
388    ) -> OperatorResult<<Check as Mode>::Output<O>, ()> {
389        self.0.do_parse_prefix_check(inp, pre_expr, f)
390    }
391    #[inline(always)]
392    fn do_parse_prefix_emit<'parse>(
393        &self,
394        inp: &mut InputRef<'src, 'parse, I, E>,
395        pre_expr: &input::Checkpoint<'src, 'parse, I, <E::State as Inspector<'src, I>>::Checkpoint>,
396        f: &dyn Fn(&mut InputRef<'src, 'parse, I, E>, i32) -> PResult<Emit, O>,
397    ) -> OperatorResult<<Emit as Mode>::Output<O>, ()> {
398        self.0.do_parse_prefix_emit(inp, pre_expr, f)
399    }
400    #[inline(always)]
401    fn do_parse_postfix_check<'parse>(
402        &self,
403        inp: &mut InputRef<'src, 'parse, I, E>,
404        pre_expr: &input::Cursor<'src, 'parse, I>,
405        pre_op: &input::Checkpoint<'src, 'parse, I, <E::State as Inspector<'src, I>>::Checkpoint>,
406        lhs: (),
407        min_power: i32,
408    ) -> OperatorResult<(), ()> {
409        self.0
410            .do_parse_postfix_check(inp, pre_expr, pre_op, lhs, min_power)
411    }
412    #[inline(always)]
413    fn do_parse_postfix_emit<'parse>(
414        &self,
415        inp: &mut InputRef<'src, 'parse, I, E>,
416        pre_expr: &input::Cursor<'src, 'parse, I>,
417        pre_op: &input::Checkpoint<'src, 'parse, I, <E::State as Inspector<'src, I>>::Checkpoint>,
418        lhs: O,
419        min_power: i32,
420    ) -> OperatorResult<O, O> {
421        self.0
422            .do_parse_postfix_emit(inp, pre_expr, pre_op, lhs, min_power)
423    }
424    #[inline(always)]
425    fn do_parse_infix_check<'parse>(
426        &self,
427        inp: &mut InputRef<'src, 'parse, I, E>,
428        pre_expr: &input::Cursor<'src, 'parse, I>,
429        pre_op: &input::Checkpoint<'src, 'parse, I, <E::State as Inspector<'src, I>>::Checkpoint>,
430        lhs: (),
431        min_power: i32,
432        f: &dyn Fn(&mut InputRef<'src, 'parse, I, E>, i32) -> PResult<Check, O>,
433    ) -> OperatorResult<(), ()> {
434        self.0
435            .do_parse_infix_check(inp, pre_expr, pre_op, lhs, min_power, &f)
436    }
437    #[inline(always)]
438    fn do_parse_infix_emit<'parse>(
439        &self,
440        inp: &mut InputRef<'src, 'parse, I, E>,
441        pre_expr: &input::Cursor<'src, 'parse, I>,
442        pre_op: &input::Checkpoint<'src, 'parse, I, <E::State as Inspector<'src, I>>::Checkpoint>,
443        lhs: O,
444        min_power: i32,
445        f: &dyn Fn(&mut InputRef<'src, 'parse, I, E>, i32) -> PResult<Emit, O>,
446    ) -> OperatorResult<O, O> {
447        self.0
448            .do_parse_infix_emit(inp, pre_expr, pre_op, lhs, min_power, &f)
449    }
450}
451
452/// Defines the [associativity](https://en.wikipedia.org/wiki/Associative_property) and precedence of an [`infix`]
453/// operator (see [`left`], [`right`] and [`none`]).
454///
455/// Higher numbers should be used for higher precedence operators.
456#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
457pub enum Associativity {
458    /// Specifies that the operator should be left-associative, with the given precedence (see [`left`]).
459    Left(u16),
460    /// Specifies that the operator should be right-associative, with the given precedence (see [`right`]).
461    Right(u16),
462    /// Specifies that the operator is non-associative, with the given precedence (see [`none`]).
463    None(u16),
464}
465
466/// Specifies a left [`Associativity`] with the given precedence.
467///
468/// Left-associative operators are evaluated from the left-most terms, moving rightward. For example, the expression
469/// `a + b + c + d` will be evaluated as `((a + b) + c) + d` because addition is conventionally left-associative.
470pub fn left(precedence: u16) -> Associativity {
471    Associativity::Left(precedence)
472}
473
474/// Specifies a right [`Associativity`] with the given precedence.
475///
476/// Right-associative operators are evaluated from the right-most terms, moving leftward. For example, the expression
477/// `a ^ b ^ c ^ d` will be evaluated as `a ^ (b ^ (c ^ d))` because exponents are conventionally right-associative.
478pub fn right(precedence: u16) -> Associativity {
479    Associativity::Right(precedence)
480}
481
482/// Specifies no [`Associativity`] with the given precedence.
483///
484/// Non-associative operators can't be chained. For example, the expression
485/// `a < b < c` will produce an error, because comparisons are conventionally non-associative.
486pub fn none(precedence: u16) -> Associativity {
487    Associativity::None(precedence)
488}
489
490impl Associativity {
491    fn left_power(&self) -> i32 {
492        match self {
493            Self::Left(x) => *x as i32 * 2,
494            Self::Right(x) => *x as i32 * 2 + 1,
495            Self::None(x) => *x as i32 * 2,
496        }
497    }
498
499    fn right_power(&self) -> i32 {
500        match self {
501            Self::Left(x) => *x as i32 * 2 + 1,
502            Self::Right(x) => *x as i32 * 2,
503            Self::None(x) => *x as i32 * 2,
504        }
505    }
506}
507
508/// See [`infix`].
509pub struct Infix<'src, A, F, Atom, Op, I, E> {
510    op_parser: A,
511    fold: F,
512    associativity: Associativity,
513    #[allow(dead_code)]
514    phantom: EmptyPhantom<&'src (Atom, Op, I, E)>,
515}
516
517impl<A: Copy, F: Copy, Atom, Op, I, E> Copy for Infix<'_, A, F, Atom, Op, I, E> {}
518impl<A: Clone, F: Clone, Atom, Op, I, E> Clone for Infix<'_, A, F, Atom, Op, I, E> {
519    fn clone(&self) -> Self {
520        Self {
521            op_parser: self.op_parser.clone(),
522            fold: self.fold.clone(),
523            associativity: self.associativity,
524            phantom: EmptyPhantom::new(),
525        }
526    }
527}
528
529/// Specify a binary infix operator for a pratt parser with the given associativity, precedence, and
530/// [fold function](crate::pratt#fold-functions).
531///
532/// Operators like addition, subtraction, multiplication, division, remainder, exponentiation, etc. are infix binary
533/// operators in most languages.
534///
535/// See [`left`] and [`right`] for information about associativity.
536///
537/// The fold function (the last argument) tells the parser how to combine the operator and operands into a new
538/// expression. It must have the following signature:
539///
540/// ```ignore
541/// impl Fn(Atom, Op, Atom, &mut MapExtra<'src, '_, I, E>) -> O
542/// ```
543pub const fn infix<'src, A, F, Atom, Op, I, E>(
544    associativity: Associativity,
545    op_parser: A,
546    fold: F,
547) -> Infix<'src, A, F, Atom, Op, I, E>
548where
549    F: Fn(Atom, Op, Atom, &mut MapExtra<'src, '_, I, E>) -> Atom,
550{
551    Infix {
552        op_parser,
553        fold,
554        associativity,
555        phantom: EmptyPhantom::new(),
556    }
557}
558
559impl<'src, I, O, E, A, F, Op> Operator<'src, I, O, E> for Infix<'src, A, F, O, Op, I, E>
560where
561    I: Input<'src>,
562    E: ParserExtra<'src, I>,
563    A: Parser<'src, I, Op, E>,
564    F: Fn(O, Op, O, &mut MapExtra<'src, '_, I, E>) -> O,
565{
566    #[inline]
567    fn do_parse_infix<'parse, M: Mode>(
568        &self,
569        inp: &mut InputRef<'src, 'parse, I, E>,
570        pre_expr: &input::Cursor<'src, 'parse, I>,
571        pre_op: &input::Checkpoint<'src, 'parse, I, <E::State as Inspector<'src, I>>::Checkpoint>,
572        lhs: M::Output<O>,
573        min_power: i32,
574        f: &impl Fn(&mut InputRef<'src, 'parse, I, E>, i32) -> PResult<M, O>,
575    ) -> OperatorResult<M::Output<O>, M::Output<O>>
576    where
577        Self: Sized,
578    {
579        match self.op_parser.go::<M>(inp) {
580            Ok(op) => {
581                let binding_power = self.associativity.left_power();
582
583                let power_check = if let Associativity::None(_) = self.associativity {
584                    binding_power > min_power
585                } else {
586                    binding_power >= min_power
587                };
588                if power_check {
589                    match f(inp, self.associativity.right_power()) {
590                        Ok(rhs) => OperatorResult::Ok(M::combine(
591                            M::combine(lhs, rhs, |lhs, rhs| (lhs, rhs)),
592                            op,
593                            |(lhs, rhs), op| {
594                                (self.fold)(lhs, op, rhs, &mut MapExtra::new(pre_expr, inp))
595                            },
596                        )),
597                        Err(()) => {
598                            inp.rewind(pre_op.clone());
599                            OperatorResult::NoMatch(lhs)
600                        }
601                    }
602                } else {
603                    inp.rewind(pre_op.clone());
604
605                    if binding_power == min_power {
606                        // TODO: Add error "Ambigious operator order"
607                        OperatorResult::Err(lhs)
608                    } else {
609                        OperatorResult::NoMatch(lhs)
610                    }
611                }
612            }
613            Err(()) => {
614                inp.rewind(pre_op.clone());
615                OperatorResult::NoMatch(lhs)
616            }
617        }
618    }
619
620    op_check_and_emit!();
621}
622
623/// See [`prefix`].
624pub struct Prefix<'src, A, F, Atom, Op, I, E> {
625    op_parser: A,
626    fold: F,
627    binding_power: i32,
628    #[allow(dead_code)]
629    phantom: EmptyPhantom<&'src (Atom, Op, I, E)>,
630}
631
632impl<A: Copy, F: Copy, Atom, Op, I, E> Copy for Prefix<'_, A, F, Atom, Op, I, E> {}
633impl<A: Clone, F: Clone, Atom, Op, I, E> Clone for Prefix<'_, A, F, Atom, Op, I, E> {
634    fn clone(&self) -> Self {
635        Self {
636            op_parser: self.op_parser.clone(),
637            fold: self.fold.clone(),
638            binding_power: self.binding_power,
639            phantom: EmptyPhantom::new(),
640        }
641    }
642}
643
644/// Specify a unary prefix operator for a pratt parser with the given precedence and
645/// [fold function](crate::pratt#fold-functions).
646///
647/// Operators like negation, not, dereferencing, etc. are prefix unary operators in most languages.
648///
649/// The fold function (the last argument) tells the parser how to combine the operator and operand into a new
650/// expression. It must have the following signature:
651///
652/// ```ignore
653/// impl Fn(Op, Atom, &mut MapExtra<'src, '_, I, E>) -> O
654/// ```
655pub const fn prefix<'src, A, F, Atom, Op, I, E>(
656    precedence: u16,
657    op_parser: A,
658    fold: F,
659) -> Prefix<'src, A, F, Atom, Op, I, E>
660where
661    F: Fn(Op, Atom, &mut MapExtra<'src, '_, I, E>) -> Atom,
662{
663    Prefix {
664        op_parser,
665        fold,
666        binding_power: precedence as i32 * 2,
667        phantom: EmptyPhantom::new(),
668    }
669}
670
671impl<'src, I, O, E, A, F, Op> Operator<'src, I, O, E> for Prefix<'src, A, F, O, Op, I, E>
672where
673    I: Input<'src>,
674    E: ParserExtra<'src, I>,
675    A: Parser<'src, I, Op, E>,
676    F: Fn(Op, O, &mut MapExtra<'src, '_, I, E>) -> O,
677{
678    #[inline]
679    fn do_parse_prefix<'parse, M: Mode>(
680        &self,
681        inp: &mut InputRef<'src, 'parse, I, E>,
682        pre_expr: &input::Checkpoint<'src, 'parse, I, <E::State as Inspector<'src, I>>::Checkpoint>,
683        f: &impl Fn(&mut InputRef<'src, 'parse, I, E>, i32) -> PResult<M, O>,
684    ) -> OperatorResult<M::Output<O>, ()>
685    where
686        Self: Sized,
687    {
688        match self.op_parser.go::<M>(inp) {
689            Ok(op) => match f(inp, self.binding_power) {
690                Ok(rhs) => OperatorResult::Ok(M::combine(op, rhs, |op, rhs| {
691                    (self.fold)(op, rhs, &mut MapExtra::new(pre_expr.cursor(), inp))
692                })),
693                Err(()) => {
694                    inp.rewind(pre_expr.clone());
695                    OperatorResult::NoMatch(())
696                }
697            },
698            Err(()) => {
699                inp.rewind(pre_expr.clone());
700                OperatorResult::NoMatch(())
701            }
702        }
703    }
704
705    op_check_and_emit!();
706}
707
708/// See [`postfix`].
709pub struct Postfix<'src, A, F, Atom, Op, I, E> {
710    op_parser: A,
711    fold: F,
712    binding_power: i32,
713    #[allow(dead_code)]
714    phantom: EmptyPhantom<&'src (Atom, Op, I, E)>,
715}
716
717impl<A: Copy, F: Copy, Atom, Op, I, E> Copy for Postfix<'_, A, F, Atom, Op, I, E> {}
718impl<A: Clone, F: Clone, Atom, Op, I, E> Clone for Postfix<'_, A, F, Atom, Op, I, E> {
719    fn clone(&self) -> Self {
720        Self {
721            op_parser: self.op_parser.clone(),
722            fold: self.fold.clone(),
723            binding_power: self.binding_power,
724            phantom: EmptyPhantom::new(),
725        }
726    }
727}
728
729/// Specify a unary postfix operator for a pratt parser with the given precedence and
730/// [fold function](crate::pratt#fold-functions).
731///
732/// Operators like factorial, field access, etc. are postfix unary operators in most languages.
733///
734/// The fold function (the last argument) tells the parser how to combine the operator and operand into a new
735/// expression. It must have the following signature:
736///
737/// ```ignore
738/// impl Fn(Atom, Op, &mut MapExtra<'src, '_, I, E>) -> O
739/// ```
740pub const fn postfix<'src, A, F, Atom, Op, I, E>(
741    precedence: u16,
742    op_parser: A,
743    fold: F,
744) -> Postfix<'src, A, F, Atom, Op, I, E>
745where
746    F: Fn(Atom, Op, &mut MapExtra<'src, '_, I, E>) -> Atom,
747{
748    Postfix {
749        op_parser,
750        fold,
751        binding_power: precedence as i32 * 2 + 1,
752        phantom: EmptyPhantom::new(),
753    }
754}
755
756impl<'src, I, O, E, A, F, Op> Operator<'src, I, O, E> for Postfix<'src, A, F, O, Op, I, E>
757where
758    I: Input<'src>,
759    E: ParserExtra<'src, I>,
760    A: Parser<'src, I, Op, E>,
761    F: Fn(O, Op, &mut MapExtra<'src, '_, I, E>) -> O,
762{
763    #[inline]
764    fn do_parse_postfix<'parse, M: Mode>(
765        &self,
766        inp: &mut InputRef<'src, 'parse, I, E>,
767        pre_expr: &input::Cursor<'src, 'parse, I>,
768        pre_op: &input::Checkpoint<'src, 'parse, I, <E::State as Inspector<'src, I>>::Checkpoint>,
769        lhs: M::Output<O>,
770        min_power: i32,
771    ) -> OperatorResult<M::Output<O>, M::Output<O>>
772    where
773        Self: Sized,
774    {
775        if self.binding_power >= min_power {
776            match self.op_parser.go::<M>(inp) {
777                Ok(op) => OperatorResult::Ok(M::combine(lhs, op, |lhs, op| {
778                    (self.fold)(lhs, op, &mut MapExtra::new(pre_expr, inp))
779                })),
780                Err(()) => {
781                    inp.rewind(pre_op.clone());
782                    OperatorResult::NoMatch(lhs)
783                }
784            }
785        } else {
786            OperatorResult::NoMatch(lhs)
787        }
788    }
789
790    op_check_and_emit!();
791}
792
793/// See [`Parser::pratt`].
794#[derive(Copy, Clone)]
795pub struct Pratt<Atom, Ops> {
796    pub(crate) atom: Atom,
797    pub(crate) ops: Ops,
798}
799
800macro_rules! impl_operator_for_tuple {
801    () => {};
802    ($head:ident $($X:ident)*) => {
803        impl_operator_for_tuple!($($X)*);
804        impl_operator_for_tuple!(~ $head $($X)*);
805    };
806    (~ $($X:ident)+) => {
807        #[allow(unused_variables, non_snake_case)]
808        impl<'src, I, O, E, $($X),*> Operator<'src, I, O, E> for ($($X,)*)
809            where
810                I: Input<'src>,
811                E: ParserExtra<'src, I>,
812                $($X: Operator<'src, I, O, E>),*
813        {
814            #[inline]
815            fn do_parse_prefix<'parse, M: Mode>(
816                &self,
817                inp: &mut InputRef<'src, 'parse, I, E>,
818                pre_expr: &input::Checkpoint<'src, 'parse, I, <E::State as Inspector<'src, I>>::Checkpoint>,
819                f: &impl Fn(&mut InputRef<'src, 'parse, I, E>, i32) -> PResult<M, O>,
820            ) -> OperatorResult<M::Output<O>, ()>
821            where
822                Self: Sized,
823            {
824                let ($($X,)*) = self;
825                $(
826                    match $X.do_parse_prefix::<M>(inp, pre_expr, f) {
827                        OperatorResult::NoMatch(out) => {},
828                        result => return result,
829                    }
830                )*
831                OperatorResult::NoMatch(())
832            }
833
834            #[inline]
835            fn do_parse_postfix<'parse, M: Mode>(
836                &self,
837                inp: &mut InputRef<'src, 'parse, I, E>,
838                pre_expr: &input::Cursor<'src, 'parse, I>,
839                pre_op: &input::Checkpoint<'src, 'parse, I, <E::State as Inspector<'src, I>>::Checkpoint>,
840                mut lhs: M::Output<O>,
841                min_power: i32,
842            ) -> OperatorResult<M::Output<O>, M::Output<O>>
843            where
844                Self: Sized,
845            {
846                let ($($X,)*) = self;
847                $(
848                    match $X.do_parse_postfix::<M>(inp, pre_expr, pre_op, lhs, min_power) {
849                        OperatorResult::NoMatch(out) => lhs = out,
850                        result => return result,
851                    }
852                )*
853                OperatorResult::NoMatch(lhs)
854            }
855
856            #[inline]
857            fn do_parse_infix<'parse, M: Mode>(
858                &self,
859                inp: &mut InputRef<'src, 'parse, I, E>,
860                pre_expr: &input::Cursor<'src, 'parse, I>,
861                pre_op: &input::Checkpoint<'src, 'parse, I, <E::State as Inspector<'src, I>>::Checkpoint>,
862                mut lhs: M::Output<O>,
863                min_power: i32,
864                f: &impl Fn(&mut InputRef<'src, 'parse, I, E>, i32) -> PResult<M, O>,
865            ) -> OperatorResult<M::Output<O>, M::Output<O>>
866            where
867                Self: Sized,
868            {
869                let ($($X,)*) = self;
870                $(
871                    match $X.do_parse_infix::<M>(inp, pre_expr, pre_op, lhs, min_power, f) {
872                        OperatorResult::NoMatch(out) => lhs = out,
873                        result => return result,
874                    }
875                )*
876                OperatorResult::NoMatch(lhs)
877            }
878
879            op_check_and_emit!();
880        }
881    };
882}
883
884impl_operator_for_tuple!(A_ B_ C_ D_ E_ F_ G_ H_ I_ J_ K_ L_ M_ N_ O_ P_ Q_ R_ S_ T_ U_ V_ W_ X_ Y_ Z_);
885
886#[allow(unused_variables, non_snake_case)]
887impl<'src, I, O, E, Op> Operator<'src, I, O, E> for Vec<Op>
888where
889    I: Input<'src>,
890    E: ParserExtra<'src, I>,
891    Op: Operator<'src, I, O, E>,
892{
893    #[inline]
894    fn do_parse_prefix<'parse, M: Mode>(
895        &self,
896        inp: &mut InputRef<'src, 'parse, I, E>,
897        pre_expr: &input::Checkpoint<'src, 'parse, I, <E::State as Inspector<'src, I>>::Checkpoint>,
898        f: &impl Fn(&mut InputRef<'src, 'parse, I, E>, i32) -> PResult<M, O>,
899    ) -> OperatorResult<M::Output<O>, ()>
900    where
901        Self: Sized,
902    {
903        for op in self {
904            match op.do_parse_prefix::<M>(inp, pre_expr, f) {
905                OperatorResult::NoMatch(()) => {}
906                result => return result,
907            }
908        }
909        OperatorResult::NoMatch(())
910    }
911
912    #[inline]
913    fn do_parse_postfix<'parse, M: Mode>(
914        &self,
915        inp: &mut InputRef<'src, 'parse, I, E>,
916        pre_expr: &input::Cursor<'src, 'parse, I>,
917        pre_op: &input::Checkpoint<'src, 'parse, I, <E::State as Inspector<'src, I>>::Checkpoint>,
918        mut lhs: M::Output<O>,
919        min_power: i32,
920    ) -> OperatorResult<M::Output<O>, M::Output<O>>
921    where
922        Self: Sized,
923    {
924        for op in self {
925            match op.do_parse_postfix::<M>(inp, pre_expr, pre_op, lhs, min_power) {
926                OperatorResult::NoMatch(out) => lhs = out,
927                result => return result,
928            }
929        }
930        OperatorResult::NoMatch(lhs)
931    }
932
933    #[inline]
934    fn do_parse_infix<'parse, M: Mode>(
935        &self,
936        inp: &mut InputRef<'src, 'parse, I, E>,
937        pre_expr: &input::Cursor<'src, 'parse, I>,
938        pre_op: &input::Checkpoint<'src, 'parse, I, <E::State as Inspector<'src, I>>::Checkpoint>,
939        mut lhs: M::Output<O>,
940        min_power: i32,
941        f: &impl Fn(&mut InputRef<'src, 'parse, I, E>, i32) -> PResult<M, O>,
942    ) -> OperatorResult<M::Output<O>, M::Output<O>>
943    where
944        Self: Sized,
945    {
946        for op in self {
947            match op.do_parse_infix::<M>(inp, pre_expr, pre_op, lhs, min_power, f) {
948                OperatorResult::NoMatch(out) => lhs = out,
949                result => return result,
950            }
951        }
952        OperatorResult::NoMatch(lhs)
953    }
954
955    op_check_and_emit!();
956}
957
958#[allow(unused_variables, non_snake_case)]
959impl<'src, Atom, Ops> Pratt<Atom, Ops> {
960    #[inline]
961    fn pratt_go<M: Mode, I, O, E>(
962        &self,
963        inp: &mut InputRef<'src, '_, I, E>,
964        min_power: i32,
965    ) -> PResult<M, O>
966    where
967        I: Input<'src>,
968        E: ParserExtra<'src, I>,
969        Atom: Parser<'src, I, O, E>,
970        Ops: Operator<'src, I, O, E>,
971    {
972        let pre_expr = inp.save();
973        // Prefix unary operators
974        let mut lhs = match self
975            .ops
976            .do_parse_prefix::<M>(inp, &pre_expr, &|inp, min_power| {
977                recursive::recurse(|| self.pratt_go::<M, _, _, _>(inp, min_power))
978            }) {
979            OperatorResult::Ok(out) => out,
980            OperatorResult::NoMatch(()) => self.atom.go::<M>(inp)?,
981            OperatorResult::Err(()) => return Err(()),
982        };
983
984        loop {
985            let pre_op = inp.save();
986
987            // Postfix unary operators
988            match self
989                .ops
990                .do_parse_postfix::<M>(inp, pre_expr.cursor(), &pre_op, lhs, min_power)
991            {
992                OperatorResult::Ok(out) => {
993                    lhs = out;
994                    continue;
995                }
996                OperatorResult::NoMatch(out) => lhs = out,
997                OperatorResult::Err(out) => {
998                    inp.rewind(pre_op);
999                    return Err(());
1000                }
1001            }
1002
1003            // Infix binary operators
1004            match self.ops.do_parse_infix::<M>(
1005                inp,
1006                pre_expr.cursor(),
1007                &pre_op,
1008                lhs,
1009                min_power,
1010                &|inp, min_power| {
1011                    recursive::recurse(|| self.pratt_go::<M, _, _, _>(inp, min_power))
1012                },
1013            ) {
1014                OperatorResult::Ok(out) => {
1015                    lhs = out;
1016                    continue;
1017                }
1018                OperatorResult::NoMatch(out) => lhs = out,
1019                OperatorResult::Err(out) => {
1020                    inp.rewind(pre_op);
1021                    return Err(());
1022                }
1023            }
1024
1025            inp.rewind(pre_op);
1026            break;
1027        }
1028
1029        Ok(lhs)
1030    }
1031}
1032
1033#[allow(unused_variables, non_snake_case)]
1034impl<'src, I, O, E, Atom, Ops> Parser<'src, I, O, E> for Pratt<Atom, Ops>
1035where
1036    I: Input<'src>,
1037    E: ParserExtra<'src, I>,
1038    Atom: Parser<'src, I, O, E>,
1039    Ops: Operator<'src, I, O, E>,
1040{
1041    fn go<M: Mode>(&self, inp: &mut InputRef<'src, '_, I, E>) -> PResult<M, O> {
1042        self.pratt_go::<M, _, _, _>(inp, i32::MIN)
1043    }
1044
1045    go_extra!(O);
1046}
1047
1048#[cfg(test)]
1049mod tests {
1050    use super::*;
1051    use crate::{extra::Err, prelude::*};
1052
1053    fn factorial(x: i64) -> i64 {
1054        if x == 0 {
1055            1
1056        } else {
1057            x * factorial(x - 1)
1058        }
1059    }
1060
1061    fn parser<'src>() -> impl Parser<'src, &'src str, i64> {
1062        let atom = text::int(10).padded().from_str::<i64>().unwrapped();
1063
1064        atom.pratt((
1065            prefix(2, just('-'), |_, x: i64, _| -x),
1066            postfix(2, just('!'), |x, _, _| factorial(x)),
1067            infix(left(0), just('+'), |l, _, r, _| l + r),
1068            infix(left(0), just('-'), |l, _, r, _| l - r),
1069            infix(left(1), just('*'), |l, _, r, _| l * r),
1070            infix(left(1), just('/'), |l, _, r, _| l / r),
1071        ))
1072    }
1073
1074    #[test]
1075    fn precedence() {
1076        assert_eq!(parser().parse("2 + 3 * 4").into_result(), Ok(14));
1077        assert_eq!(parser().parse("2 * 3 + 4").into_result(), Ok(10));
1078    }
1079
1080    #[test]
1081    fn unary() {
1082        assert_eq!(parser().parse("-2").into_result(), Ok(-2));
1083        assert_eq!(parser().parse("4!").into_result(), Ok(24));
1084        assert_eq!(parser().parse("2 + 4!").into_result(), Ok(26));
1085        assert_eq!(parser().parse("-2 + 2").into_result(), Ok(0));
1086    }
1087
1088    #[allow(dead_code)]
1089    fn parser_dynamic<'src>() -> impl Parser<'src, &'src str, i64> {
1090        let atom = text::int(10).padded().from_str::<i64>().unwrapped();
1091
1092        atom.pratt(vec![
1093            prefix(2, just('-'), |_, x: i64, _| -x).boxed(),
1094            postfix(2, just('!'), |x, _, _| factorial(x)).boxed(),
1095            infix(left(0), just('+'), |l, _, r, _| l + r).boxed(),
1096            infix(left(0), just('-'), |l, _, r, _| l - r).boxed(),
1097            infix(left(1), just('*'), |l, _, r, _| l * r).boxed(),
1098            infix(left(1), just('/'), |l, _, r, _| l / r).boxed(),
1099        ])
1100    }
1101
1102    enum Expr {
1103        Literal(i64),
1104        Not(Box<Expr>),
1105        Negate(Box<Expr>),
1106        Confusion(Box<Expr>),
1107        Factorial(Box<Expr>),
1108        Value(Box<Expr>),
1109        Less(Box<Expr>, Box<Expr>),
1110        Add(Box<Expr>, Box<Expr>),
1111        Sub(Box<Expr>, Box<Expr>),
1112        Mul(Box<Expr>, Box<Expr>),
1113        Div(Box<Expr>, Box<Expr>),
1114    }
1115
1116    impl std::fmt::Display for Expr {
1117        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1118            match self {
1119                Self::Literal(literal) => write!(f, "{literal}"),
1120                Self::Not(right) => write!(f, "(~{right})"),
1121                Self::Negate(right) => write!(f, "(-{right})"),
1122                Self::Confusion(right) => write!(f, "(§{right})"),
1123                Self::Factorial(right) => write!(f, "({right}!)"),
1124                Self::Value(right) => write!(f, "({right}$)"),
1125                Self::Less(left, right) => write!(f, "({left} < {right})"),
1126                Self::Add(left, right) => write!(f, "({left} + {right})"),
1127                Self::Sub(left, right) => write!(f, "({left} - {right})"),
1128                Self::Mul(left, right) => write!(f, "({left} * {right})"),
1129                Self::Div(left, right) => write!(f, "({left} / {right})"),
1130            }
1131        }
1132    }
1133
1134    fn u(e: fn(Box<Expr>) -> Expr, r: Expr) -> Expr {
1135        e(Box::new(r))
1136    }
1137    fn i(e: fn(Box<Expr>, Box<Expr>) -> Expr, l: Expr, r: Expr) -> Expr {
1138        e(Box::new(l), Box::new(r))
1139    }
1140
1141    fn expr_parser<'src>() -> impl Parser<'src, &'src str, String, Err<Simple<'src, char>>> {
1142        let atom = text::int(10).from_str().unwrapped().map(Expr::Literal);
1143
1144        atom.pratt((
1145            infix(left(0), just('+'), |l, _, r, _| i(Expr::Add, l, r)),
1146            infix(left(0), just('-'), |l, _, r, _| i(Expr::Sub, l, r)),
1147            infix(right(1), just('*'), |l, _, r, _| i(Expr::Mul, l, r)),
1148            infix(right(1), just('/'), |l, _, r, _| i(Expr::Div, l, r)),
1149        ))
1150        .map(|x| x.to_string())
1151    }
1152
1153    fn complete_parser<'src>() -> impl Parser<'src, &'src str, String, Err<Simple<'src, char>>> {
1154        expr_parser().then_ignore(end())
1155    }
1156
1157    fn parse(input: &str) -> ParseResult<String, Simple<'_, char>> {
1158        complete_parser().parse(input)
1159    }
1160
1161    fn parse_partial(input: &str) -> ParseResult<String, Simple<'_, char>> {
1162        expr_parser().lazy().parse(input)
1163    }
1164
1165    fn unexpected<'src, C: Into<Option<MaybeRef<'src, char>>>, S: Into<SimpleSpan>>(
1166        c: C,
1167        span: S,
1168    ) -> Simple<'src, char> {
1169        <Simple<_> as LabelError<&[char], _>>::expected_found::<[DefaultExpected<char>; 0]>(
1170            [],
1171            c.into(),
1172            span.into(),
1173        )
1174    }
1175
1176    #[test]
1177    fn missing_first_expression() {
1178        assert_eq!(parse("").into_result(), Err(vec![unexpected(None, 0..0)]))
1179    }
1180
1181    #[test]
1182    fn missing_later_expression() {
1183        assert_eq!(parse("1+").into_result(), Err(vec![unexpected(None, 2..2)]),);
1184    }
1185
1186    #[test]
1187    fn invalid_first_expression() {
1188        assert_eq!(
1189            parse("?").into_result(),
1190            Err(vec![unexpected(Some('?'.into()), 0..1)]),
1191        );
1192    }
1193
1194    #[test]
1195    fn invalid_later_expression() {
1196        assert_eq!(
1197            parse("1+?").into_result(),
1198            Err(vec![dbg!(unexpected(Some('?'.into()), 2..3))]),
1199        );
1200    }
1201
1202    #[test]
1203    fn invalid_operator() {
1204        assert_eq!(
1205            parse("1?").into_result(),
1206            Err(vec![unexpected(Some('?'.into()), 1..2)]),
1207        );
1208    }
1209
1210    #[test]
1211    fn invalid_operator_incomplete() {
1212        assert_eq!(parse_partial("1?").into_result(), Ok("1".to_string()),);
1213    }
1214
1215    #[test]
1216    fn complex_nesting() {
1217        assert_eq!(
1218            parse_partial("1+2*3/4*5-6*7+8-9+10").into_result(),
1219            Ok("(((((1 + (2 * (3 / (4 * 5)))) - (6 * 7)) + 8) - 9) + 10)".to_string()),
1220        );
1221    }
1222
1223    #[test]
1224    fn with_prefix_ops() {
1225        let atom = text::int::<_, Err<Simple<char>>>(10)
1226            .from_str()
1227            .unwrapped()
1228            .map(Expr::Literal);
1229
1230        let parser = atom
1231            .pratt((
1232                // -- Prefix
1233                // Because we defined '*' and '/' as right associative operators,
1234                // in order to get these to function as expected, their strength
1235                // must be higher
1236                prefix(2, just('-'), |_, r, _| u(Expr::Negate, r)),
1237                prefix(2, just('~'), |_, r, _| u(Expr::Not, r)),
1238                // This is what happens when not
1239                prefix(1, just('§'), |_, r, _| u(Expr::Confusion, r)),
1240                // -- Infix
1241                infix(left(0), just('+'), |l, _, r, _| i(Expr::Add, l, r)),
1242                infix(left(0), just('-'), |l, _, r, _| i(Expr::Sub, l, r)),
1243                infix(right(1), just('*'), |l, _, r, _| i(Expr::Mul, l, r)),
1244                infix(right(1), just('/'), |l, _, r, _| i(Expr::Div, l, r)),
1245            ))
1246            .map(|x| x.to_string());
1247
1248        assert_eq!(
1249            parser.parse("-1+§~2*3").into_result(),
1250            Ok("((-1) + (§((~2) * 3)))".to_string()),
1251        )
1252    }
1253
1254    #[test]
1255    fn with_postfix_ops() {
1256        let atom = text::int::<_, Err<Simple<char>>>(10)
1257            .from_str()
1258            .unwrapped()
1259            .map(Expr::Literal);
1260
1261        let parser = atom
1262            .pratt((
1263                // -- Postfix
1264                // Because we defined '*' and '/' as right associative operators,
1265                // in order to get these to function as expected, their strength
1266                // must be higher
1267                postfix(2, just('!'), |l, _, _| u(Expr::Factorial, l)),
1268                // This is what happens when not
1269                postfix(0, just('$'), |l, _, _| u(Expr::Value, l)),
1270                // -- Infix
1271                infix(left(1), just('+'), |l, _, r, _| i(Expr::Add, l, r)),
1272                infix(left(1), just('-'), |l, _, r, _| i(Expr::Sub, l, r)),
1273                infix(right(2), just('*'), |l, _, r, _| i(Expr::Mul, l, r)),
1274                infix(right(2), just('/'), |l, _, r, _| i(Expr::Div, l, r)),
1275            ))
1276            .map(|x| x.to_string());
1277
1278        assert_eq!(
1279            parser.parse("1+2!$*3").into_result(),
1280            Ok("(((1 + (2!))$) * 3)".to_string()),
1281        )
1282    }
1283
1284    #[test]
1285    fn with_pre_and_postfix_ops() {
1286        let atom = text::int::<_, Err<Simple<char>>>(10)
1287            .from_str()
1288            .unwrapped()
1289            .map(Expr::Literal);
1290
1291        let parser = atom
1292            .pratt((
1293                // -- Prefix
1294                prefix(4, just('-'), |_, r, _| u(Expr::Negate, r)),
1295                prefix(4, just('~'), |_, r, _| u(Expr::Not, r)),
1296                prefix(1, just('§'), |_, r, _| u(Expr::Confusion, r)),
1297                // -- Postfix
1298                postfix(5, just('!'), |l, _, _| u(Expr::Factorial, l)),
1299                postfix(0, just('$'), |l, _, _| u(Expr::Value, l)),
1300                // -- Infix
1301                infix(left(1), just('+'), |l, _, r, _| i(Expr::Add, l, r)),
1302                infix(left(1), just('-'), |l, _, r, _| i(Expr::Sub, l, r)),
1303                infix(right(2), just('*'), |l, _, r, _| i(Expr::Mul, l, r)),
1304                infix(right(2), just('/'), |l, _, r, _| i(Expr::Div, l, r)),
1305            ))
1306            .map(|x| x.to_string());
1307        assert_eq!(
1308            parser.parse("§1+-~2!$*3").into_result(),
1309            Ok("(((§(1 + (-(~(2!)))))$) * 3)".to_string()),
1310        )
1311    }
1312
1313    fn non_associative_parser<'src>(
1314    ) -> impl Parser<'src, &'src str, String, Err<Simple<'src, char>>> {
1315        let atom = text::int(10).from_str().unwrapped().map(Expr::Literal);
1316
1317        atom.pratt((
1318            infix(none(1), just('<'), |l, _, r, _| i(Expr::Less, l, r)),
1319            infix(left(2), just('+'), |l, _, r, _| i(Expr::Add, l, r)),
1320            infix(left(2), just('-'), |l, _, r, _| i(Expr::Sub, l, r)),
1321            infix(right(3), just('*'), |l, _, r, _| i(Expr::Mul, l, r)),
1322            infix(right(3), just('/'), |l, _, r, _| i(Expr::Div, l, r)),
1323        ))
1324        .map(|x| x.to_string())
1325    }
1326
1327    #[test]
1328    fn with_non_associative_infix_ops() {
1329        assert_eq!(
1330            non_associative_parser().parse("1+2*3<10/2").into_result(),
1331            Ok("((1 + (2 * 3)) < (10 / 2))".to_string()),
1332        )
1333    }
1334
1335    #[test]
1336    fn with_chained_non_associative_infix_ops() {
1337        assert_eq!(
1338            non_associative_parser().parse("1<2<3").into_result(),
1339            Err(vec![dbg!(unexpected(Some('<'.into()), 3..4))])
1340        );
1341        assert_eq!(
1342            non_associative_parser()
1343                .parse("1+2*3<10/2<42")
1344                .into_result(),
1345            Err(vec![dbg!(unexpected(Some('<'.into()), 10..11))])
1346        )
1347    }
1348}