| 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 | |
| 49 | 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 | |
| 83 | 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 | |