Skip to content

Commit 4fb556e

Browse files
committed
Use typle for tuple functions
This generates almost identical code to the existing macros while being more readable. The only semantic difference is for `Choice`, where the final option does not rewind the input.
1 parent 902a047 commit 4fb556e

File tree

4 files changed

+170
-240
lines changed

4 files changed

+170
-240
lines changed

Cargo.lock

Lines changed: 18 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ spin = { version = "0.9", features = ["once"], default-features = false, optiona
7979
lexical = { version = "6.1.1", default-features = false, features = ["parse-integers", "parse-floats", "format"], optional = true }
8080
either = { version = "1.8.1", optional = true }
8181
serde = { version = "1.0", default-features = false, optional = true, features = ["derive"] }
82+
typle = "0.9.6"
8283
unicode-ident = "1.0.10"
8384

8485
[dev-dependencies]

src/pratt.rs

Lines changed: 107 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@
8989
//! );
9090
//! ```
9191
92+
use typle::typle;
93+
9294
use super::*;
9395

9496
trait Operator<'a, I, O, E>
@@ -404,117 +406,124 @@ pub struct Pratt<Atom, Ops> {
404406
pub(crate) ops: Ops,
405407
}
406408

407-
macro_rules! impl_pratt_for_tuple {
408-
() => {};
409-
($head:ident $($X:ident)*) => {
410-
impl_pratt_for_tuple!($($X)*);
411-
impl_pratt_for_tuple!(~ $head $($X)*);
412-
};
413-
(~ $($X:ident)+) => {
414-
#[allow(unused_variables, non_snake_case)]
415-
impl<'a, Atom, $($X),*> Pratt<Atom, ($($X,)*)> {
416-
#[inline]
417-
fn pratt_go<M: Mode, I, O, E>(&self, inp: &mut InputRef<'a, '_, I, E>, min_power: u32) -> PResult<M, O>
418-
where
419-
I: Input<'a>,
420-
E: ParserExtra<'a, I>,
421-
Atom: Parser<'a, I, O, E>,
422-
$($X: Operator<'a, I, O, E>),*
423-
{
424-
let pre_expr = inp.save();
425-
let mut lhs = 'choice: {
426-
let ($($X,)*) = &self.ops;
427-
428-
// Prefix unary operators
429-
$(
430-
if $X::IS_PREFIX {
431-
match $X.op_parser().go::<M>(inp) {
432-
Ok(op) => {
433-
match recursive::recurse(|| self.pratt_go::<M, _, _, _>(inp, $X.associativity().left_power())) {
434-
Ok(rhs) => break 'choice M::combine(op, rhs, |op, rhs| {
435-
$X.fold_prefix(op, rhs, &mut MapExtra::new(pre_expr.offset(), inp))
436-
}),
437-
Err(()) => inp.rewind(pre_expr),
438-
}
439-
},
409+
#[typle(Tuple for 1..=26)]
410+
impl<'a, Atom, T: Tuple> Pratt<Atom, T> {
411+
#[inline]
412+
fn pratt_go<M: Mode, I, O, E>(
413+
&self,
414+
inp: &mut InputRef<'a, '_, I, E>,
415+
min_power: u32,
416+
) -> PResult<M, O>
417+
where
418+
I: Input<'a>,
419+
E: ParserExtra<'a, I>,
420+
Atom: Parser<'a, I, O, E>,
421+
T<_>: Operator<'a, I, O, E>,
422+
{
423+
let pre_expr = inp.save();
424+
let mut lhs = 'choice: {
425+
// Prefix unary operators
426+
for typle_index!(i) in 0..T::LEN {
427+
if T::<{ i }>::IS_PREFIX {
428+
let t = &self.ops[[i]];
429+
match t.op_parser().go::<M>(inp) {
430+
Ok(op) => {
431+
match recursive::recurse(|| {
432+
self.pratt_go::<M, _, _, _>(inp, t.associativity().left_power())
433+
}) {
434+
Ok(rhs) => {
435+
break 'choice M::combine(op, rhs, |op, rhs| {
436+
t.fold_prefix(
437+
op,
438+
rhs,
439+
&mut MapExtra::new(pre_expr.offset(), inp),
440+
)
441+
})
442+
}
440443
Err(()) => inp.rewind(pre_expr),
441444
}
442445
}
443-
)*
444-
445-
self.atom.go::<M>(inp)?
446-
};
447-
448-
loop {
449-
let ($($X,)*) = &self.ops;
450-
451-
let pre_op = inp.save();
452-
453-
// Postfix unary operators
454-
$(
455-
let assoc = $X.associativity();
456-
if $X::IS_POSTFIX && assoc.right_power() >= min_power {
457-
match $X.op_parser().go::<M>(inp) {
458-
Ok(op) => {
459-
lhs = M::combine(lhs, op, |lhs, op| {
460-
$X.fold_postfix(lhs, op, &mut MapExtra::new(pre_expr.offset(), inp))
461-
});
462-
continue
463-
},
464-
Err(()) => inp.rewind(pre_op),
465-
}
446+
Err(()) => inp.rewind(pre_expr),
447+
}
448+
}
449+
}
450+
451+
self.atom.go::<M>(inp)?
452+
};
453+
454+
'start: loop {
455+
let pre_op = inp.save();
456+
457+
// Postfix unary operators
458+
for typle_index!(i) in 0..T::LEN {
459+
let t = &self.ops[[i]];
460+
let assoc = t.associativity();
461+
if T::<{ i }>::IS_POSTFIX && assoc.right_power() >= min_power {
462+
match t.op_parser().go::<M>(inp) {
463+
Ok(op) => {
464+
lhs = M::combine(lhs, op, |lhs, op| {
465+
t.fold_postfix(lhs, op, &mut MapExtra::new(pre_expr.offset(), inp))
466+
});
467+
continue 'start;
466468
}
467-
)*
468-
469-
// Infix binary operators
470-
$(
471-
let assoc = $X.associativity();
472-
if $X::IS_INFIX && assoc.left_power() >= min_power {
473-
match $X.op_parser().go::<M>(inp) {
474-
Ok(op) => match recursive::recurse(|| self.pratt_go::<M, _, _, _>(inp, assoc.right_power())) {
475-
Ok(rhs) => {
476-
lhs = M::combine(
477-
M::combine(lhs, rhs, |lhs, rhs| (lhs, rhs)),
469+
Err(()) => inp.rewind(pre_op),
470+
}
471+
}
472+
}
473+
474+
// Infix binary operators
475+
for typle_index!(i) in 0..T::LEN {
476+
let t = &self.ops[[i]];
477+
let assoc = t.associativity();
478+
if T::<{ i }>::IS_INFIX && assoc.left_power() >= min_power {
479+
match t.op_parser().go::<M>(inp) {
480+
Ok(op) => match recursive::recurse(|| {
481+
self.pratt_go::<M, _, _, _>(inp, assoc.right_power())
482+
}) {
483+
Ok(rhs) => {
484+
lhs = M::combine(
485+
M::combine(lhs, rhs, |lhs, rhs| (lhs, rhs)),
486+
op,
487+
|(lhs, rhs), op| {
488+
t.fold_infix(
489+
lhs,
478490
op,
479-
|(lhs, rhs), op| {
480-
$X.fold_infix(lhs, op, rhs, &mut MapExtra::new(pre_expr.offset(), inp))
481-
},
482-
);
483-
continue
491+
rhs,
492+
&mut MapExtra::new(pre_expr.offset(), inp),
493+
)
484494
},
485-
Err(()) => inp.rewind(pre_op),
486-
},
487-
Err(()) => inp.rewind(pre_op),
495+
);
496+
continue 'start;
488497
}
489-
}
490-
)*
491-
492-
inp.rewind(pre_op);
493-
break;
498+
Err(()) => inp.rewind(pre_op),
499+
},
500+
Err(()) => inp.rewind(pre_op),
501+
}
494502
}
495-
496-
Ok(lhs)
497503
}
498-
}
499504

500-
#[allow(unused_variables, non_snake_case)]
501-
impl<'a, I, O, E, Atom, $($X),*> ParserSealed<'a, I, O, E> for Pratt<Atom, ($($X,)*)>
502-
where
503-
I: Input<'a>,
504-
E: ParserExtra<'a, I>,
505-
Atom: Parser<'a, I, O, E>,
506-
$($X: Operator<'a, I, O, E>),*
507-
{
508-
fn go<M: Mode>(&self, inp: &mut InputRef<'a, '_, I, E>) -> PResult<M, O> {
509-
self.pratt_go::<M, _, _, _>(inp, 0)
510-
}
511-
512-
go_extra!(O);
505+
inp.rewind(pre_op);
506+
break;
513507
}
514-
};
508+
509+
Ok(lhs)
510+
}
515511
}
516512

517-
impl_pratt_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_);
513+
#[typle(Tuple for 1..=26)]
514+
impl<'a, I, O, E, Atom, T: Tuple> ParserSealed<'a, I, O, E> for Pratt<Atom, T>
515+
where
516+
I: Input<'a>,
517+
E: ParserExtra<'a, I>,
518+
Atom: Parser<'a, I, O, E>,
519+
T<_>: Operator<'a, I, O, E>,
520+
{
521+
fn go<M: Mode>(&self, inp: &mut InputRef<'a, '_, I, E>) -> PResult<M, O> {
522+
self.pratt_go::<M, _, _, _>(inp, 0)
523+
}
524+
525+
go_extra!(O);
526+
}
518527

519528
#[cfg(test)]
520529
mod tests {

0 commit comments

Comments
 (0)