Fix precedence of expression inside relational patterns.

According to the spec, the expression inside a relational pattern is
`bitwiseOrExpression`.  We were only allowing `shiftExpression`.

Bug: https://github.com/dart-lang/sdk/issues/50035
Change-Id: Ie1a5746f1060b84e6e1b856a622e89db698b4684
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/292285
Commit-Queue: Paul Berry <paulberry@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
This commit is contained in:
Paul Berry 2023-04-01 16:30:49 +00:00 committed by Commit Queue
parent cd519446b6
commit 406bdf33e8
48 changed files with 1662 additions and 36 deletions

View file

@ -15,6 +15,7 @@ import '../scanner/scanner.dart' show ErrorToken, Token;
import '../scanner/token.dart'
show
ASSIGNMENT_PRECEDENCE,
BITWISE_OR_PRECEDENCE,
BeginToken,
CASCADE_PRECEDENCE,
EQUALITY_PRECEDENCE,
@ -24,7 +25,6 @@ import '../scanner/token.dart'
PREFIX_PRECEDENCE,
RELATIONAL_PRECEDENCE,
SELECTOR_PRECEDENCE,
SHIFT_PRECEDENCE,
StringToken,
SyntheticBeginToken,
SyntheticKeywordToken,
@ -9775,12 +9775,7 @@ class Parser {
if (type.isRelationalOperator || type.isEqualityOperator) {
// TODO(paulberry): maybe handle other operators for error recovery?
Token operator = next;
// Note: the spec says we should use RELATIONAL_PRECEDENCE here, but
// that leads to parsing ambiguities. So we use SHIFT_PRECEDENCE, as
// suggested in https://github.com/dart-lang/language/issues/2501.
// TODO(paulberry): update this code if necessary when that issue is
// resolved.
token = parsePrecedenceExpression(next, SHIFT_PRECEDENCE,
token = parsePrecedenceExpression(next, BITWISE_OR_PRECEDENCE,
/* allowCascades = */ false, ConstantPatternContext.none);
listener.handleRelationalPattern(operator);
isLastPatternAllowedInsideUnaryPattern = false;

View file

@ -7872,6 +7872,92 @@ NullCheckPattern
''');
}
test_relational_containingBitwiseOrExpression_equality() {
_parse('''
void f(x) {
switch (x) {
case == 1 | 2:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
RelationalPattern
operator: ==
operand: BinaryExpression
leftOperand: IntegerLiteral
literal: 1
operator: |
rightOperand: IntegerLiteral
literal: 2
''');
}
test_relational_containingBitwiseOrExpression_relational() {
_parse('''
void f(x) {
switch (x) {
case > 1 | 2:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
RelationalPattern
operator: >
operand: BinaryExpression
leftOperand: IntegerLiteral
literal: 1
operator: |
rightOperand: IntegerLiteral
literal: 2
''');
}
test_relational_containingRelationalExpression_equality() {
// The patterns grammar doesn't allow a relational expression inside a
// relational pattern (even though technically it would be unambiguous).
// TODO(paulberry): try to improve parser error recovery in this scenario.
_parse('''
void f(x) {
switch (x) {
case == 1 > 0:
break;
}
}
''', errors: [
error(ParserErrorCode.EXPECTED_TOKEN, 41, 1),
error(ParserErrorCode.MISSING_IDENTIFIER, 41, 1),
error(ParserErrorCode.EXPECTED_TOKEN, 43, 1),
error(ParserErrorCode.MISSING_IDENTIFIER, 44, 1),
error(ParserErrorCode.UNEXPECTED_TOKEN, 44, 1),
]);
// We don't care what the parsed AST is, just that there are errors.
}
test_relational_containingRelationalExpression_relational() {
// The patterns grammar doesn't allow a relational expression inside a
// relational pattern (even though technically it would be unambiguous).
// TODO(paulberry): try to improve parser error recovery in this scenario.
_parse('''
void f(x) {
switch (x) {
case > 1 > 0:
break;
}
}
''', errors: [
error(ParserErrorCode.EXPECTED_TOKEN, 40, 1),
error(ParserErrorCode.MISSING_IDENTIFIER, 40, 1),
error(ParserErrorCode.EXPECTED_TOKEN, 42, 1),
error(ParserErrorCode.MISSING_IDENTIFIER, 43, 1),
error(ParserErrorCode.UNEXPECTED_TOKEN, 43, 1),
]);
// We don't care what the parsed AST is, just that there are errors.
}
test_relational_insideCase_equal() {
_parse('''
void f(x) {

View file

@ -74,7 +74,7 @@ parseUnit(f)
parseListPatternSuffix({, PatternContext.matching)
parsePattern([, PatternContext.matching, precedence: 1)
parsePrimaryPattern([, PatternContext.matching)
parsePrecedenceExpression(==, 12, false, ConstantPatternContext.none)
parsePrecedenceExpression(==, 9, false, ConstantPatternContext.none)
parseUnaryExpression(==, false, ConstantPatternContext.none)
parsePrimary(==, expression, ConstantPatternContext.none)
parseParenthesizedExpressionFunctionLiteralOrRecordLiteral(==, ConstantPatternContext.none)

View file

@ -84,7 +84,7 @@ parseUnit(f)
listener: endLiteralString(0, :)
parsePattern(:, PatternContext.matching, precedence: 1)
parsePrimaryPattern(:, PatternContext.matching)
parsePrecedenceExpression(==, 12, false, ConstantPatternContext.none)
parsePrecedenceExpression(==, 9, false, ConstantPatternContext.none)
parseUnaryExpression(==, false, ConstantPatternContext.none)
parsePrimary(==, expression, ConstantPatternContext.none)
parseParenthesizedExpressionFunctionLiteralOrRecordLiteral(==, ConstantPatternContext.none)

View file

@ -76,7 +76,7 @@ parseUnit(f)
listener: handleIdentifier(bar, namedArgumentReference)
parsePattern(:, PatternContext.matching, precedence: 1)
parsePrimaryPattern(:, PatternContext.matching)
parsePrecedenceExpression(==, 12, false, ConstantPatternContext.none)
parsePrecedenceExpression(==, 9, false, ConstantPatternContext.none)
parseUnaryExpression(==, false, ConstantPatternContext.none)
parsePrimary(==, expression, ConstantPatternContext.none)
parseParenthesizedExpressionFunctionLiteralOrRecordLiteral(==, ConstantPatternContext.none)

View file

@ -73,7 +73,7 @@ parseUnit(f)
parseParenthesizedPatternOrRecordPattern({, PatternContext.matching)
parsePattern((, PatternContext.matching, precedence: 1)
parsePrimaryPattern((, PatternContext.matching)
parsePrecedenceExpression(==, 12, false, ConstantPatternContext.none)
parsePrecedenceExpression(==, 9, false, ConstantPatternContext.none)
parseUnaryExpression(==, false, ConstantPatternContext.none)
parsePrimary(==, expression, ConstantPatternContext.none)
parseParenthesizedExpressionFunctionLiteralOrRecordLiteral(==, ConstantPatternContext.none)

View file

@ -0,0 +1,6 @@
void f(x) {
switch (x) {
case == 1 | 2:
break;
}
}

View file

@ -0,0 +1,43 @@
beginCompilationUnit(void)
beginMetadataStar(void)
endMetadataStar(0)
beginTopLevelMember(void)
beginTopLevelMethod(, null, null)
handleVoidKeyword(void)
handleIdentifier(f, topLevelFunctionDeclaration)
handleNoTypeVariables(()
beginFormalParameters((, MemberKind.TopLevelMethod)
beginMetadataStar(x)
endMetadataStar(0)
beginFormalParameter(x, MemberKind.TopLevelMethod, null, null, null)
handleNoType(()
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)
handleLiteralInt(1)
beginBinaryExpression(|)
handleLiteralInt(2)
endBinaryExpression(|)
handleRelationalPattern(==)
handleSwitchCaseNoWhenClause(2)
endCaseExpression(case, null, :)
beginSwitchCase(0, 1, case)
handleBreakStatement(false, break, ;)
endSwitchCase(0, 1, null, null, 1, case, })
endSwitchBlock(1, {, })
endSwitchStatement(switch, })
endBlockFunctionBody(1, {, })
endTopLevelMethod(void, null, })
endTopLevelDeclaration()
endCompilationUnit(1, )

View file

@ -0,0 +1,106 @@
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(x)
listener: endMetadataStar(0)
listener: beginFormalParameter(x, MemberKind.TopLevelMethod, null, null, null)
listener: handleNoType(()
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)
parsePrimaryPattern(case, PatternContext.matching)
parsePrecedenceExpression(==, 9, false, ConstantPatternContext.none)
parseUnaryExpression(==, false, ConstantPatternContext.none)
parsePrimary(==, expression, ConstantPatternContext.none)
parseLiteralInt(==)
listener: handleLiteralInt(1)
listener: beginBinaryExpression(|)
parsePrecedenceExpression(|, 10, false, ConstantPatternContext.none)
parseUnaryExpression(|, false, ConstantPatternContext.none)
parsePrimary(|, expression, ConstantPatternContext.none)
parseLiteralInt(|)
listener: handleLiteralInt(2)
listener: endBinaryExpression(|)
listener: handleRelationalPattern(==)
listener: handleSwitchCaseNoWhenClause(2)
ensureColon(2)
listener: endCaseExpression(case, null, :)
peekPastLabels(break)
parseStatementsInSwitchCase(:, break, case, 0, 1, null, null)
listener: beginSwitchCase(0, 1, case)
parseStatement(:)
parseStatementX(:)
parseBreakStatement(:)
isBreakAllowed()
ensureSemicolon(break)
listener: handleBreakStatement(false, break, ;)
peekPastLabels(})
listener: endSwitchCase(0, 1, null, null, 1, case, })
notEofOrValue(}, })
listener: endSwitchBlock(1, {, })
listener: endSwitchStatement(switch, })
notEofOrValue(}, })
listener: endBlockFunctionBody(1, {, })
listener: endTopLevelMethod(void, null, })
listener: endTopLevelDeclaration()
reportAllErrorTokens(void)
listener: endCompilationUnit(1, )

View file

@ -0,0 +1,15 @@
void f(x) {
switch (x) {
case == 1 | 2:
break;
}
}
void[KeywordToken] f[StringToken]([BeginToken]x[StringToken])[SimpleToken] {[BeginToken]
switch[KeywordToken] ([BeginToken]x[StringToken])[SimpleToken] {[BeginToken]
case[KeywordToken] ==[SimpleToken] 1[StringToken] |[SimpleToken] 2[StringToken]:[SimpleToken]
break[KeywordToken];[SimpleToken]
}[SimpleToken]
}[SimpleToken]
[SimpleToken]

View file

@ -0,0 +1,15 @@
void f(x) {
switch (x) {
case == 1 | 2:
break;
}
}
void[KeywordToken] f[StringToken]([BeginToken]x[StringToken])[SimpleToken] {[BeginToken]
switch[KeywordToken] ([BeginToken]x[StringToken])[SimpleToken] {[BeginToken]
case[KeywordToken] ==[SimpleToken] 1[StringToken] |[SimpleToken] 2[StringToken]:[SimpleToken]
break[KeywordToken];[SimpleToken]
}[SimpleToken]
}[SimpleToken]
[SimpleToken]

View file

@ -0,0 +1,6 @@
void f(x) {
switch (x) {
case > 1 | 2:
break;
}
}

View file

@ -0,0 +1,43 @@
beginCompilationUnit(void)
beginMetadataStar(void)
endMetadataStar(0)
beginTopLevelMember(void)
beginTopLevelMethod(, null, null)
handleVoidKeyword(void)
handleIdentifier(f, topLevelFunctionDeclaration)
handleNoTypeVariables(()
beginFormalParameters((, MemberKind.TopLevelMethod)
beginMetadataStar(x)
endMetadataStar(0)
beginFormalParameter(x, MemberKind.TopLevelMethod, null, null, null)
handleNoType(()
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)
handleLiteralInt(1)
beginBinaryExpression(|)
handleLiteralInt(2)
endBinaryExpression(|)
handleRelationalPattern(>)
handleSwitchCaseNoWhenClause(2)
endCaseExpression(case, null, :)
beginSwitchCase(0, 1, case)
handleBreakStatement(false, break, ;)
endSwitchCase(0, 1, null, null, 1, case, })
endSwitchBlock(1, {, })
endSwitchStatement(switch, })
endBlockFunctionBody(1, {, })
endTopLevelMethod(void, null, })
endTopLevelDeclaration()
endCompilationUnit(1, )

View file

@ -0,0 +1,106 @@
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(x)
listener: endMetadataStar(0)
listener: beginFormalParameter(x, MemberKind.TopLevelMethod, null, null, null)
listener: handleNoType(()
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)
parsePrimaryPattern(case, PatternContext.matching)
parsePrecedenceExpression(>, 9, false, ConstantPatternContext.none)
parseUnaryExpression(>, false, ConstantPatternContext.none)
parsePrimary(>, expression, ConstantPatternContext.none)
parseLiteralInt(>)
listener: handleLiteralInt(1)
listener: beginBinaryExpression(|)
parsePrecedenceExpression(|, 10, false, ConstantPatternContext.none)
parseUnaryExpression(|, false, ConstantPatternContext.none)
parsePrimary(|, expression, ConstantPatternContext.none)
parseLiteralInt(|)
listener: handleLiteralInt(2)
listener: endBinaryExpression(|)
listener: handleRelationalPattern(>)
listener: handleSwitchCaseNoWhenClause(2)
ensureColon(2)
listener: endCaseExpression(case, null, :)
peekPastLabels(break)
parseStatementsInSwitchCase(:, break, case, 0, 1, null, null)
listener: beginSwitchCase(0, 1, case)
parseStatement(:)
parseStatementX(:)
parseBreakStatement(:)
isBreakAllowed()
ensureSemicolon(break)
listener: handleBreakStatement(false, break, ;)
peekPastLabels(})
listener: endSwitchCase(0, 1, null, null, 1, case, })
notEofOrValue(}, })
listener: endSwitchBlock(1, {, })
listener: endSwitchStatement(switch, })
notEofOrValue(}, })
listener: endBlockFunctionBody(1, {, })
listener: endTopLevelMethod(void, null, })
listener: endTopLevelDeclaration()
reportAllErrorTokens(void)
listener: endCompilationUnit(1, )

View file

@ -0,0 +1,15 @@
void f(x) {
switch (x) {
case > 1 | 2:
break;
}
}
void[KeywordToken] f[StringToken]([BeginToken]x[StringToken])[SimpleToken] {[BeginToken]
switch[KeywordToken] ([BeginToken]x[StringToken])[SimpleToken] {[BeginToken]
case[KeywordToken] >[SimpleToken] 1[StringToken] |[SimpleToken] 2[StringToken]:[SimpleToken]
break[KeywordToken];[SimpleToken]
}[SimpleToken]
}[SimpleToken]
[SimpleToken]

View file

@ -0,0 +1,15 @@
void f(x) {
switch (x) {
case > 1 | 2:
break;
}
}
void[KeywordToken] f[StringToken]([BeginToken]x[StringToken])[SimpleToken] {[BeginToken]
switch[KeywordToken] ([BeginToken]x[StringToken])[SimpleToken] {[BeginToken]
case[KeywordToken] >[SimpleToken] 1[StringToken] |[SimpleToken] 2[StringToken]:[SimpleToken]
break[KeywordToken];[SimpleToken]
}[SimpleToken]
}[SimpleToken]
[SimpleToken]

View file

@ -0,0 +1,6 @@
void f(x) {
switch (x) {
case == 1 > 0:
break;
}
}

View file

@ -0,0 +1,85 @@
Problems reported:
parser/patterns/relational_containingRelationalExpression_equality:3:15: Expected ':' before this.
case == 1 > 0:
^
parser/patterns/relational_containingRelationalExpression_equality:3:15: Expected an identifier, but got '>'.
case == 1 > 0:
^
parser/patterns/relational_containingRelationalExpression_equality:3:17: Expected ';' after this.
case == 1 > 0:
^
parser/patterns/relational_containingRelationalExpression_equality:3:18: Expected an identifier, but got ':'.
case == 1 > 0:
^
parser/patterns/relational_containingRelationalExpression_equality:3:17: Expected ';' after this.
case == 1 > 0:
^
parser/patterns/relational_containingRelationalExpression_equality:3:18: Unexpected token ':'.
case == 1 > 0:
^
beginCompilationUnit(void)
beginMetadataStar(void)
endMetadataStar(0)
beginTopLevelMember(void)
beginTopLevelMethod(, null, null)
handleVoidKeyword(void)
handleIdentifier(f, topLevelFunctionDeclaration)
handleNoTypeVariables(()
beginFormalParameters((, MemberKind.TopLevelMethod)
beginMetadataStar(x)
endMetadataStar(0)
beginFormalParameter(x, MemberKind.TopLevelMethod, null, null, null)
handleNoType(()
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)
handleLiteralInt(1)
handleRelationalPattern(==)
handleSwitchCaseNoWhenClause(1)
handleRecoverableError(Message[ExpectedButGot, Expected ':' before this., null, {string: :}], >, >)
endCaseExpression(case, null, :)
beginSwitchCase(0, 1, case)
handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '>'., Try inserting an identifier before '>'., {lexeme: >}], >, >)
handleIdentifier(, expression)
handleNoTypeArguments(>)
handleNoArguments(>)
handleSend(, >)
beginBinaryExpression(>)
handleLiteralInt(0)
endBinaryExpression(>)
handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], 0, 0)
handleExpressionStatement(;)
handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ':'., Try inserting an identifier before ':'., {lexeme: :}], :, :)
handleIdentifier(, expression)
handleNoTypeArguments(:)
handleNoArguments(:)
handleSend(, :)
handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], 0, 0)
handleExpressionStatement(;)
handleRecoverableError(Message[UnexpectedToken, Unexpected token ':'., null, {lexeme: :}], :, :)
handleBreakStatement(false, break, ;)
endSwitchCase(0, 1, null, null, 3, case, })
endSwitchBlock(1, {, })
endSwitchStatement(switch, })
endBlockFunctionBody(1, {, })
endTopLevelMethod(void, null, })
endTopLevelDeclaration()
endCompilationUnit(1, )

View file

@ -0,0 +1,170 @@
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(x)
listener: endMetadataStar(0)
listener: beginFormalParameter(x, MemberKind.TopLevelMethod, null, null, null)
listener: handleNoType(()
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)
parsePrimaryPattern(case, PatternContext.matching)
parsePrecedenceExpression(==, 9, false, ConstantPatternContext.none)
parseUnaryExpression(==, false, ConstantPatternContext.none)
parsePrimary(==, expression, ConstantPatternContext.none)
parseLiteralInt(==)
listener: handleLiteralInt(1)
listener: handleRelationalPattern(==)
listener: handleSwitchCaseNoWhenClause(1)
ensureColon(1)
rewriteAndRecover(1, Message[ExpectedButGot, Expected ':' before this., null, {string: :}], :)
reportRecoverableError(>, Message[ExpectedButGot, Expected ':' before this., null, {string: :}])
listener: handleRecoverableError(Message[ExpectedButGot, Expected ':' before this., null, {string: :}], >, >)
rewriter()
listener: endCaseExpression(case, null, :)
peekPastLabels(>)
parseStatementsInSwitchCase(:, >, case, 0, 1, null, null)
listener: beginSwitchCase(0, 1, case)
parseStatement(:)
parseStatementX(:)
parseExpressionStatementOrDeclaration(:, null)
parseExpressionStatementOrDeclarationAfterModifiers(:, :, null, null, null, null)
looksLikeLocalFunction(>)
parseExpressionStatement(:)
parseExpression(:)
looksLikeOuterPatternEquals(:)
skipOuterPattern(:)
parsePrecedenceExpression(:, 1, true, ConstantPatternContext.none)
parseUnaryExpression(:, true, ConstantPatternContext.none)
parsePrimary(:, expression, ConstantPatternContext.none)
parseSend(:, expression, ConstantPatternContext.none)
isNextIdentifier(:)
ensureIdentifier(:, expression)
reportRecoverableErrorWithToken(>, Instance of 'Template<(Token) => Message>')
listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '>'., Try inserting an identifier before '>'., {lexeme: >}], >, >)
rewriter()
listener: handleIdentifier(, expression)
listener: handleNoTypeArguments(>)
parseArgumentsOpt()
listener: handleNoArguments(>)
listener: handleSend(, >)
listener: beginBinaryExpression(>)
parsePrecedenceExpression(>, 9, true, ConstantPatternContext.none)
parseUnaryExpression(>, true, ConstantPatternContext.none)
parsePrimary(>, expression, ConstantPatternContext.none)
parseLiteralInt(>)
listener: handleLiteralInt(0)
listener: endBinaryExpression(>)
ensureSemicolon(0)
reportRecoverableError(0, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], 0, 0)
rewriter()
listener: handleExpressionStatement(;)
peekPastLabels(:)
parseStatement(;)
parseStatementX(;)
parseExpressionStatementOrDeclaration(;, null)
parseExpressionStatementOrDeclarationAfterModifiers(;, ;, null, null, null, null)
looksLikeLocalFunction(:)
parseExpressionStatement(;)
parseExpression(;)
looksLikeOuterPatternEquals(;)
skipOuterPattern(;)
parsePrecedenceExpression(;, 1, true, ConstantPatternContext.none)
parseUnaryExpression(;, true, ConstantPatternContext.none)
parsePrimary(;, expression, ConstantPatternContext.none)
parseSend(;, expression, ConstantPatternContext.none)
isNextIdentifier(;)
ensureIdentifier(;, expression)
reportRecoverableErrorWithToken(:, Instance of 'Template<(Token) => Message>')
listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ':'., Try inserting an identifier before ':'., {lexeme: :}], :, :)
rewriter()
listener: handleIdentifier(, expression)
listener: handleNoTypeArguments(:)
parseArgumentsOpt()
listener: handleNoArguments(:)
listener: handleSend(, :)
ensureSemicolon()
reportRecoverableError(0, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], 0, 0)
rewriter()
listener: handleExpressionStatement(;)
reportRecoverableError(:, Message[UnexpectedToken, Unexpected token ':'., null, {lexeme: :}])
listener: handleRecoverableError(Message[UnexpectedToken, Unexpected token ':'., null, {lexeme: :}], :, :)
peekPastLabels(break)
parseStatement(:)
parseStatementX(:)
parseBreakStatement(:)
isBreakAllowed()
ensureSemicolon(break)
listener: handleBreakStatement(false, break, ;)
peekPastLabels(})
listener: endSwitchCase(0, 1, null, null, 3, case, })
notEofOrValue(}, })
listener: endSwitchBlock(1, {, })
listener: endSwitchStatement(switch, })
notEofOrValue(}, })
listener: endBlockFunctionBody(1, {, })
listener: endTopLevelMethod(void, null, })
listener: endTopLevelDeclaration()
reportAllErrorTokens(void)
listener: endCompilationUnit(1, )

View file

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

View file

@ -0,0 +1,15 @@
void f(x) {
switch (x) {
case == 1 > 0:
break;
}
}
void[KeywordToken] f[StringToken]([BeginToken]x[StringToken])[SimpleToken] {[BeginToken]
switch[KeywordToken] ([BeginToken]x[StringToken])[SimpleToken] {[BeginToken]
case[KeywordToken] ==[SimpleToken] 1[StringToken] >[SimpleToken] 0[StringToken]:[SimpleToken]
break[KeywordToken];[SimpleToken]
}[SimpleToken]
}[SimpleToken]
[SimpleToken]

View file

@ -0,0 +1,6 @@
void f(x) {
switch (x) {
case > 1 > 0:
break;
}
}

View file

@ -0,0 +1,85 @@
Problems reported:
parser/patterns/relational_containingRelationalExpression_relational:3:14: Expected ':' before this.
case > 1 > 0:
^
parser/patterns/relational_containingRelationalExpression_relational:3:14: Expected an identifier, but got '>'.
case > 1 > 0:
^
parser/patterns/relational_containingRelationalExpression_relational:3:16: Expected ';' after this.
case > 1 > 0:
^
parser/patterns/relational_containingRelationalExpression_relational:3:17: Expected an identifier, but got ':'.
case > 1 > 0:
^
parser/patterns/relational_containingRelationalExpression_relational:3:16: Expected ';' after this.
case > 1 > 0:
^
parser/patterns/relational_containingRelationalExpression_relational:3:17: Unexpected token ':'.
case > 1 > 0:
^
beginCompilationUnit(void)
beginMetadataStar(void)
endMetadataStar(0)
beginTopLevelMember(void)
beginTopLevelMethod(, null, null)
handleVoidKeyword(void)
handleIdentifier(f, topLevelFunctionDeclaration)
handleNoTypeVariables(()
beginFormalParameters((, MemberKind.TopLevelMethod)
beginMetadataStar(x)
endMetadataStar(0)
beginFormalParameter(x, MemberKind.TopLevelMethod, null, null, null)
handleNoType(()
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)
handleLiteralInt(1)
handleRelationalPattern(>)
handleSwitchCaseNoWhenClause(1)
handleRecoverableError(Message[ExpectedButGot, Expected ':' before this., null, {string: :}], >, >)
endCaseExpression(case, null, :)
beginSwitchCase(0, 1, case)
handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '>'., Try inserting an identifier before '>'., {lexeme: >}], >, >)
handleIdentifier(, expression)
handleNoTypeArguments(>)
handleNoArguments(>)
handleSend(, >)
beginBinaryExpression(>)
handleLiteralInt(0)
endBinaryExpression(>)
handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], 0, 0)
handleExpressionStatement(;)
handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ':'., Try inserting an identifier before ':'., {lexeme: :}], :, :)
handleIdentifier(, expression)
handleNoTypeArguments(:)
handleNoArguments(:)
handleSend(, :)
handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], 0, 0)
handleExpressionStatement(;)
handleRecoverableError(Message[UnexpectedToken, Unexpected token ':'., null, {lexeme: :}], :, :)
handleBreakStatement(false, break, ;)
endSwitchCase(0, 1, null, null, 3, case, })
endSwitchBlock(1, {, })
endSwitchStatement(switch, })
endBlockFunctionBody(1, {, })
endTopLevelMethod(void, null, })
endTopLevelDeclaration()
endCompilationUnit(1, )

View file

@ -0,0 +1,170 @@
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(x)
listener: endMetadataStar(0)
listener: beginFormalParameter(x, MemberKind.TopLevelMethod, null, null, null)
listener: handleNoType(()
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)
parsePrimaryPattern(case, PatternContext.matching)
parsePrecedenceExpression(>, 9, false, ConstantPatternContext.none)
parseUnaryExpression(>, false, ConstantPatternContext.none)
parsePrimary(>, expression, ConstantPatternContext.none)
parseLiteralInt(>)
listener: handleLiteralInt(1)
listener: handleRelationalPattern(>)
listener: handleSwitchCaseNoWhenClause(1)
ensureColon(1)
rewriteAndRecover(1, Message[ExpectedButGot, Expected ':' before this., null, {string: :}], :)
reportRecoverableError(>, Message[ExpectedButGot, Expected ':' before this., null, {string: :}])
listener: handleRecoverableError(Message[ExpectedButGot, Expected ':' before this., null, {string: :}], >, >)
rewriter()
listener: endCaseExpression(case, null, :)
peekPastLabels(>)
parseStatementsInSwitchCase(:, >, case, 0, 1, null, null)
listener: beginSwitchCase(0, 1, case)
parseStatement(:)
parseStatementX(:)
parseExpressionStatementOrDeclaration(:, null)
parseExpressionStatementOrDeclarationAfterModifiers(:, :, null, null, null, null)
looksLikeLocalFunction(>)
parseExpressionStatement(:)
parseExpression(:)
looksLikeOuterPatternEquals(:)
skipOuterPattern(:)
parsePrecedenceExpression(:, 1, true, ConstantPatternContext.none)
parseUnaryExpression(:, true, ConstantPatternContext.none)
parsePrimary(:, expression, ConstantPatternContext.none)
parseSend(:, expression, ConstantPatternContext.none)
isNextIdentifier(:)
ensureIdentifier(:, expression)
reportRecoverableErrorWithToken(>, Instance of 'Template<(Token) => Message>')
listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '>'., Try inserting an identifier before '>'., {lexeme: >}], >, >)
rewriter()
listener: handleIdentifier(, expression)
listener: handleNoTypeArguments(>)
parseArgumentsOpt()
listener: handleNoArguments(>)
listener: handleSend(, >)
listener: beginBinaryExpression(>)
parsePrecedenceExpression(>, 9, true, ConstantPatternContext.none)
parseUnaryExpression(>, true, ConstantPatternContext.none)
parsePrimary(>, expression, ConstantPatternContext.none)
parseLiteralInt(>)
listener: handleLiteralInt(0)
listener: endBinaryExpression(>)
ensureSemicolon(0)
reportRecoverableError(0, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], 0, 0)
rewriter()
listener: handleExpressionStatement(;)
peekPastLabels(:)
parseStatement(;)
parseStatementX(;)
parseExpressionStatementOrDeclaration(;, null)
parseExpressionStatementOrDeclarationAfterModifiers(;, ;, null, null, null, null)
looksLikeLocalFunction(:)
parseExpressionStatement(;)
parseExpression(;)
looksLikeOuterPatternEquals(;)
skipOuterPattern(;)
parsePrecedenceExpression(;, 1, true, ConstantPatternContext.none)
parseUnaryExpression(;, true, ConstantPatternContext.none)
parsePrimary(;, expression, ConstantPatternContext.none)
parseSend(;, expression, ConstantPatternContext.none)
isNextIdentifier(;)
ensureIdentifier(;, expression)
reportRecoverableErrorWithToken(:, Instance of 'Template<(Token) => Message>')
listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ':'., Try inserting an identifier before ':'., {lexeme: :}], :, :)
rewriter()
listener: handleIdentifier(, expression)
listener: handleNoTypeArguments(:)
parseArgumentsOpt()
listener: handleNoArguments(:)
listener: handleSend(, :)
ensureSemicolon()
reportRecoverableError(0, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], 0, 0)
rewriter()
listener: handleExpressionStatement(;)
reportRecoverableError(:, Message[UnexpectedToken, Unexpected token ':'., null, {lexeme: :}])
listener: handleRecoverableError(Message[UnexpectedToken, Unexpected token ':'., null, {lexeme: :}], :, :)
peekPastLabels(break)
parseStatement(:)
parseStatementX(:)
parseBreakStatement(:)
isBreakAllowed()
ensureSemicolon(break)
listener: handleBreakStatement(false, break, ;)
peekPastLabels(})
listener: endSwitchCase(0, 1, null, null, 3, case, })
notEofOrValue(}, })
listener: endSwitchBlock(1, {, })
listener: endSwitchStatement(switch, })
notEofOrValue(}, })
listener: endBlockFunctionBody(1, {, })
listener: endTopLevelMethod(void, null, })
listener: endTopLevelDeclaration()
reportAllErrorTokens(void)
listener: endCompilationUnit(1, )

View file

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

View file

@ -0,0 +1,15 @@
void f(x) {
switch (x) {
case > 1 > 0:
break;
}
}
void[KeywordToken] f[StringToken]([BeginToken]x[StringToken])[SimpleToken] {[BeginToken]
switch[KeywordToken] ([BeginToken]x[StringToken])[SimpleToken] {[BeginToken]
case[KeywordToken] >[SimpleToken] 1[StringToken] >[SimpleToken] 0[StringToken]:[SimpleToken]
break[KeywordToken];[SimpleToken]
}[SimpleToken]
}[SimpleToken]
[SimpleToken]

View file

@ -68,7 +68,7 @@ parseUnit(void)
listener: beginCaseExpression(case)
parsePattern(case, PatternContext.matching, precedence: 1)
parsePrimaryPattern(case, PatternContext.matching)
parsePrecedenceExpression(==, 12, false, ConstantPatternContext.none)
parsePrecedenceExpression(==, 9, false, ConstantPatternContext.none)
parseUnaryExpression(==, false, ConstantPatternContext.none)
parsePrimary(==, expression, ConstantPatternContext.none)
parseLiteralInt(==)

View file

@ -68,7 +68,7 @@ parseUnit(void)
listener: beginCaseExpression(case)
parsePattern(case, PatternContext.matching, precedence: 1)
parsePrimaryPattern(case, PatternContext.matching)
parsePrecedenceExpression(>, 12, false, ConstantPatternContext.none)
parsePrecedenceExpression(>, 9, false, ConstantPatternContext.none)
parseUnaryExpression(>, false, ConstantPatternContext.none)
parsePrimary(>, expression, ConstantPatternContext.none)
parseLiteralInt(>)

View file

@ -71,7 +71,7 @@ parseUnit(test)
listener: beginCaseExpression(case)
parsePattern(case, PatternContext.matching, precedence: 1)
parsePrimaryPattern(case, PatternContext.matching)
parsePrecedenceExpression(==, 12, false, ConstantPatternContext.none)
parsePrecedenceExpression(==, 9, false, ConstantPatternContext.none)
parseUnaryExpression(==, false, ConstantPatternContext.none)
parsePrimary(==, expression, ConstantPatternContext.none)
parseLiteralInt(==)

View file

@ -71,7 +71,7 @@ parseUnit(test)
listener: beginCaseExpression(case)
parsePattern(case, PatternContext.matching, precedence: 1)
parsePrimaryPattern(case, PatternContext.matching)
parsePrecedenceExpression(>, 12, false, ConstantPatternContext.none)
parsePrecedenceExpression(>, 9, false, ConstantPatternContext.none)
parseUnaryExpression(>, false, ConstantPatternContext.none)
parsePrimary(>, expression, ConstantPatternContext.none)
parseLiteralInt(>)

View file

@ -71,7 +71,7 @@ parseUnit(test)
listener: beginCaseExpression(case)
parsePattern(case, PatternContext.matching, precedence: 1)
parsePrimaryPattern(case, PatternContext.matching)
parsePrecedenceExpression(>=, 12, false, ConstantPatternContext.none)
parsePrecedenceExpression(>=, 9, false, ConstantPatternContext.none)
parseUnaryExpression(>=, false, ConstantPatternContext.none)
parsePrimary(>=, expression, ConstantPatternContext.none)
parseLiteralInt(>=)

View file

@ -71,7 +71,7 @@ parseUnit(test)
listener: beginCaseExpression(case)
parsePattern(case, PatternContext.matching, precedence: 1)
parsePrimaryPattern(case, PatternContext.matching)
parsePrecedenceExpression(<, 12, false, ConstantPatternContext.none)
parsePrecedenceExpression(<, 9, false, ConstantPatternContext.none)
parseUnaryExpression(<, false, ConstantPatternContext.none)
parsePrimary(<, expression, ConstantPatternContext.none)
parseLiteralInt(<)

View file

@ -71,7 +71,7 @@ parseUnit(test)
listener: beginCaseExpression(case)
parsePattern(case, PatternContext.matching, precedence: 1)
parsePrimaryPattern(case, PatternContext.matching)
parsePrecedenceExpression(<=, 12, false, ConstantPatternContext.none)
parsePrecedenceExpression(<=, 9, false, ConstantPatternContext.none)
parseUnaryExpression(<=, false, ConstantPatternContext.none)
parsePrimary(<=, expression, ConstantPatternContext.none)
parseLiteralInt(<=)

View file

@ -71,7 +71,7 @@ parseUnit(test)
listener: beginCaseExpression(case)
parsePattern(case, PatternContext.matching, precedence: 1)
parsePrimaryPattern(case, PatternContext.matching)
parsePrecedenceExpression(!=, 12, false, ConstantPatternContext.none)
parsePrecedenceExpression(!=, 9, false, ConstantPatternContext.none)
parseUnaryExpression(!=, false, ConstantPatternContext.none)
parsePrimary(!=, expression, ConstantPatternContext.none)
parseLiteralInt(!=)

View file

@ -121,7 +121,7 @@ parseUnit(class)
listener: handleIdentifier(f, namedArgumentReference)
parsePattern(:, PatternContext.matching, precedence: 1)
parsePrimaryPattern(:, PatternContext.matching)
parsePrecedenceExpression(==, 12, false, ConstantPatternContext.none)
parsePrecedenceExpression(==, 9, false, ConstantPatternContext.none)
parseUnaryExpression(==, false, ConstantPatternContext.none)
parsePrimary(==, expression, ConstantPatternContext.none)
parseLiteralInt(==)

View file

@ -63,7 +63,7 @@ parseUnit(test)
listener: handleSend(x, case)
parsePattern(case, PatternContext.matching, precedence: 1)
parsePrimaryPattern(case, PatternContext.matching)
parsePrecedenceExpression(==, 12, false, ConstantPatternContext.none)
parsePrecedenceExpression(==, 9, false, ConstantPatternContext.none)
parseUnaryExpression(==, false, ConstantPatternContext.none)
parsePrimary(==, expression, ConstantPatternContext.none)
parseLiteralInt(==)

View file

@ -75,7 +75,7 @@ parseUnit(test)
parseListPatternSuffix(case, PatternContext.matching)
parsePattern([, PatternContext.matching, precedence: 1)
parsePrimaryPattern([, PatternContext.matching)
parsePrecedenceExpression(==, 12, false, ConstantPatternContext.none)
parsePrecedenceExpression(==, 9, false, ConstantPatternContext.none)
parseUnaryExpression(==, false, ConstantPatternContext.none)
parsePrimary(==, expression, ConstantPatternContext.none)
parseLiteralInt(==)

View file

@ -71,7 +71,7 @@ parseUnit(test)
listener: beginCaseExpression(case)
parsePattern(case, PatternContext.matching, precedence: 1)
parsePrimaryPattern(case, PatternContext.matching)
parsePrecedenceExpression(==, 12, false, ConstantPatternContext.none)
parsePrecedenceExpression(==, 9, false, ConstantPatternContext.none)
parseUnaryExpression(==, false, ConstantPatternContext.none)
parsePrimary(==, expression, ConstantPatternContext.none)
parseLiteralInt(==)

View file

@ -81,7 +81,7 @@ parseUnit(test)
listener: beginBinaryPattern(&&)
parsePattern(&&, PatternContext.matching, precedence: 7)
parsePrimaryPattern(&&, PatternContext.matching)
parsePrecedenceExpression(==, 12, false, ConstantPatternContext.none)
parsePrecedenceExpression(==, 9, false, ConstantPatternContext.none)
parseUnaryExpression(==, false, ConstantPatternContext.none)
parsePrimary(==, expression, ConstantPatternContext.none)
parseLiteralInt(==)

View file

@ -71,7 +71,7 @@ parseUnit(test)
listener: beginCaseExpression(case)
parsePattern(case, PatternContext.matching, precedence: 1)
parsePrimaryPattern(case, PatternContext.matching)
parsePrecedenceExpression(==, 12, false, ConstantPatternContext.none)
parsePrecedenceExpression(==, 9, false, ConstantPatternContext.none)
parseUnaryExpression(==, false, ConstantPatternContext.none)
parsePrimary(==, expression, ConstantPatternContext.none)
parseLiteralInt(==)

View file

@ -81,7 +81,7 @@ parseUnit(test)
listener: beginBinaryPattern(||)
parsePattern(||, PatternContext.matching, precedence: 6)
parsePrimaryPattern(||, PatternContext.matching)
parsePrecedenceExpression(==, 12, false, ConstantPatternContext.none)
parsePrecedenceExpression(==, 9, false, ConstantPatternContext.none)
parseUnaryExpression(==, false, ConstantPatternContext.none)
parsePrimary(==, expression, ConstantPatternContext.none)
parseLiteralInt(==)

View file

@ -85,7 +85,7 @@ parseUnit(test)
listener: endLiteralString(0, :)
parsePattern(:, PatternContext.matching, precedence: 1)
parsePrimaryPattern(:, PatternContext.matching)
parsePrecedenceExpression(==, 12, false, ConstantPatternContext.none)
parsePrecedenceExpression(==, 9, false, ConstantPatternContext.none)
parseUnaryExpression(==, false, ConstantPatternContext.none)
parsePrimary(==, expression, ConstantPatternContext.none)
parseLiteralInt(==)

View file

@ -74,7 +74,7 @@ parseUnit(test)
parseParenthesizedPatternOrRecordPattern(case, PatternContext.matching)
parsePattern((, PatternContext.matching, precedence: 1)
parsePrimaryPattern((, PatternContext.matching)
parsePrecedenceExpression(==, 12, false, ConstantPatternContext.none)
parsePrecedenceExpression(==, 9, false, ConstantPatternContext.none)
parseUnaryExpression(==, false, ConstantPatternContext.none)
parsePrimary(==, expression, ConstantPatternContext.none)
parseLiteralInt(==)

View file

@ -76,7 +76,7 @@ parseUnit(test)
listener: handleIdentifier(n, namedRecordFieldReference)
parsePattern(:, PatternContext.matching, precedence: 1)
parsePrimaryPattern(:, PatternContext.matching)
parsePrecedenceExpression(==, 12, false, ConstantPatternContext.none)
parsePrecedenceExpression(==, 9, false, ConstantPatternContext.none)
parseUnaryExpression(==, false, ConstantPatternContext.none)
parsePrimary(==, expression, ConstantPatternContext.none)
parseLiteralInt(==)

View file

@ -74,7 +74,7 @@ parseUnit(test)
parseParenthesizedPatternOrRecordPattern(case, PatternContext.matching)
parsePattern((, PatternContext.matching, precedence: 1)
parsePrimaryPattern((, PatternContext.matching)
parsePrecedenceExpression(==, 12, false, ConstantPatternContext.none)
parsePrecedenceExpression(==, 9, false, ConstantPatternContext.none)
parseUnaryExpression(==, false, ConstantPatternContext.none)
parsePrimary(==, expression, ConstantPatternContext.none)
parseLiteralInt(==)

View file

@ -72,7 +72,7 @@ parseUnit(void)
parseListPatternSuffix(case, PatternContext.matching)
parsePattern(..., PatternContext.matching, precedence: 1)
parsePrimaryPattern(..., PatternContext.matching)
parsePrecedenceExpression(==, 12, false, ConstantPatternContext.none)
parsePrecedenceExpression(==, 9, false, ConstantPatternContext.none)
parseUnaryExpression(==, false, ConstantPatternContext.none)
parsePrimary(==, expression, ConstantPatternContext.none)
parseLiteralNull(==)
@ -91,7 +91,7 @@ parseUnit(void)
parseListPatternSuffix(case, PatternContext.matching)
parsePattern(..., PatternContext.matching, precedence: 1)
parsePrimaryPattern(..., PatternContext.matching)
parsePrecedenceExpression(!=, 12, false, ConstantPatternContext.none)
parsePrecedenceExpression(!=, 9, false, ConstantPatternContext.none)
parseUnaryExpression(!=, false, ConstantPatternContext.none)
parsePrimary(!=, expression, ConstantPatternContext.none)
parseLiteralNull(!=)
@ -110,7 +110,7 @@ parseUnit(void)
parseListPatternSuffix(case, PatternContext.matching)
parsePattern(..., PatternContext.matching, precedence: 1)
parsePrimaryPattern(..., PatternContext.matching)
parsePrecedenceExpression(<, 12, false, ConstantPatternContext.none)
parsePrecedenceExpression(<, 9, false, ConstantPatternContext.none)
parseUnaryExpression(<, false, ConstantPatternContext.none)
parsePrimary(<, expression, ConstantPatternContext.none)
parseLiteralInt(<)
@ -129,7 +129,7 @@ parseUnit(void)
parseListPatternSuffix(case, PatternContext.matching)
parsePattern(..., PatternContext.matching, precedence: 1)
parsePrimaryPattern(..., PatternContext.matching)
parsePrecedenceExpression(>, 12, false, ConstantPatternContext.none)
parsePrecedenceExpression(>, 9, false, ConstantPatternContext.none)
parseUnaryExpression(>, false, ConstantPatternContext.none)
parsePrimary(>, expression, ConstantPatternContext.none)
parseLiteralInt(>)
@ -148,7 +148,7 @@ parseUnit(void)
parseListPatternSuffix(case, PatternContext.matching)
parsePattern(..., PatternContext.matching, precedence: 1)
parsePrimaryPattern(..., PatternContext.matching)
parsePrecedenceExpression(<=, 12, false, ConstantPatternContext.none)
parsePrecedenceExpression(<=, 9, false, ConstantPatternContext.none)
parseUnaryExpression(<=, false, ConstantPatternContext.none)
parsePrimary(<=, expression, ConstantPatternContext.none)
parseLiteralInt(<=)
@ -167,7 +167,7 @@ parseUnit(void)
parseListPatternSuffix(case, PatternContext.matching)
parsePattern(..., PatternContext.matching, precedence: 1)
parsePrimaryPattern(..., PatternContext.matching)
parsePrecedenceExpression(>=, 12, false, ConstantPatternContext.none)
parsePrecedenceExpression(>=, 9, false, ConstantPatternContext.none)
parseUnaryExpression(>=, false, ConstantPatternContext.none)
parsePrimary(>=, expression, ConstantPatternContext.none)
parseLiteralInt(>=)

View file

@ -0,0 +1,358 @@
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// SharedOptions=--enable-experiment=patterns
// Test certain expression types that are not allowed inside a relational
// pattern.
void usingEquals(x) {
// relationalExpression
if (x case == 1 < 2) {}
// ^
// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
// [cfe] Expected ')' before this.
if (x case == 1 <= 2) {}
// ^^
// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
// [cfe] Expected ')' before this.
if (x case == 1 > 2) {}
// ^
// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
// [cfe] Expected ')' before this.
if (x case == 1 >= 2) {}
// ^^
// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
// [cfe] Expected ')' before this.
if (x case == 1 is int) {}
// ^^
// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
// [cfe] Expected ')' before this.
if (x case == 1 as int) {}
// ^^^^
// [analyzer] SYNTACTIC_ERROR.INVALID_INSIDE_UNARY_PATTERN
// [cfe] This pattern cannot appear inside a unary pattern (cast pattern, null check pattern, or null assert pattern) without parentheses.
// equalityExpression
if (x case == 1 == 2) {}
// ^^
// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
// [cfe] Expected ')' before this.
if (x case == 1 != 2) {}
// ^^
// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
// [cfe] Expected ')' before this.
// ifNullExpression
if (x case == 1 ?? 2) {}
// ^^
// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
// [cfe] Expected ')' before this.
// conditionalExpression
if (x case == true ? 1 : 2) {}
// ^^^^^^^
// [analyzer] SYNTACTIC_ERROR.INVALID_INSIDE_UNARY_PATTERN
// [cfe] This pattern cannot appear inside a unary pattern (cast pattern, null check pattern, or null assert pattern) without parentheses.
// ^
// [analyzer] STATIC_WARNING.UNNECESSARY_NULL_CHECK_PATTERN
// [cfe] The null-check pattern will have no effect because the matched type isn't nullable.
// ^
// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
// [cfe] Expected ')' before this.
}
void usingNotEquals(x) {
// relationalExpression
if (x case != 1 < 2) {}
// ^
// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
// [cfe] Expected ')' before this.
if (x case != 1 <= 2) {}
// ^^
// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
// [cfe] Expected ')' before this.
if (x case != 1 > 2) {}
// ^
// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
// [cfe] Expected ')' before this.
if (x case != 1 >= 2) {}
// ^^
// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
// [cfe] Expected ')' before this.
if (x case != 1 is int) {}
// ^^
// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
// [cfe] Expected ')' before this.
if (x case != 1 as int) {}
// ^^^^
// [analyzer] SYNTACTIC_ERROR.INVALID_INSIDE_UNARY_PATTERN
// [cfe] This pattern cannot appear inside a unary pattern (cast pattern, null check pattern, or null assert pattern) without parentheses.
// equalityExpression
if (x case != 1 == 2) {}
// ^^
// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
// [cfe] Expected ')' before this.
if (x case != 1 != 2) {}
// ^^
// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
// [cfe] Expected ')' before this.
// ifNullExpression
if (x case != 1 ?? 2) {}
// ^^
// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
// [cfe] Expected ')' before this.
// conditionalExpression
if (x case != true ? 1 : 2) {}
// ^^^^^^^
// [analyzer] SYNTACTIC_ERROR.INVALID_INSIDE_UNARY_PATTERN
// [cfe] This pattern cannot appear inside a unary pattern (cast pattern, null check pattern, or null assert pattern) without parentheses.
// ^
// [analyzer] STATIC_WARNING.UNNECESSARY_NULL_CHECK_PATTERN
// [cfe] The null-check pattern will have no effect because the matched type isn't nullable.
// ^
// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
// [cfe] Expected ')' before this.
}
void usingLessThanOrEquals(x) {
// relationalExpression
if (x case <= 1 < 2) {}
// ^
// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
// [cfe] Expected ')' before this.
if (x case <= 1 <= 2) {}
// ^^
// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
// [cfe] Expected ')' before this.
if (x case <= 1 > 2) {}
// ^
// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
// [cfe] Expected ')' before this.
if (x case <= 1 >= 2) {}
// ^^
// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
// [cfe] Expected ')' before this.
if (x case <= 1 is int) {}
// ^^
// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
// [cfe] Expected ')' before this.
if (x case <= 1 as int) {}
// ^^^^
// [analyzer] SYNTACTIC_ERROR.INVALID_INSIDE_UNARY_PATTERN
// [cfe] This pattern cannot appear inside a unary pattern (cast pattern, null check pattern, or null assert pattern) without parentheses.
// equalityExpression
if (x case <= 1 == 2) {}
// ^^
// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
// [cfe] Expected ')' before this.
if (x case <= 1 != 2) {}
// ^^
// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
// [cfe] Expected ')' before this.
// ifNullExpression
if (x case <= 1 ?? 2) {}
// ^^
// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
// [cfe] Expected ')' before this.
// conditionalExpression
if (x case <= true ? 1 : 2) {}
// ^^^^^^^
// [analyzer] SYNTACTIC_ERROR.INVALID_INSIDE_UNARY_PATTERN
// [cfe] This pattern cannot appear inside a unary pattern (cast pattern, null check pattern, or null assert pattern) without parentheses.
// ^^^^
// [analyzer] COMPILE_TIME_ERROR.RELATIONAL_PATTERN_OPERAND_TYPE_NOT_ASSIGNABLE
// [cfe] The argument type 'bool' can't be assigned to the parameter type 'num'.
// ^
// [analyzer] STATIC_WARNING.UNNECESSARY_NULL_CHECK_PATTERN
// [cfe] The null-check pattern will have no effect because the matched type isn't nullable.
// ^
// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
// [cfe] Expected ')' before this.
}
void usingLessThan(x) {
// relationalExpression
if (x case < 1 < 2) {}
// ^
// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
// [cfe] Expected ')' before this.
if (x case < 1 <= 2) {}
// ^^
// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
// [cfe] Expected ')' before this.
if (x case < 1 > 2) {}
// ^
// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
// [cfe] Expected ')' before this.
if (x case < 1 >= 2) {}
// ^^
// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
// [cfe] Expected ')' before this.
if (x case < 1 is int) {}
// ^^
// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
// [cfe] Expected ')' before this.
if (x case < 1 as int) {}
// ^^^
// [analyzer] SYNTACTIC_ERROR.INVALID_INSIDE_UNARY_PATTERN
// [cfe] This pattern cannot appear inside a unary pattern (cast pattern, null check pattern, or null assert pattern) without parentheses.
// equalityExpression
if (x case < 1 == 2) {}
// ^^
// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
// [cfe] Expected ')' before this.
if (x case < 1 != 2) {}
// ^^
// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
// [cfe] Expected ')' before this.
// ifNullExpression
if (x case < 1 ?? 2) {}
// ^^
// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
// [cfe] Expected ')' before this.
// conditionalExpression
if (x case < true ? 1 : 2) {}
// ^^^^^^
// [analyzer] SYNTACTIC_ERROR.INVALID_INSIDE_UNARY_PATTERN
// [cfe] This pattern cannot appear inside a unary pattern (cast pattern, null check pattern, or null assert pattern) without parentheses.
// ^^^^
// [analyzer] COMPILE_TIME_ERROR.RELATIONAL_PATTERN_OPERAND_TYPE_NOT_ASSIGNABLE
// [cfe] The argument type 'bool' can't be assigned to the parameter type 'num'.
// ^
// [analyzer] STATIC_WARNING.UNNECESSARY_NULL_CHECK_PATTERN
// [cfe] The null-check pattern will have no effect because the matched type isn't nullable.
// ^
// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
// [cfe] Expected ')' before this.
}
void usingGreaterThanOrEquals(x) {
// relationalExpression
if (x case >= 1 < 2) {}
// ^
// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
// [cfe] Expected ')' before this.
if (x case >= 1 <= 2) {}
// ^^
// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
// [cfe] Expected ')' before this.
if (x case >= 1 > 2) {}
// ^
// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
// [cfe] Expected ')' before this.
if (x case >= 1 >= 2) {}
// ^^
// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
// [cfe] Expected ')' before this.
if (x case >= 1 is int) {}
// ^^
// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
// [cfe] Expected ')' before this.
if (x case >= 1 as int) {}
// ^^^^
// [analyzer] SYNTACTIC_ERROR.INVALID_INSIDE_UNARY_PATTERN
// [cfe] This pattern cannot appear inside a unary pattern (cast pattern, null check pattern, or null assert pattern) without parentheses.
// equalityExpression
if (x case >= 1 == 2) {}
// ^^
// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
// [cfe] Expected ')' before this.
if (x case >= 1 != 2) {}
// ^^
// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
// [cfe] Expected ')' before this.
// ifNullExpression
if (x case >= 1 ?? 2) {}
// ^^
// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
// [cfe] Expected ')' before this.
// conditionalExpression
if (x case >= true ? 1 : 2) {}
// ^^^^^^^
// [analyzer] SYNTACTIC_ERROR.INVALID_INSIDE_UNARY_PATTERN
// [cfe] This pattern cannot appear inside a unary pattern (cast pattern, null check pattern, or null assert pattern) without parentheses.
// ^^^^
// [analyzer] COMPILE_TIME_ERROR.RELATIONAL_PATTERN_OPERAND_TYPE_NOT_ASSIGNABLE
// [cfe] The argument type 'bool' can't be assigned to the parameter type 'num'.
// ^
// [analyzer] STATIC_WARNING.UNNECESSARY_NULL_CHECK_PATTERN
// [cfe] The null-check pattern will have no effect because the matched type isn't nullable.
// ^
// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
// [cfe] Expected ')' before this.
}
void usingGreaterThan(x) {
// relationalExpression
if (x case > 1 < 2) {}
// ^
// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
// [cfe] Expected ')' before this.
if (x case > 1 <= 2) {}
// ^^
// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
// [cfe] Expected ')' before this.
if (x case > 1 > 2) {}
// ^
// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
// [cfe] Expected ')' before this.
if (x case > 1 >= 2) {}
// ^^
// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
// [cfe] Expected ')' before this.
if (x case > 1 is int) {}
// ^^
// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
// [cfe] Expected ')' before this.
if (x case > 1 as int) {}
// ^^^
// [analyzer] SYNTACTIC_ERROR.INVALID_INSIDE_UNARY_PATTERN
// [cfe] This pattern cannot appear inside a unary pattern (cast pattern, null check pattern, or null assert pattern) without parentheses.
// equalityExpression
if (x case > 1 == 2) {}
// ^^
// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
// [cfe] Expected ')' before this.
if (x case > 1 != 2) {}
// ^^
// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
// [cfe] Expected ')' before this.
// ifNullExpression
if (x case > 1 ?? 2) {}
// ^^
// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
// [cfe] Expected ')' before this.
// conditionalExpression
if (x case > true ? 1 : 2) {}
// ^^^^^^
// [analyzer] SYNTACTIC_ERROR.INVALID_INSIDE_UNARY_PATTERN
// [cfe] This pattern cannot appear inside a unary pattern (cast pattern, null check pattern, or null assert pattern) without parentheses.
// ^^^^
// [analyzer] COMPILE_TIME_ERROR.RELATIONAL_PATTERN_OPERAND_TYPE_NOT_ASSIGNABLE
// [cfe] The argument type 'bool' can't be assigned to the parameter type 'num'.
// ^
// [analyzer] STATIC_WARNING.UNNECESSARY_NULL_CHECK_PATTERN
// [cfe] The null-check pattern will have no effect because the matched type isn't nullable.
// ^
// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
// [cfe] Expected ')' before this.
}
main() {}

View file

@ -0,0 +1,231 @@
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// SharedOptions=--enable-experiment=patterns
// Test that all the expression types permitted by the grammar are allowed
// inside a relational pattern.
import 'package:expect/expect.dart';
void usingEquals() {
// bitwiseOrExpression
Expect.isTrue(switch(7) { == 5 | 6 => true, _ => false });
// bitwiseXorExpression
Expect.isTrue(switch(3) { == 5 ^ 6 => true, _ => false });
// bitwiseAndExpression
Expect.isTrue(switch(4) { == 5 & 6 => true, _ => false });
// shiftExpression
Expect.isTrue(switch(4) { == 1 << 2 => true, _ => false });
Expect.isTrue(switch(1) { == 4 >> 2 => true, _ => false });
// additiveExpression
Expect.isTrue(switch(4) { == 3 + 1 => true, _ => false });
Expect.isTrue(switch(2) { == 3 - 1 => true, _ => false });
// multiplicativeExpression
Expect.isTrue(switch(10) { == 5 * 2 => true, _ => false });
Expect.isTrue(switch(2.5) { == 5 / 2 => true, _ => false });
Expect.isTrue(switch(1) { == 5 % 2 => true, _ => false });
Expect.isTrue(switch(2) { == 5 ~/ 2 => true, _ => false });
// unaryExpression
Expect.isTrue(switch(-3) { == -3 => true, _ => false });
Expect.isTrue(switch(true) { == !false => true, _ => false });
Expect.isTrue(switch(~3) { == ~3 => true, _ => false });
// assignableExpression
Expect.isTrue(switch(3) { == 'foo'.length => true, _ => false });
// primary
Expect.isTrue(switch('xyz') { == 'xyz' => true, _ => false });
}
void usingNotEquals() {
// bitwiseOrExpression
Expect.isFalse(switch(7) { != 5 | 6 => true, _ => false });
// bitwiseXorExpression
Expect.isFalse(switch(3) { != 5 ^ 6 => true, _ => false });
// bitwiseAndExpression
Expect.isFalse(switch(4) { != 5 & 6 => true, _ => false });
// shiftExpression
Expect.isFalse(switch(4) { != 1 << 2 => true, _ => false });
Expect.isFalse(switch(1) { != 4 >> 2 => true, _ => false });
// additiveExpression
Expect.isFalse(switch(4) { != 3 + 1 => true, _ => false });
Expect.isFalse(switch(2) { != 3 - 1 => true, _ => false });
// multiplicativeExpression
Expect.isFalse(switch(10) { != 5 * 2 => true, _ => false });
Expect.isFalse(switch(2.5) { != 5 / 2 => true, _ => false });
Expect.isFalse(switch(1) { != 5 % 2 => true, _ => false });
Expect.isFalse(switch(2) { != 5 ~/ 2 => true, _ => false });
// unaryExpression
Expect.isFalse(switch(-3) { != -3 => true, _ => false });
Expect.isFalse(switch(true) { != !false => true, _ => false });
Expect.isFalse(switch(~3) { != ~3 => true, _ => false });
// assignableExpression
Expect.isFalse(switch(3) { != 'foo'.length => true, _ => false });
// primary
Expect.isFalse(switch('xyz') { != 'xyz' => true, _ => false });
}
void usingLessThanOrEquals() {
// bitwiseOrExpression
Expect.isTrue(switch(7) { <= 5 | 6 => true, _ => false });
// bitwiseXorExpression
Expect.isTrue(switch(3) { <= 5 ^ 6 => true, _ => false });
// bitwiseAndExpression
Expect.isTrue(switch(4) { <= 5 & 6 => true, _ => false });
// shiftExpression
Expect.isTrue(switch(4) { <= 1 << 2 => true, _ => false });
Expect.isTrue(switch(1) { <= 4 >> 2 => true, _ => false });
// additiveExpression
Expect.isTrue(switch(4) { <= 3 + 1 => true, _ => false });
Expect.isTrue(switch(2) { <= 3 - 1 => true, _ => false });
// multiplicativeExpression
Expect.isTrue(switch(10) { <= 5 * 2 => true, _ => false });
Expect.isTrue(switch(2.5) { <= 5 / 2 => true, _ => false });
Expect.isTrue(switch(1) { <= 5 % 2 => true, _ => false });
Expect.isTrue(switch(2) { <= 5 ~/ 2 => true, _ => false });
// unaryExpression
Expect.isTrue(switch(-3) { <= -3 => true, _ => false });
Expect.isTrue(switch(~3) { <= ~3 => true, _ => false });
// assignableExpression
Expect.isTrue(switch(3) { <= 'foo'.length => true, _ => false });
// primary
Expect.isTrue(switch(3) { <= 3 => true, _ => false });
}
void usingLessThan() {
// bitwiseOrExpression
Expect.isFalse(switch(7) { < 5 | 6 => true, _ => false });
// bitwiseXorExpression
Expect.isFalse(switch(3) { < 5 ^ 6 => true, _ => false });
// bitwiseAndExpression
Expect.isFalse(switch(4) { < 5 & 6 => true, _ => false });
// shiftExpression
Expect.isFalse(switch(4) { < 1 << 2 => true, _ => false });
Expect.isFalse(switch(1) { < 4 >> 2 => true, _ => false });
// additiveExpression
Expect.isFalse(switch(4) { < 3 + 1 => true, _ => false });
Expect.isFalse(switch(2) { < 3 - 1 => true, _ => false });
// multiplicativeExpression
Expect.isFalse(switch(10) { < 5 * 2 => true, _ => false });
Expect.isFalse(switch(2.5) { < 5 / 2 => true, _ => false });
Expect.isFalse(switch(1) { < 5 % 2 => true, _ => false });
Expect.isFalse(switch(2) { < 5 ~/ 2 => true, _ => false });
// unaryExpression
Expect.isFalse(switch(-3) { < -3 => true, _ => false });
Expect.isFalse(switch(~3) { < ~3 => true, _ => false });
// assignableExpression
Expect.isFalse(switch(3) { < 'foo'.length => true, _ => false });
// primary
Expect.isFalse(switch(3) { < 3 => true, _ => false });
}
void usingGreaterThanOrEquals() {
// bitwiseOrExpression
Expect.isTrue(switch(7) { >= 5 | 6 => true, _ => false });
// bitwiseXorExpression
Expect.isTrue(switch(3) { >= 5 ^ 6 => true, _ => false });
// bitwiseAndExpression
Expect.isTrue(switch(4) { >= 5 & 6 => true, _ => false });
// shiftExpression
Expect.isTrue(switch(4) { >= 1 << 2 => true, _ => false });
Expect.isTrue(switch(1) { >= 4 >> 2 => true, _ => false });
// additiveExpression
Expect.isTrue(switch(4) { >= 3 + 1 => true, _ => false });
Expect.isTrue(switch(2) { >= 3 - 1 => true, _ => false });
// multiplicativeExpression
Expect.isTrue(switch(10) { >= 5 * 2 => true, _ => false });
Expect.isTrue(switch(2.5) { >= 5 / 2 => true, _ => false });
Expect.isTrue(switch(1) { >= 5 % 2 => true, _ => false });
Expect.isTrue(switch(2) { >= 5 ~/ 2 => true, _ => false });
// unaryExpression
Expect.isTrue(switch(-3) { >= -3 => true, _ => false });
Expect.isTrue(switch(~3) { >= ~3 => true, _ => false });
// assignableExpression
Expect.isTrue(switch(3) { >= 'foo'.length => true, _ => false });
// primary
Expect.isTrue(switch(3) { >= 3 => true, _ => false });
}
void usingGreaterThan() {
// bitwiseOrExpression
Expect.isFalse(switch(7) { > 5 | 6 => true, _ => false });
// bitwiseXorExpression
Expect.isFalse(switch(3) { > 5 ^ 6 => true, _ => false });
// bitwiseAndExpression
Expect.isFalse(switch(4) { > 5 & 6 => true, _ => false });
// shiftExpression
Expect.isFalse(switch(4) { > 1 << 2 => true, _ => false });
Expect.isFalse(switch(1) { > 4 >> 2 => true, _ => false });
// additiveExpression
Expect.isFalse(switch(4) { > 3 + 1 => true, _ => false });
Expect.isFalse(switch(2) { > 3 - 1 => true, _ => false });
// multiplicativeExpression
Expect.isFalse(switch(10) { > 5 * 2 => true, _ => false });
Expect.isFalse(switch(2.5) { > 5 / 2 => true, _ => false });
Expect.isFalse(switch(1) { > 5 % 2 => true, _ => false });
Expect.isFalse(switch(2) { > 5 ~/ 2 => true, _ => false });
// unaryExpression
Expect.isFalse(switch(-3) { > -3 => true, _ => false });
Expect.isFalse(switch(~3) { > ~3 => true, _ => false });
// assignableExpression
Expect.isFalse(switch(3) { > 'foo'.length => true, _ => false });
// primary
Expect.isFalse(switch(3) { > 3 => true, _ => false });
}
main() {
usingEquals();
usingNotEquals();
usingLessThanOrEquals();
usingLessThan();
usingGreaterThanOrEquals();
usingGreaterThan();
}