Skip to content

Commit 1675f05

Browse files
authored
Merge pull request RustPython#1305 from RustPython/fix-try-else
Repair try-except-else syntax. Fixes RustPython#1300.
2 parents 2ea516c + 19112ce commit 1675f05

File tree

3 files changed

+52
-19
lines changed

3 files changed

+52
-19
lines changed

parser/src/ast.rs

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ pub enum Top {
2424

2525
#[derive(Debug, PartialEq)]
2626
pub struct Program {
27-
pub statements: Vec<Statement>,
27+
pub statements: Suite,
2828
}
2929

3030
#[derive(Debug, PartialEq)]
@@ -40,6 +40,7 @@ pub struct Located<T> {
4040
}
4141

4242
pub type Statement = Located<StatementType>;
43+
pub type Suite = Vec<Statement>;
4344

4445
/// Abstract syntax tree nodes for python statements.
4546
#[derive(Debug, PartialEq)]
@@ -90,39 +91,39 @@ pub enum StatementType {
9091
},
9192
If {
9293
test: Expression,
93-
body: Vec<Statement>,
94-
orelse: Option<Vec<Statement>>,
94+
body: Suite,
95+
orelse: Option<Suite>,
9596
},
9697
While {
9798
test: Expression,
98-
body: Vec<Statement>,
99-
orelse: Option<Vec<Statement>>,
99+
body: Suite,
100+
orelse: Option<Suite>,
100101
},
101102
With {
102103
is_async: bool,
103104
items: Vec<WithItem>,
104-
body: Vec<Statement>,
105+
body: Suite,
105106
},
106107
For {
107108
is_async: bool,
108109
target: Box<Expression>,
109110
iter: Box<Expression>,
110-
body: Vec<Statement>,
111-
orelse: Option<Vec<Statement>>,
111+
body: Suite,
112+
orelse: Option<Suite>,
112113
},
113114
Raise {
114115
exception: Option<Expression>,
115116
cause: Option<Expression>,
116117
},
117118
Try {
118-
body: Vec<Statement>,
119+
body: Suite,
119120
handlers: Vec<ExceptHandler>,
120-
orelse: Option<Vec<Statement>>,
121-
finalbody: Option<Vec<Statement>>,
121+
orelse: Option<Suite>,
122+
finalbody: Option<Suite>,
122123
},
123124
ClassDef {
124125
name: String,
125-
body: Vec<Statement>,
126+
body: Suite,
126127
bases: Vec<Expression>,
127128
keywords: Vec<Keyword>,
128129
decorator_list: Vec<Expression>,
@@ -131,7 +132,7 @@ pub enum StatementType {
131132
is_async: bool,
132133
name: String,
133134
args: Box<Parameters>,
134-
body: Vec<Statement>,
135+
body: Suite,
135136
decorator_list: Vec<Expression>,
136137
returns: Option<Expression>,
137138
},
@@ -331,7 +332,7 @@ pub struct ExceptHandler {
331332
pub location: Location,
332333
pub typ: Option<Expression>,
333334
pub name: Option<String>,
334-
pub body: Vec<Statement>,
335+
pub body: Suite,
335336
}
336337

337338
#[derive(Debug, PartialEq)]

parser/src/python.lalrpop

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,22 +31,22 @@ Program: ast::Program = {
3131
};
3232

3333
// A file line either has a declaration, or an empty newline:
34-
FileLine: Vec<ast::Statement> = {
34+
FileLine: ast::Suite = {
3535
Statement,
3636
"\n" => vec![],
3737
};
3838

39-
Suite: Vec<ast::Statement> = {
39+
Suite: ast::Suite = {
4040
SimpleStatement,
4141
"\n" indent <s:Statement+> dedent => s.into_iter().flatten().collect(),
4242
};
4343

44-
Statement: Vec<ast::Statement> = {
44+
Statement: ast::Suite = {
4545
SimpleStatement,
4646
<s:CompoundStatement> => vec![s],
4747
};
4848

49-
SimpleStatement: Vec<ast::Statement> = {
49+
SimpleStatement: ast::Suite = {
5050
<s1:SmallStatement> <s2:(";" SmallStatement)*> ";"? "\n" => {
5151
let mut statements = vec![s1];
5252
statements.extend(s2.into_iter().map(|e| e.1));
@@ -365,7 +365,7 @@ ForStatement: ast::Statement = {
365365
};
366366

367367
TryStatement: ast::Statement = {
368-
<location:@L> "try" ":" <body:Suite> <handlers:ExceptClause*> <else_suite:("else" ":" Suite)?> <finally:("finally" ":" Suite)?> => {
368+
<location:@L> "try" ":" <body:Suite> <handlers:ExceptClause+> <else_suite:("else" ":" Suite)?> <finally:("finally" ":" Suite)?> => {
369369
let orelse = else_suite.map(|s| s.2);
370370
let finalbody = finally.map(|s| s.2);
371371
ast::Statement {
@@ -378,6 +378,20 @@ TryStatement: ast::Statement = {
378378
},
379379
}
380380
},
381+
<location:@L> "try" ":" <body:Suite> <finally:("finally" ":" Suite)> => {
382+
let handlers = vec![];
383+
let orelse = None;
384+
let finalbody = Some(finally.2);
385+
ast::Statement {
386+
location,
387+
node: ast::StatementType::Try {
388+
body,
389+
handlers,
390+
orelse,
391+
finalbody,
392+
},
393+
}
394+
},
381395
};
382396

383397
ExceptClause: ast::ExceptHandler = {

tests/snippets/try_exceptions.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,3 +238,21 @@ def y():
238238
raise NameError from ex
239239
except NameError as ex2:
240240
pass
241+
242+
243+
# the else clause requires at least one except clause:
244+
with assertRaises(SyntaxError):
245+
exec("""
246+
try:
247+
pass
248+
else:
249+
pass
250+
""")
251+
252+
253+
# Try requires at least except or finally (or both)
254+
with assertRaises(SyntaxError):
255+
exec("""
256+
try:
257+
pass
258+
""")

0 commit comments

Comments
 (0)