diff --git a/parser/src/parser.rs b/parser/src/parser.rs index 2c43f96..386257c 100644 --- a/parser/src/parser.rs +++ b/parser/src/parser.rs @@ -913,6 +913,11 @@ type type = int type match = int type case = int +# soft keyword as value +type foo = type +type foo = match +type foo = case + # multine definitions type \ X = int @@ -959,6 +964,8 @@ type ( X = int ) type = 1 +type = x = 1 +x = type = 1 "#; insta::assert_debug_snapshot!(ast::Suite::parse(source, "").unwrap()); } diff --git a/parser/src/snapshots/rustpython_parser__parser__tests__parse_type_declaration.snap b/parser/src/snapshots/rustpython_parser__parser__tests__parse_type_declaration.snap index b21c77f..e309701 100644 --- a/parser/src/snapshots/rustpython_parser__parser__tests__parse_type_declaration.snap +++ b/parser/src/snapshots/rustpython_parser__parser__tests__parse_type_declaration.snap @@ -636,10 +636,82 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" ), TypeAlias( StmtTypeAlias { - range: 367..382, + range: 369..384, name: Name( ExprName { - range: 375..376, + range: 374..377, + id: Identifier( + "foo", + ), + ctx: Load, + }, + ), + type_params: [], + value: Name( + ExprName { + range: 380..384, + id: Identifier( + "type", + ), + ctx: Load, + }, + ), + }, + ), + TypeAlias( + StmtTypeAlias { + range: 385..401, + name: Name( + ExprName { + range: 390..393, + id: Identifier( + "foo", + ), + ctx: Load, + }, + ), + type_params: [], + value: Name( + ExprName { + range: 396..401, + id: Identifier( + "match", + ), + ctx: Load, + }, + ), + }, + ), + TypeAlias( + StmtTypeAlias { + range: 402..417, + name: Name( + ExprName { + range: 407..410, + id: Identifier( + "foo", + ), + ctx: Load, + }, + ), + type_params: [], + value: Name( + ExprName { + range: 413..417, + id: Identifier( + "case", + ), + ctx: Load, + }, + ), + }, + ), + TypeAlias( + StmtTypeAlias { + range: 441..456, + name: Name( + ExprName { + range: 449..450, id: Identifier( "X", ), @@ -649,7 +721,7 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" type_params: [], value: Name( ExprName { - range: 379..382, + range: 453..456, id: Identifier( "int", ), @@ -660,10 +732,10 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" ), TypeAlias( StmtTypeAlias { - range: 383..398, + range: 457..472, name: Name( ExprName { - range: 388..389, + range: 462..463, id: Identifier( "X", ), @@ -673,7 +745,7 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" type_params: [], value: Name( ExprName { - range: 395..398, + range: 469..472, id: Identifier( "int", ), @@ -684,10 +756,10 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" ), TypeAlias( StmtTypeAlias { - range: 399..414, + range: 473..488, name: Name( ExprName { - range: 404..405, + range: 478..479, id: Identifier( "X", ), @@ -697,7 +769,7 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" type_params: [], value: Name( ExprName { - range: 411..414, + range: 485..488, id: Identifier( "int", ), @@ -708,10 +780,10 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" ), TypeAlias( StmtTypeAlias { - range: 415..435, + range: 489..509, name: Name( ExprName { - range: 420..421, + range: 494..495, id: Identifier( "X", ), @@ -721,7 +793,7 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" type_params: [], value: Name( ExprName { - range: 430..433, + range: 504..507, id: Identifier( "int", ), diff --git a/parser/src/snapshots/rustpython_parser__parser__tests__type_as_identifier.snap b/parser/src/snapshots/rustpython_parser__parser__tests__type_as_identifier.snap index 3d8e5d0..f2841a8 100644 --- a/parser/src/snapshots/rustpython_parser__parser__tests__type_as_identifier.snap +++ b/parser/src/snapshots/rustpython_parser__parser__tests__type_as_identifier.snap @@ -1001,4 +1001,74 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" type_comment: None, }, ), + Assign( + StmtAssign { + range: 626..638, + targets: [ + Name( + ExprName { + range: 626..630, + id: Identifier( + "type", + ), + ctx: Store, + }, + ), + Name( + ExprName { + range: 633..634, + id: Identifier( + "x", + ), + ctx: Store, + }, + ), + ], + value: Constant( + ExprConstant { + range: 637..638, + value: Int( + 1, + ), + kind: None, + }, + ), + type_comment: None, + }, + ), + Assign( + StmtAssign { + range: 639..651, + targets: [ + Name( + ExprName { + range: 639..640, + id: Identifier( + "x", + ), + ctx: Store, + }, + ), + Name( + ExprName { + range: 643..647, + id: Identifier( + "type", + ), + ctx: Store, + }, + ), + ], + value: Constant( + ExprConstant { + range: 650..651, + value: Int( + 1, + ), + kind: None, + }, + ), + type_comment: None, + }, + ), ] diff --git a/parser/src/soft_keywords.rs b/parser/src/soft_keywords.rs index d9d5aba..e491bf0 100644 --- a/parser/src/soft_keywords.rs +++ b/parser/src/soft_keywords.rs @@ -90,36 +90,37 @@ where } // For `type` all of the following conditions must be met: // 1. The token is at the start of a logical line. - // 2. The type token is followed by a name token. - // 3. The name token is followed by an equality token. + // 2. The type token is immediately followed by a name token. + // 3. The name token is eventually followed by an equality token. Tok::Type => { if !self.start_of_line { next = Some(Ok((soft_to_name(tok), *range))); } else { let mut nesting = 0; + let mut first = true; let mut seen_name = false; let mut seen_equal = false; while let Some(Ok((tok, _))) = self.underlying.peek() { match tok { - Tok::Newline => break, - Tok::Name { .. } if nesting == 0 => seen_name = true, - // We treat a soft keyword token following a type token as a - // name to support cases like `type type = int` or `type match = int` - Tok::Type | Tok::Match | Tok::Case if nesting == 0 => { - seen_name = true - } + Tok::Newline => break, + Tok::Name { .. } | + // We treat a soft keyword token following a type token as a + // name to support cases like `type type = int` or `type match = int` + Tok::Type | Tok::Match | Tok::Case + if first => seen_name = true, Tok::Equal if nesting == 0 && seen_name => seen_equal = true, Tok::Lpar | Tok::Lsqb | Tok::Lbrace => nesting += 1, Tok::Rpar | Tok::Rsqb | Tok::Rbrace => nesting -= 1, _ => {} } + first = false; } if !(seen_name && seen_equal) { next = Some(Ok((soft_to_name(tok), *range))); } } } - _ => (), // Not a soft keyword token + _ => (), // Not a soft keyword token } }