Fix parse expression "a ~ b"
This fixes an infinite loop that I introduced in the parser
on Wed Feb 27 commit 8f12d634fea19d42c363bef65cffd5582a3997ec
when adding support for the "!" NNBD postfix assert non-null operator.
To the best of my knowledge, this problem only manifests
when parsing the expression "a ~ b".
Fix https://github.com/dart-lang/sdk/issues/36255
Change-Id: If20f45620eee0f7cf9b4b6a93640bd3b921d23b9
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/97265
Reviewed-by: Paul Berry <paulberry@google.com>
Commit-Queue: Dan Rubel <danrubel@google.com>
diff --git a/pkg/analyzer/test/generated/parser_fasta_test.dart b/pkg/analyzer/test/generated/parser_fasta_test.dart
index f5becf3..55ece47 100644
--- a/pkg/analyzer/test/generated/parser_fasta_test.dart
+++ b/pkg/analyzer/test/generated/parser_fasta_test.dart
@@ -907,6 +907,21 @@
@reflectiveTest
class ExpressionParserTest_Fasta extends FastaParserTestCase
with ExpressionParserTestMixin {
+ void test_binaryExpression_allOperators() {
+ // https://github.com/dart-lang/sdk/issues/36255
+ for (TokenType type in TokenType.all) {
+ if (type.precedence > 0) {
+ var source = 'a ${type.lexeme} b';
+ try {
+ parseExpression(source);
+ } on TestFailure {
+ // Ensure that there are no infinite loops or exceptions thrown
+ // by the parser. Test failures are fine.
+ }
+ }
+ }
+ }
+
void test_listLiteral_spread() {
// TODO(danrubel): Remove this once spread_collections is enabled by default
ListLiteral list = parseExpression('[1, ...[2]]', errors: [
diff --git a/pkg/front_end/lib/src/fasta/parser/parser.dart b/pkg/front_end/lib/src/fasta/parser/parser.dart
index 774daef..afe9a91 100644
--- a/pkg/front_end/lib/src/fasta/parser/parser.dart
+++ b/pkg/front_end/lib/src/fasta/parser/parser.dart
@@ -3824,13 +3824,12 @@
listener.handleUnaryPostfixAssignmentExpression(token.next);
token = next;
}
- } else if (identical(tokenLevel, PREFIX_PRECEDENCE)) {
+ } else if (identical(tokenLevel, PREFIX_PRECEDENCE) &&
+ (identical(type, TokenType.BANG))) {
// The '!' has prefix precedence but here it's being used as a
// postfix operator to assert the expression has a non-null value.
- if ((identical(type, TokenType.BANG))) {
- listener.handleNonNullAssertExpression(token.next);
- token = next;
- }
+ listener.handleNonNullAssertExpression(token.next);
+ token = next;
} else if (identical(tokenLevel, SELECTOR_PRECEDENCE)) {
if (identical(type, TokenType.PERIOD) ||
identical(type, TokenType.QUESTION_PERIOD)) {