Skip to content
This repository was archived by the owner on Jul 27, 2023. It is now read-only.

Commit 6a13314

Browse files
committed
Refactor if statement, introduce nodes for elif and else
1 parent 510be51 commit 6a13314

7 files changed

+10714
-10525
lines changed

ast/src/generic.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -650,12 +650,12 @@ pub struct StmtIf {
650650
pub range: TextRange,
651651
pub test: Box<Expr>,
652652
pub body: Vec<Stmt>,
653-
pub orelse: Vec<Stmt>,
653+
pub elif_else_clauses: Vec<ElifElseClause>,
654654
}
655655

656656
impl Node for StmtIf {
657657
const NAME: &'static str = "If";
658-
const FIELD_NAMES: &'static [&'static str] = &["test", "body", "orelse"];
658+
const FIELD_NAMES: &'static [&'static str] = &["test", "body", "elif_else_clauses"];
659659
}
660660
impl From<StmtIf> for Stmt {
661661
fn from(payload: StmtIf) -> Self {
@@ -668,6 +668,18 @@ impl From<StmtIf> for Ast {
668668
}
669669
}
670670

671+
#[derive(Clone, Debug, PartialEq)]
672+
pub struct ElifElseClause {
673+
pub range: TextRange,
674+
pub test: Option<Expr>,
675+
pub body: Vec<Stmt>,
676+
}
677+
678+
impl Node for ElifElseClause {
679+
const NAME: &'static str = "ElifElse";
680+
const FIELD_NAMES: &'static [&'static str] = &["test", "body"];
681+
}
682+
671683
/// See also [With](https://docs.python.org/3/library/ast.html#ast.With)
672684
#[derive(Clone, Debug, PartialEq)]
673685
pub struct StmtWith {

ast/src/ranged.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,11 @@ impl Ranged for crate::generic::StmtIf {
127127
self.range
128128
}
129129
}
130+
impl Ranged for crate::generic::ElifElseClause {
131+
fn range(&self) -> TextRange {
132+
self.range
133+
}
134+
}
130135
impl Ranged for crate::generic::StmtWith {
131136
fn range(&self) -> TextRange {
132137
self.range

parser/src/python.lalrpop

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -760,25 +760,24 @@ ClassPattern: ast::Pattern = {
760760
}
761761

762762
IfStatement: ast::Stmt = {
763-
<location:@L> "if" <test:NamedExpressionTest> ":" <body:Suite> <s2:(<@L> "elif" <NamedExpressionTest> ":" <Suite>)*> <s3:("else" ":" <Suite>)?> => {
764-
// Determine last else:
765-
let mut last = s3.unwrap_or_default();
766-
let end_location = last
763+
<location:@L> "if" <test:NamedExpressionTest> ":" <body:Suite> <s2:(<@L> "elif" <NamedExpressionTest> ":" <Suite>)*> <s3:(<@L> "else" ":" <Suite>)?> => {
764+
let elif_else_clauses: Vec<_> = s2.into_iter().map(|(start, test, body)| ast::ElifElseClause {
765+
range: (start..body.last().unwrap().end()).into(),
766+
test: Some(test),
767+
body,
768+
}).chain(s3.into_iter().map(|(start, body)| ast::ElifElseClause {
769+
range: (start..body.last().unwrap().end()).into(),
770+
test: None,
771+
body,
772+
})).collect();
773+
774+
let end_location = elif_else_clauses
767775
.last()
768-
.or_else(|| s2.last().and_then(|last| last.2.last()))
769-
.or_else(|| body.last())
770-
.unwrap()
771-
.end();
772-
// handle elif:
773-
for i in s2.into_iter().rev() {
774-
let x = ast::Stmt::If(
775-
ast::StmtIf { test: Box::new(i.1), body: i.2, orelse: last, range: (i.0..end_location).into() }
776-
);
777-
last = vec![x];
778-
}
776+
.map(|last| last.end())
777+
.unwrap_or_else(|| body.last().unwrap().end());
779778

780779
ast::Stmt::If(
781-
ast::StmtIf { test: Box::new(test), body, orelse: last, range: (location..end_location).into() }
780+
ast::StmtIf { test: Box::new(test), body, elif_else_clauses, range: (location..end_location).into() }
782781
)
783782
},
784783
};

parser/src/python.rs

Lines changed: 10635 additions & 10466 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

parser/src/snapshots/rustpython_parser__context__tests__assign_named_expr.snap

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

parser/src/snapshots/rustpython_parser__parser__tests__match_as_identifier.snap

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

parser/src/snapshots/rustpython_parser__parser__tests__parse_if_elif_else.snap

Lines changed: 43 additions & 39 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)