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