1 use syn::{ 2 AttrStyle, Attribute, BinOp, Expr, ExprArray, ExprAsync, ExprAwait, ExprBlock, ExprBreak, 3 ExprCall, ExprConst, ExprContinue, ExprField, ExprForLoop, ExprIf, ExprIndex, ExprInfer, 4 ExprLit, ExprLoop, ExprMacro, ExprMatch, ExprMethodCall, ExprParen, ExprPath, ExprRepeat, 5 ExprReturn, ExprStruct, ExprTry, ExprTryBlock, ExprTuple, ExprUnsafe, ExprWhile, ExprYield, 6 ReturnType, 7 }; 8 9 // Reference: https://doc.rust-lang.org/reference/expressions.html#expression-precedence 10 #[derive(Copy, Clone, PartialEq, PartialOrd)] 11 pub enum Precedence { 12 // return, break, closures 13 Jump, 14 // = += -= *= /= %= &= |= ^= <<= >>= 15 Assign, 16 // .. ..= 17 Range, 18 // || 19 Or, 20 // && 21 And, 22 // let 23 Let, 24 // == != < > <= >= 25 Compare, 26 // | 27 BitOr, 28 // ^ 29 BitXor, 30 // & 31 BitAnd, 32 // << >> 33 Shift, 34 // + - 35 Sum, 36 // * / % 37 Product, 38 // as 39 Cast, 40 // unary - * ! & &mut 41 Prefix, 42 // paths, loops, function calls, array indexing, field expressions, method calls 43 Unambiguous, 44 } 45 46 impl Precedence { 47 pub(crate) const MIN: Self = Precedence::Jump; 48 of_binop(op: &BinOp) -> Self49 pub(crate) fn of_binop(op: &BinOp) -> Self { 50 match op { 51 #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] 52 BinOp::Add(_) | BinOp::Sub(_) => Precedence::Sum, 53 BinOp::Mul(_) | BinOp::Div(_) | BinOp::Rem(_) => Precedence::Product, 54 BinOp::And(_) => Precedence::And, 55 BinOp::Or(_) => Precedence::Or, 56 BinOp::BitXor(_) => Precedence::BitXor, 57 BinOp::BitAnd(_) => Precedence::BitAnd, 58 BinOp::BitOr(_) => Precedence::BitOr, 59 BinOp::Shl(_) | BinOp::Shr(_) => Precedence::Shift, 60 61 BinOp::Eq(_) 62 | BinOp::Lt(_) 63 | BinOp::Le(_) 64 | BinOp::Ne(_) 65 | BinOp::Ge(_) 66 | BinOp::Gt(_) => Precedence::Compare, 67 68 BinOp::AddAssign(_) 69 | BinOp::SubAssign(_) 70 | BinOp::MulAssign(_) 71 | BinOp::DivAssign(_) 72 | BinOp::RemAssign(_) 73 | BinOp::BitXorAssign(_) 74 | BinOp::BitAndAssign(_) 75 | BinOp::BitOrAssign(_) 76 | BinOp::ShlAssign(_) 77 | BinOp::ShrAssign(_) => Precedence::Assign, 78 79 _ => Precedence::MIN, 80 } 81 } 82 of(e: &Expr) -> Self83 pub(crate) fn of(e: &Expr) -> Self { 84 fn prefix_attrs(attrs: &[Attribute]) -> Precedence { 85 for attr in attrs { 86 if let AttrStyle::Outer = attr.style { 87 return Precedence::Prefix; 88 } 89 } 90 Precedence::Unambiguous 91 } 92 93 match e { 94 #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] 95 Expr::Closure(e) => match e.output { 96 ReturnType::Default => Precedence::Jump, 97 ReturnType::Type(..) => prefix_attrs(&e.attrs), 98 }, 99 100 Expr::Break(ExprBreak { expr, .. }) 101 | Expr::Return(ExprReturn { expr, .. }) 102 | Expr::Yield(ExprYield { expr, .. }) => match expr { 103 Some(_) => Precedence::Jump, 104 None => Precedence::Unambiguous, 105 }, 106 107 Expr::Assign(_) => Precedence::Assign, 108 Expr::Range(_) => Precedence::Range, 109 Expr::Binary(e) => Precedence::of_binop(&e.op), 110 Expr::Let(_) => Precedence::Let, 111 Expr::Cast(_) => Precedence::Cast, 112 Expr::RawAddr(_) | Expr::Reference(_) | Expr::Unary(_) => Precedence::Prefix, 113 114 Expr::Array(ExprArray { attrs, .. }) 115 | Expr::Async(ExprAsync { attrs, .. }) 116 | Expr::Await(ExprAwait { attrs, .. }) 117 | Expr::Block(ExprBlock { attrs, .. }) 118 | Expr::Call(ExprCall { attrs, .. }) 119 | Expr::Const(ExprConst { attrs, .. }) 120 | Expr::Continue(ExprContinue { attrs, .. }) 121 | Expr::Field(ExprField { attrs, .. }) 122 | Expr::ForLoop(ExprForLoop { attrs, .. }) 123 | Expr::If(ExprIf { attrs, .. }) 124 | Expr::Index(ExprIndex { attrs, .. }) 125 | Expr::Infer(ExprInfer { attrs, .. }) 126 | Expr::Lit(ExprLit { attrs, .. }) 127 | Expr::Loop(ExprLoop { attrs, .. }) 128 | Expr::Macro(ExprMacro { attrs, .. }) 129 | Expr::Match(ExprMatch { attrs, .. }) 130 | Expr::MethodCall(ExprMethodCall { attrs, .. }) 131 | Expr::Paren(ExprParen { attrs, .. }) 132 | Expr::Path(ExprPath { attrs, .. }) 133 | Expr::Repeat(ExprRepeat { attrs, .. }) 134 | Expr::Struct(ExprStruct { attrs, .. }) 135 | Expr::Try(ExprTry { attrs, .. }) 136 | Expr::TryBlock(ExprTryBlock { attrs, .. }) 137 | Expr::Tuple(ExprTuple { attrs, .. }) 138 | Expr::Unsafe(ExprUnsafe { attrs, .. }) 139 | Expr::While(ExprWhile { attrs, .. }) => prefix_attrs(attrs), 140 141 Expr::Group(e) => Precedence::of(&e.expr), 142 143 Expr::Verbatim(_) => Precedence::Unambiguous, 144 145 _ => Precedence::Unambiguous, 146 } 147 } 148 } 149