| 1 | |
| 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 | |
| 20 | pub(crate) enum Precedence {
|
| 21 | |
| 22 | Jump,
|
| 23 | |
| 24 | Assign,
|
| 25 | |
| 26 | Range,
|
| 27 | |
| 28 | Or,
|
| 29 | |
| 30 | And,
|
| 31 | |
| 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 | |
| 49 | Cast,
|
| 50 | |
| 51 | #[cfg(feature = "printing")]
|
| 52 | Prefix,
|
| 53 | |
| 54 | #[cfg(feature = "printing")]
|
| 55 | Unambiguous,
|
| 56 | }
|
| 57 |
|
| 58 | impl 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 |
|
| 192 | impl Copy for Precedence {}
|
| 193 |
|
| 194 | impl Clone for Precedence {
|
| 195 | fn clone(&self) -> Self {
|
| 196 | *self
|
| 197 | }
|
| 198 | }
|
| 199 |
|
| 200 | impl PartialEq for Precedence {
|
| 201 | fn eq(&self, other: &Self) -> bool {
|
| 202 | *self as u8 == *other as u8
|
| 203 | }
|
| 204 | }
|
| 205 |
|
| 206 | impl 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 | }
|