diff --git a/src/parser/pat.rs b/src/parser/pat.rs index 1127c53..49a611e 100644 --- a/src/parser/pat.rs +++ b/src/parser/pat.rs @@ -18,26 +18,36 @@ pub enum Prec { Tuple, /// Type annotation: `Pat : Pat` Typed, - /// Range pattern: `Pat .. Pat`, `Pat ..= Pat` - Range, /// Function pattern: `Pat -> Pat` Fn, + /// Range pattern: `Pat .. Pat`, `Pat ..= Pat` + Range, /// The highest precedence Max, } +macro_rules! intify { + ($enum:ident($value:path) = $min:ident, $max: ident, $($variant:ident),*$(,)?) => { + #[expect(non_upper_case_globals)] { + const $min: u32 = $enum::$min as _; + const $max: u32 = $enum::$max as _; + $(const $variant: u32 = $enum::$variant as _;)* + match $value { + ..=$min => $enum::$min, + $($variant => $enum::$variant,)* + $max.. => $enum::$max, + } + }}; +} + impl Prec { + const fn from_int(value: u32) -> Self { + intify! {Prec(value) = Min, Max, Alt, Tuple, Typed, Fn, Range} + } + /// Returns the level of precedence higher than this one const fn next(self) -> Self { - match self { - Self::Min => Self::Alt, - Self::Alt => Self::Tuple, - Self::Tuple => Self::Typed, - Self::Typed => Self::Range, - Self::Range => Self::Fn, - Self::Fn => Self::Max, - Self::Max => Self::Max, - } + Self::from_int(self as u32 + 1) } } @@ -45,12 +55,12 @@ impl Prec { /// and its [precedence level](Prec) fn from_infix(token: &Token) -> Option<(PatOp, Prec)> { Some(match token.kind { - TKind::DotDot => (PatOp::RangeEx, Prec::Range), - TKind::DotDotEq => (PatOp::RangeIn, Prec::Range), - TKind::Colon => (PatOp::Typed, Prec::Typed), - TKind::Comma => (PatOp::Tuple, Prec::Tuple), TKind::Arrow => (PatOp::Fn, Prec::Fn), TKind::Bar => (PatOp::Alt, Prec::Alt), + TKind::Colon => (PatOp::Typed, Prec::Typed), + TKind::Comma => (PatOp::Tuple, Prec::Tuple), + TKind::DotDot => (PatOp::RangeEx, Prec::Range), + TKind::DotDotEq => (PatOp::RangeIn, Prec::Range), _ => None?, }) } @@ -135,7 +145,7 @@ impl<'t> Parse<'t> for Pat { { let kind = tok.kind; head = match op { - PatOp::Typed => Pat::Op(PatOp::Typed, vec![head, p.consume().parse(Prec::Max)?]), + PatOp::Typed => Pat::Op(PatOp::Typed, vec![head, p.consume().parse(prec.next())?]), PatOp::Fn => Pat::Op(PatOp::Fn, vec![head, p.consume().parse(Prec::Fn.next())?]), op @ (PatOp::RangeEx | PatOp::RangeIn) => Pat::Op( op,