precedence.rs 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. // SPDX-License-Identifier: Apache-2.0 OR MIT
  2. #[cfg(all(feature = "printing", feature = "full"))]
  3. use crate::attr::{AttrStyle, Attribute};
  4. #[cfg(feature = "printing")]
  5. use crate::expr::Expr;
  6. #[cfg(all(feature = "printing", feature = "full"))]
  7. use crate::expr::{
  8. ExprArray, ExprAsync, ExprAwait, ExprBlock, ExprBreak, ExprCall, ExprConst, ExprContinue,
  9. ExprField, ExprForLoop, ExprGroup, ExprIf, ExprIndex, ExprInfer, ExprLit, ExprLoop, ExprMacro,
  10. ExprMatch, ExprMethodCall, ExprParen, ExprPath, ExprRepeat, ExprReturn, ExprStruct, ExprTry,
  11. ExprTryBlock, ExprTuple, ExprUnsafe, ExprWhile, ExprYield,
  12. };
  13. use crate::op::BinOp;
  14. #[cfg(all(feature = "printing", feature = "full"))]
  15. use crate::ty::ReturnType;
  16. use std::cmp::Ordering;
  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. impl Precedence {
  56. pub(crate) const MIN: Self = Precedence::Jump;
  57. pub(crate) fn of_binop(op: &BinOp) -> Self {
  58. match op {
  59. BinOp::Add(_) | BinOp::Sub(_) => Precedence::Sum,
  60. BinOp::Mul(_) | BinOp::Div(_) | BinOp::Rem(_) => Precedence::Product,
  61. BinOp::And(_) => Precedence::And,
  62. BinOp::Or(_) => Precedence::Or,
  63. BinOp::BitXor(_) => Precedence::BitXor,
  64. BinOp::BitAnd(_) => Precedence::BitAnd,
  65. BinOp::BitOr(_) => Precedence::BitOr,
  66. BinOp::Shl(_) | BinOp::Shr(_) => Precedence::Shift,
  67. BinOp::Eq(_)
  68. | BinOp::Lt(_)
  69. | BinOp::Le(_)
  70. | BinOp::Ne(_)
  71. | BinOp::Ge(_)
  72. | BinOp::Gt(_) => Precedence::Compare,
  73. BinOp::AddAssign(_)
  74. | BinOp::SubAssign(_)
  75. | BinOp::MulAssign(_)
  76. | BinOp::DivAssign(_)
  77. | BinOp::RemAssign(_)
  78. | BinOp::BitXorAssign(_)
  79. | BinOp::BitAndAssign(_)
  80. | BinOp::BitOrAssign(_)
  81. | BinOp::ShlAssign(_)
  82. | BinOp::ShrAssign(_) => Precedence::Assign,
  83. }
  84. }
  85. #[cfg(feature = "printing")]
  86. pub(crate) fn of(e: &Expr) -> Self {
  87. #[cfg(feature = "full")]
  88. fn prefix_attrs(attrs: &[Attribute]) -> Precedence {
  89. for attr in attrs {
  90. if let AttrStyle::Outer = attr.style {
  91. return Precedence::Prefix;
  92. }
  93. }
  94. Precedence::Unambiguous
  95. }
  96. match e {
  97. #[cfg(feature = "full")]
  98. Expr::Closure(e) => match e.output {
  99. ReturnType::Default => Precedence::Jump,
  100. ReturnType::Type(..) => prefix_attrs(&e.attrs),
  101. },
  102. #[cfg(feature = "full")]
  103. Expr::Break(ExprBreak { expr, .. })
  104. | Expr::Return(ExprReturn { expr, .. })
  105. | Expr::Yield(ExprYield { expr, .. }) => match expr {
  106. Some(_) => Precedence::Jump,
  107. None => Precedence::Unambiguous,
  108. },
  109. Expr::Assign(_) => Precedence::Assign,
  110. Expr::Range(_) => Precedence::Range,
  111. Expr::Binary(e) => Precedence::of_binop(&e.op),
  112. Expr::Let(_) => Precedence::Let,
  113. Expr::Cast(_) => Precedence::Cast,
  114. Expr::RawAddr(_) | Expr::Reference(_) | Expr::Unary(_) => Precedence::Prefix,
  115. #[cfg(feature = "full")]
  116. Expr::Array(ExprArray { attrs, .. })
  117. | Expr::Async(ExprAsync { attrs, .. })
  118. | Expr::Await(ExprAwait { attrs, .. })
  119. | Expr::Block(ExprBlock { attrs, .. })
  120. | Expr::Call(ExprCall { attrs, .. })
  121. | Expr::Const(ExprConst { attrs, .. })
  122. | Expr::Continue(ExprContinue { attrs, .. })
  123. | Expr::Field(ExprField { attrs, .. })
  124. | Expr::ForLoop(ExprForLoop { attrs, .. })
  125. | Expr::Group(ExprGroup { attrs, .. })
  126. | Expr::If(ExprIf { attrs, .. })
  127. | Expr::Index(ExprIndex { attrs, .. })
  128. | Expr::Infer(ExprInfer { attrs, .. })
  129. | Expr::Lit(ExprLit { attrs, .. })
  130. | Expr::Loop(ExprLoop { attrs, .. })
  131. | Expr::Macro(ExprMacro { attrs, .. })
  132. | Expr::Match(ExprMatch { attrs, .. })
  133. | Expr::MethodCall(ExprMethodCall { attrs, .. })
  134. | Expr::Paren(ExprParen { attrs, .. })
  135. | Expr::Path(ExprPath { attrs, .. })
  136. | Expr::Repeat(ExprRepeat { attrs, .. })
  137. | Expr::Struct(ExprStruct { attrs, .. })
  138. | Expr::Try(ExprTry { attrs, .. })
  139. | Expr::TryBlock(ExprTryBlock { attrs, .. })
  140. | Expr::Tuple(ExprTuple { attrs, .. })
  141. | Expr::Unsafe(ExprUnsafe { attrs, .. })
  142. | Expr::While(ExprWhile { attrs, .. }) => prefix_attrs(attrs),
  143. #[cfg(not(feature = "full"))]
  144. Expr::Array(_)
  145. | Expr::Async(_)
  146. | Expr::Await(_)
  147. | Expr::Block(_)
  148. | Expr::Call(_)
  149. | Expr::Const(_)
  150. | Expr::Continue(_)
  151. | Expr::Field(_)
  152. | Expr::ForLoop(_)
  153. | Expr::Group(_)
  154. | Expr::If(_)
  155. | Expr::Index(_)
  156. | Expr::Infer(_)
  157. | Expr::Lit(_)
  158. | Expr::Loop(_)
  159. | Expr::Macro(_)
  160. | Expr::Match(_)
  161. | Expr::MethodCall(_)
  162. | Expr::Paren(_)
  163. | Expr::Path(_)
  164. | Expr::Repeat(_)
  165. | Expr::Struct(_)
  166. | Expr::Try(_)
  167. | Expr::TryBlock(_)
  168. | Expr::Tuple(_)
  169. | Expr::Unsafe(_)
  170. | Expr::While(_) => Precedence::Unambiguous,
  171. Expr::Verbatim(_) => Precedence::Unambiguous,
  172. #[cfg(not(feature = "full"))]
  173. Expr::Break(_) | Expr::Closure(_) | Expr::Return(_) | Expr::Yield(_) => unreachable!(),
  174. }
  175. }
  176. }
  177. impl Copy for Precedence {}
  178. impl Clone for Precedence {
  179. fn clone(&self) -> Self {
  180. *self
  181. }
  182. }
  183. impl PartialEq for Precedence {
  184. fn eq(&self, other: &Self) -> bool {
  185. *self as u8 == *other as u8
  186. }
  187. }
  188. impl PartialOrd for Precedence {
  189. fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
  190. let this = *self as u8;
  191. let other = *other as u8;
  192. Some(this.cmp(&other))
  193. }
  194. }