Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1// SPDX-License-Identifier: Apache-2.0 OR MIT
2
3#[cfg(all(feature = "printing", feature = "full"))]
4use crate::attr::{AttrStyle, Attribute};
5#[cfg(feature = "printing")]
6use crate::expr::Expr;
7#[cfg(all(feature = "printing", feature = "full"))]
8use 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};
14use crate::op::BinOp;
15#[cfg(all(feature = "printing", feature = "full"))]
16use crate::ty::ReturnType;
17use std::cmp::Ordering;
18
19// Reference: https://doc.rust-lang.org/reference/expressions.html#expression-precedence
20pub(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
58impl 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
192impl Copy for Precedence {}
193
194impl Clone for Precedence {
195 fn clone(&self) -> Self {
196 *self
197 }
198}
199
200impl PartialEq for Precedence {
201 fn eq(&self, other: &Self) -> bool {
202 *self as u8 == *other as u8
203 }
204}
205
206impl 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}