[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>
This commit is contained in:
Paul Berry 2023-05-12 18:43:39 +00:00 committed by Commit Queue
parent 48346c458a
commit 8d2b2a197d
27 changed files with 1339 additions and 0 deletions

View file

@ -10061,6 +10061,12 @@ class Parser {
listener.handleRestPattern(dots, hasSubPattern: hasSubPattern);
} else {
token = parsePattern(token, patternContext);
if (identical(next, token.next)) {
// No tokens were consumed (though it's possible that a synthetic
// token was inserted). If this happens, go ahead and skip the next
// token to ensure that progress is made.
token = token.next!;
}
}
next = token.next!;
++count;
@ -10136,6 +10142,12 @@ class Parser {
new SyntheticToken(TokenType.COLON, next.charOffset));
}
token = parsePattern(colon, patternContext);
if (identical(next, token.next)) {
// No tokens were consumed (though it's possible that a synthetic
// token was inserted). If this happens, go ahead and skip the next
// token to ensure that progress is made.
token = token.next!;
}
listener.handleMapPatternEntry(colon, token.next!);
}
++count;

View file

@ -9730,6 +9730,158 @@ SwitchExpression
''');
}
test_syntheticIdentifier_insideListPattern() {
_parse('''
void f(Object? x) {
switch (x) {
case [if]:
};
}
''', errors: [
error(ParserErrorCode.MISSING_IDENTIFIER, 45, 2),
]);
var node = findNode.switchPatternCase('case');
assertParsedNodeText(node, r'''
SwitchPatternCase
keyword: case
guardedPattern: GuardedPattern
pattern: ListPattern
leftBracket: [
elements
ConstantPattern
expression: SimpleIdentifier
token: <empty> <synthetic>
rightBracket: ]
colon: :
''');
}
test_syntheticIdentifier_insideMapPattern() {
_parse('''
void f(Object? x) {
switch (x) {
case {0: if}:
};
}
''', errors: [
error(ParserErrorCode.MISSING_IDENTIFIER, 48, 2),
error(ParserErrorCode.EXPECTED_TOKEN, 48, 2),
error(ParserErrorCode.EXPECTED_TOKEN, 48, 2),
]);
var node = findNode.switchPatternCase('case');
assertParsedNodeText(node, r'''
SwitchPatternCase
keyword: case
guardedPattern: GuardedPattern
pattern: MapPattern
leftBracket: {
elements
MapPatternEntry
key: IntegerLiteral
literal: 0
separator: :
value: ConstantPattern
expression: SimpleIdentifier
token: <empty> <synthetic>
MapPatternEntry
key: SimpleIdentifier
token: <empty> <synthetic>
separator: : <synthetic>
value: ConstantPattern
expression: SimpleIdentifier
token: <empty> <synthetic>
rightBracket: }
colon: :
''');
}
test_syntheticIdentifier_insideParenthesizedPattern() {
_parse('''
void f(Object? x) {
switch (x) {
case (if):
};
}
''', errors: [
error(ParserErrorCode.MISSING_IDENTIFIER, 45, 2),
error(ParserErrorCode.EXPECTED_TOKEN, 45, 2),
]);
var node = findNode.switchPatternCase('case');
assertParsedNodeText(node, r'''
SwitchPatternCase
keyword: case
guardedPattern: GuardedPattern
pattern: ParenthesizedPattern
leftParenthesis: (
pattern: ConstantPattern
expression: SimpleIdentifier
token: <empty> <synthetic>
rightParenthesis: )
colon: :
''');
}
test_syntheticIdentifier_insideRecordPattern() {
_parse('''
void f(Object? x) {
switch (x) {
case (_, if):
};
}
''', errors: [
error(ParserErrorCode.MISSING_IDENTIFIER, 48, 2),
error(ParserErrorCode.EXPECTED_TOKEN, 48, 2),
]);
var node = findNode.switchPatternCase('case');
assertParsedNodeText(node, r'''
SwitchPatternCase
keyword: case
guardedPattern: GuardedPattern
pattern: RecordPattern
leftParenthesis: (
fields
PatternField
pattern: WildcardPattern
name: _
PatternField
pattern: ConstantPattern
expression: SimpleIdentifier
token: <empty> <synthetic>
rightParenthesis: )
colon: :
''');
}
test_syntheticIdentifier_insideSwitchExpression() {
_parse('''
void f(Object? x) => switch (x) {if};
''', errors: [
error(ParserErrorCode.MISSING_IDENTIFIER, 33, 2),
error(ParserErrorCode.EXPECTED_TOKEN, 33, 2),
error(ParserErrorCode.EXPECTED_TOKEN, 33, 2),
]);
var node = findNode.switchExpression('if');
assertParsedNodeText(node, r'''
SwitchExpression
switchKeyword: switch
leftParenthesis: (
expression: SimpleIdentifier
token: x
rightParenthesis: )
leftBracket: {
cases
SwitchExpressionCase
guardedPattern: GuardedPattern
pattern: ConstantPattern
expression: SimpleIdentifier
token: <empty> <synthetic>
arrow: => <synthetic>
expression: SimpleIdentifier
token: <empty> <synthetic>
rightBracket: }
''');
}
test_typeQuestionBeforeWhen_conditional() {
// The logic for parsing types has special disambiguation rules for deciding
// whether a trailing `?` should be included in the type; these rules are

View file

@ -0,0 +1,5 @@
void f(Object? x) {
switch (x) {
case [if]:
};
}

View file

@ -0,0 +1,59 @@
Problems reported:
parser/patterns/syntheticIdentifier_insideListPattern:3:11: Expected an identifier, but got 'if'.
case [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([)
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()
handleListPattern(1, [, ])
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, )

View file

@ -0,0 +1,119 @@
parseUnit(void)
skipErrorTokens(void)
listener: beginCompilationUnit(void)
syntheticPreviousToken(void)
parseTopLevelDeclarationImpl(, Instance of 'DirectiveContext')
parseMetadataStar()
listener: beginMetadataStar(void)
listener: endMetadataStar(0)
parseTopLevelMemberImpl()
listener: beginTopLevelMember(void)
parseTopLevelMethod(, null, null, , Instance of 'VoidType', null, f, false)
listener: beginTopLevelMethod(, null, null)
listener: handleVoidKeyword(void)
ensureIdentifierPotentiallyRecovered(void, topLevelFunctionDeclaration, false)
listener: handleIdentifier(f, topLevelFunctionDeclaration)
parseMethodTypeVar(f)
listener: handleNoTypeVariables(()
parseGetterOrFormalParameters(f, f, false, MemberKind.TopLevelMethod)
parseFormalParameters(f, MemberKind.TopLevelMethod)
parseFormalParametersRest((, MemberKind.TopLevelMethod)
listener: beginFormalParameters((, MemberKind.TopLevelMethod)
parseFormalParameter((, FormalParameterKind.requiredPositional, MemberKind.TopLevelMethod)
parseMetadataStar(()
listener: beginMetadataStar(Object)
listener: endMetadataStar(0)
listener: beginFormalParameter(Object, MemberKind.TopLevelMethod, null, null, null)
listener: handleIdentifier(Object, typeReference)
listener: handleNoTypeArguments(?)
listener: handleType(Object, ?)
ensureIdentifier(?, formalParameterDeclaration)
listener: handleIdentifier(x, formalParameterDeclaration)
listener: handleFormalParameterWithoutValue())
listener: endFormalParameter(null, null, null, x, null, null, FormalParameterKind.requiredPositional, MemberKind.TopLevelMethod)
listener: endFormalParameters(1, (, ), MemberKind.TopLevelMethod)
parseAsyncModifierOpt())
listener: handleAsyncModifier(null, null)
inPlainSync()
parseFunctionBody(), false, false)
listener: beginBlockFunctionBody({)
notEofOrValue(}, switch)
parseStatement({)
parseStatementX({)
parseSwitchStatement({)
listener: beginSwitchStatement(switch)
ensureParenthesizedCondition(switch, allowCase: false)
parseExpressionInParenthesisRest((, allowCase: false)
parseExpression(()
looksLikeOuterPatternEquals(()
skipOuterPattern(()
skipObjectPatternRest(x)
parsePrecedenceExpression((, 1, true, ConstantPatternContext.none)
parseUnaryExpression((, true, ConstantPatternContext.none)
parsePrimary((, expression, ConstantPatternContext.none)
parseSendOrFunctionLiteral((, expression, ConstantPatternContext.none)
parseSend((, expression, ConstantPatternContext.none)
isNextIdentifier(()
ensureIdentifier((, expression)
listener: handleIdentifier(x, expression)
listener: handleNoTypeArguments())
parseArgumentsOpt(x)
listener: handleNoArguments())
listener: handleSend(x, ))
ensureCloseParen(x, ()
listener: handleParenthesizedCondition((, null, null)
parseSwitchBlock())
ensureBlock(), null, switch statement)
listener: beginSwitchBlock({)
notEofOrValue(}, case)
peekPastLabels(case)
listener: beginCaseExpression(case)
parsePattern(case, PatternContext.matching, precedence: 1)
listener: beginPattern(case)
parsePrimaryPattern(case, PatternContext.matching)
listener: handleNoTypeArguments([)
parseListPatternSuffix(case, PatternContext.matching)
parsePattern([, PatternContext.matching, precedence: 1)
listener: beginPattern([)
parsePrimaryPattern([, PatternContext.matching)
listener: beginConstantPattern(null)
parsePrecedenceExpression([, 7, false, ConstantPatternContext.implicit)
parseUnaryExpression([, false, ConstantPatternContext.implicit)
parsePrimary([, expression, ConstantPatternContext.implicit)
inPlainSync()
parseSend([, expression, ConstantPatternContext.implicit)
isNextIdentifier([)
ensureIdentifier([, expression)
reportRecoverableErrorWithToken(if, Instance of 'Template<(Token) => Message>')
listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'if'., Try inserting an identifier before 'if'., {lexeme: if}], if, if)
rewriter()
listener: handleIdentifier(, expression)
listener: handleNoTypeArguments(if)
parseArgumentsOpt()
listener: handleNoArguments(if)
listener: handleSend(, if)
listener: endConstantPattern(null)
listener: endPattern()
listener: handleListPattern(1, [, ])
listener: endPattern(])
listener: handleSwitchCaseNoWhenClause(])
ensureColon(])
listener: endCaseExpression(case, null, :)
peekPastLabels(})
parseStatementsInSwitchCase(:, }, case, 0, 1, null, null)
listener: beginSwitchCase(0, 1, case)
listener: endSwitchCase(0, 1, null, null, 0, case, })
notEofOrValue(}, })
listener: endSwitchBlock(1, {, })
listener: endSwitchStatement(switch, })
notEofOrValue(}, ;)
parseStatement(})
parseStatementX(})
parseEmptyStatement(})
listener: handleEmptyStatement(;)
notEofOrValue(}, })
listener: endBlockFunctionBody(2, {, })
listener: endTopLevelMethod(void, null, })
listener: endTopLevelDeclaration()
reportAllErrorTokens(void)
listener: endCompilationUnit(1, )

View file

@ -0,0 +1,15 @@
NOTICE: Stream was rewritten by parser!
void f(Object? x) {
switch (x) {
case [*synthetic*if]:
};
}
void[KeywordToken] f[StringToken]([BeginToken]Object[StringToken]?[SimpleToken] x[StringToken])[SimpleToken] {[BeginToken]
switch[KeywordToken] ([BeginToken]x[StringToken])[SimpleToken] {[BeginToken]
case[KeywordToken] [[BeginToken][SyntheticStringToken]if[KeywordToken]][SimpleToken]:[SimpleToken]
}[SimpleToken];[SimpleToken]
}[SimpleToken]
[SimpleToken]

View file

@ -0,0 +1,13 @@
void f(Object? x) {
switch (x) {
case [if]:
};
}
void[KeywordToken] f[StringToken]([BeginToken]Object[StringToken]?[SimpleToken] x[StringToken])[SimpleToken] {[BeginToken]
switch[KeywordToken] ([BeginToken]x[StringToken])[SimpleToken] {[BeginToken]
case[KeywordToken] [[BeginToken]if[KeywordToken]][SimpleToken]:[SimpleToken]
}[SimpleToken];[SimpleToken]
}[SimpleToken]
[SimpleToken]

View file

@ -0,0 +1,5 @@
void f(Object? x) {
switch (x) {
case {0: if}:
};
}

View file

@ -0,0 +1,94 @@
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, )

View file

@ -0,0 +1,176 @@
parseUnit(void)
skipErrorTokens(void)
listener: beginCompilationUnit(void)
syntheticPreviousToken(void)
parseTopLevelDeclarationImpl(, Instance of 'DirectiveContext')
parseMetadataStar()
listener: beginMetadataStar(void)
listener: endMetadataStar(0)
parseTopLevelMemberImpl()
listener: beginTopLevelMember(void)
parseTopLevelMethod(, null, null, , Instance of 'VoidType', null, f, false)
listener: beginTopLevelMethod(, null, null)
listener: handleVoidKeyword(void)
ensureIdentifierPotentiallyRecovered(void, topLevelFunctionDeclaration, false)
listener: handleIdentifier(f, topLevelFunctionDeclaration)
parseMethodTypeVar(f)
listener: handleNoTypeVariables(()
parseGetterOrFormalParameters(f, f, false, MemberKind.TopLevelMethod)
parseFormalParameters(f, MemberKind.TopLevelMethod)
parseFormalParametersRest((, MemberKind.TopLevelMethod)
listener: beginFormalParameters((, MemberKind.TopLevelMethod)
parseFormalParameter((, FormalParameterKind.requiredPositional, MemberKind.TopLevelMethod)
parseMetadataStar(()
listener: beginMetadataStar(Object)
listener: endMetadataStar(0)
listener: beginFormalParameter(Object, MemberKind.TopLevelMethod, null, null, null)
listener: handleIdentifier(Object, typeReference)
listener: handleNoTypeArguments(?)
listener: handleType(Object, ?)
ensureIdentifier(?, formalParameterDeclaration)
listener: handleIdentifier(x, formalParameterDeclaration)
listener: handleFormalParameterWithoutValue())
listener: endFormalParameter(null, null, null, x, null, null, FormalParameterKind.requiredPositional, MemberKind.TopLevelMethod)
listener: endFormalParameters(1, (, ), MemberKind.TopLevelMethod)
parseAsyncModifierOpt())
listener: handleAsyncModifier(null, null)
inPlainSync()
parseFunctionBody(), false, false)
listener: beginBlockFunctionBody({)
notEofOrValue(}, switch)
parseStatement({)
parseStatementX({)
parseSwitchStatement({)
listener: beginSwitchStatement(switch)
ensureParenthesizedCondition(switch, allowCase: false)
parseExpressionInParenthesisRest((, allowCase: false)
parseExpression(()
looksLikeOuterPatternEquals(()
skipOuterPattern(()
skipObjectPatternRest(x)
parsePrecedenceExpression((, 1, true, ConstantPatternContext.none)
parseUnaryExpression((, true, ConstantPatternContext.none)
parsePrimary((, expression, ConstantPatternContext.none)
parseSendOrFunctionLiteral((, expression, ConstantPatternContext.none)
parseSend((, expression, ConstantPatternContext.none)
isNextIdentifier(()
ensureIdentifier((, expression)
listener: handleIdentifier(x, expression)
listener: handleNoTypeArguments())
parseArgumentsOpt(x)
listener: handleNoArguments())
listener: handleSend(x, ))
ensureCloseParen(x, ()
listener: handleParenthesizedCondition((, null, null)
parseSwitchBlock())
ensureBlock(), null, switch statement)
listener: beginSwitchBlock({)
notEofOrValue(}, case)
peekPastLabels(case)
listener: beginCaseExpression(case)
parsePattern(case, PatternContext.matching, precedence: 1)
listener: beginPattern(case)
parsePrimaryPattern(case, PatternContext.matching)
listener: handleNoTypeArguments({)
parseMapPatternSuffix(case, PatternContext.matching)
parseExpression({)
looksLikeOuterPatternEquals({)
skipOuterPattern({)
parsePrecedenceExpression({, 1, true, ConstantPatternContext.none)
parseUnaryExpression({, true, ConstantPatternContext.none)
parsePrimary({, expression, ConstantPatternContext.none)
parseLiteralInt({)
listener: handleLiteralInt(0)
parsePattern(:, PatternContext.matching, precedence: 1)
listener: beginPattern(:)
parsePrimaryPattern(:, PatternContext.matching)
listener: beginConstantPattern(null)
parsePrecedenceExpression(:, 7, false, ConstantPatternContext.implicit)
parseUnaryExpression(:, false, ConstantPatternContext.implicit)
parsePrimary(:, expression, ConstantPatternContext.implicit)
inPlainSync()
parseSend(:, expression, ConstantPatternContext.implicit)
isNextIdentifier(:)
ensureIdentifier(:, expression)
reportRecoverableErrorWithToken(if, Instance of 'Template<(Token) => Message>')
listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'if'., Try inserting an identifier before 'if'., {lexeme: if}], if, if)
rewriter()
listener: handleIdentifier(, expression)
listener: handleNoTypeArguments(if)
parseArgumentsOpt()
listener: handleNoArguments(if)
listener: handleSend(, if)
listener: endConstantPattern(null)
listener: endPattern()
listener: handleMapPatternEntry(:, if)
rewriteAndRecover(, Message[ExpectedButGot, Expected ',' before this., null, {string: ,}], ,)
reportRecoverableError(if, Message[ExpectedButGot, Expected ',' before this., null, {string: ,}])
listener: handleRecoverableError(Message[ExpectedButGot, Expected ',' before this., null, {string: ,}], if, if)
rewriter()
parseExpression(,)
looksLikeOuterPatternEquals(,)
skipOuterPattern(,)
parsePrecedenceExpression(,, 1, true, ConstantPatternContext.none)
parseUnaryExpression(,, true, ConstantPatternContext.none)
parsePrimary(,, expression, ConstantPatternContext.none)
inPlainSync()
parseSend(,, expression, ConstantPatternContext.none)
isNextIdentifier(,)
ensureIdentifier(,, expression)
reportRecoverableErrorWithToken(if, Instance of 'Template<(Token) => Message>')
listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'if'., Try inserting an identifier before 'if'., {lexeme: if}], if, if)
rewriter()
listener: handleIdentifier(, expression)
listener: handleNoTypeArguments(if)
parseArgumentsOpt()
listener: handleNoArguments(if)
listener: handleSend(, if)
rewriteAndRecover(, Message[ExpectedButGot, Expected ':' before this., null, {string: :}], :)
reportRecoverableError(if, Message[ExpectedButGot, Expected ':' before this., null, {string: :}])
listener: handleRecoverableError(Message[ExpectedButGot, Expected ':' before this., null, {string: :}], if, if)
rewriter()
parsePattern(:, PatternContext.matching, precedence: 1)
listener: beginPattern(:)
parsePrimaryPattern(:, PatternContext.matching)
listener: beginConstantPattern(null)
parsePrecedenceExpression(:, 7, false, ConstantPatternContext.implicit)
parseUnaryExpression(:, false, ConstantPatternContext.implicit)
parsePrimary(:, expression, ConstantPatternContext.implicit)
inPlainSync()
parseSend(:, expression, ConstantPatternContext.implicit)
isNextIdentifier(:)
ensureIdentifier(:, expression)
reportRecoverableErrorWithToken(if, Instance of 'Template<(Token) => Message>')
listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'if'., Try inserting an identifier before 'if'., {lexeme: if}], if, if)
rewriter()
listener: handleIdentifier(, expression)
listener: handleNoTypeArguments(if)
parseArgumentsOpt()
listener: handleNoArguments(if)
listener: handleSend(, if)
listener: endConstantPattern(null)
listener: endPattern()
listener: handleMapPatternEntry(:, })
listener: handleMapPattern(2, {, })
listener: endPattern(})
listener: handleSwitchCaseNoWhenClause(})
ensureColon(})
listener: endCaseExpression(case, null, :)
peekPastLabels(})
parseStatementsInSwitchCase(:, }, case, 0, 1, null, null)
listener: beginSwitchCase(0, 1, case)
listener: endSwitchCase(0, 1, null, null, 0, case, })
notEofOrValue(}, })
listener: endSwitchBlock(1, {, })
listener: endSwitchStatement(switch, })
notEofOrValue(}, ;)
parseStatement(})
parseStatementX(})
parseEmptyStatement(})
listener: handleEmptyStatement(;)
notEofOrValue(}, })
listener: endBlockFunctionBody(2, {, })
listener: endTopLevelMethod(void, null, })
listener: endTopLevelDeclaration()
reportAllErrorTokens(void)
listener: endCompilationUnit(1, )

View file

@ -0,0 +1,15 @@
NOTICE: Stream was rewritten by parser!
void f(Object? x) {
switch (x) {
case {0: *synthetic*,*synthetic*:*synthetic*if}:
};
}
void[KeywordToken] f[StringToken]([BeginToken]Object[StringToken]?[SimpleToken] x[StringToken])[SimpleToken] {[BeginToken]
switch[KeywordToken] ([BeginToken]x[StringToken])[SimpleToken] {[BeginToken]
case[KeywordToken] {[BeginToken]0[StringToken]:[SimpleToken] [SyntheticStringToken],[SyntheticToken][SyntheticStringToken]:[SyntheticToken][SyntheticStringToken]if[KeywordToken]}[SimpleToken]:[SimpleToken]
}[SimpleToken];[SimpleToken]
}[SimpleToken]
[SimpleToken]

View file

@ -0,0 +1,13 @@
void f(Object? x) {
switch (x) {
case {0: if}:
};
}
void[KeywordToken] f[StringToken]([BeginToken]Object[StringToken]?[SimpleToken] x[StringToken])[SimpleToken] {[BeginToken]
switch[KeywordToken] ([BeginToken]x[StringToken])[SimpleToken] {[BeginToken]
case[KeywordToken] {[BeginToken]0[StringToken]:[SimpleToken] if[KeywordToken]}[SimpleToken]:[SimpleToken]
}[SimpleToken];[SimpleToken]
}[SimpleToken]
[SimpleToken]

View file

@ -0,0 +1,5 @@
void f(Object? x) {
switch (x) {
case (if):
};
}

View file

@ -0,0 +1,63 @@
Problems reported:
parser/patterns/syntheticIdentifier_insideParenthesizedPattern:3:11: Expected an identifier, but got 'if'.
case (if):
^^
parser/patterns/syntheticIdentifier_insideParenthesizedPattern:3:11: Expected ')' before this.
case (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)
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()
handleRecoverableError(Message[ExpectedButGot, Expected ')' before this., null, {string: )}], if, if)
handleParenthesizedPattern(()
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, )

View file

@ -0,0 +1,121 @@
parseUnit(void)
skipErrorTokens(void)
listener: beginCompilationUnit(void)
syntheticPreviousToken(void)
parseTopLevelDeclarationImpl(, Instance of 'DirectiveContext')
parseMetadataStar()
listener: beginMetadataStar(void)
listener: endMetadataStar(0)
parseTopLevelMemberImpl()
listener: beginTopLevelMember(void)
parseTopLevelMethod(, null, null, , Instance of 'VoidType', null, f, false)
listener: beginTopLevelMethod(, null, null)
listener: handleVoidKeyword(void)
ensureIdentifierPotentiallyRecovered(void, topLevelFunctionDeclaration, false)
listener: handleIdentifier(f, topLevelFunctionDeclaration)
parseMethodTypeVar(f)
listener: handleNoTypeVariables(()
parseGetterOrFormalParameters(f, f, false, MemberKind.TopLevelMethod)
parseFormalParameters(f, MemberKind.TopLevelMethod)
parseFormalParametersRest((, MemberKind.TopLevelMethod)
listener: beginFormalParameters((, MemberKind.TopLevelMethod)
parseFormalParameter((, FormalParameterKind.requiredPositional, MemberKind.TopLevelMethod)
parseMetadataStar(()
listener: beginMetadataStar(Object)
listener: endMetadataStar(0)
listener: beginFormalParameter(Object, MemberKind.TopLevelMethod, null, null, null)
listener: handleIdentifier(Object, typeReference)
listener: handleNoTypeArguments(?)
listener: handleType(Object, ?)
ensureIdentifier(?, formalParameterDeclaration)
listener: handleIdentifier(x, formalParameterDeclaration)
listener: handleFormalParameterWithoutValue())
listener: endFormalParameter(null, null, null, x, null, null, FormalParameterKind.requiredPositional, MemberKind.TopLevelMethod)
listener: endFormalParameters(1, (, ), MemberKind.TopLevelMethod)
parseAsyncModifierOpt())
listener: handleAsyncModifier(null, null)
inPlainSync()
parseFunctionBody(), false, false)
listener: beginBlockFunctionBody({)
notEofOrValue(}, switch)
parseStatement({)
parseStatementX({)
parseSwitchStatement({)
listener: beginSwitchStatement(switch)
ensureParenthesizedCondition(switch, allowCase: false)
parseExpressionInParenthesisRest((, allowCase: false)
parseExpression(()
looksLikeOuterPatternEquals(()
skipOuterPattern(()
skipObjectPatternRest(x)
parsePrecedenceExpression((, 1, true, ConstantPatternContext.none)
parseUnaryExpression((, true, ConstantPatternContext.none)
parsePrimary((, expression, ConstantPatternContext.none)
parseSendOrFunctionLiteral((, expression, ConstantPatternContext.none)
parseSend((, expression, ConstantPatternContext.none)
isNextIdentifier(()
ensureIdentifier((, expression)
listener: handleIdentifier(x, expression)
listener: handleNoTypeArguments())
parseArgumentsOpt(x)
listener: handleNoArguments())
listener: handleSend(x, ))
ensureCloseParen(x, ()
listener: handleParenthesizedCondition((, null, null)
parseSwitchBlock())
ensureBlock(), null, switch statement)
listener: beginSwitchBlock({)
notEofOrValue(}, case)
peekPastLabels(case)
listener: beginCaseExpression(case)
parsePattern(case, PatternContext.matching, precedence: 1)
listener: beginPattern(case)
parsePrimaryPattern(case, PatternContext.matching)
parseParenthesizedPatternOrRecordPattern(case, PatternContext.matching)
parsePattern((, PatternContext.matching, precedence: 1)
listener: beginPattern(()
parsePrimaryPattern((, PatternContext.matching)
listener: beginConstantPattern(null)
parsePrecedenceExpression((, 7, false, ConstantPatternContext.implicit)
parseUnaryExpression((, false, ConstantPatternContext.implicit)
parsePrimary((, expression, ConstantPatternContext.implicit)
inPlainSync()
parseSend((, expression, ConstantPatternContext.implicit)
isNextIdentifier(()
ensureIdentifier((, expression)
reportRecoverableErrorWithToken(if, Instance of 'Template<(Token) => Message>')
listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'if'., Try inserting an identifier before 'if'., {lexeme: if}], if, if)
rewriter()
listener: handleIdentifier(, expression)
listener: handleNoTypeArguments(if)
parseArgumentsOpt()
listener: handleNoArguments(if)
listener: handleSend(, if)
listener: endConstantPattern(null)
listener: endPattern()
ensureCloseParen(, ()
reportRecoverableError(if, Message[ExpectedButGot, Expected ')' before this., null, {string: )}])
listener: handleRecoverableError(Message[ExpectedButGot, Expected ')' before this., null, {string: )}], if, if)
listener: handleParenthesizedPattern(()
listener: endPattern())
listener: handleSwitchCaseNoWhenClause())
ensureColon())
listener: endCaseExpression(case, null, :)
peekPastLabels(})
parseStatementsInSwitchCase(:, }, case, 0, 1, null, null)
listener: beginSwitchCase(0, 1, case)
listener: endSwitchCase(0, 1, null, null, 0, case, })
notEofOrValue(}, })
listener: endSwitchBlock(1, {, })
listener: endSwitchStatement(switch, })
notEofOrValue(}, ;)
parseStatement(})
parseStatementX(})
parseEmptyStatement(})
listener: handleEmptyStatement(;)
notEofOrValue(}, })
listener: endBlockFunctionBody(2, {, })
listener: endTopLevelMethod(void, null, })
listener: endTopLevelDeclaration()
reportAllErrorTokens(void)
listener: endCompilationUnit(1, )

View file

@ -0,0 +1,15 @@
NOTICE: Stream was rewritten by parser!
void f(Object? x) {
switch (x) {
case (*synthetic*if):
};
}
void[KeywordToken] f[StringToken]([BeginToken]Object[StringToken]?[SimpleToken] x[StringToken])[SimpleToken] {[BeginToken]
switch[KeywordToken] ([BeginToken]x[StringToken])[SimpleToken] {[BeginToken]
case[KeywordToken] ([BeginToken][SyntheticStringToken]if[KeywordToken])[SimpleToken]:[SimpleToken]
}[SimpleToken];[SimpleToken]
}[SimpleToken]
[SimpleToken]

View file

@ -0,0 +1,13 @@
void f(Object? x) {
switch (x) {
case (if):
};
}
void[KeywordToken] f[StringToken]([BeginToken]Object[StringToken]?[SimpleToken] x[StringToken])[SimpleToken] {[BeginToken]
switch[KeywordToken] ([BeginToken]x[StringToken])[SimpleToken] {[BeginToken]
case[KeywordToken] ([BeginToken]if[KeywordToken])[SimpleToken]:[SimpleToken]
}[SimpleToken];[SimpleToken]
}[SimpleToken]
[SimpleToken]

View file

@ -0,0 +1,5 @@
void f(Object? x) {
switch (x) {
case (_, if):
};
}

View file

@ -0,0 +1,69 @@
Problems reported:
parser/patterns/syntheticIdentifier_insideRecordPattern:3:14: Expected an identifier, but got 'if'.
case (_, if):
^^
parser/patterns/syntheticIdentifier_insideRecordPattern:3:14: Expected ')' before this.
case (_, 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)
beginPattern(()
handleNoType(_)
handleWildcardPattern(null, _)
endPattern(_)
handlePatternField(null)
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()
handlePatternField(null)
handleRecoverableError(Message[ExpectedButGot, Expected ')' before this., null, {string: )}], if, if)
handleRecordPattern((, 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, )

View file

@ -0,0 +1,130 @@
parseUnit(void)
skipErrorTokens(void)
listener: beginCompilationUnit(void)
syntheticPreviousToken(void)
parseTopLevelDeclarationImpl(, Instance of 'DirectiveContext')
parseMetadataStar()
listener: beginMetadataStar(void)
listener: endMetadataStar(0)
parseTopLevelMemberImpl()
listener: beginTopLevelMember(void)
parseTopLevelMethod(, null, null, , Instance of 'VoidType', null, f, false)
listener: beginTopLevelMethod(, null, null)
listener: handleVoidKeyword(void)
ensureIdentifierPotentiallyRecovered(void, topLevelFunctionDeclaration, false)
listener: handleIdentifier(f, topLevelFunctionDeclaration)
parseMethodTypeVar(f)
listener: handleNoTypeVariables(()
parseGetterOrFormalParameters(f, f, false, MemberKind.TopLevelMethod)
parseFormalParameters(f, MemberKind.TopLevelMethod)
parseFormalParametersRest((, MemberKind.TopLevelMethod)
listener: beginFormalParameters((, MemberKind.TopLevelMethod)
parseFormalParameter((, FormalParameterKind.requiredPositional, MemberKind.TopLevelMethod)
parseMetadataStar(()
listener: beginMetadataStar(Object)
listener: endMetadataStar(0)
listener: beginFormalParameter(Object, MemberKind.TopLevelMethod, null, null, null)
listener: handleIdentifier(Object, typeReference)
listener: handleNoTypeArguments(?)
listener: handleType(Object, ?)
ensureIdentifier(?, formalParameterDeclaration)
listener: handleIdentifier(x, formalParameterDeclaration)
listener: handleFormalParameterWithoutValue())
listener: endFormalParameter(null, null, null, x, null, null, FormalParameterKind.requiredPositional, MemberKind.TopLevelMethod)
listener: endFormalParameters(1, (, ), MemberKind.TopLevelMethod)
parseAsyncModifierOpt())
listener: handleAsyncModifier(null, null)
inPlainSync()
parseFunctionBody(), false, false)
listener: beginBlockFunctionBody({)
notEofOrValue(}, switch)
parseStatement({)
parseStatementX({)
parseSwitchStatement({)
listener: beginSwitchStatement(switch)
ensureParenthesizedCondition(switch, allowCase: false)
parseExpressionInParenthesisRest((, allowCase: false)
parseExpression(()
looksLikeOuterPatternEquals(()
skipOuterPattern(()
skipObjectPatternRest(x)
parsePrecedenceExpression((, 1, true, ConstantPatternContext.none)
parseUnaryExpression((, true, ConstantPatternContext.none)
parsePrimary((, expression, ConstantPatternContext.none)
parseSendOrFunctionLiteral((, expression, ConstantPatternContext.none)
parseSend((, expression, ConstantPatternContext.none)
isNextIdentifier(()
ensureIdentifier((, expression)
listener: handleIdentifier(x, expression)
listener: handleNoTypeArguments())
parseArgumentsOpt(x)
listener: handleNoArguments())
listener: handleSend(x, ))
ensureCloseParen(x, ()
listener: handleParenthesizedCondition((, null, null)
parseSwitchBlock())
ensureBlock(), null, switch statement)
listener: beginSwitchBlock({)
notEofOrValue(}, case)
peekPastLabels(case)
listener: beginCaseExpression(case)
parsePattern(case, PatternContext.matching, precedence: 1)
listener: beginPattern(case)
parsePrimaryPattern(case, PatternContext.matching)
parseParenthesizedPatternOrRecordPattern(case, PatternContext.matching)
parsePattern((, PatternContext.matching, precedence: 1)
listener: beginPattern(()
parsePrimaryPattern((, PatternContext.matching)
parseVariablePattern((, PatternContext.matching, typeInfo: Instance of 'NoType')
listener: handleNoType(_)
listener: handleWildcardPattern(null, _)
listener: endPattern(_)
listener: handlePatternField(null)
parsePattern(,, PatternContext.matching, precedence: 1)
listener: beginPattern(,)
parsePrimaryPattern(,, PatternContext.matching)
listener: beginConstantPattern(null)
parsePrecedenceExpression(,, 7, false, ConstantPatternContext.implicit)
parseUnaryExpression(,, false, ConstantPatternContext.implicit)
parsePrimary(,, expression, ConstantPatternContext.implicit)
inPlainSync()
parseSend(,, expression, ConstantPatternContext.implicit)
isNextIdentifier(,)
ensureIdentifier(,, expression)
reportRecoverableErrorWithToken(if, Instance of 'Template<(Token) => Message>')
listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'if'., Try inserting an identifier before 'if'., {lexeme: if}], if, if)
rewriter()
listener: handleIdentifier(, expression)
listener: handleNoTypeArguments(if)
parseArgumentsOpt()
listener: handleNoArguments(if)
listener: handleSend(, if)
listener: endConstantPattern(null)
listener: endPattern()
listener: handlePatternField(null)
ensureCloseParen(, ()
reportRecoverableError(if, Message[ExpectedButGot, Expected ')' before this., null, {string: )}])
listener: handleRecoverableError(Message[ExpectedButGot, Expected ')' before this., null, {string: )}], if, if)
listener: handleRecordPattern((, 2)
listener: endPattern())
listener: handleSwitchCaseNoWhenClause())
ensureColon())
listener: endCaseExpression(case, null, :)
peekPastLabels(})
parseStatementsInSwitchCase(:, }, case, 0, 1, null, null)
listener: beginSwitchCase(0, 1, case)
listener: endSwitchCase(0, 1, null, null, 0, case, })
notEofOrValue(}, })
listener: endSwitchBlock(1, {, })
listener: endSwitchStatement(switch, })
notEofOrValue(}, ;)
parseStatement(})
parseStatementX(})
parseEmptyStatement(})
listener: handleEmptyStatement(;)
notEofOrValue(}, })
listener: endBlockFunctionBody(2, {, })
listener: endTopLevelMethod(void, null, })
listener: endTopLevelDeclaration()
reportAllErrorTokens(void)
listener: endCompilationUnit(1, )

View file

@ -0,0 +1,15 @@
NOTICE: Stream was rewritten by parser!
void f(Object? x) {
switch (x) {
case (_, *synthetic*if):
};
}
void[KeywordToken] f[StringToken]([BeginToken]Object[StringToken]?[SimpleToken] x[StringToken])[SimpleToken] {[BeginToken]
switch[KeywordToken] ([BeginToken]x[StringToken])[SimpleToken] {[BeginToken]
case[KeywordToken] ([BeginToken]_[StringToken],[SimpleToken] [SyntheticStringToken]if[KeywordToken])[SimpleToken]:[SimpleToken]
}[SimpleToken];[SimpleToken]
}[SimpleToken]
[SimpleToken]

View file

@ -0,0 +1,13 @@
void f(Object? x) {
switch (x) {
case (_, if):
};
}
void[KeywordToken] f[StringToken]([BeginToken]Object[StringToken]?[SimpleToken] x[StringToken])[SimpleToken] {[BeginToken]
switch[KeywordToken] ([BeginToken]x[StringToken])[SimpleToken] {[BeginToken]
case[KeywordToken] ([BeginToken]_[StringToken],[SimpleToken] if[KeywordToken])[SimpleToken]:[SimpleToken]
}[SimpleToken];[SimpleToken]
}[SimpleToken]
[SimpleToken]

View file

@ -0,0 +1 @@
void f(Object? x) => switch (x) {if};

View file

@ -0,0 +1,70 @@
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, )

View file

@ -0,0 +1,129 @@
parseUnit(void)
skipErrorTokens(void)
listener: beginCompilationUnit(void)
syntheticPreviousToken(void)
parseTopLevelDeclarationImpl(, Instance of 'DirectiveContext')
parseMetadataStar()
listener: beginMetadataStar(void)
listener: endMetadataStar(0)
parseTopLevelMemberImpl()
listener: beginTopLevelMember(void)
parseTopLevelMethod(, null, null, , Instance of 'VoidType', null, f, false)
listener: beginTopLevelMethod(, null, null)
listener: handleVoidKeyword(void)
ensureIdentifierPotentiallyRecovered(void, topLevelFunctionDeclaration, false)
listener: handleIdentifier(f, topLevelFunctionDeclaration)
parseMethodTypeVar(f)
listener: handleNoTypeVariables(()
parseGetterOrFormalParameters(f, f, false, MemberKind.TopLevelMethod)
parseFormalParameters(f, MemberKind.TopLevelMethod)
parseFormalParametersRest((, MemberKind.TopLevelMethod)
listener: beginFormalParameters((, MemberKind.TopLevelMethod)
parseFormalParameter((, FormalParameterKind.requiredPositional, MemberKind.TopLevelMethod)
parseMetadataStar(()
listener: beginMetadataStar(Object)
listener: endMetadataStar(0)
listener: beginFormalParameter(Object, MemberKind.TopLevelMethod, null, null, null)
listener: handleIdentifier(Object, typeReference)
listener: handleNoTypeArguments(?)
listener: handleType(Object, ?)
ensureIdentifier(?, formalParameterDeclaration)
listener: handleIdentifier(x, formalParameterDeclaration)
listener: handleFormalParameterWithoutValue())
listener: endFormalParameter(null, null, null, x, null, null, FormalParameterKind.requiredPositional, MemberKind.TopLevelMethod)
listener: endFormalParameters(1, (, ), MemberKind.TopLevelMethod)
parseAsyncModifierOpt())
listener: handleAsyncModifier(null, null)
inPlainSync()
parseFunctionBody(), false, false)
parseExpressionFunctionBody(=>, false)
parseExpression(=>)
looksLikeOuterPatternEquals(=>)
skipOuterPattern(=>)
parsePrecedenceExpression(=>, 1, true, ConstantPatternContext.none)
parseUnaryExpression(=>, true, ConstantPatternContext.none)
parsePrimary(=>, expression, ConstantPatternContext.none)
inPlainSync()
parseSwitchExpression(=>)
listener: beginSwitchExpression(switch)
ensureParenthesizedCondition(switch, allowCase: false)
parseExpressionInParenthesisRest((, allowCase: false)
parseExpression(()
looksLikeOuterPatternEquals(()
skipOuterPattern(()
skipObjectPatternRest(x)
parsePrecedenceExpression((, 1, true, ConstantPatternContext.none)
parseUnaryExpression((, true, ConstantPatternContext.none)
parsePrimary((, expression, ConstantPatternContext.none)
parseSendOrFunctionLiteral((, expression, ConstantPatternContext.none)
parseSend((, expression, ConstantPatternContext.none)
isNextIdentifier(()
ensureIdentifier((, expression)
listener: handleIdentifier(x, expression)
listener: handleNoTypeArguments())
parseArgumentsOpt(x)
listener: handleNoArguments())
listener: handleSend(x, ))
ensureCloseParen(x, ()
listener: handleParenthesizedCondition((, null, null)
ensureBlock(), null, switch expression)
listener: beginSwitchExpressionBlock({)
listener: beginSwitchExpressionCase()
parsePattern({, PatternContext.matching, precedence: 1)
listener: beginPattern({)
parsePrimaryPattern({, PatternContext.matching)
listener: beginConstantPattern(null)
parsePrecedenceExpression({, 7, false, ConstantPatternContext.implicit)
parseUnaryExpression({, false, ConstantPatternContext.implicit)
parsePrimary({, expression, ConstantPatternContext.implicit)
inPlainSync()
parseSend({, expression, ConstantPatternContext.implicit)
isNextIdentifier({)
ensureIdentifier({, expression)
reportRecoverableErrorWithToken(if, Instance of 'Template<(Token) => Message>')
listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'if'., Try inserting an identifier before 'if'., {lexeme: if}], if, if)
rewriter()
listener: handleIdentifier(, expression)
listener: handleNoTypeArguments(if)
parseArgumentsOpt()
listener: handleNoArguments(if)
listener: handleSend(, if)
listener: endConstantPattern(null)
listener: endPattern()
listener: handleSwitchExpressionCasePattern()
ensureFunctionArrow()
rewriteAndRecover(, Message[ExpectedButGot, Expected '=>' before this., null, {string: =>}], =>)
reportRecoverableError(if, Message[ExpectedButGot, Expected '=>' before this., null, {string: =>}])
listener: handleRecoverableError(Message[ExpectedButGot, Expected '=>' before this., null, {string: =>}], if, if)
rewriter()
parseExpression(=>)
looksLikeOuterPatternEquals(=>)
skipOuterPattern(=>)
parsePrecedenceExpression(=>, 1, true, ConstantPatternContext.none)
parseUnaryExpression(=>, true, ConstantPatternContext.none)
parsePrimary(=>, expression, ConstantPatternContext.none)
inPlainSync()
parseSend(=>, expression, ConstantPatternContext.none)
isNextIdentifier(=>)
ensureIdentifier(=>, expression)
reportRecoverableErrorWithToken(if, Instance of 'Template<(Token) => Message>')
listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'if'., Try inserting an identifier before 'if'., {lexeme: if}], if, if)
rewriter()
listener: handleIdentifier(, expression)
listener: handleNoTypeArguments(if)
parseArgumentsOpt()
listener: handleNoArguments(if)
listener: handleSend(, if)
listener: endSwitchExpressionCase(null, =>, )
findNextCommaOrSemicolon(if, })
reportRecoverableError(if, Message[ExpectedButGot, Expected '}' before this., null, {string: }}])
listener: handleRecoverableError(Message[ExpectedButGot, Expected '}' before this., null, {string: }}], if, if)
listener: endSwitchExpressionBlock(1, {, })
listener: endSwitchExpression(switch, })
ensureSemicolon(})
listener: handleExpressionFunctionBody(=>, ;)
inGenerator()
listener: endTopLevelMethod(void, null, ;)
listener: endTopLevelDeclaration()
reportAllErrorTokens(void)
listener: endCompilationUnit(1, )

View file

@ -0,0 +1,7 @@
NOTICE: Stream was rewritten by parser!
void f(Object? x) => switch (x) {*synthetic*=>*synthetic*if};
void[KeywordToken] f[StringToken]([BeginToken]Object[StringToken]?[SimpleToken] x[StringToken])[SimpleToken] =>[SimpleToken] switch[KeywordToken] ([BeginToken]x[StringToken])[SimpleToken] {[BeginToken][SyntheticStringToken]=>[SyntheticToken][SyntheticStringToken]if[KeywordToken]}[SimpleToken];[SimpleToken]
[SimpleToken]

View file

@ -0,0 +1,5 @@
void f(Object? x) => switch (x) {if};
void[KeywordToken] f[StringToken]([BeginToken]Object[StringToken]?[SimpleToken] x[StringToken])[SimpleToken] =>[SimpleToken] switch[KeywordToken] ([BeginToken]x[StringToken])[SimpleToken] {[BeginToken]if[KeywordToken]}[SimpleToken];[SimpleToken]
[SimpleToken]