1 // SPDX-License-Identifier: Apache-2.0 OR MIT 2 3 #[cfg(all(feature = "printing", feature = "full"))] 4 use crate::attr::{AttrStyle, Attribute}; 5 #[cfg(feature = "printing")] 6 use crate::expr::Expr; 7 #[cfg(all(feature = "printing", feature = "full"))] 8 use crate::expr::{ 9 ExprArray, ExprAsync, ExprAwait, ExprBlock, ExprBreak, ExprCall, ExprConst, ExprContinue, 10 ExprField, ExprForLoop, ExprGroup, ExprIf, ExprIndex, ExprInfer, ExprLit, ExprLoop, ExprMacro, 11 ExprMatch, ExprMethodCall, ExprParen, ExprPath, ExprRepeat, ExprReturn, ExprStruct, ExprTry, 12 ExprTryBlock, ExprTuple, ExprUnsafe, ExprWhile, ExprYield, 13 }; 14 use crate::op::BinOp; 15 #[cfg(all(feature = "printing", feature = "full"))] 16 use crate::ty::ReturnType; 17 use std::cmp::Ordering; 18 19 // Reference: https://doc.rust-lang.org/reference/expressions.html#expression-precedence 20 pub(crate) enum Precedence { 21 // return, break, closures 22 Jump, 23 // = += -= *= /= %= &= |= ^= <<= >>= 24 Assign, 25 // .. ..= 26 Range, 27 // || 28 Or, 29 // && 30 And, 31 // let 32 #[cfg(feature = "printing")] 33 Let, 34 // == != < > <= >= 35 Compare, 36 // | 37 BitOr, 38 // ^ 39 BitXor, 40 // & 41 BitAnd, 42 // << >> 43 Shift, 44 // + - 45 Sum, 46 // * / % 47 Product, 48 // as 49 Cast, 50 // unary - * ! & &mut 51 #[cfg(feature = "printing")] 52 Prefix, 53 // paths, loops, function calls, array indexing, field expressions, method calls 54 #[cfg(feature = "printing")] 55 Unambiguous, 56 } 57 58 impl Precedence { 59 pub(crate) const MIN: Self = Precedence::Jump; 60 61 pub(crate) fn of_binop(op: &BinOp) -> Self { 62 match op { 63 BinOp::Add(_) | BinOp::Sub(_) => Precedence::Sum, 64 BinOp::Mul(_) | BinOp::Div(_) | BinOp::Rem(_) => Precedence::Product, 65 BinOp::And(_) => Precedence::And, 66 BinOp::Or(_) => Precedence::Or, 67 BinOp::BitXor(_) => Precedence::BitXor, 68 BinOp::BitAnd(_) => Precedence::BitAnd, 69 BinOp::BitOr(_) => Precedence::BitOr, 70 BinOp::Shl(_) | BinOp::Shr(_) => Precedence::Shift, 71 72 BinOp::Eq(_) 73 | BinOp::Lt(_) 74 | BinOp::Le(_) 75 | BinOp::Ne(_) 76 | BinOp::Ge(_) 77 | BinOp::Gt(_) => Precedence::Compare, 78 79 BinOp::AddAssign(_) 80 | BinOp::SubAssign(_) 81 | BinOp::MulAssign(_) 82 | BinOp::DivAssign(_) 83 | BinOp::RemAssign(_) 84 | BinOp::BitXorAssign(_) 85 | BinOp::BitAndAssign(_) 86 | BinOp::BitOrAssign(_) 87 | BinOp::ShlAssign(_) 88 | BinOp::ShrAssign(_) => Precedence::Assign, 89 } 90 } 91 92 #[cfg(feature = "printing")] 93 pub(crate) fn of(e: &Expr) -> Self { 94 #[cfg(feature = "full")] 95 fn prefix_attrs(attrs: &[Attribute]) -> Precedence { 96 for attr in attrs { 97 if let AttrStyle::Outer = attr.style { 98 return Precedence::Prefix; 99 } 100 } 101 Precedence::Unambiguous 102 } 103 104 match e { 105 #[cfg(feature = "full")] 106 Expr::Closure(e) => match e.output { 107 ReturnType::Default => Precedence::Jump, 108 ReturnType::Type(..) => prefix_attrs(&e.attrs), 109 }, 110 111 #[cfg(feature = "full")] 112 Expr::Break(ExprBreak { expr, .. }) 113 | Expr::Return(ExprReturn { expr, .. }) 114 | Expr::Yield(ExprYield { expr, .. }) => match expr { 115 Some(_) => Precedence::Jump, 116 None => Precedence::Unambiguous, 117 }, 118 119 Expr::Assign(_) => Precedence::Assign, 120 Expr::Range(_) => Precedence::Range, 121 Expr::Binary(e) => Precedence::of_binop(&e.op), 122 Expr::Let(_) => Precedence::Let, 123 Expr::Cast(_) => Precedence::Cast, 124 Expr::RawAddr(_) | Expr::Reference(_) | Expr::Unary(_) => Precedence::Prefix, 125 126 #[cfg(feature = "full")] 127 Expr::Array(ExprArray { attrs, .. }) 128 | Expr::Async(ExprAsync { attrs, .. }) 129 | Expr::Await(ExprAwait { attrs, .. }) 130 | Expr::Block(ExprBlock { attrs, .. }) 131 | Expr::Call(ExprCall { attrs, .. }) 132 | Expr::Const(ExprConst { attrs, .. }) 133 | Expr::Continue(ExprContinue { attrs, .. }) 134 | Expr::Field(ExprField { attrs, .. }) 135 | Expr::ForLoop(ExprForLoop { attrs, .. }) 136 | Expr::Group(ExprGroup { attrs, .. }) 137 | Expr::If(ExprIf { attrs, .. }) 138 | Expr::Index(ExprIndex { attrs, .. }) 139 | Expr::Infer(ExprInfer { attrs, .. }) 140 | Expr::Lit(ExprLit { attrs, .. }) 141 | Expr::Loop(ExprLoop { attrs, .. }) 142 | Expr::Macro(ExprMacro { attrs, .. }) 143 | Expr::Match(ExprMatch { attrs, .. }) 144 | Expr::MethodCall(ExprMethodCall { attrs, .. }) 145 | Expr::Paren(ExprParen { attrs, .. }) 146 | Expr::Path(ExprPath { attrs, .. }) 147 | Expr::Repeat(ExprRepeat { attrs, .. }) 148 | Expr::Struct(ExprStruct { attrs, .. }) 149 | Expr::Try(ExprTry { attrs, .. }) 150 | Expr::TryBlock(ExprTryBlock { attrs, .. }) 151 | Expr::Tuple(ExprTuple { attrs, .. }) 152 | Expr::Unsafe(ExprUnsafe { attrs, .. }) 153 | Expr::While(ExprWhile { attrs, .. }) => prefix_attrs(attrs), 154 155 #[cfg(not(feature = "full"))] 156 Expr::Array(_) 157 | Expr::Async(_) 158 | Expr::Await(_) 159 | Expr::Block(_) 160 | Expr::Call(_) 161 | Expr::Const(_) 162 | Expr::Continue(_) 163 | Expr::Field(_) 164 | Expr::ForLoop(_) 165 | Expr::Group(_) 166 | Expr::If(_) 167 | Expr::Index(_) 168 | Expr::Infer(_) 169 | Expr::Lit(_) 170 | Expr::Loop(_) 171 | Expr::Macro(_) 172 | Expr::Match(_) 173 | Expr::MethodCall(_) 174 | Expr::Paren(_) 175 | Expr::Path(_) 176 | Expr::Repeat(_) 177 | Expr::Struct(_) 178 | Expr::Try(_) 179 | Expr::TryBlock(_) 180 | Expr::Tuple(_) 181 | Expr::Unsafe(_) 182 | Expr::While(_) => Precedence::Unambiguous, 183 184 Expr::Verbatim(_) => Precedence::Unambiguous, 185 186 #[cfg(not(feature = "full"))] 187 Expr::Break(_) | Expr::Closure(_) | Expr::Return(_) | Expr::Yield(_) => unreachable!(), 188 } 189 } 190 } 191 192 impl Copy for Precedence {} 193 194 impl Clone for Precedence { 195 fn clone(&self) -> Self { 196 *self 197 } 198 } 199 200 impl PartialEq for Precedence { 201 fn eq(&self, other: &Self) -> bool { 202 *self as u8 == *other as u8 203 } 204 } 205 206 impl PartialOrd for Precedence { 207 fn partial_cmp(&self, other: &Self) -> Option<Ordering> { 208 let this = *self as u8; 209 let other = *other as u8; 210 Some(this.cmp(&other)) 211 } 212 } 213