| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212 |
- // SPDX-License-Identifier: Apache-2.0 OR MIT
- #[cfg(all(feature = "printing", feature = "full"))]
- use crate::attr::{AttrStyle, Attribute};
- #[cfg(feature = "printing")]
- use crate::expr::Expr;
- #[cfg(all(feature = "printing", feature = "full"))]
- use crate::expr::{
- ExprArray, ExprAsync, ExprAwait, ExprBlock, ExprBreak, ExprCall, ExprConst, ExprContinue,
- ExprField, ExprForLoop, ExprGroup, ExprIf, ExprIndex, ExprInfer, ExprLit, ExprLoop, ExprMacro,
- ExprMatch, ExprMethodCall, ExprParen, ExprPath, ExprRepeat, ExprReturn, ExprStruct, ExprTry,
- ExprTryBlock, ExprTuple, ExprUnsafe, ExprWhile, ExprYield,
- };
- use crate::op::BinOp;
- #[cfg(all(feature = "printing", feature = "full"))]
- use crate::ty::ReturnType;
- use std::cmp::Ordering;
- // Reference: https://doc.rust-lang.org/reference/expressions.html#expression-precedence
- pub(crate) enum Precedence {
- // return, break, closures
- Jump,
- // = += -= *= /= %= &= |= ^= <<= >>=
- Assign,
- // .. ..=
- Range,
- // ||
- Or,
- // &&
- And,
- // let
- #[cfg(feature = "printing")]
- Let,
- // == != < > <= >=
- Compare,
- // |
- BitOr,
- // ^
- BitXor,
- // &
- BitAnd,
- // << >>
- Shift,
- // + -
- Sum,
- // * / %
- Product,
- // as
- Cast,
- // unary - * ! & &mut
- #[cfg(feature = "printing")]
- Prefix,
- // paths, loops, function calls, array indexing, field expressions, method calls
- #[cfg(feature = "printing")]
- Unambiguous,
- }
- impl Precedence {
- pub(crate) const MIN: Self = Precedence::Jump;
- pub(crate) fn of_binop(op: &BinOp) -> Self {
- match op {
- BinOp::Add(_) | BinOp::Sub(_) => Precedence::Sum,
- BinOp::Mul(_) | BinOp::Div(_) | BinOp::Rem(_) => Precedence::Product,
- BinOp::And(_) => Precedence::And,
- BinOp::Or(_) => Precedence::Or,
- BinOp::BitXor(_) => Precedence::BitXor,
- BinOp::BitAnd(_) => Precedence::BitAnd,
- BinOp::BitOr(_) => Precedence::BitOr,
- BinOp::Shl(_) | BinOp::Shr(_) => Precedence::Shift,
- BinOp::Eq(_)
- | BinOp::Lt(_)
- | BinOp::Le(_)
- | BinOp::Ne(_)
- | BinOp::Ge(_)
- | BinOp::Gt(_) => Precedence::Compare,
- BinOp::AddAssign(_)
- | BinOp::SubAssign(_)
- | BinOp::MulAssign(_)
- | BinOp::DivAssign(_)
- | BinOp::RemAssign(_)
- | BinOp::BitXorAssign(_)
- | BinOp::BitAndAssign(_)
- | BinOp::BitOrAssign(_)
- | BinOp::ShlAssign(_)
- | BinOp::ShrAssign(_) => Precedence::Assign,
- }
- }
- #[cfg(feature = "printing")]
- pub(crate) fn of(e: &Expr) -> Self {
- #[cfg(feature = "full")]
- fn prefix_attrs(attrs: &[Attribute]) -> Precedence {
- for attr in attrs {
- if let AttrStyle::Outer = attr.style {
- return Precedence::Prefix;
- }
- }
- Precedence::Unambiguous
- }
- match e {
- #[cfg(feature = "full")]
- Expr::Closure(e) => match e.output {
- ReturnType::Default => Precedence::Jump,
- ReturnType::Type(..) => prefix_attrs(&e.attrs),
- },
- #[cfg(feature = "full")]
- Expr::Break(ExprBreak { expr, .. })
- | Expr::Return(ExprReturn { expr, .. })
- | Expr::Yield(ExprYield { expr, .. }) => match expr {
- Some(_) => Precedence::Jump,
- None => Precedence::Unambiguous,
- },
- Expr::Assign(_) => Precedence::Assign,
- Expr::Range(_) => Precedence::Range,
- Expr::Binary(e) => Precedence::of_binop(&e.op),
- Expr::Let(_) => Precedence::Let,
- Expr::Cast(_) => Precedence::Cast,
- Expr::RawAddr(_) | Expr::Reference(_) | Expr::Unary(_) => Precedence::Prefix,
- #[cfg(feature = "full")]
- Expr::Array(ExprArray { attrs, .. })
- | Expr::Async(ExprAsync { attrs, .. })
- | Expr::Await(ExprAwait { attrs, .. })
- | Expr::Block(ExprBlock { attrs, .. })
- | Expr::Call(ExprCall { attrs, .. })
- | Expr::Const(ExprConst { attrs, .. })
- | Expr::Continue(ExprContinue { attrs, .. })
- | Expr::Field(ExprField { attrs, .. })
- | Expr::ForLoop(ExprForLoop { attrs, .. })
- | Expr::Group(ExprGroup { attrs, .. })
- | Expr::If(ExprIf { attrs, .. })
- | Expr::Index(ExprIndex { attrs, .. })
- | Expr::Infer(ExprInfer { attrs, .. })
- | Expr::Lit(ExprLit { attrs, .. })
- | Expr::Loop(ExprLoop { attrs, .. })
- | Expr::Macro(ExprMacro { attrs, .. })
- | Expr::Match(ExprMatch { attrs, .. })
- | Expr::MethodCall(ExprMethodCall { attrs, .. })
- | Expr::Paren(ExprParen { attrs, .. })
- | Expr::Path(ExprPath { attrs, .. })
- | Expr::Repeat(ExprRepeat { attrs, .. })
- | Expr::Struct(ExprStruct { attrs, .. })
- | Expr::Try(ExprTry { attrs, .. })
- | Expr::TryBlock(ExprTryBlock { attrs, .. })
- | Expr::Tuple(ExprTuple { attrs, .. })
- | Expr::Unsafe(ExprUnsafe { attrs, .. })
- | Expr::While(ExprWhile { attrs, .. }) => prefix_attrs(attrs),
- #[cfg(not(feature = "full"))]
- Expr::Array(_)
- | Expr::Async(_)
- | Expr::Await(_)
- | Expr::Block(_)
- | Expr::Call(_)
- | Expr::Const(_)
- | Expr::Continue(_)
- | Expr::Field(_)
- | Expr::ForLoop(_)
- | Expr::Group(_)
- | Expr::If(_)
- | Expr::Index(_)
- | Expr::Infer(_)
- | Expr::Lit(_)
- | Expr::Loop(_)
- | Expr::Macro(_)
- | Expr::Match(_)
- | Expr::MethodCall(_)
- | Expr::Paren(_)
- | Expr::Path(_)
- | Expr::Repeat(_)
- | Expr::Struct(_)
- | Expr::Try(_)
- | Expr::TryBlock(_)
- | Expr::Tuple(_)
- | Expr::Unsafe(_)
- | Expr::While(_) => Precedence::Unambiguous,
- Expr::Verbatim(_) => Precedence::Unambiguous,
- #[cfg(not(feature = "full"))]
- Expr::Break(_) | Expr::Closure(_) | Expr::Return(_) | Expr::Yield(_) => unreachable!(),
- }
- }
- }
- impl Copy for Precedence {}
- impl Clone for Precedence {
- fn clone(&self) -> Self {
- *self
- }
- }
- impl PartialEq for Precedence {
- fn eq(&self, other: &Self) -> bool {
- *self as u8 == *other as u8
- }
- }
- impl PartialOrd for Precedence {
- fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
- let this = *self as u8;
- let other = *other as u8;
- Some(this.cmp(&other))
- }
- }
|