• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
of_binop(op: &BinOp) -> Self49     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 
of(e: &Expr) -> Self83     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