xref: /linux/rust/syn/precedence.rs (revision 808c999fc9e7c366fd47da564e69d579c1dc8279)
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 = *self as u8;
207         let other = *other as u8;
208         Some(this.cmp(&other))
209     }
210 }
211