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