-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Better error recovery for match patterns #10477
Conversation
|
b7242be
to
e1f1cc8
Compare
1cf7954
to
707d62a
Compare
e1f1cc8
to
801539c
Compare
801539c
to
ebeea51
Compare
case *a: | ||
case *a,: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Star pattern is only allowed inside a sequence pattern as per the grammar.
let cls = match cls { | ||
Pattern::MatchAs(ast::PatternMatchAs { | ||
pattern: None, | ||
name: Some(ident), | ||
.. | ||
}) => { | ||
if ident.is_valid() { | ||
Box::new(Expr::Name(ast::ExprName { | ||
range: ident.range(), | ||
id: ident.id, | ||
ctx: ExprContext::Load, | ||
})) | ||
} else { | ||
Box::new(Expr::Name(ast::ExprName { | ||
range: ident.range(), | ||
id: String::new(), | ||
ctx: ExprContext::Invalid, | ||
})) | ||
} | ||
} | ||
Pattern::MatchValue(ast::PatternMatchValue { value, .. }) | ||
if matches!(&*value, Expr::Attribute(_)) => | ||
{ | ||
value | ||
} | ||
pattern => { | ||
self.add_error( | ||
ParseErrorType::OtherError("invalid value for a class pattern".to_string()), | ||
&pattern, | ||
); | ||
Box::new(recovery::pattern_to_expr(pattern)) | ||
} | ||
}; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is mainly moved from down below because class comes first and then the arguments. It's only to maintain the flow of parsing.
The change here is to use recovery::pattern_to_expr
.
if let Pattern::MatchAs(ast::PatternMatchAs { | ||
name: Some(attr), .. | ||
pattern: None, | ||
name: Some(attr), | ||
.. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To disallow:
match subject:
case Foo(a as b = 1):
pass
# Positional pattern cannot follow keyword pattern | ||
# case Foo(x, y=1, z): | ||
# pass |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this intentionally commented out?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. So, positional pattern cannot follow keyword pattern in a class pattern (case Foo(x=1, y): ...
is invalid) but this means the pre-order assert in the invalid code fails.
I'll probably need to have a mathod on PatternArguments
similar to how's one for Arguments
(arguments_source_order
) to return an argument in the order defined in source.
I need to think about this because it's only required while testing.
...ython_parser/tests/snapshots/invalid_syntax@statements__match__invalid_class_pattern.py.snap
Outdated
Show resolved
Hide resolved
..._parser/tests/snapshots/invalid_syntax@statements__match__invalid_lhs_or_rhs_pattern.py.snap
Outdated
Show resolved
Hide resolved
..._parser/tests/snapshots/invalid_syntax@statements__match__invalid_lhs_or_rhs_pattern.py.snap
Outdated
Show resolved
Hide resolved
..._parser/tests/snapshots/invalid_syntax@statements__match__invalid_lhs_or_rhs_pattern.py.snap
Outdated
Show resolved
Hide resolved
...hon_parser/tests/snapshots/invalid_syntax@statements__match__invalid_mapping_pattern.py.snap
Show resolved
Hide resolved
// It's not possible to retain multiple double starred patterns because | ||
// of the way the mapping node is represented in the grammar. The last | ||
// value will always win. | ||
rest = Some(identifier); | ||
} else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, this is a problem because we now drop "nodes", meaning the MatchPatternMapping
range covers nodes that aren't represented in the AST.
Any chance we could convert the star to a starred expression instead and push a pattern at the right position? If not, then we may need to bail out early here, even if it means that the error recovery isn't as good as it could be (or we have to change the AST representation)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any chance we could convert the star to a starred expression instead and push a pattern at the right position?
Not really because there's no way to represent a double starred expression in the AST, there's only a ExprStarred
which is for *foo
.
If not, then we may need to bail out early here, even if it means that the error recovery isn't as good as it could be (or we have to change the AST representation)
I could see what bailing would look like but I'd prefer to change the AST representation even it means a bit more work to be done.
Thinking quickly about the AST representation, there are two solutions which comes to my mind:
- Add a new
Pattern
variant for**data
and store it inMatchPatternMapping::patterns
field. This is probably not a good idea - Replace the
keys
,patterns
andrest
fields with a singleentries
field which is an enum with two kind (MappingPattern::DoubleStar
andMappingPattern::KeyValue
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, this is happening in a list parsing so might involve using the parser context flags.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm also leaning on changing the AST (e.g. similar to Pyright's AST). What's important to me is that we don't spend too much time now working on error recovery. I'm also okay marking this as a todo (creating an issue) and following up on this later because the focus now is on replacing the parser, not on perfect error recovery.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I'd prefer to not to do it now as well. I'll open an issue for it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
crates/ruff_python_parser/resources/invalid/statements/match/invalid_mapping_pattern.py
Outdated
Show resolved
Hide resolved
## Summary This PR is a follow-up to #10477 which does the following: 1. Improve error message around complex literal pattern. Remove usage of "lhs" and "rhs" term from user facing messages. 2. Better error recovery for unary plus. This isn't allowed in the literal pattern so we'll just parse it and throw an error directly. 3. Fix a bug where we disallowed a unary sub in sequence pattern 4. Reduce error range for invalid key value for a mapping pattern ## Test Plan Add new test cases, update and review the snapshots
## Summary This PR addresses the feedback given here: #10477 (comment) **Problem:** The `as` pattern containing both the pattern and name (`foo as bar`) cannot be converted to an expression as there's no AST node to represent that. The solution for now is to not drop any nodes, panic in the conversion if the parser is doing so, and make sure the calling code is avoiding the panic. There are 3 places where the conversion happens: 1. Mapping pattern 2. Class pattern 3. Complex literal pattern Another thing to keep in mind is that the `parse_match_pattern_lhs` method only parses the `as` pattern if it's parenthesized. The reason being that the `(` is ambiguous as to whether it's a parenthesized pattern or the start of a sequence pattern. Now, the mapping items are parsed using list parsing and it's only called if the start token is in the FIRST set which the `(` token isn't. This avoids the panic in mapping pattern. For the class and complex literal pattern, the starting point is `parse_match_pattern_lhs` method. It then checks if the parser is at `(` (as in `Foo(x, y)`) or `+`/`-` (as in `1 + 1j`) and continues with the respective parsing methods. We want to avoid going further in case we have an `as` pattern to avoid the panic. This means we'll exit early in that case. ## Test Plan Added a few test cases, updated the snapshots. Note that this PR isn't focused on error recovery, it's to avoid dropping any potential node which is the case when converting from an `as` pattern to an expression. Another thing to note is that the following test case fails (not added) because the error recovery is bad and the node ranges aren't in order: ```python match subject: case {x as y: 1}: pass ``` <details><summary>Click here to view the AST and errors for the above code:</summary> <p> ```rs Module( ModModule { range: 0..50, body: [ Match( StmtMatch { range: 0..49, subject: Name( ExprName { range: 6..13, id: "subject", ctx: Load, }, ), cases: [ MatchCase { range: 19..49, pattern: MatchMapping( PatternMatchMapping { range: 24..35, keys: [ Name( ExprName { range: 25..26, id: "x", ctx: Store, }, ), Name( ExprName { range: 30..31, id: "y", ctx: Store, }, ), ], patterns: [ MatchValue( PatternMatchValue { range: 29..29, value: Name( ExprName { range: 27..29, id: "as", ctx: Load, }, ), }, ), MatchValue( PatternMatchValue { range: 33..34, value: NumberLiteral( ExprNumberLiteral { range: 33..34, value: Int( 1, ), }, ), }, ), ], rest: None, }, ), guard: None, body: [ Pass( StmtPass { range: 45..49, }, ), ], }, ], }, ), ], }, ) ``` Errors: ``` Syntax Error: invalid mapping pattern key at byte range 25..26 | 1 | match subject: 2 | case {x as y: 1}: | ^ Syntax Error: invalid mapping pattern key 3 | pass | Syntax Error: expected Colon, found As at byte range 27..29 | 1 | match subject: 2 | case {x as y: 1}: | ^^ Syntax Error: expected Colon, found As 3 | pass | Syntax Error: expected Comma, found Name at byte range 30..31 | 1 | match subject: 2 | case {x as y: 1}: | ^ Syntax Error: expected Comma, found Name 3 | pass | ``` </p> </details>
## Summary This fixes the bug which I encountered in #10523 (comment) ## Test Plan Add the failing test case and update the snapshot.
## Summary This PR updates the match statement's pattern parsing logic to better facilitate the error recovery. The following changes are made: ### Disallow star pattern (`*<name>`) outside of sequence pattern This is done by passing an enum stating whether to allow star pattern or not and is based on where the parser is in the stack. <details><summary>Call stack for pattern parsing functions:</summary> <p> I took notes on where would I requires changing this, so sharing it for documenting purposes: * `parse_match_patterns` * `parse_match_pattern` (`AllowStarPattern::Yes`) * Error if it’s a star pattern and it's not a sequence pattern * `parse_sequence_match_pattern` * `parse_match_pattern` (`AllowStarPattern::Yes`) * `parse_match_pattern` (`allow_star_pattern: AllowStarPattern`) * `parse_match_pattern_lhs` (`allow_star_pattern: AllowStarPattern`) * `parse_match_pattern_mapping` * `parse_match_pattern_lhs` (`AllowStarPattern::No`) * `parse_match_pattern` (`AllowStarPattern::No`) * `parse_match_pattern_star` * `parse_delimited_match_pattern` * `parse_match_pattern` (`AllowStarPattern::Yes`) * `parse_sequence_match_pattern` * `parse_match_pattern_literal` * `parse_attr_expr_for_match_pattern` * `parse_match_pattern_class` * `parse_match_pattern` (`AllowStarPattern::No`) * `parse_complex_literal_pattern` * `parse_match_pattern_lhs` (`AllowStarPattern::No`) </p> </details> The mapping pattern `FIRST` set has been updated to include `*` to allow the parser to recover from this error in mapping pattern. Otherwise, the list parsing would completely skip parsing it. ### Convert `Pattern` to `Expr` In certain cases, the parser expects a specific type of pattern and uses that to extract information. For example, in complex literal, we parse the LHS and RHS as patterns but the LHS can only be a real number while the RHS can only be a complex number. This means that if the parser found any other pattern kind then we would convert the pattern into an equivalent expression and add an appropriate error. This will help any downstream tools. Refer to `recovery::pattern_to_expr` for more details. ### Extract complex number literal pattern parsing logic Earlier, this was inside the `parse_match_pattern_lhs` which made the method a bit more complex than it needed to be. The logic has been extracted to a new `parse_complex_pattern_literal` and is called when the parser encounters a pattern followed by either `+` or `-`. The parser only allows a valid complex literal pattern which is `real_number +/- complex_number`. For any other case, an appropriate error will be raised. ## Review Refer to the test cases to help in the review process. ## Test Plan Add test cases and update the snapshots.
## Summary This PR updates the match statement's pattern parsing logic to better facilitate the error recovery. The following changes are made: ### Disallow star pattern (`*<name>`) outside of sequence pattern This is done by passing an enum stating whether to allow star pattern or not and is based on where the parser is in the stack. <details><summary>Call stack for pattern parsing functions:</summary> <p> I took notes on where would I requires changing this, so sharing it for documenting purposes: * `parse_match_patterns` * `parse_match_pattern` (`AllowStarPattern::Yes`) * Error if it’s a star pattern and it's not a sequence pattern * `parse_sequence_match_pattern` * `parse_match_pattern` (`AllowStarPattern::Yes`) * `parse_match_pattern` (`allow_star_pattern: AllowStarPattern`) * `parse_match_pattern_lhs` (`allow_star_pattern: AllowStarPattern`) * `parse_match_pattern_mapping` * `parse_match_pattern_lhs` (`AllowStarPattern::No`) * `parse_match_pattern` (`AllowStarPattern::No`) * `parse_match_pattern_star` * `parse_delimited_match_pattern` * `parse_match_pattern` (`AllowStarPattern::Yes`) * `parse_sequence_match_pattern` * `parse_match_pattern_literal` * `parse_attr_expr_for_match_pattern` * `parse_match_pattern_class` * `parse_match_pattern` (`AllowStarPattern::No`) * `parse_complex_literal_pattern` * `parse_match_pattern_lhs` (`AllowStarPattern::No`) </p> </details> The mapping pattern `FIRST` set has been updated to include `*` to allow the parser to recover from this error in mapping pattern. Otherwise, the list parsing would completely skip parsing it. ### Convert `Pattern` to `Expr` In certain cases, the parser expects a specific type of pattern and uses that to extract information. For example, in complex literal, we parse the LHS and RHS as patterns but the LHS can only be a real number while the RHS can only be a complex number. This means that if the parser found any other pattern kind then we would convert the pattern into an equivalent expression and add an appropriate error. This will help any downstream tools. Refer to `recovery::pattern_to_expr` for more details. ### Extract complex number literal pattern parsing logic Earlier, this was inside the `parse_match_pattern_lhs` which made the method a bit more complex than it needed to be. The logic has been extracted to a new `parse_complex_pattern_literal` and is called when the parser encounters a pattern followed by either `+` or `-`. The parser only allows a valid complex literal pattern which is `real_number +/- complex_number`. For any other case, an appropriate error will be raised. ## Review Refer to the test cases to help in the review process. ## Test Plan Add test cases and update the snapshots.
## Summary This PR updates the match statement's pattern parsing logic to better facilitate the error recovery. The following changes are made: ### Disallow star pattern (`*<name>`) outside of sequence pattern This is done by passing an enum stating whether to allow star pattern or not and is based on where the parser is in the stack. <details><summary>Call stack for pattern parsing functions:</summary> <p> I took notes on where would I requires changing this, so sharing it for documenting purposes: * `parse_match_patterns` * `parse_match_pattern` (`AllowStarPattern::Yes`) * Error if it’s a star pattern and it's not a sequence pattern * `parse_sequence_match_pattern` * `parse_match_pattern` (`AllowStarPattern::Yes`) * `parse_match_pattern` (`allow_star_pattern: AllowStarPattern`) * `parse_match_pattern_lhs` (`allow_star_pattern: AllowStarPattern`) * `parse_match_pattern_mapping` * `parse_match_pattern_lhs` (`AllowStarPattern::No`) * `parse_match_pattern` (`AllowStarPattern::No`) * `parse_match_pattern_star` * `parse_delimited_match_pattern` * `parse_match_pattern` (`AllowStarPattern::Yes`) * `parse_sequence_match_pattern` * `parse_match_pattern_literal` * `parse_attr_expr_for_match_pattern` * `parse_match_pattern_class` * `parse_match_pattern` (`AllowStarPattern::No`) * `parse_complex_literal_pattern` * `parse_match_pattern_lhs` (`AllowStarPattern::No`) </p> </details> The mapping pattern `FIRST` set has been updated to include `*` to allow the parser to recover from this error in mapping pattern. Otherwise, the list parsing would completely skip parsing it. ### Convert `Pattern` to `Expr` In certain cases, the parser expects a specific type of pattern and uses that to extract information. For example, in complex literal, we parse the LHS and RHS as patterns but the LHS can only be a real number while the RHS can only be a complex number. This means that if the parser found any other pattern kind then we would convert the pattern into an equivalent expression and add an appropriate error. This will help any downstream tools. Refer to `recovery::pattern_to_expr` for more details. ### Extract complex number literal pattern parsing logic Earlier, this was inside the `parse_match_pattern_lhs` which made the method a bit more complex than it needed to be. The logic has been extracted to a new `parse_complex_pattern_literal` and is called when the parser encounters a pattern followed by either `+` or `-`. The parser only allows a valid complex literal pattern which is `real_number +/- complex_number`. For any other case, an appropriate error will be raised. ## Review Refer to the test cases to help in the review process. ## Test Plan Add test cases and update the snapshots.
## Summary This PR updates the match statement's pattern parsing logic to better facilitate the error recovery. The following changes are made: ### Disallow star pattern (`*<name>`) outside of sequence pattern This is done by passing an enum stating whether to allow star pattern or not and is based on where the parser is in the stack. <details><summary>Call stack for pattern parsing functions:</summary> <p> I took notes on where would I requires changing this, so sharing it for documenting purposes: * `parse_match_patterns` * `parse_match_pattern` (`AllowStarPattern::Yes`) * Error if it’s a star pattern and it's not a sequence pattern * `parse_sequence_match_pattern` * `parse_match_pattern` (`AllowStarPattern::Yes`) * `parse_match_pattern` (`allow_star_pattern: AllowStarPattern`) * `parse_match_pattern_lhs` (`allow_star_pattern: AllowStarPattern`) * `parse_match_pattern_mapping` * `parse_match_pattern_lhs` (`AllowStarPattern::No`) * `parse_match_pattern` (`AllowStarPattern::No`) * `parse_match_pattern_star` * `parse_delimited_match_pattern` * `parse_match_pattern` (`AllowStarPattern::Yes`) * `parse_sequence_match_pattern` * `parse_match_pattern_literal` * `parse_attr_expr_for_match_pattern` * `parse_match_pattern_class` * `parse_match_pattern` (`AllowStarPattern::No`) * `parse_complex_literal_pattern` * `parse_match_pattern_lhs` (`AllowStarPattern::No`) </p> </details> The mapping pattern `FIRST` set has been updated to include `*` to allow the parser to recover from this error in mapping pattern. Otherwise, the list parsing would completely skip parsing it. ### Convert `Pattern` to `Expr` In certain cases, the parser expects a specific type of pattern and uses that to extract information. For example, in complex literal, we parse the LHS and RHS as patterns but the LHS can only be a real number while the RHS can only be a complex number. This means that if the parser found any other pattern kind then we would convert the pattern into an equivalent expression and add an appropriate error. This will help any downstream tools. Refer to `recovery::pattern_to_expr` for more details. ### Extract complex number literal pattern parsing logic Earlier, this was inside the `parse_match_pattern_lhs` which made the method a bit more complex than it needed to be. The logic has been extracted to a new `parse_complex_pattern_literal` and is called when the parser encounters a pattern followed by either `+` or `-`. The parser only allows a valid complex literal pattern which is `real_number +/- complex_number`. For any other case, an appropriate error will be raised. ## Review Refer to the test cases to help in the review process. ## Test Plan Add test cases and update the snapshots.
## Summary This PR updates the match statement's pattern parsing logic to better facilitate the error recovery. The following changes are made: ### Disallow star pattern (`*<name>`) outside of sequence pattern This is done by passing an enum stating whether to allow star pattern or not and is based on where the parser is in the stack. <details><summary>Call stack for pattern parsing functions:</summary> <p> I took notes on where would I requires changing this, so sharing it for documenting purposes: * `parse_match_patterns` * `parse_match_pattern` (`AllowStarPattern::Yes`) * Error if it’s a star pattern and it's not a sequence pattern * `parse_sequence_match_pattern` * `parse_match_pattern` (`AllowStarPattern::Yes`) * `parse_match_pattern` (`allow_star_pattern: AllowStarPattern`) * `parse_match_pattern_lhs` (`allow_star_pattern: AllowStarPattern`) * `parse_match_pattern_mapping` * `parse_match_pattern_lhs` (`AllowStarPattern::No`) * `parse_match_pattern` (`AllowStarPattern::No`) * `parse_match_pattern_star` * `parse_delimited_match_pattern` * `parse_match_pattern` (`AllowStarPattern::Yes`) * `parse_sequence_match_pattern` * `parse_match_pattern_literal` * `parse_attr_expr_for_match_pattern` * `parse_match_pattern_class` * `parse_match_pattern` (`AllowStarPattern::No`) * `parse_complex_literal_pattern` * `parse_match_pattern_lhs` (`AllowStarPattern::No`) </p> </details> The mapping pattern `FIRST` set has been updated to include `*` to allow the parser to recover from this error in mapping pattern. Otherwise, the list parsing would completely skip parsing it. ### Convert `Pattern` to `Expr` In certain cases, the parser expects a specific type of pattern and uses that to extract information. For example, in complex literal, we parse the LHS and RHS as patterns but the LHS can only be a real number while the RHS can only be a complex number. This means that if the parser found any other pattern kind then we would convert the pattern into an equivalent expression and add an appropriate error. This will help any downstream tools. Refer to `recovery::pattern_to_expr` for more details. ### Extract complex number literal pattern parsing logic Earlier, this was inside the `parse_match_pattern_lhs` which made the method a bit more complex than it needed to be. The logic has been extracted to a new `parse_complex_pattern_literal` and is called when the parser encounters a pattern followed by either `+` or `-`. The parser only allows a valid complex literal pattern which is `real_number +/- complex_number`. For any other case, an appropriate error will be raised. ## Review Refer to the test cases to help in the review process. ## Test Plan Add test cases and update the snapshots.
## Summary This PR updates the match statement's pattern parsing logic to better facilitate the error recovery. The following changes are made: ### Disallow star pattern (`*<name>`) outside of sequence pattern This is done by passing an enum stating whether to allow star pattern or not and is based on where the parser is in the stack. <details><summary>Call stack for pattern parsing functions:</summary> <p> I took notes on where would I requires changing this, so sharing it for documenting purposes: * `parse_match_patterns` * `parse_match_pattern` (`AllowStarPattern::Yes`) * Error if it’s a star pattern and it's not a sequence pattern * `parse_sequence_match_pattern` * `parse_match_pattern` (`AllowStarPattern::Yes`) * `parse_match_pattern` (`allow_star_pattern: AllowStarPattern`) * `parse_match_pattern_lhs` (`allow_star_pattern: AllowStarPattern`) * `parse_match_pattern_mapping` * `parse_match_pattern_lhs` (`AllowStarPattern::No`) * `parse_match_pattern` (`AllowStarPattern::No`) * `parse_match_pattern_star` * `parse_delimited_match_pattern` * `parse_match_pattern` (`AllowStarPattern::Yes`) * `parse_sequence_match_pattern` * `parse_match_pattern_literal` * `parse_attr_expr_for_match_pattern` * `parse_match_pattern_class` * `parse_match_pattern` (`AllowStarPattern::No`) * `parse_complex_literal_pattern` * `parse_match_pattern_lhs` (`AllowStarPattern::No`) </p> </details> The mapping pattern `FIRST` set has been updated to include `*` to allow the parser to recover from this error in mapping pattern. Otherwise, the list parsing would completely skip parsing it. ### Convert `Pattern` to `Expr` In certain cases, the parser expects a specific type of pattern and uses that to extract information. For example, in complex literal, we parse the LHS and RHS as patterns but the LHS can only be a real number while the RHS can only be a complex number. This means that if the parser found any other pattern kind then we would convert the pattern into an equivalent expression and add an appropriate error. This will help any downstream tools. Refer to `recovery::pattern_to_expr` for more details. ### Extract complex number literal pattern parsing logic Earlier, this was inside the `parse_match_pattern_lhs` which made the method a bit more complex than it needed to be. The logic has been extracted to a new `parse_complex_pattern_literal` and is called when the parser encounters a pattern followed by either `+` or `-`. The parser only allows a valid complex literal pattern which is `real_number +/- complex_number`. For any other case, an appropriate error will be raised. ## Review Refer to the test cases to help in the review process. ## Test Plan Add test cases and update the snapshots.
## Summary This PR updates the match statement's pattern parsing logic to better facilitate the error recovery. The following changes are made: ### Disallow star pattern (`*<name>`) outside of sequence pattern This is done by passing an enum stating whether to allow star pattern or not and is based on where the parser is in the stack. <details><summary>Call stack for pattern parsing functions:</summary> <p> I took notes on where would I requires changing this, so sharing it for documenting purposes: * `parse_match_patterns` * `parse_match_pattern` (`AllowStarPattern::Yes`) * Error if it’s a star pattern and it's not a sequence pattern * `parse_sequence_match_pattern` * `parse_match_pattern` (`AllowStarPattern::Yes`) * `parse_match_pattern` (`allow_star_pattern: AllowStarPattern`) * `parse_match_pattern_lhs` (`allow_star_pattern: AllowStarPattern`) * `parse_match_pattern_mapping` * `parse_match_pattern_lhs` (`AllowStarPattern::No`) * `parse_match_pattern` (`AllowStarPattern::No`) * `parse_match_pattern_star` * `parse_delimited_match_pattern` * `parse_match_pattern` (`AllowStarPattern::Yes`) * `parse_sequence_match_pattern` * `parse_match_pattern_literal` * `parse_attr_expr_for_match_pattern` * `parse_match_pattern_class` * `parse_match_pattern` (`AllowStarPattern::No`) * `parse_complex_literal_pattern` * `parse_match_pattern_lhs` (`AllowStarPattern::No`) </p> </details> The mapping pattern `FIRST` set has been updated to include `*` to allow the parser to recover from this error in mapping pattern. Otherwise, the list parsing would completely skip parsing it. ### Convert `Pattern` to `Expr` In certain cases, the parser expects a specific type of pattern and uses that to extract information. For example, in complex literal, we parse the LHS and RHS as patterns but the LHS can only be a real number while the RHS can only be a complex number. This means that if the parser found any other pattern kind then we would convert the pattern into an equivalent expression and add an appropriate error. This will help any downstream tools. Refer to `recovery::pattern_to_expr` for more details. ### Extract complex number literal pattern parsing logic Earlier, this was inside the `parse_match_pattern_lhs` which made the method a bit more complex than it needed to be. The logic has been extracted to a new `parse_complex_pattern_literal` and is called when the parser encounters a pattern followed by either `+` or `-`. The parser only allows a valid complex literal pattern which is `real_number +/- complex_number`. For any other case, an appropriate error will be raised. ## Review Refer to the test cases to help in the review process. ## Test Plan Add test cases and update the snapshots.
## Summary This PR updates the match statement's pattern parsing logic to better facilitate the error recovery. The following changes are made: ### Disallow star pattern (`*<name>`) outside of sequence pattern This is done by passing an enum stating whether to allow star pattern or not and is based on where the parser is in the stack. <details><summary>Call stack for pattern parsing functions:</summary> <p> I took notes on where would I requires changing this, so sharing it for documenting purposes: * `parse_match_patterns` * `parse_match_pattern` (`AllowStarPattern::Yes`) * Error if it’s a star pattern and it's not a sequence pattern * `parse_sequence_match_pattern` * `parse_match_pattern` (`AllowStarPattern::Yes`) * `parse_match_pattern` (`allow_star_pattern: AllowStarPattern`) * `parse_match_pattern_lhs` (`allow_star_pattern: AllowStarPattern`) * `parse_match_pattern_mapping` * `parse_match_pattern_lhs` (`AllowStarPattern::No`) * `parse_match_pattern` (`AllowStarPattern::No`) * `parse_match_pattern_star` * `parse_delimited_match_pattern` * `parse_match_pattern` (`AllowStarPattern::Yes`) * `parse_sequence_match_pattern` * `parse_match_pattern_literal` * `parse_attr_expr_for_match_pattern` * `parse_match_pattern_class` * `parse_match_pattern` (`AllowStarPattern::No`) * `parse_complex_literal_pattern` * `parse_match_pattern_lhs` (`AllowStarPattern::No`) </p> </details> The mapping pattern `FIRST` set has been updated to include `*` to allow the parser to recover from this error in mapping pattern. Otherwise, the list parsing would completely skip parsing it. ### Convert `Pattern` to `Expr` In certain cases, the parser expects a specific type of pattern and uses that to extract information. For example, in complex literal, we parse the LHS and RHS as patterns but the LHS can only be a real number while the RHS can only be a complex number. This means that if the parser found any other pattern kind then we would convert the pattern into an equivalent expression and add an appropriate error. This will help any downstream tools. Refer to `recovery::pattern_to_expr` for more details. ### Extract complex number literal pattern parsing logic Earlier, this was inside the `parse_match_pattern_lhs` which made the method a bit more complex than it needed to be. The logic has been extracted to a new `parse_complex_pattern_literal` and is called when the parser encounters a pattern followed by either `+` or `-`. The parser only allows a valid complex literal pattern which is `real_number +/- complex_number`. For any other case, an appropriate error will be raised. ## Review Refer to the test cases to help in the review process. ## Test Plan Add test cases and update the snapshots.
## Summary This PR updates the match statement's pattern parsing logic to better facilitate the error recovery. The following changes are made: ### Disallow star pattern (`*<name>`) outside of sequence pattern This is done by passing an enum stating whether to allow star pattern or not and is based on where the parser is in the stack. <details><summary>Call stack for pattern parsing functions:</summary> <p> I took notes on where would I requires changing this, so sharing it for documenting purposes: * `parse_match_patterns` * `parse_match_pattern` (`AllowStarPattern::Yes`) * Error if it’s a star pattern and it's not a sequence pattern * `parse_sequence_match_pattern` * `parse_match_pattern` (`AllowStarPattern::Yes`) * `parse_match_pattern` (`allow_star_pattern: AllowStarPattern`) * `parse_match_pattern_lhs` (`allow_star_pattern: AllowStarPattern`) * `parse_match_pattern_mapping` * `parse_match_pattern_lhs` (`AllowStarPattern::No`) * `parse_match_pattern` (`AllowStarPattern::No`) * `parse_match_pattern_star` * `parse_delimited_match_pattern` * `parse_match_pattern` (`AllowStarPattern::Yes`) * `parse_sequence_match_pattern` * `parse_match_pattern_literal` * `parse_attr_expr_for_match_pattern` * `parse_match_pattern_class` * `parse_match_pattern` (`AllowStarPattern::No`) * `parse_complex_literal_pattern` * `parse_match_pattern_lhs` (`AllowStarPattern::No`) </p> </details> The mapping pattern `FIRST` set has been updated to include `*` to allow the parser to recover from this error in mapping pattern. Otherwise, the list parsing would completely skip parsing it. ### Convert `Pattern` to `Expr` In certain cases, the parser expects a specific type of pattern and uses that to extract information. For example, in complex literal, we parse the LHS and RHS as patterns but the LHS can only be a real number while the RHS can only be a complex number. This means that if the parser found any other pattern kind then we would convert the pattern into an equivalent expression and add an appropriate error. This will help any downstream tools. Refer to `recovery::pattern_to_expr` for more details. ### Extract complex number literal pattern parsing logic Earlier, this was inside the `parse_match_pattern_lhs` which made the method a bit more complex than it needed to be. The logic has been extracted to a new `parse_complex_pattern_literal` and is called when the parser encounters a pattern followed by either `+` or `-`. The parser only allows a valid complex literal pattern which is `real_number +/- complex_number`. For any other case, an appropriate error will be raised. ## Review Refer to the test cases to help in the review process. ## Test Plan Add test cases and update the snapshots.
## Summary This PR updates the match statement's pattern parsing logic to better facilitate the error recovery. The following changes are made: ### Disallow star pattern (`*<name>`) outside of sequence pattern This is done by passing an enum stating whether to allow star pattern or not and is based on where the parser is in the stack. <details><summary>Call stack for pattern parsing functions:</summary> <p> I took notes on where would I requires changing this, so sharing it for documenting purposes: * `parse_match_patterns` * `parse_match_pattern` (`AllowStarPattern::Yes`) * Error if it’s a star pattern and it's not a sequence pattern * `parse_sequence_match_pattern` * `parse_match_pattern` (`AllowStarPattern::Yes`) * `parse_match_pattern` (`allow_star_pattern: AllowStarPattern`) * `parse_match_pattern_lhs` (`allow_star_pattern: AllowStarPattern`) * `parse_match_pattern_mapping` * `parse_match_pattern_lhs` (`AllowStarPattern::No`) * `parse_match_pattern` (`AllowStarPattern::No`) * `parse_match_pattern_star` * `parse_delimited_match_pattern` * `parse_match_pattern` (`AllowStarPattern::Yes`) * `parse_sequence_match_pattern` * `parse_match_pattern_literal` * `parse_attr_expr_for_match_pattern` * `parse_match_pattern_class` * `parse_match_pattern` (`AllowStarPattern::No`) * `parse_complex_literal_pattern` * `parse_match_pattern_lhs` (`AllowStarPattern::No`) </p> </details> The mapping pattern `FIRST` set has been updated to include `*` to allow the parser to recover from this error in mapping pattern. Otherwise, the list parsing would completely skip parsing it. ### Convert `Pattern` to `Expr` In certain cases, the parser expects a specific type of pattern and uses that to extract information. For example, in complex literal, we parse the LHS and RHS as patterns but the LHS can only be a real number while the RHS can only be a complex number. This means that if the parser found any other pattern kind then we would convert the pattern into an equivalent expression and add an appropriate error. This will help any downstream tools. Refer to `recovery::pattern_to_expr` for more details. ### Extract complex number literal pattern parsing logic Earlier, this was inside the `parse_match_pattern_lhs` which made the method a bit more complex than it needed to be. The logic has been extracted to a new `parse_complex_pattern_literal` and is called when the parser encounters a pattern followed by either `+` or `-`. The parser only allows a valid complex literal pattern which is `real_number +/- complex_number`. For any other case, an appropriate error will be raised. ## Review Refer to the test cases to help in the review process. ## Test Plan Add test cases and update the snapshots.
## Summary This PR updates the match statement's pattern parsing logic to better facilitate the error recovery. The following changes are made: ### Disallow star pattern (`*<name>`) outside of sequence pattern This is done by passing an enum stating whether to allow star pattern or not and is based on where the parser is in the stack. <details><summary>Call stack for pattern parsing functions:</summary> <p> I took notes on where would I requires changing this, so sharing it for documenting purposes: * `parse_match_patterns` * `parse_match_pattern` (`AllowStarPattern::Yes`) * Error if it’s a star pattern and it's not a sequence pattern * `parse_sequence_match_pattern` * `parse_match_pattern` (`AllowStarPattern::Yes`) * `parse_match_pattern` (`allow_star_pattern: AllowStarPattern`) * `parse_match_pattern_lhs` (`allow_star_pattern: AllowStarPattern`) * `parse_match_pattern_mapping` * `parse_match_pattern_lhs` (`AllowStarPattern::No`) * `parse_match_pattern` (`AllowStarPattern::No`) * `parse_match_pattern_star` * `parse_delimited_match_pattern` * `parse_match_pattern` (`AllowStarPattern::Yes`) * `parse_sequence_match_pattern` * `parse_match_pattern_literal` * `parse_attr_expr_for_match_pattern` * `parse_match_pattern_class` * `parse_match_pattern` (`AllowStarPattern::No`) * `parse_complex_literal_pattern` * `parse_match_pattern_lhs` (`AllowStarPattern::No`) </p> </details> The mapping pattern `FIRST` set has been updated to include `*` to allow the parser to recover from this error in mapping pattern. Otherwise, the list parsing would completely skip parsing it. ### Convert `Pattern` to `Expr` In certain cases, the parser expects a specific type of pattern and uses that to extract information. For example, in complex literal, we parse the LHS and RHS as patterns but the LHS can only be a real number while the RHS can only be a complex number. This means that if the parser found any other pattern kind then we would convert the pattern into an equivalent expression and add an appropriate error. This will help any downstream tools. Refer to `recovery::pattern_to_expr` for more details. ### Extract complex number literal pattern parsing logic Earlier, this was inside the `parse_match_pattern_lhs` which made the method a bit more complex than it needed to be. The logic has been extracted to a new `parse_complex_pattern_literal` and is called when the parser encounters a pattern followed by either `+` or `-`. The parser only allows a valid complex literal pattern which is `real_number +/- complex_number`. For any other case, an appropriate error will be raised. ## Review Refer to the test cases to help in the review process. ## Test Plan Add test cases and update the snapshots.
## Summary This PR updates the match statement's pattern parsing logic to better facilitate the error recovery. The following changes are made: ### Disallow star pattern (`*<name>`) outside of sequence pattern This is done by passing an enum stating whether to allow star pattern or not and is based on where the parser is in the stack. <details><summary>Call stack for pattern parsing functions:</summary> <p> I took notes on where would I requires changing this, so sharing it for documenting purposes: * `parse_match_patterns` * `parse_match_pattern` (`AllowStarPattern::Yes`) * Error if it’s a star pattern and it's not a sequence pattern * `parse_sequence_match_pattern` * `parse_match_pattern` (`AllowStarPattern::Yes`) * `parse_match_pattern` (`allow_star_pattern: AllowStarPattern`) * `parse_match_pattern_lhs` (`allow_star_pattern: AllowStarPattern`) * `parse_match_pattern_mapping` * `parse_match_pattern_lhs` (`AllowStarPattern::No`) * `parse_match_pattern` (`AllowStarPattern::No`) * `parse_match_pattern_star` * `parse_delimited_match_pattern` * `parse_match_pattern` (`AllowStarPattern::Yes`) * `parse_sequence_match_pattern` * `parse_match_pattern_literal` * `parse_attr_expr_for_match_pattern` * `parse_match_pattern_class` * `parse_match_pattern` (`AllowStarPattern::No`) * `parse_complex_literal_pattern` * `parse_match_pattern_lhs` (`AllowStarPattern::No`) </p> </details> The mapping pattern `FIRST` set has been updated to include `*` to allow the parser to recover from this error in mapping pattern. Otherwise, the list parsing would completely skip parsing it. ### Convert `Pattern` to `Expr` In certain cases, the parser expects a specific type of pattern and uses that to extract information. For example, in complex literal, we parse the LHS and RHS as patterns but the LHS can only be a real number while the RHS can only be a complex number. This means that if the parser found any other pattern kind then we would convert the pattern into an equivalent expression and add an appropriate error. This will help any downstream tools. Refer to `recovery::pattern_to_expr` for more details. ### Extract complex number literal pattern parsing logic Earlier, this was inside the `parse_match_pattern_lhs` which made the method a bit more complex than it needed to be. The logic has been extracted to a new `parse_complex_pattern_literal` and is called when the parser encounters a pattern followed by either `+` or `-`. The parser only allows a valid complex literal pattern which is `real_number +/- complex_number`. For any other case, an appropriate error will be raised. ## Review Refer to the test cases to help in the review process. ## Test Plan Add test cases and update the snapshots.
Summary
This PR updates the match statement's pattern parsing logic to better facilitate the error recovery. The following changes are made:
Disallow star pattern (
*<name>
) outside of sequence patternThis is done by passing an enum stating whether to allow star pattern or not and is based on where the parser is in the stack.
Call stack for pattern parsing functions:
I took notes on where would I requires changing this, so sharing it for documenting purposes:
parse_match_patterns
parse_match_pattern
(AllowStarPattern::Yes
)parse_sequence_match_pattern
parse_match_pattern
(AllowStarPattern::Yes
)parse_match_pattern
(allow_star_pattern: AllowStarPattern
)parse_match_pattern_lhs
(allow_star_pattern: AllowStarPattern
)parse_match_pattern_mapping
parse_match_pattern_lhs
(AllowStarPattern::No
)parse_match_pattern
(AllowStarPattern::No
)parse_match_pattern_star
parse_delimited_match_pattern
parse_match_pattern
(AllowStarPattern::Yes
)parse_sequence_match_pattern
parse_match_pattern_literal
parse_attr_expr_for_match_pattern
parse_match_pattern_class
parse_match_pattern
(AllowStarPattern::No
)parse_complex_literal_pattern
parse_match_pattern_lhs
(AllowStarPattern::No
)The mapping pattern
FIRST
set has been updated to include*
to allow the parser to recover from this error in mapping pattern. Otherwise, the list parsing would completely skip parsing it.Convert
Pattern
toExpr
In certain cases, the parser expects a specific type of pattern and uses that to extract information. For example, in complex literal, we parse the LHS and RHS as patterns but the LHS can only be a real number while the RHS can only be a complex number. This means that if the parser found any other pattern kind then we would convert the pattern into an equivalent expression and add an appropriate error. This will help any downstream tools.
Refer to
recovery::pattern_to_expr
for more details.Extract complex number literal pattern parsing logic
Earlier, this was inside the
parse_match_pattern_lhs
which made the method a bit more complex than it needed to be. The logic has been extracted to a newparse_complex_pattern_literal
and is called when the parser encounters a pattern followed by either+
or-
.The parser only allows a valid complex literal pattern which is
real_number +/- complex_number
. For any other case, an appropriate error will be raised.Review
Refer to the test cases to help in the review process.
Test Plan
Add test cases and update the snapshots.