diff --git a/src/parser/esprima_cpp/esprima.cpp b/src/parser/esprima_cpp/esprima.cpp index e6c910768..5cd999290 100644 --- a/src/parser/esprima_cpp/esprima.cpp +++ b/src/parser/esprima_cpp/esprima.cpp @@ -2964,10 +2964,19 @@ class Parser { ASTNode expr = this->inheritCoverGrammar(builder, &Parser::parseExponentiationExpression); + bool allowAndOr = true; + bool allowNullishCoalescing = true; ALLOC_TOKEN(token); *token = this->lookahead; int prec = this->binaryPrecedence(token); if (prec > 0) { + if (token->type == Token::PunctuatorToken) { + if (token->valuePunctuatorKind == PunctuatorKind::LogicalAnd || token->valuePunctuatorKind == PunctuatorKind::LogicalOr) { + allowNullishCoalescing = false; + } else if (token->valuePunctuatorKind == PunctuatorKind::NullishCoalescing) { + allowAndOr = false; + } + } this->nextToken(); token->prec = prec; @@ -2995,6 +3004,20 @@ class Parser { break; } + if (this->lookahead.type == Token::PunctuatorToken) { + if (!allowAndOr && (this->lookahead.valuePunctuatorKind == PunctuatorKind::LogicalAnd || this->lookahead.valuePunctuatorKind == PunctuatorKind::LogicalOr)) { + this->throwError(Messages::CannotChainLogicalWithNullish); + } else if (!allowNullishCoalescing && (this->lookahead.valuePunctuatorKind == PunctuatorKind::NullishCoalescing)) { + this->throwError(Messages::CannotChainLogicalWithNullish); + } + + if (this->lookahead.valuePunctuatorKind == PunctuatorKind::LogicalAnd || this->lookahead.valuePunctuatorKind == PunctuatorKind::LogicalOr) { + allowNullishCoalescing = false; + } else if (this->lookahead.valuePunctuatorKind == PunctuatorKind::NullishCoalescing) { + allowAndOr = false; + } + } + // Reduce: make a binary expression from the three topmost entries. while ((stack.size() > 1) && (prec <= tokenStack.back().prec)) { right = stack.back(); @@ -3084,9 +3107,6 @@ class Parser { case LogicalAnd: return builder.createBinaryExpressionLogicalAndNode(left, right); case NullishCoalescing: - if (left->isLogicalOperation() || right->isLogicalOperation()) { - this->throwError(Messages::CannotChainLogicalWithNullish); - } return builder.createBinaryExpressionNullishCoalescingNode(left, right); default: RELEASE_ASSERT_NOT_REACHED();