1use super::*;
94
95pub enum OperatorResult<T, E> {
97 Ok(T),
99 NoMatch(E),
101 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
204pub trait Operator<'src, I, O, E>
206where
207 I: Input<'src>,
208 E: ParserExtra<'src, I>,
209{
210 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
324pub 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#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
457pub enum Associativity {
458 Left(u16),
460 Right(u16),
462 None(u16),
464}
465
466pub fn left(precedence: u16) -> Associativity {
471 Associativity::Left(precedence)
472}
473
474pub fn right(precedence: u16) -> Associativity {
479 Associativity::Right(precedence)
480}
481
482pub 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
508pub 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
529pub 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 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
623pub 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
644pub 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
708pub 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
729pub 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#[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 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 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 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(2, just('-'), |_, r, _| u(Expr::Negate, r)),
1237 prefix(2, just('~'), |_, r, _| u(Expr::Not, r)),
1238 prefix(1, just('§'), |_, r, _| u(Expr::Confusion, r)),
1240 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(2, just('!'), |l, _, _| u(Expr::Factorial, l)),
1268 postfix(0, just('$'), |l, _, _| u(Expr::Value, l)),
1270 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(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(5, just('!'), |l, _, _| u(Expr::Factorial, l)),
1299 postfix(0, just('$'), |l, _, _| u(Expr::Value, l)),
1300 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}