Files
sdk/pkg/front_end/parser_testcases/patterns/syntheticIdentifier_insideMapPattern.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

95 lines
4.0 KiB
Plaintext

Problems reported:
parser/patterns/syntheticIdentifier_insideMapPattern:3:14: Expected an identifier, but got 'if'.
case {0: if}:
^^
parser/patterns/syntheticIdentifier_insideMapPattern:3:14: Expected ',' before this.
case {0: if}:
^^
parser/patterns/syntheticIdentifier_insideMapPattern:3:14: Expected an identifier, but got 'if'.
case {0: if}:
^^
parser/patterns/syntheticIdentifier_insideMapPattern:3:14: Expected ':' before this.
case {0: if}:
^^
parser/patterns/syntheticIdentifier_insideMapPattern:3:14: Expected an identifier, but got 'if'.
case {0: 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)
beginBlockFunctionBody({)
beginSwitchStatement(switch)
handleIdentifier(x, expression)
handleNoTypeArguments())
handleNoArguments())
handleSend(x, ))
handleParenthesizedCondition((, null, null)
beginSwitchBlock({)
beginCaseExpression(case)
beginPattern(case)
handleNoTypeArguments({)
handleLiteralInt(0)
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()
handleMapPatternEntry(:, if)
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)
handleRecoverableError(Message[ExpectedButGot, Expected ':' before this., null, {string: :}], if, if)
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()
handleMapPatternEntry(:, })
handleMapPattern(2, {, })
endPattern(})
handleSwitchCaseNoWhenClause(})
endCaseExpression(case, null, :)
beginSwitchCase(0, 1, case)
endSwitchCase(0, 1, null, null, 0, case, })
endSwitchBlock(1, {, })
endSwitchStatement(switch, })
handleEmptyStatement(;)
endBlockFunctionBody(2, {, })
endTopLevelMethod(void, null, })
endTopLevelDeclaration()
endCompilationUnit(1, )