diff options
| author | Nicholas Nethercote <n.nethercote@gmail.com> | 2024-12-19 18:24:07 +1100 |
|---|---|---|
| committer | Nicholas Nethercote <n.nethercote@gmail.com> | 2025-02-27 09:53:17 +1100 |
| commit | ceafbad81fcf71423d4dc7a90fe962bc5895b108 (patch) | |
| tree | 263d73b402ee77cdfcfea0adbaf1dec5e2a45433 /compiler/rustc_ast/src | |
| parent | a8364f3b2ad63c19037bdf060e49ad9ca07e16b6 (diff) | |
| download | rust-ceafbad81fcf71423d4dc7a90fe962bc5895b108.tar.gz rust-ceafbad81fcf71423d4dc7a90fe962bc5895b108.zip | |
Introduce `AssocOp::Binary`.
It mirrors `ExprKind::Binary`, and contains a `BinOpKind`. This makes `AssocOp` more like `ExprKind`. Note that the variants removed from `AssocOp` are all named differently to `BinOpToken`, e.g. `Multiply` instead of `Mul`, so that's an inconsistency removed. The commit adds `precedence` and `fixity` methods to `BinOpKind`, and calls them from the corresponding methods in `AssocOp`. This avoids the need to create an `AssocOp` from a `BinOpKind` in a bunch of places, and `AssocOp::from_ast_binop` is removed. `AssocOp::to_ast_binop` is also no longer needed. Overall things are shorter and nicer.
Diffstat (limited to 'compiler/rustc_ast/src')
| -rw-r--r-- | compiler/rustc_ast/src/ast.rs | 35 | ||||
| -rw-r--r-- | compiler/rustc_ast/src/util/parser.rs | 182 |
2 files changed, 74 insertions, 143 deletions
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 29c1d34a125..65dd0a34aec 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -39,7 +39,7 @@ pub use crate::format::*; use crate::ptr::P; use crate::token::{self, CommentKind, Delimiter}; use crate::tokenstream::{DelimSpan, LazyAttrTokenStream, TokenStream}; -use crate::util::parser::{AssocOp, ExprPrecedence}; +use crate::util::parser::{ExprPrecedence, Fixity}; /// A "Label" is an identifier of some point in sources, /// e.g. in the following code: @@ -937,8 +937,37 @@ impl BinOpKind { matches!(self, BinOpKind::And | BinOpKind::Or) } + pub fn precedence(&self) -> ExprPrecedence { + use BinOpKind::*; + match *self { + Mul | Div | Rem => ExprPrecedence::Product, + Add | Sub => ExprPrecedence::Sum, + Shl | Shr => ExprPrecedence::Shift, + BitAnd => ExprPrecedence::BitAnd, + BitXor => ExprPrecedence::BitXor, + BitOr => ExprPrecedence::BitOr, + Lt | Gt | Le | Ge | Eq | Ne => ExprPrecedence::Compare, + And => ExprPrecedence::LAnd, + Or => ExprPrecedence::LOr, + } + } + + pub fn fixity(&self) -> Fixity { + use BinOpKind::*; + match self { + Eq | Ne | Lt | Le | Gt | Ge => Fixity::None, + Add | Sub | Mul | Div | Rem | And | Or | BitXor | BitAnd | BitOr | Shl | Shr => { + Fixity::Left + } + } + } + pub fn is_comparison(self) -> bool { - crate::util::parser::AssocOp::from_ast_binop(self).is_comparison() + use BinOpKind::*; + match self { + Eq | Ne | Lt | Le | Gt | Ge => true, + Add | Sub | Mul | Div | Rem | And | Or | BitXor | BitAnd | BitOr | Shl | Shr => false, + } } /// Returns `true` if the binary operator takes its arguments by value. @@ -1332,7 +1361,7 @@ impl Expr { ExprKind::Range(..) => ExprPrecedence::Range, // Binop-like expr kinds, handled by `AssocOp`. - ExprKind::Binary(op, ..) => AssocOp::from_ast_binop(op.node).precedence(), + ExprKind::Binary(op, ..) => op.node.precedence(), ExprKind::Cast(..) => ExprPrecedence::Cast, ExprKind::Assign(..) | diff --git a/compiler/rustc_ast/src/util/parser.rs b/compiler/rustc_ast/src/util/parser.rs index 69df9ff93b4..e7c26aa3092 100644 --- a/compiler/rustc_ast/src/util/parser.rs +++ b/compiler/rustc_ast/src/util/parser.rs @@ -3,51 +3,15 @@ use rustc_span::kw; use crate::ast::{self, BinOpKind}; use crate::token::{self, BinOpToken, Token}; -/// Associative operator with precedence. -/// -/// This is the enum which specifies operator precedence and fixity to the parser. +/// Associative operator. #[derive(Copy, Clone, PartialEq, Debug)] pub enum AssocOp { - /// `+` - Add, - /// `-` - Subtract, - /// `*` - Multiply, - /// `/` - Divide, - /// `%` - Modulus, - /// `&&` - LAnd, - /// `||` - LOr, - /// `^` - BitXor, - /// `&` - BitAnd, - /// `|` - BitOr, - /// `<<` - ShiftLeft, - /// `>>` - ShiftRight, - /// `==` - Equal, - /// `<` - Less, - /// `<=` - LessEqual, - /// `!=` - NotEqual, - /// `>` - Greater, - /// `>=` - GreaterEqual, - /// `=` - Assign, + /// A binary op. + Binary(BinOpKind), /// `?=` where ? is one of the assignable BinOps AssignOp(BinOpKind), + /// `=` + Assign, /// `as` As, /// `..` range @@ -67,11 +31,21 @@ pub enum Fixity { } impl AssocOp { - /// Creates a new AssocOP from a token + /// Creates a new AssocOp from a token. pub fn from_token(t: &Token) -> Option<AssocOp> { use AssocOp::*; match t.kind { token::Eq => Some(Assign), + token::BinOp(BinOpToken::Plus) => Some(Binary(BinOpKind::Add)), + token::BinOp(BinOpToken::Minus) => Some(Binary(BinOpKind::Sub)), + token::BinOp(BinOpToken::Star) => Some(Binary(BinOpKind::Mul)), + token::BinOp(BinOpToken::Slash) => Some(Binary(BinOpKind::Div)), + token::BinOp(BinOpToken::Percent) => Some(Binary(BinOpKind::Rem)), + token::BinOp(BinOpToken::Caret) => Some(Binary(BinOpKind::BitXor)), + token::BinOp(BinOpToken::And) => Some(Binary(BinOpKind::BitAnd)), + token::BinOp(BinOpToken::Or) => Some(Binary(BinOpKind::BitOr)), + token::BinOp(BinOpToken::Shl) => Some(Binary(BinOpKind::Shl)), + token::BinOp(BinOpToken::Shr) => Some(Binary(BinOpKind::Shr)), token::BinOpEq(BinOpToken::Plus) => Some(AssignOp(BinOpKind::Add)), token::BinOpEq(BinOpToken::Minus) => Some(AssignOp(BinOpKind::Sub)), token::BinOpEq(BinOpToken::Star) => Some(AssignOp(BinOpKind::Mul)), @@ -82,74 +56,31 @@ impl AssocOp { token::BinOpEq(BinOpToken::Or) => Some(AssignOp(BinOpKind::BitOr)), token::BinOpEq(BinOpToken::Shl) => Some(AssignOp(BinOpKind::Shl)), token::BinOpEq(BinOpToken::Shr) => Some(AssignOp(BinOpKind::Shr)), - token::BinOp(BinOpToken::Plus) => Some(Add), - token::BinOp(BinOpToken::Minus) => Some(Subtract), - token::BinOp(BinOpToken::Star) => Some(Multiply), - token::BinOp(BinOpToken::Slash) => Some(Divide), - token::BinOp(BinOpToken::Percent) => Some(Modulus), - token::BinOp(BinOpToken::Caret) => Some(BitXor), - token::BinOp(BinOpToken::And) => Some(BitAnd), - token::BinOp(BinOpToken::Or) => Some(BitOr), - token::BinOp(BinOpToken::Shl) => Some(ShiftLeft), - token::BinOp(BinOpToken::Shr) => Some(ShiftRight), - token::Lt => Some(Less), - token::Le => Some(LessEqual), - token::Ge => Some(GreaterEqual), - token::Gt => Some(Greater), - token::EqEq => Some(Equal), - token::Ne => Some(NotEqual), - token::AndAnd => Some(LAnd), - token::OrOr => Some(LOr), + token::Lt => Some(Binary(BinOpKind::Lt)), + token::Le => Some(Binary(BinOpKind::Le)), + token::Ge => Some(Binary(BinOpKind::Ge)), + token::Gt => Some(Binary(BinOpKind::Gt)), + token::EqEq => Some(Binary(BinOpKind::Eq)), + token::Ne => Some(Binary(BinOpKind::Ne)), + token::AndAnd => Some(Binary(BinOpKind::And)), + token::OrOr => Some(Binary(BinOpKind::Or)), token::DotDot => Some(DotDot), token::DotDotEq => Some(DotDotEq), // DotDotDot is no longer supported, but we need some way to display the error token::DotDotDot => Some(DotDotEq), // `<-` should probably be `< -` - token::LArrow => Some(Less), + token::LArrow => Some(Binary(BinOpKind::Lt)), _ if t.is_keyword(kw::As) => Some(As), _ => None, } } - /// Creates a new AssocOp from ast::BinOpKind. - pub fn from_ast_binop(op: BinOpKind) -> Self { - use AssocOp::*; - match op { - BinOpKind::Lt => Less, - BinOpKind::Gt => Greater, - BinOpKind::Le => LessEqual, - BinOpKind::Ge => GreaterEqual, - BinOpKind::Eq => Equal, - BinOpKind::Ne => NotEqual, - BinOpKind::Mul => Multiply, - BinOpKind::Div => Divide, - BinOpKind::Rem => Modulus, - BinOpKind::Add => Add, - BinOpKind::Sub => Subtract, - BinOpKind::Shl => ShiftLeft, - BinOpKind::Shr => ShiftRight, - BinOpKind::BitAnd => BitAnd, - BinOpKind::BitXor => BitXor, - BinOpKind::BitOr => BitOr, - BinOpKind::And => LAnd, - BinOpKind::Or => LOr, - } - } - /// Gets the precedence of this operator pub fn precedence(&self) -> ExprPrecedence { use AssocOp::*; match *self { As => ExprPrecedence::Cast, - Multiply | Divide | Modulus => ExprPrecedence::Product, - Add | Subtract => ExprPrecedence::Sum, - ShiftLeft | ShiftRight => ExprPrecedence::Shift, - BitAnd => ExprPrecedence::BitAnd, - BitXor => ExprPrecedence::BitXor, - BitOr => ExprPrecedence::BitOr, - Less | Greater | LessEqual | GreaterEqual | Equal | NotEqual => ExprPrecedence::Compare, - LAnd => ExprPrecedence::LAnd, - LOr => ExprPrecedence::LOr, + Binary(bin_op) => bin_op.precedence(), DotDot | DotDotEq => ExprPrecedence::Range, Assign | AssignOp(_) => ExprPrecedence::Assign, } @@ -161,22 +92,17 @@ impl AssocOp { // NOTE: it is a bug to have an operators that has same precedence but different fixities! match *self { Assign | AssignOp(_) => Fixity::Right, - As | Multiply | Divide | Modulus | Add | Subtract | ShiftLeft | ShiftRight | BitAnd - | BitXor | BitOr | LAnd | LOr => Fixity::Left, - Less | Greater | LessEqual | GreaterEqual | Equal | NotEqual | DotDot | DotDotEq => { - Fixity::None - } + Binary(binop) => binop.fixity(), + As => Fixity::Left, + DotDot | DotDotEq => Fixity::None, } } pub fn is_comparison(&self) -> bool { use AssocOp::*; match *self { - Less | Greater | LessEqual | GreaterEqual | Equal | NotEqual => true, - Assign | AssignOp(_) | As | Multiply | Divide | Modulus | Add | Subtract - | ShiftLeft | ShiftRight | BitAnd | BitXor | BitOr | LAnd | LOr | DotDot | DotDotEq => { - false - } + Binary(binop) => binop.is_comparison(), + Assign | AssignOp(_) | As | DotDot | DotDotEq => false, } } @@ -184,34 +110,7 @@ impl AssocOp { use AssocOp::*; match *self { Assign | AssignOp(_) => true, - Less | Greater | LessEqual | GreaterEqual | Equal | NotEqual | As | Multiply - | Divide | Modulus | Add | Subtract | ShiftLeft | ShiftRight | BitAnd | BitXor - | BitOr | LAnd | LOr | DotDot | DotDotEq => false, - } - } - - pub fn to_ast_binop(&self) -> Option<BinOpKind> { - use AssocOp::*; - match *self { - Less => Some(BinOpKind::Lt), - Greater => Some(BinOpKind::Gt), - LessEqual => Some(BinOpKind::Le), - GreaterEqual => Some(BinOpKind::Ge), - Equal => Some(BinOpKind::Eq), - NotEqual => Some(BinOpKind::Ne), - Multiply => Some(BinOpKind::Mul), - Divide => Some(BinOpKind::Div), - Modulus => Some(BinOpKind::Rem), - Add => Some(BinOpKind::Add), - Subtract => Some(BinOpKind::Sub), - ShiftLeft => Some(BinOpKind::Shl), - ShiftRight => Some(BinOpKind::Shr), - BitAnd => Some(BinOpKind::BitAnd), - BitXor => Some(BinOpKind::BitXor), - BitOr => Some(BinOpKind::BitOr), - LAnd => Some(BinOpKind::And), - LOr => Some(BinOpKind::Or), - Assign | AssignOp(_) | As | DotDot | DotDotEq => None, + As | Binary(_) | DotDot | DotDotEq => false, } } @@ -221,16 +120,19 @@ impl AssocOp { /// parentheses while having a high degree of confidence on the correctness of the suggestion. pub fn can_continue_expr_unambiguously(&self) -> bool { use AssocOp::*; + use BinOpKind::*; matches!( self, - BitXor | // `{ 42 } ^ 3` Assign | // `{ 42 } = { 42 }` - Divide | // `{ 42 } / 42` - Modulus | // `{ 42 } % 2` - ShiftRight | // `{ 42 } >> 2` - LessEqual | // `{ 42 } <= 3` - Greater | // `{ 42 } > 3` - GreaterEqual | // `{ 42 } >= 3` + Binary( + BitXor | // `{ 42 } ^ 3` + Div | // `{ 42 } / 42` + Rem | // `{ 42 } % 2` + Shr | // `{ 42 } >> 2` + Le | // `{ 42 } <= 3` + Gt | // `{ 42 } > 3` + Ge // `{ 42 } >= 3` + ) | AssignOp(_) | // `{ 42 } +=` // Equal | // `{ 42 } == { 42 }` Accepting these here would regress incorrect // NotEqual | // `{ 42 } != { 42 } struct literals parser recovery. |
