From e541294ab21a039fce0bc5b6556d31a02bf05882 Mon Sep 17 00:00:00 2001 From: HyukWoo Park Date: Tue, 5 Nov 2024 21:30:42 +0900 Subject: [PATCH] Fix a parsing bug in nullish-coalescing Signed-off-by: HyukWoo Park --- src/parser/esprima_cpp/esprima.cpp | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) 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();