diff --git a/parser/python.lalrpop b/parser/python.lalrpop index 78b7136..d37f93e 100644 --- a/parser/python.lalrpop +++ b/parser/python.lalrpop @@ -451,6 +451,27 @@ TryStatement: ast::Stmt = { }, } }, + "try" ":" => { + let orelse = else_suite.map(|s| s.2).unwrap_or_default(); + let finalbody = finally.map(|s| s.2).unwrap_or_default(); + let end_location = finalbody + .last() + .or_else(|| orelse.last()) + .map(|last| last.end_location) + .or_else(|| handlers.last().map(|last| last.end_location)) + .unwrap(); + ast::Stmt { + custom: (), + location, + end_location, + node: ast::StmtKind::TryStar { + body, + handlers, + orelse, + finalbody, + }, + } + }, "try" ":" => { let handlers = vec![]; let orelse = vec![]; @@ -470,6 +491,34 @@ TryStatement: ast::Stmt = { }, }; +ExceptStarClause: ast::Excepthandler = { + "except" "*" > ":" => { + let end_location = body.last().unwrap().end_location.unwrap(); + ast::Excepthandler::new( + location, + end_location, + ast::ExcepthandlerKind::ExceptHandler { + type_: Some(Box::new(typ)), + name: None, + body, + }, + ) + }, + "except" "*" "as" Identifier)> ":" => { + let end_location = body.last().unwrap().end_location.unwrap(); + ast::Excepthandler::new( + location, + end_location, + ast::ExcepthandlerKind::ExceptHandler { + type_: Some(Box::new(x.0)), + name: Some(x.2), + body, + }, + ) + }, +}; + + ExceptClause: ast::Excepthandler = { "except" ?> ":" => { let end_location = body.last().unwrap().end_location.unwrap(); diff --git a/parser/src/parser.rs b/parser/src/parser.rs index 7f82802..cc3cb18 100644 --- a/parser/src/parser.rs +++ b/parser/src/parser.rs @@ -405,6 +405,37 @@ with (0 as a, 1 as b,): pass insta::assert_debug_snapshot!(parse_ast); } + #[test] + fn test_try() { + let parse_ast = parse_program( + r#"try: + raise ValueError(1) +except TypeError as e: + print(f'caught {type(e)}') +except OSError as e: + print(f'caught {type(e)}')"#, + "", + ) + .unwrap(); + insta::assert_debug_snapshot!(parse_ast); + } + + #[test] + fn test_try_star() { + let parse_ast = parse_program( + r#"try: + raise ExceptionGroup("eg", + [ValueError(1), TypeError(2), OSError(3), OSError(4)]) +except* TypeError as e: + print(f'caught {type(e)} with nested {e.exceptions}') +except* OSError as e: + print(f'caught {type(e)} with nested {e.exceptions}')"#, + "", + ) + .unwrap(); + insta::assert_debug_snapshot!(parse_ast); + } + #[test] fn test_dict_unpacking() { let parse_ast = parse_expression(r#"{"a": "b", **c, "d": "e"}"#, "").unwrap(); diff --git a/parser/src/snapshots/rustpython_parser__parser__tests__try.snap b/parser/src/snapshots/rustpython_parser__parser__tests__try.snap new file mode 100644 index 0000000..5b6037a --- /dev/null +++ b/parser/src/snapshots/rustpython_parser__parser__tests__try.snap @@ -0,0 +1,487 @@ +--- +source: compiler/parser/src/parser.rs +expression: parse_ast +--- +[ + Located { + location: Location { + row: 1, + column: 0, + }, + end_location: Some( + Location { + row: 6, + column: 30, + }, + ), + custom: (), + node: Try { + body: [ + Located { + location: Location { + row: 2, + column: 4, + }, + end_location: Some( + Location { + row: 2, + column: 23, + }, + ), + custom: (), + node: Raise { + exc: Some( + Located { + location: Location { + row: 2, + column: 10, + }, + end_location: Some( + Location { + row: 2, + column: 23, + }, + ), + custom: (), + node: Call { + func: Located { + location: Location { + row: 2, + column: 10, + }, + end_location: Some( + Location { + row: 2, + column: 20, + }, + ), + custom: (), + node: Name { + id: "ValueError", + ctx: Load, + }, + }, + args: [ + Located { + location: Location { + row: 2, + column: 21, + }, + end_location: Some( + Location { + row: 2, + column: 22, + }, + ), + custom: (), + node: Constant { + value: Int( + 1, + ), + kind: None, + }, + }, + ], + keywords: [], + }, + }, + ), + cause: None, + }, + }, + ], + handlers: [ + Located { + location: Location { + row: 3, + column: 0, + }, + end_location: Some( + Location { + row: 4, + column: 30, + }, + ), + custom: (), + node: ExceptHandler { + type_: Some( + Located { + location: Location { + row: 3, + column: 7, + }, + end_location: Some( + Location { + row: 3, + column: 16, + }, + ), + custom: (), + node: Name { + id: "TypeError", + ctx: Load, + }, + }, + ), + name: Some( + "e", + ), + body: [ + Located { + location: Location { + row: 4, + column: 4, + }, + end_location: Some( + Location { + row: 4, + column: 30, + }, + ), + custom: (), + node: Expr { + value: Located { + location: Location { + row: 4, + column: 4, + }, + end_location: Some( + Location { + row: 4, + column: 30, + }, + ), + custom: (), + node: Call { + func: Located { + location: Location { + row: 4, + column: 4, + }, + end_location: Some( + Location { + row: 4, + column: 9, + }, + ), + custom: (), + node: Name { + id: "print", + ctx: Load, + }, + }, + args: [ + Located { + location: Location { + row: 4, + column: 10, + }, + end_location: Some( + Location { + row: 4, + column: 29, + }, + ), + custom: (), + node: JoinedStr { + values: [ + Located { + location: Location { + row: 4, + column: 10, + }, + end_location: Some( + Location { + row: 4, + column: 29, + }, + ), + custom: (), + node: Constant { + value: Str( + "caught ", + ), + kind: None, + }, + }, + Located { + location: Location { + row: 4, + column: 10, + }, + end_location: Some( + Location { + row: 4, + column: 29, + }, + ), + custom: (), + node: FormattedValue { + value: Located { + location: Location { + row: 4, + column: 20, + }, + end_location: Some( + Location { + row: 4, + column: 27, + }, + ), + custom: (), + node: Call { + func: Located { + location: Location { + row: 4, + column: 20, + }, + end_location: Some( + Location { + row: 4, + column: 24, + }, + ), + custom: (), + node: Name { + id: "type", + ctx: Load, + }, + }, + args: [ + Located { + location: Location { + row: 4, + column: 25, + }, + end_location: Some( + Location { + row: 4, + column: 26, + }, + ), + custom: (), + node: Name { + id: "e", + ctx: Load, + }, + }, + ], + keywords: [], + }, + }, + conversion: 0, + format_spec: None, + }, + }, + ], + }, + }, + ], + keywords: [], + }, + }, + }, + }, + ], + }, + }, + Located { + location: Location { + row: 5, + column: 0, + }, + end_location: Some( + Location { + row: 6, + column: 30, + }, + ), + custom: (), + node: ExceptHandler { + type_: Some( + Located { + location: Location { + row: 5, + column: 7, + }, + end_location: Some( + Location { + row: 5, + column: 14, + }, + ), + custom: (), + node: Name { + id: "OSError", + ctx: Load, + }, + }, + ), + name: Some( + "e", + ), + body: [ + Located { + location: Location { + row: 6, + column: 4, + }, + end_location: Some( + Location { + row: 6, + column: 30, + }, + ), + custom: (), + node: Expr { + value: Located { + location: Location { + row: 6, + column: 4, + }, + end_location: Some( + Location { + row: 6, + column: 30, + }, + ), + custom: (), + node: Call { + func: Located { + location: Location { + row: 6, + column: 4, + }, + end_location: Some( + Location { + row: 6, + column: 9, + }, + ), + custom: (), + node: Name { + id: "print", + ctx: Load, + }, + }, + args: [ + Located { + location: Location { + row: 6, + column: 10, + }, + end_location: Some( + Location { + row: 6, + column: 29, + }, + ), + custom: (), + node: JoinedStr { + values: [ + Located { + location: Location { + row: 6, + column: 10, + }, + end_location: Some( + Location { + row: 6, + column: 29, + }, + ), + custom: (), + node: Constant { + value: Str( + "caught ", + ), + kind: None, + }, + }, + Located { + location: Location { + row: 6, + column: 10, + }, + end_location: Some( + Location { + row: 6, + column: 29, + }, + ), + custom: (), + node: FormattedValue { + value: Located { + location: Location { + row: 6, + column: 20, + }, + end_location: Some( + Location { + row: 6, + column: 27, + }, + ), + custom: (), + node: Call { + func: Located { + location: Location { + row: 6, + column: 20, + }, + end_location: Some( + Location { + row: 6, + column: 24, + }, + ), + custom: (), + node: Name { + id: "type", + ctx: Load, + }, + }, + args: [ + Located { + location: Location { + row: 6, + column: 25, + }, + end_location: Some( + Location { + row: 6, + column: 26, + }, + ), + custom: (), + node: Name { + id: "e", + ctx: Load, + }, + }, + ], + keywords: [], + }, + }, + conversion: 0, + format_spec: None, + }, + }, + ], + }, + }, + ], + keywords: [], + }, + }, + }, + }, + ], + }, + }, + ], + orelse: [], + finalbody: [], + }, + }, +] diff --git a/parser/src/snapshots/rustpython_parser__parser__tests__try_star.snap b/parser/src/snapshots/rustpython_parser__parser__tests__try_star.snap new file mode 100644 index 0000000..472f316 --- /dev/null +++ b/parser/src/snapshots/rustpython_parser__parser__tests__try_star.snap @@ -0,0 +1,861 @@ +--- +source: compiler/parser/src/parser.rs +expression: parse_ast +--- +[ + Located { + location: Location { + row: 1, + column: 0, + }, + end_location: Some( + Location { + row: 7, + column: 57, + }, + ), + custom: (), + node: TryStar { + body: [ + Located { + location: Location { + row: 2, + column: 4, + }, + end_location: Some( + Location { + row: 3, + column: 62, + }, + ), + custom: (), + node: Raise { + exc: Some( + Located { + location: Location { + row: 2, + column: 10, + }, + end_location: Some( + Location { + row: 3, + column: 62, + }, + ), + custom: (), + node: Call { + func: Located { + location: Location { + row: 2, + column: 10, + }, + end_location: Some( + Location { + row: 2, + column: 24, + }, + ), + custom: (), + node: Name { + id: "ExceptionGroup", + ctx: Load, + }, + }, + args: [ + Located { + location: Location { + row: 2, + column: 25, + }, + end_location: Some( + Location { + row: 2, + column: 29, + }, + ), + custom: (), + node: Constant { + value: Str( + "eg", + ), + kind: None, + }, + }, + Located { + location: Location { + row: 3, + column: 8, + }, + end_location: Some( + Location { + row: 3, + column: 61, + }, + ), + custom: (), + node: List { + elts: [ + Located { + location: Location { + row: 3, + column: 9, + }, + end_location: Some( + Location { + row: 3, + column: 22, + }, + ), + custom: (), + node: Call { + func: Located { + location: Location { + row: 3, + column: 9, + }, + end_location: Some( + Location { + row: 3, + column: 19, + }, + ), + custom: (), + node: Name { + id: "ValueError", + ctx: Load, + }, + }, + args: [ + Located { + location: Location { + row: 3, + column: 20, + }, + end_location: Some( + Location { + row: 3, + column: 21, + }, + ), + custom: (), + node: Constant { + value: Int( + 1, + ), + kind: None, + }, + }, + ], + keywords: [], + }, + }, + Located { + location: Location { + row: 3, + column: 24, + }, + end_location: Some( + Location { + row: 3, + column: 36, + }, + ), + custom: (), + node: Call { + func: Located { + location: Location { + row: 3, + column: 24, + }, + end_location: Some( + Location { + row: 3, + column: 33, + }, + ), + custom: (), + node: Name { + id: "TypeError", + ctx: Load, + }, + }, + args: [ + Located { + location: Location { + row: 3, + column: 34, + }, + end_location: Some( + Location { + row: 3, + column: 35, + }, + ), + custom: (), + node: Constant { + value: Int( + 2, + ), + kind: None, + }, + }, + ], + keywords: [], + }, + }, + Located { + location: Location { + row: 3, + column: 38, + }, + end_location: Some( + Location { + row: 3, + column: 48, + }, + ), + custom: (), + node: Call { + func: Located { + location: Location { + row: 3, + column: 38, + }, + end_location: Some( + Location { + row: 3, + column: 45, + }, + ), + custom: (), + node: Name { + id: "OSError", + ctx: Load, + }, + }, + args: [ + Located { + location: Location { + row: 3, + column: 46, + }, + end_location: Some( + Location { + row: 3, + column: 47, + }, + ), + custom: (), + node: Constant { + value: Int( + 3, + ), + kind: None, + }, + }, + ], + keywords: [], + }, + }, + Located { + location: Location { + row: 3, + column: 50, + }, + end_location: Some( + Location { + row: 3, + column: 60, + }, + ), + custom: (), + node: Call { + func: Located { + location: Location { + row: 3, + column: 50, + }, + end_location: Some( + Location { + row: 3, + column: 57, + }, + ), + custom: (), + node: Name { + id: "OSError", + ctx: Load, + }, + }, + args: [ + Located { + location: Location { + row: 3, + column: 58, + }, + end_location: Some( + Location { + row: 3, + column: 59, + }, + ), + custom: (), + node: Constant { + value: Int( + 4, + ), + kind: None, + }, + }, + ], + keywords: [], + }, + }, + ], + ctx: Load, + }, + }, + ], + keywords: [], + }, + }, + ), + cause: None, + }, + }, + ], + handlers: [ + Located { + location: Location { + row: 4, + column: 0, + }, + end_location: Some( + Location { + row: 5, + column: 57, + }, + ), + custom: (), + node: ExceptHandler { + type_: Some( + Located { + location: Location { + row: 4, + column: 8, + }, + end_location: Some( + Location { + row: 4, + column: 17, + }, + ), + custom: (), + node: Name { + id: "TypeError", + ctx: Load, + }, + }, + ), + name: Some( + "e", + ), + body: [ + Located { + location: Location { + row: 5, + column: 4, + }, + end_location: Some( + Location { + row: 5, + column: 57, + }, + ), + custom: (), + node: Expr { + value: Located { + location: Location { + row: 5, + column: 4, + }, + end_location: Some( + Location { + row: 5, + column: 57, + }, + ), + custom: (), + node: Call { + func: Located { + location: Location { + row: 5, + column: 4, + }, + end_location: Some( + Location { + row: 5, + column: 9, + }, + ), + custom: (), + node: Name { + id: "print", + ctx: Load, + }, + }, + args: [ + Located { + location: Location { + row: 5, + column: 10, + }, + end_location: Some( + Location { + row: 5, + column: 56, + }, + ), + custom: (), + node: JoinedStr { + values: [ + Located { + location: Location { + row: 5, + column: 10, + }, + end_location: Some( + Location { + row: 5, + column: 56, + }, + ), + custom: (), + node: Constant { + value: Str( + "caught ", + ), + kind: None, + }, + }, + Located { + location: Location { + row: 5, + column: 10, + }, + end_location: Some( + Location { + row: 5, + column: 56, + }, + ), + custom: (), + node: FormattedValue { + value: Located { + location: Location { + row: 5, + column: 20, + }, + end_location: Some( + Location { + row: 5, + column: 27, + }, + ), + custom: (), + node: Call { + func: Located { + location: Location { + row: 5, + column: 20, + }, + end_location: Some( + Location { + row: 5, + column: 24, + }, + ), + custom: (), + node: Name { + id: "type", + ctx: Load, + }, + }, + args: [ + Located { + location: Location { + row: 5, + column: 25, + }, + end_location: Some( + Location { + row: 5, + column: 26, + }, + ), + custom: (), + node: Name { + id: "e", + ctx: Load, + }, + }, + ], + keywords: [], + }, + }, + conversion: 0, + format_spec: None, + }, + }, + Located { + location: Location { + row: 5, + column: 10, + }, + end_location: Some( + Location { + row: 5, + column: 56, + }, + ), + custom: (), + node: Constant { + value: Str( + " with nested ", + ), + kind: None, + }, + }, + Located { + location: Location { + row: 5, + column: 10, + }, + end_location: Some( + Location { + row: 5, + column: 56, + }, + ), + custom: (), + node: FormattedValue { + value: Located { + location: Location { + row: 5, + column: 42, + }, + end_location: Some( + Location { + row: 5, + column: 54, + }, + ), + custom: (), + node: Attribute { + value: Located { + location: Location { + row: 5, + column: 42, + }, + end_location: Some( + Location { + row: 5, + column: 43, + }, + ), + custom: (), + node: Name { + id: "e", + ctx: Load, + }, + }, + attr: "exceptions", + ctx: Load, + }, + }, + conversion: 0, + format_spec: None, + }, + }, + ], + }, + }, + ], + keywords: [], + }, + }, + }, + }, + ], + }, + }, + Located { + location: Location { + row: 6, + column: 0, + }, + end_location: Some( + Location { + row: 7, + column: 57, + }, + ), + custom: (), + node: ExceptHandler { + type_: Some( + Located { + location: Location { + row: 6, + column: 8, + }, + end_location: Some( + Location { + row: 6, + column: 15, + }, + ), + custom: (), + node: Name { + id: "OSError", + ctx: Load, + }, + }, + ), + name: Some( + "e", + ), + body: [ + Located { + location: Location { + row: 7, + column: 4, + }, + end_location: Some( + Location { + row: 7, + column: 57, + }, + ), + custom: (), + node: Expr { + value: Located { + location: Location { + row: 7, + column: 4, + }, + end_location: Some( + Location { + row: 7, + column: 57, + }, + ), + custom: (), + node: Call { + func: Located { + location: Location { + row: 7, + column: 4, + }, + end_location: Some( + Location { + row: 7, + column: 9, + }, + ), + custom: (), + node: Name { + id: "print", + ctx: Load, + }, + }, + args: [ + Located { + location: Location { + row: 7, + column: 10, + }, + end_location: Some( + Location { + row: 7, + column: 56, + }, + ), + custom: (), + node: JoinedStr { + values: [ + Located { + location: Location { + row: 7, + column: 10, + }, + end_location: Some( + Location { + row: 7, + column: 56, + }, + ), + custom: (), + node: Constant { + value: Str( + "caught ", + ), + kind: None, + }, + }, + Located { + location: Location { + row: 7, + column: 10, + }, + end_location: Some( + Location { + row: 7, + column: 56, + }, + ), + custom: (), + node: FormattedValue { + value: Located { + location: Location { + row: 7, + column: 20, + }, + end_location: Some( + Location { + row: 7, + column: 27, + }, + ), + custom: (), + node: Call { + func: Located { + location: Location { + row: 7, + column: 20, + }, + end_location: Some( + Location { + row: 7, + column: 24, + }, + ), + custom: (), + node: Name { + id: "type", + ctx: Load, + }, + }, + args: [ + Located { + location: Location { + row: 7, + column: 25, + }, + end_location: Some( + Location { + row: 7, + column: 26, + }, + ), + custom: (), + node: Name { + id: "e", + ctx: Load, + }, + }, + ], + keywords: [], + }, + }, + conversion: 0, + format_spec: None, + }, + }, + Located { + location: Location { + row: 7, + column: 10, + }, + end_location: Some( + Location { + row: 7, + column: 56, + }, + ), + custom: (), + node: Constant { + value: Str( + " with nested ", + ), + kind: None, + }, + }, + Located { + location: Location { + row: 7, + column: 10, + }, + end_location: Some( + Location { + row: 7, + column: 56, + }, + ), + custom: (), + node: FormattedValue { + value: Located { + location: Location { + row: 7, + column: 42, + }, + end_location: Some( + Location { + row: 7, + column: 54, + }, + ), + custom: (), + node: Attribute { + value: Located { + location: Location { + row: 7, + column: 42, + }, + end_location: Some( + Location { + row: 7, + column: 43, + }, + ), + custom: (), + node: Name { + id: "e", + ctx: Load, + }, + }, + attr: "exceptions", + ctx: Load, + }, + }, + conversion: 0, + format_spec: None, + }, + }, + ], + }, + }, + ], + keywords: [], + }, + }, + }, + }, + ], + }, + }, + ], + orelse: [], + finalbody: [], + }, + }, +]