diff --git a/parser/src/ast.rs b/parser/src/ast.rs index dc7b2a14d..d56169fd0 100644 --- a/parser/src/ast.rs +++ b/parser/src/ast.rs @@ -24,7 +24,7 @@ pub enum Top { #[derive(Debug, PartialEq)] pub struct Program { - pub statements: Vec, + pub statements: Suite, } #[derive(Debug, PartialEq)] @@ -40,6 +40,7 @@ pub struct Located { } pub type Statement = Located; +pub type Suite = Vec; /// Abstract syntax tree nodes for python statements. #[derive(Debug, PartialEq)] @@ -90,39 +91,39 @@ pub enum StatementType { }, If { test: Expression, - body: Vec, - orelse: Option>, + body: Suite, + orelse: Option, }, While { test: Expression, - body: Vec, - orelse: Option>, + body: Suite, + orelse: Option, }, With { is_async: bool, items: Vec, - body: Vec, + body: Suite, }, For { is_async: bool, target: Box, iter: Box, - body: Vec, - orelse: Option>, + body: Suite, + orelse: Option, }, Raise { exception: Option, cause: Option, }, Try { - body: Vec, + body: Suite, handlers: Vec, - orelse: Option>, - finalbody: Option>, + orelse: Option, + finalbody: Option, }, ClassDef { name: String, - body: Vec, + body: Suite, bases: Vec, keywords: Vec, decorator_list: Vec, @@ -131,7 +132,7 @@ pub enum StatementType { is_async: bool, name: String, args: Box, - body: Vec, + body: Suite, decorator_list: Vec, returns: Option, }, @@ -331,7 +332,7 @@ pub struct ExceptHandler { pub location: Location, pub typ: Option, pub name: Option, - pub body: Vec, + pub body: Suite, } #[derive(Debug, PartialEq)] diff --git a/parser/src/python.lalrpop b/parser/src/python.lalrpop index 968b6c88d..f6ac629bc 100644 --- a/parser/src/python.lalrpop +++ b/parser/src/python.lalrpop @@ -31,22 +31,22 @@ Program: ast::Program = { }; // A file line either has a declaration, or an empty newline: -FileLine: Vec = { +FileLine: ast::Suite = { Statement, "\n" => vec![], }; -Suite: Vec = { +Suite: ast::Suite = { SimpleStatement, "\n" indent dedent => s.into_iter().flatten().collect(), }; -Statement: Vec = { +Statement: ast::Suite = { SimpleStatement, => vec![s], }; -SimpleStatement: Vec = { +SimpleStatement: ast::Suite = { ";"? "\n" => { let mut statements = vec![s1]; statements.extend(s2.into_iter().map(|e| e.1)); @@ -365,8 +365,8 @@ ForStatement: ast::Statement = { }; TryStatement: ast::Statement = { - "try" ":" => { - let orelse = else_suite.map(|s| s.2); + "try" ":" => { + let (handlers, orelse) = handlers.unwrap_or_default(); let finalbody = finally.map(|s| s.2); ast::Statement { location, @@ -380,6 +380,13 @@ TryStatement: ast::Statement = { }, }; +ExceptionHandlers: (Vec, Option) = { + => { + let orelse = else_suite.map(|s| s.2); + (handlers, orelse) + }, +}; + ExceptClause: ast::ExceptHandler = { "except" ":" => { ast::ExceptHandler { diff --git a/tests/snippets/try_exceptions.py b/tests/snippets/try_exceptions.py index a4b2f5d6a..40100cb72 100644 --- a/tests/snippets/try_exceptions.py +++ b/tests/snippets/try_exceptions.py @@ -238,3 +238,12 @@ try: raise NameError from ex except NameError as ex2: pass + + +with assertRaises(SyntaxError): + exec("""if True: + try: + pass + else: + pass + """)