Files
sdk/pkg/front_end/parser_testcases/patterns/syntheticIdentifier_insideSwitchExpression.dart.expect
T
Paul Berry 8d2b2a197d [parser] Ensure that list and map pattern parsing always makes progress.
In rare circumstances involving syntax errors, the `parsePattern`
method inserts a synthetic token but does not consume any
tokens. Usually when this happens it's not a problem, because whatever
method is calling `parsePattern` consumes some tokens, so the parser
always makes progress. However, when parsing list patterns, after
calling `parsePattern`, the parser would look for a `,`, and if it
didn't find one, it would supply a synthetic `,` and call
`parsePattern` again, resulting in an infinite loop. A similar
situation happened with map patterns, though the situation was more
complex because in between the calls to `parsePattern`, the parser
would also create synthetic key expressions and `:`s.

To fix the problem, when parsing a list or map pattern, after the call
to `parsePattern`, the parser checks whether any tokens were
consumed. If no tokens were consumed, it ignores the next token from
the input stream in order to make progress.

I also investigated whether there were similar issues with
parenthesized/record patterns and switch expressions, since those
constructs also consist of a sequence of patterns separated by tokens
and other things that could in principle be supplied
synthetically. Fortunately, parser recovery doesn't get into an
infinite loop in those cases, so I didn't make any further
changes. But I did include test cases to make sure.

Fixes #52352.

Bug: https://github.com/dart-lang/sdk/issues/52352
Change-Id: Idc8140236f6054deb1fd3c862036fe47dd84f30b
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/302803
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
2023-05-12 18:43:39 +00:00

71 lines
3.1 KiB
Plaintext

Problems reported:
parser/patterns/syntheticIdentifier_insideSwitchExpression:1:34: Expected an identifier, but got 'if'.
void f(Object? x) => switch (x) {if};
^^
parser/patterns/syntheticIdentifier_insideSwitchExpression:1:34: Expected '=>' before this.
void f(Object? x) => switch (x) {if};
^^
parser/patterns/syntheticIdentifier_insideSwitchExpression:1:34: Expected an identifier, but got 'if'.
void f(Object? x) => switch (x) {if};
^^
parser/patterns/syntheticIdentifier_insideSwitchExpression:1:34: Expected '}' before this.
void f(Object? x) => switch (x) {if};
^^
beginCompilationUnit(void)
beginMetadataStar(void)
endMetadataStar(0)
beginTopLevelMember(void)
beginTopLevelMethod(, null, null)
handleVoidKeyword(void)
handleIdentifier(f, topLevelFunctionDeclaration)
handleNoTypeVariables(()
beginFormalParameters((, MemberKind.TopLevelMethod)
beginMetadataStar(Object)
endMetadataStar(0)
beginFormalParameter(Object, MemberKind.TopLevelMethod, null, null, null)
handleIdentifier(Object, typeReference)
handleNoTypeArguments(?)
handleType(Object, ?)
handleIdentifier(x, formalParameterDeclaration)
handleFormalParameterWithoutValue())
endFormalParameter(null, null, null, x, null, null, FormalParameterKind.requiredPositional, MemberKind.TopLevelMethod)
endFormalParameters(1, (, ), MemberKind.TopLevelMethod)
handleAsyncModifier(null, null)
beginSwitchExpression(switch)
handleIdentifier(x, expression)
handleNoTypeArguments())
handleNoArguments())
handleSend(x, ))
handleParenthesizedCondition((, null, null)
beginSwitchExpressionBlock({)
beginSwitchExpressionCase()
beginPattern({)
beginConstantPattern(null)
handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'if'., Try inserting an identifier before 'if'., {lexeme: if}], if, if)
handleIdentifier(, expression)
handleNoTypeArguments(if)
handleNoArguments(if)
handleSend(, if)
endConstantPattern(null)
endPattern()
handleSwitchExpressionCasePattern()
handleRecoverableError(Message[ExpectedButGot, Expected '=>' before this., null, {string: =>}], if, if)
handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'if'., Try inserting an identifier before 'if'., {lexeme: if}], if, if)
handleIdentifier(, expression)
handleNoTypeArguments(if)
handleNoArguments(if)
handleSend(, if)
endSwitchExpressionCase(null, =>, )
handleRecoverableError(Message[ExpectedButGot, Expected '}' before this., null, {string: }}], if, if)
endSwitchExpressionBlock(1, {, })
endSwitchExpression(switch, })
handleExpressionFunctionBody(=>, ;)
endTopLevelMethod(void, null, ;)
endTopLevelDeclaration()
endCompilationUnit(1, )