Skip to content

Commit 2a4d835

Browse files
authored
Use the common OperatorPrecedence for the parser (#16747)
## Summary This change continues to resolve #16071 (and continues the work started in #16162). Specifically, this PR changes the code in the parser so that it uses the `OperatorPrecedence` struct from `ruff_python_ast` instead of its own version. This is part of an effort to get rid of the redundant definitions of `OperatorPrecedence` throughout the codebase. Note that this PR only makes this change for `ruff_python_parser` -- we still want to make a similar change for the formatter (namely the `OperatorPrecedence` defined in the expression part of the formatter, the pattern one is different). I separated the work to keep the PRs small and easily reviewable. ## Test Plan Because this is an internal change, I didn't add any additional tests. Existing tests do pass.
1 parent 04a8756 commit 2a4d835

File tree

3 files changed

+19
-95
lines changed

3 files changed

+19
-95
lines changed

crates/ruff_python_ast/src/operator_precedence.rs

+15
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,12 @@ impl OperatorPrecedence {
131131
pub fn from_expr(expr: &Expr) -> Self {
132132
Self::from(&ExprRef::from(expr))
133133
}
134+
135+
/// Returns `true` if the precedence is right-associative i.e., the operations are evaluated
136+
/// from right to left.
137+
pub fn is_right_associative(self) -> bool {
138+
matches!(self, OperatorPrecedence::Exponent)
139+
}
134140
}
135141

136142
impl From<&Expr> for OperatorPrecedence {
@@ -177,3 +183,12 @@ impl From<BoolOp> for OperatorPrecedence {
177183
}
178184
}
179185
}
186+
187+
impl From<UnaryOp> for OperatorPrecedence {
188+
fn from(unary_op: UnaryOp) -> Self {
189+
match unary_op {
190+
UnaryOp::UAdd | UnaryOp::USub | UnaryOp::Invert => Self::PosNegBitNot,
191+
UnaryOp::Not => Self::Not,
192+
}
193+
}
194+
}

crates/ruff_python_parser/src/parser/expression.rs

+4-94
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use rustc_hash::{FxBuildHasher, FxHashSet};
77
use ruff_python_ast::name::Name;
88
use ruff_python_ast::{
99
self as ast, BoolOp, CmpOp, ConversionFlag, Expr, ExprContext, FStringElement, FStringElements,
10-
IpyEscapeKind, Number, Operator, StringFlags, UnaryOp,
10+
IpyEscapeKind, Number, Operator, OperatorPrecedence, StringFlags, UnaryOp,
1111
};
1212
use ruff_text_size::{Ranged, TextLen, TextRange, TextSize};
1313

@@ -228,7 +228,7 @@ impl<'src> Parser<'src> {
228228
///
229229
/// [Python grammar]: https://docs.python.org/3/reference/grammar.html
230230
fn parse_simple_expression(&mut self, context: ExpressionContext) -> ParsedExpr {
231-
self.parse_binary_expression_or_higher(OperatorPrecedence::Initial, context)
231+
self.parse_binary_expression_or_higher(OperatorPrecedence::None, context)
232232
}
233233

234234
/// Parses a binary expression using the [Pratt parsing algorithm].
@@ -360,7 +360,7 @@ impl<'src> Parser<'src> {
360360
TokenKind::Star => {
361361
let starred_expr = self.parse_starred_expression(context);
362362

363-
if left_precedence > OperatorPrecedence::Initial
363+
if left_precedence > OperatorPrecedence::None
364364
|| !context.is_starred_expression_allowed()
365365
{
366366
self.add_error(ParseErrorType::InvalidStarredExpressionUsage, &starred_expr);
@@ -393,7 +393,7 @@ impl<'src> Parser<'src> {
393393
TokenKind::Yield => {
394394
let expr = self.parse_yield_expression();
395395

396-
if left_precedence > OperatorPrecedence::Initial
396+
if left_precedence > OperatorPrecedence::None
397397
|| !context.is_yield_expression_allowed()
398398
{
399399
self.add_error(ParseErrorType::InvalidYieldExpressionUsage, &expr);
@@ -2596,57 +2596,6 @@ impl Ranged for ParsedExpr {
25962596
}
25972597
}
25982598

2599-
/// Represents the precedence levels for various operators and expressions of Python.
2600-
/// Variants at the top have lower precedence and variants at the bottom have
2601-
/// higher precedence.
2602-
///
2603-
/// Note: Some expressions like if-else, named expression (`:=`), lambda, subscription,
2604-
/// slicing, call and attribute reference expressions, that are mentioned in the link
2605-
/// below are better handled in other parts of the parser.
2606-
///
2607-
/// See: <https://docs.python.org/3/reference/expressions.html#operator-precedence>
2608-
#[derive(Debug, Ord, Eq, PartialEq, PartialOrd, Copy, Clone)]
2609-
pub(super) enum OperatorPrecedence {
2610-
/// The initial precedence when parsing an expression.
2611-
Initial,
2612-
/// Precedence of boolean `or` operator.
2613-
Or,
2614-
/// Precedence of boolean `and` operator.
2615-
And,
2616-
/// Precedence of boolean `not` unary operator.
2617-
Not,
2618-
/// Precedence of comparisons operators (`<`, `<=`, `>`, `>=`, `!=`, `==`),
2619-
/// memberships tests (`in`, `not in`) and identity tests (`is` `is not`).
2620-
ComparisonsMembershipIdentity,
2621-
/// Precedence of `Bitwise OR` (`|`) operator.
2622-
BitOr,
2623-
/// Precedence of `Bitwise XOR` (`^`) operator.
2624-
BitXor,
2625-
/// Precedence of `Bitwise AND` (`&`) operator.
2626-
BitAnd,
2627-
/// Precedence of left and right shift operators (`<<`, `>>`).
2628-
LeftRightShift,
2629-
/// Precedence of addition (`+`) and subtraction (`-`) operators.
2630-
AddSub,
2631-
/// Precedence of multiplication (`*`), matrix multiplication (`@`), division (`/`), floor
2632-
/// division (`//`) and remainder operators (`%`).
2633-
MulDivRemain,
2634-
/// Precedence of positive (`+`), negative (`-`), `Bitwise NOT` (`~`) unary operators.
2635-
PosNegBitNot,
2636-
/// Precedence of exponentiation operator (`**`).
2637-
Exponent,
2638-
/// Precedence of `await` expression.
2639-
Await,
2640-
}
2641-
2642-
impl OperatorPrecedence {
2643-
/// Returns `true` if the precedence is right-associative i.e., the operations are evaluated
2644-
/// from right to left.
2645-
fn is_right_associative(self) -> bool {
2646-
matches!(self, OperatorPrecedence::Exponent)
2647-
}
2648-
}
2649-
26502599
#[derive(Debug)]
26512600
enum BinaryLikeOperator {
26522601
Boolean(BoolOp),
@@ -2678,45 +2627,6 @@ impl BinaryLikeOperator {
26782627
}
26792628
}
26802629

2681-
impl From<BoolOp> for OperatorPrecedence {
2682-
#[inline]
2683-
fn from(op: BoolOp) -> Self {
2684-
match op {
2685-
BoolOp::And => OperatorPrecedence::And,
2686-
BoolOp::Or => OperatorPrecedence::Or,
2687-
}
2688-
}
2689-
}
2690-
2691-
impl From<UnaryOp> for OperatorPrecedence {
2692-
#[inline]
2693-
fn from(op: UnaryOp) -> Self {
2694-
match op {
2695-
UnaryOp::Not => OperatorPrecedence::Not,
2696-
_ => OperatorPrecedence::PosNegBitNot,
2697-
}
2698-
}
2699-
}
2700-
2701-
impl From<Operator> for OperatorPrecedence {
2702-
#[inline]
2703-
fn from(op: Operator) -> Self {
2704-
match op {
2705-
Operator::Add | Operator::Sub => OperatorPrecedence::AddSub,
2706-
Operator::Mult
2707-
| Operator::Div
2708-
| Operator::FloorDiv
2709-
| Operator::Mod
2710-
| Operator::MatMult => OperatorPrecedence::MulDivRemain,
2711-
Operator::BitAnd => OperatorPrecedence::BitAnd,
2712-
Operator::BitOr => OperatorPrecedence::BitOr,
2713-
Operator::BitXor => OperatorPrecedence::BitXor,
2714-
Operator::LShift | Operator::RShift => OperatorPrecedence::LeftRightShift,
2715-
Operator::Pow => OperatorPrecedence::Exponent,
2716-
}
2717-
}
2718-
}
2719-
27202630
/// Represents the precedence used for parsing the value part of a starred expression.
27212631
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
27222632
pub(super) enum StarredExpressionPrecedence {

crates/ruff_python_parser/tests/snapshots/valid_syntax@expressions__bin_op.py.snap

-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
---
22
source: crates/ruff_python_parser/tests/fixtures.rs
33
input_file: crates/ruff_python_parser/resources/valid/expressions/bin_op.py
4-
snapshot_kind: text
54
---
65
## AST
76

0 commit comments

Comments
 (0)