xref: /linux/rust/syn/precedence.rs (revision 784faa8eca8270671e0ed6d9d21f04bbb80fc5f7)
1 // SPDX-License-Identifier: Apache-2.0 OR MIT
2 
3 #[cfg(all(feature = "printing", feature = "full"))]
4 use crate::attr::{AttrStyle, Attribute};
5 #[cfg(feature = "printing")]
6 use crate::expr::Expr;
7 #[cfg(all(feature = "printing", feature = "full"))]
8 use 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 };
14 use crate::op::BinOp;
15 #[cfg(all(feature = "printing", feature = "full"))]
16 use crate::ty::ReturnType;
17 use std::cmp::Ordering;
18 
19 // Reference: https://doc.rust-lang.org/reference/expressions.html#expression-precedence
20 pub(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 
58 impl Precedence {
59     pub(crate) const MIN: Self = Precedence::Jump;
60 
of_binop(op: &BinOp) -> Self61     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")]
of(e: &Expr) -> Self93     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 
192 impl Copy for Precedence {}
193 
194 impl Clone for Precedence {
clone(&self) -> Self195     fn clone(&self) -> Self {
196         *self
197     }
198 }
199 
200 impl PartialEq for Precedence {
eq(&self, other: &Self) -> bool201     fn eq(&self, other: &Self) -> bool {
202         *self as u8 == *other as u8
203     }
204 }
205 
206 impl PartialOrd for Precedence {
partial_cmp(&self, other: &Self) -> Option<Ordering>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 }
213