1 /**
2 * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "lexer/token/tokenType.h"
17 #include "parser/parserFlags.h"
18 #include "ir/astNode.h"
19 #include "ir/base/classDefinition.h"
20 #include "ir/base/decorator.h"
21 #include "ir/base/metaProperty.h"
22 #include "ir/base/methodDefinition.h"
23 #include "ir/base/property.h"
24 #include "ir/base/scriptFunction.h"
25 #include "ir/base/spreadElement.h"
26 #include "ir/base/templateElement.h"
27 #include "ir/expression.h"
28 #include "ir/expressions/arrayExpression.h"
29 #include "ir/expressions/arrowFunctionExpression.h"
30 #include "ir/expressions/assignmentExpression.h"
31 #include "ir/expressions/awaitExpression.h"
32 #include "ir/expressions/binaryExpression.h"
33 #include "ir/expressions/callExpression.h"
34 #include "ir/expressions/chainExpression.h"
35 #include "ir/expressions/classExpression.h"
36 #include "ir/expressions/conditionalExpression.h"
37 #include "ir/expressions/directEvalExpression.h"
38 #include "ir/expressions/functionExpression.h"
39 #include "ir/expressions/identifier.h"
40 #include "ir/expressions/importExpression.h"
41 #include "ir/expressions/literals/bigIntLiteral.h"
42 #include "ir/expressions/literals/booleanLiteral.h"
43 #include "ir/expressions/literals/nullLiteral.h"
44 #include "ir/expressions/literals/numberLiteral.h"
45 #include "ir/expressions/literals/regExpLiteral.h"
46 #include "ir/expressions/literals/charLiteral.h"
47 #include "ir/expressions/literals/stringLiteral.h"
48 #include "ir/expressions/literals/undefinedLiteral.h"
49 #include "ir/expressions/memberExpression.h"
50 #include "ir/expressions/newExpression.h"
51 #include "ir/expressions/objectExpression.h"
52 #include "ir/expressions/omittedExpression.h"
53 #include "ir/expressions/sequenceExpression.h"
54 #include "ir/expressions/superExpression.h"
55 #include "ir/expressions/taggedTemplateExpression.h"
56 #include "ir/expressions/templateLiteral.h"
57 #include "ir/expressions/thisExpression.h"
58 #include "ir/expressions/typeofExpression.h"
59 #include "ir/expressions/unaryExpression.h"
60 #include "ir/expressions/updateExpression.h"
61 #include "ir/expressions/yieldExpression.h"
62 #include "ir/statements/blockStatement.h"
63 #include "ir/statements/classDeclaration.h"
64 #include "ir/ts/tsAsExpression.h"
65 #include "ir/ts/tsNonNullExpression.h"
66 #include "ir/validationInfo.h"
67 #include "lexer/lexer.h"
68 #include "lexer/regexp/regexp.h"
69 #include "lexer/token/letters.h"
70 #include "lexer/token/sourceLocation.h"
71 #include "lexer/token/token.h"
72 #include "macros.h"
73 #include "util/errorRecovery.h"
74
75 #include <memory>
76
77 #include "parser/parserStatusContext.h"
78 #include "parserImpl.h"
79
80 namespace ark::es2panda::parser {
ParseYieldExpression()81 ir::YieldExpression *ParserImpl::ParseYieldExpression()
82 {
83 ASSERT(lexer_->GetToken().Type() == lexer::TokenType::KEYW_YIELD);
84
85 lexer::SourcePosition startLoc = lexer_->GetToken().Start();
86 lexer::SourcePosition endLoc = lexer_->GetToken().End();
87
88 if ((lexer_->GetToken().Flags() & lexer::TokenFlags::HAS_ESCAPE) != 0) {
89 LogSyntaxError("Unexpected identifier");
90 }
91
92 lexer_->NextToken();
93
94 bool isDelegate = false;
95 ir::Expression *argument = nullptr;
96
97 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MULTIPLY && !lexer_->GetToken().NewLine()) {
98 isDelegate = true;
99 lexer_->NextToken();
100
101 argument = ParseExpression();
102 if (argument != nullptr) { // Error processing.
103 endLoc = argument->End();
104 }
105 } else if (!lexer_->GetToken().NewLine() && lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE &&
106 lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS &&
107 lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET &&
108 lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COMMA &&
109 lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON &&
110 lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COLON &&
111 lexer_->GetToken().Type() != lexer::TokenType::EOS) {
112 argument = ParseExpression();
113 if (argument != nullptr) { // Error processing.
114 endLoc = argument->End();
115 }
116 }
117
118 auto *yieldNode = AllocNode<ir::YieldExpression>(argument, isDelegate);
119 yieldNode->SetRange({startLoc, endLoc});
120
121 return yieldNode;
122 }
123
ParsePotentialExpressionSequence(ir::Expression * expr,ExpressionParseFlags flags)124 ir::Expression *ParserImpl::ParsePotentialExpressionSequence(ir::Expression *expr, ExpressionParseFlags flags)
125 {
126 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA &&
127 (flags & ExpressionParseFlags::ACCEPT_COMMA) != 0) {
128 return ParseSequenceExpression(expr, (flags & ExpressionParseFlags::ACCEPT_REST) != 0);
129 }
130
131 return expr;
132 }
133
134 // NOLINTNEXTLINE(google-default-arguments)
ParseExpression(ExpressionParseFlags flags)135 ir::Expression *ParserImpl::ParseExpression(ExpressionParseFlags flags)
136 {
137 if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_YIELD &&
138 (flags & ExpressionParseFlags::DISALLOW_YIELD) == 0U) {
139 ir::YieldExpression *yieldExpr = ParseYieldExpression();
140
141 return ParsePotentialExpressionSequence(yieldExpr, flags);
142 }
143
144 ir::Expression *unaryExpressionNode = ParseUnaryOrPrefixUpdateExpression(flags);
145 ir::Expression *assignmentExpression = ParseAssignmentExpression(unaryExpressionNode, flags);
146 if (assignmentExpression == nullptr) { // Error processing.
147 return nullptr;
148 }
149
150 if (lexer_->GetToken().NewLine()) {
151 return assignmentExpression;
152 }
153
154 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA &&
155 (flags & ExpressionParseFlags::ACCEPT_COMMA) != 0U) {
156 return ParseSequenceExpression(assignmentExpression, (flags & ExpressionParseFlags::ACCEPT_REST) != 0U);
157 }
158
159 return assignmentExpression;
160 }
161
ParseArrayExpressionRightBracketHelper(bool containsRest,bool trailingComma,const lexer::SourcePosition & startLoc)162 bool ParserImpl::ParseArrayExpressionRightBracketHelper(bool containsRest, bool trailingComma,
163 const lexer::SourcePosition &startLoc)
164 {
165 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
166 if (containsRest) {
167 LogSyntaxError("Rest element must be last element", startLoc);
168 }
169
170 lexer_->NextToken(); // eat comma
171
172 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
173 return true;
174 }
175
176 return trailingComma;
177 }
178
179 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
180 // array_2.sts
181 LogSyntaxError("Unexpected token, expected ',' or ']'");
182 lexer_->NextToken();
183 if (lexer::Token::IsPunctuatorToken(lexer_->GetToken().Type())) {
184 // [0, 1, 2} -> [0, 1, 2]
185 // the problem is that ["abc". "sss", "aaa"] -> ["abc"] "sss", "aaa"]
186 lexer_->GetToken().SetTokenType(lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET);
187 }
188 // [0 1, 2] -> [0, 1, 2] ; we just skeep the token in this case
189 }
190
191 return trailingComma;
192 }
193
194 // NOLINTNEXTLINE(google-default-arguments)
ParseArrayExpression(ExpressionParseFlags flags)195 ir::ArrayExpression *ParserImpl::ParseArrayExpression(ExpressionParseFlags flags)
196 {
197 lexer::SourcePosition startLoc = lexer_->GetToken().Start();
198
199 ArenaVector<ir::Expression *> elements(Allocator()->Adapter());
200
201 lexer_->NextToken();
202
203 bool trailingComma = false;
204 bool inPattern = (flags & ExpressionParseFlags::MUST_BE_PATTERN) != 0;
205
206 while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET &&
207 lexer_->GetToken().Type() != lexer::TokenType::EOS) {
208 util::ErrorRecursionGuard infiniteLoopBlocker(lexer_);
209
210 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
211 auto *omitted = AllocNode<ir::OmittedExpression>();
212 omitted->SetRange(lexer_->GetToken().Loc());
213 elements.push_back(omitted);
214 lexer_->NextToken();
215 continue;
216 }
217
218 ir::Expression *element {};
219 if (inPattern) {
220 element = ParsePatternElement();
221 } else if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD) {
222 element = ParseSpreadElement(ExpressionParseFlags::POTENTIALLY_IN_PATTERN);
223 } else {
224 element = ParseExpression(ExpressionParseFlags::POTENTIALLY_IN_PATTERN);
225 }
226
227 bool containsRest = false;
228 if (element != nullptr) { // Error processing.
229 containsRest = element->IsRestElement();
230 elements.push_back(element);
231 }
232
233 trailingComma = ParseArrayExpressionRightBracketHelper(containsRest, trailingComma, startLoc);
234 }
235
236 auto nodeType = inPattern ? ir::AstNodeType::ARRAY_PATTERN : ir::AstNodeType::ARRAY_EXPRESSION;
237 auto *arrayExpressionNode =
238 AllocNode<ir::ArrayExpression>(nodeType, std::move(elements), Allocator(), trailingComma);
239 arrayExpressionNode->SetRange({startLoc, lexer_->GetToken().End()});
240 lexer_->NextToken();
241
242 if (inPattern) {
243 arrayExpressionNode->SetDeclaration();
244 }
245
246 ParseArrayExpressionErrorCheck(arrayExpressionNode, flags, inPattern);
247 return arrayExpressionNode;
248 }
249
ParseArrayExpressionErrorCheck(ir::ArrayExpression * arrayExpressionNode,const ExpressionParseFlags flags,const bool inPattern)250 void ParserImpl::ParseArrayExpressionErrorCheck(ir::ArrayExpression *arrayExpressionNode,
251 const ExpressionParseFlags flags, const bool inPattern)
252 {
253 if ((flags & ExpressionParseFlags::POTENTIALLY_IN_PATTERN) == 0) {
254 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION &&
255 !arrayExpressionNode->ConvertibleToArrayPattern()) {
256 LogSyntaxError("Invalid left-hand side in array destructuring pattern", arrayExpressionNode->Start());
257 } else if (!inPattern && lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
258 ir::ValidationInfo info = arrayExpressionNode->ValidateExpression();
259 if (info.Fail()) {
260 LogSyntaxError(info.msg.Utf8(), info.pos);
261 }
262 }
263 }
264 }
265
ValidateArrowParameter(ir::Expression * expr,bool * seenOptional)266 ParserStatus ParserImpl::ValidateArrowParameter(ir::Expression *expr, [[maybe_unused]] bool *seenOptional)
267 {
268 switch (expr->Type()) {
269 case ir::AstNodeType::SPREAD_ELEMENT: {
270 if (!expr->AsSpreadElement()->ConvertibleToRest(true)) {
271 LogSyntaxError("Invalid rest element.");
272 }
273
274 [[fallthrough]];
275 }
276 case ir::AstNodeType::REST_ELEMENT: {
277 ValidateArrowParameterBindings(expr->AsRestElement()->Argument());
278 return ParserStatus::HAS_COMPLEX_PARAM;
279 }
280 case ir::AstNodeType::IDENTIFIER: {
281 ValidateArrowParameterBindings(expr);
282 return ParserStatus::NO_OPTS;
283 }
284 case ir::AstNodeType::OBJECT_EXPRESSION: {
285 if (ir::ObjectExpression *objectPattern = expr->AsObjectExpression();
286 !objectPattern->ConvertibleToObjectPattern()) {
287 LogSyntaxError("Invalid destructuring assignment target");
288 }
289
290 ValidateArrowParameterBindings(expr);
291 return ParserStatus::HAS_COMPLEX_PARAM;
292 }
293 case ir::AstNodeType::ARRAY_EXPRESSION: {
294 if (ir::ArrayExpression *arrayPattern = expr->AsArrayExpression();
295 !arrayPattern->ConvertibleToArrayPattern()) {
296 LogSyntaxError("Invalid destructuring assignment target");
297 }
298
299 ValidateArrowParameterBindings(expr);
300 return ParserStatus::HAS_COMPLEX_PARAM;
301 }
302 case ir::AstNodeType::ASSIGNMENT_EXPRESSION: {
303 ValidateArrowParameterAssignment(expr->AsAssignmentExpression());
304 ValidateArrowParameterBindings(expr);
305 return ParserStatus::HAS_COMPLEX_PARAM;
306 }
307 default: {
308 break;
309 }
310 }
311 LogSyntaxError("Insufficient formal parameter in arrow function.");
312 return ParserStatus::NO_OPTS;
313 }
314
ValidateArrowParameterAssignment(ir::AssignmentExpression * expr)315 void ParserImpl::ValidateArrowParameterAssignment(ir::AssignmentExpression *expr)
316 {
317 if (expr->Right()->IsYieldExpression()) {
318 LogSyntaxError("yield is not allowed in arrow function parameters");
319 } else if (expr->Right()->IsAwaitExpression()) {
320 LogSyntaxError("await is not allowed in arrow function parameters");
321 } else if (!expr->ConvertibleToAssignmentPattern()) {
322 LogSyntaxError("Invalid destructuring assignment target");
323 }
324 }
325
ParseArrowFunctionExpressionBody(ArrowFunctionContext * arrowFunctionContext,ArrowFunctionDescriptor * desc,ir::TSTypeParameterDeclaration * typeParamDecl,ir::TypeNode * returnTypeAnnotation)326 ir::ArrowFunctionExpression *ParserImpl::ParseArrowFunctionExpressionBody(ArrowFunctionContext *arrowFunctionContext,
327 ArrowFunctionDescriptor *desc,
328 ir::TSTypeParameterDeclaration *typeParamDecl,
329 ir::TypeNode *returnTypeAnnotation)
330 {
331 context_.Status() |= desc->newStatus;
332
333 lexer_->NextToken(); // eat '=>'
334 ir::ScriptFunction *funcNode {};
335
336 ir::AstNode *body = nullptr;
337 lexer::SourcePosition endLoc;
338 lexer::SourcePosition bodyStart = lexer_->GetToken().Start();
339
340 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
341 body = ParseExpression();
342 if (body == nullptr) { // Error processing.
343 endLoc = lexer_->GetToken().End();
344 } else {
345 endLoc = body->AsExpression()->End();
346 }
347
348 arrowFunctionContext->AddFlag(ir::ScriptFunctionFlags::EXPRESSION);
349 } else {
350 lexer_->NextToken();
351 auto statements = ParseStatementList();
352 body = AllocNode<ir::BlockStatement>(Allocator(), std::move(statements));
353 body->SetRange({bodyStart, lexer_->GetToken().End()});
354
355 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
356 // This check is redundant since we have ParseStatementList()
357 // It is impossible to leave without eos/} or error.
358 LogExpectedToken(lexer::TokenType::PUNCTUATOR_RIGHT_BRACE);
359 }
360
361 lexer_->NextToken();
362 endLoc = body->End();
363 }
364
365 // clang-format off
366 funcNode = AllocNode<ir::ScriptFunction>(
367 Allocator(), ir::ScriptFunction::ScriptFunctionData {
368 body,
369 ir::FunctionSignature(typeParamDecl, std::move(desc->params), returnTypeAnnotation),
370 arrowFunctionContext->Flags(),
371 {},
372 context_.GetLanguage()});
373 // clang-format on
374 funcNode->SetRange({desc->startLoc, endLoc});
375
376 auto *arrowFuncNode = AllocNode<ir::ArrowFunctionExpression>(funcNode);
377 arrowFuncNode->SetRange(funcNode->Range());
378
379 return arrowFuncNode;
380 }
381
ConvertToArrowParameter(ir::Expression * expr,bool isAsync)382 ArrowFunctionDescriptor ParserImpl::ConvertToArrowParameter(ir::Expression *expr, bool isAsync)
383 {
384 auto arrowStatus = isAsync ? ParserStatus::ASYNC_FUNCTION : ParserStatus::NO_OPTS;
385 ArenaVector<ir::Expression *> params(Allocator()->Adapter());
386
387 if (expr == nullptr) {
388 return ArrowFunctionDescriptor {std::move(params), lexer_->GetToken().Start(), arrowStatus};
389 }
390
391 bool seenOptional = false;
392
393 switch (expr->Type()) {
394 case ir::AstNodeType::REST_ELEMENT:
395 case ir::AstNodeType::IDENTIFIER:
396 case ir::AstNodeType::OBJECT_EXPRESSION:
397 case ir::AstNodeType::ASSIGNMENT_EXPRESSION:
398 case ir::AstNodeType::ARRAY_EXPRESSION: {
399 arrowStatus |= ValidateArrowParameter(expr, &seenOptional);
400
401 params.push_back(expr);
402 break;
403 }
404 case ir::AstNodeType::SEQUENCE_EXPRESSION: {
405 auto &sequence = expr->AsSequenceExpression()->Sequence();
406
407 for (auto *it : sequence) {
408 arrowStatus |= ValidateArrowParameter(it, &seenOptional);
409 }
410
411 params.swap(sequence);
412 break;
413 }
414 case ir::AstNodeType::CALL_EXPRESSION: {
415 if (isAsync) {
416 auto *callExpression = expr->AsCallExpression();
417 auto &arguments = callExpression->Arguments();
418
419 if (callExpression->HasTrailingComma()) {
420 ASSERT(!arguments.empty());
421 LogSyntaxError("Rest parameter must be last formal parameter", arguments.back()->End());
422 }
423
424 for (auto *it : arguments) {
425 arrowStatus |= ValidateArrowParameter(it, &seenOptional);
426 }
427
428 params.swap(arguments);
429 break;
430 }
431
432 [[fallthrough]];
433 }
434 default: {
435 LogSyntaxError("Unexpected token, arrow (=>)");
436 }
437 }
438
439 return ArrowFunctionDescriptor {std::move(params), expr->Start(), arrowStatus};
440 }
441
ParseArrowFunctionExpression(ir::Expression * expr,ir::TSTypeParameterDeclaration * typeParamDecl,ir::TypeNode * returnTypeAnnotation,bool isAsync)442 ir::ArrowFunctionExpression *ParserImpl::ParseArrowFunctionExpression(ir::Expression *expr,
443 ir::TSTypeParameterDeclaration *typeParamDecl,
444 ir::TypeNode *returnTypeAnnotation, bool isAsync)
445 {
446 ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_ARROW);
447
448 if (lexer_->GetToken().NewLine()) {
449 LogSyntaxError(
450 "expected '=>' on the same line after an argument list, "
451 "got line terminator");
452 }
453
454 ArrowFunctionContext arrowFunctionContext(this, isAsync);
455 FunctionParameterContext functionParamContext(&context_);
456 ArrowFunctionDescriptor desc = ConvertToArrowParameter(expr, isAsync);
457
458 return ParseArrowFunctionExpressionBody(&arrowFunctionContext, &desc, typeParamDecl, returnTypeAnnotation);
459 }
460
ValidateArrowFunctionRestParameter(ir::SpreadElement * restElement)461 bool ParserImpl::ValidateArrowFunctionRestParameter([[maybe_unused]] ir::SpreadElement *restElement)
462 {
463 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
464 // unexpected_token_3.js
465 LogSyntaxError("Rest parameter must be the last formal parameter.");
466 return false;
467 }
468
469 return true;
470 }
471
472 // NOLINTNEXTLINE(google-default-arguments)
ParseCoverParenthesizedExpressionAndArrowParameterList(ExpressionParseFlags flags)473 ir::Expression *ParserImpl::ParseCoverParenthesizedExpressionAndArrowParameterList(
474 [[maybe_unused]] ExpressionParseFlags flags) // CC-OFF(G.FMT.06-CPP) project code style
475 {
476 ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS);
477 lexer::SourcePosition start = lexer_->GetToken().Start();
478 lexer_->NextToken();
479
480 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD) {
481 ir::SpreadElement *restElement = ParseSpreadElement(ExpressionParseFlags::MUST_BE_PATTERN);
482 if (restElement != nullptr) { // Error processing.
483 restElement->SetGrouped();
484 restElement->SetStart(start);
485 }
486
487 if (ValidateArrowFunctionRestParameter(restElement)) { // Error processing.
488 lexer_->NextToken();
489 }
490
491 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_ARROW) {
492 // test exists for js extension only
493 LogExpectedToken(lexer::TokenType::PUNCTUATOR_ARROW);
494 }
495
496 return ParseArrowFunctionExpression(restElement, nullptr, nullptr, false);
497 }
498
499 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
500 lexer_->NextToken();
501
502 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_ARROW) {
503 // test exists for js extension only
504 LogExpectedToken(lexer::TokenType::PUNCTUATOR_ARROW);
505 }
506
507 auto *arrowExpr = ParseArrowFunctionExpression(nullptr, nullptr, nullptr, false);
508 arrowExpr->SetStart(start);
509 arrowExpr->AsArrowFunctionExpression()->Function()->SetStart(start);
510
511 return arrowExpr;
512 }
513
514 ir::Expression *expr = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA | ExpressionParseFlags::ACCEPT_REST |
515 ExpressionParseFlags::POTENTIALLY_IN_PATTERN);
516
517 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
518 // test exists for js extension only
519 LogExpectedToken(lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS);
520 }
521
522 if (expr != nullptr) { // Error processing.
523 expr->SetGrouped();
524 expr->SetRange({start, lexer_->GetToken().End()});
525 }
526
527 lexer_->NextToken();
528
529 return expr;
530 }
531
ValidateGroupedExpression(ir::Expression * lhsExpression)532 bool ParserImpl::ValidateGroupedExpression(ir::Expression *lhsExpression)
533 {
534 if (lhsExpression == nullptr) { // Error processing.
535 return false;
536 }
537
538 lexer::TokenType tokenType = lexer_->GetToken().Type();
539 if (lhsExpression->IsGrouped() && tokenType != lexer::TokenType::PUNCTUATOR_ARROW) {
540 if (lhsExpression->IsSequenceExpression()) {
541 for (auto *seq : lhsExpression->AsSequenceExpression()->Sequence()) {
542 ValidateParenthesizedExpression(seq);
543 }
544 } else {
545 ValidateParenthesizedExpression(lhsExpression);
546 }
547 }
548
549 return true;
550 }
551
ValidateParenthesizedExpression(ir::Expression * lhsExpression)552 void ParserImpl::ValidateParenthesizedExpression(ir::Expression *lhsExpression)
553 {
554 switch (lhsExpression->Type()) {
555 case ir::AstNodeType::IDENTIFIER: {
556 auto info = lhsExpression->AsIdentifier()->ValidateExpression();
557 if (info.Fail()) {
558 LogSyntaxError(info.msg.Utf8(), info.pos);
559 }
560 break;
561 }
562 case ir::AstNodeType::MEMBER_EXPRESSION: {
563 break;
564 }
565 case ir::AstNodeType::ARRAY_EXPRESSION: {
566 auto info = lhsExpression->AsArrayExpression()->ValidateExpression();
567 if (info.Fail()) {
568 LogSyntaxError(info.msg.Utf8(), info.pos);
569 }
570 break;
571 }
572 case ir::AstNodeType::OBJECT_EXPRESSION: {
573 auto info = lhsExpression->AsObjectExpression()->ValidateExpression();
574 if (info.Fail()) {
575 LogSyntaxError(info.msg.Utf8(), info.pos);
576 }
577 break;
578 }
579 case ir::AstNodeType::ASSIGNMENT_EXPRESSION: {
580 if (lhsExpression->AsAssignmentExpression()->ConvertibleToAssignmentPattern(false)) {
581 break;
582 }
583 [[fallthrough]];
584 }
585 case ir::AstNodeType::SPREAD_ELEMENT: {
586 LogSyntaxError("Invalid left-hand side in assignment expression");
587 break;
588 }
589 default: {
590 break;
591 }
592 }
593 }
594
ParsePrefixAssertionExpression()595 ir::Expression *ParserImpl::ParsePrefixAssertionExpression()
596 {
597 LogUnexpectedToken(lexer_->GetToken().Type());
598 return nullptr;
599 }
600
ParseAssignmentExpressionHelper()601 ir::Expression *ParserImpl::ParseAssignmentExpressionHelper()
602 {
603 lexer_->NextToken();
604 ir::Expression *consequent = ParseExpression();
605
606 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COLON) {
607 if (lexer::Token::IsPunctuatorToken(lexer_->GetToken().Type())) {
608 // typo happened like ';'
609 // unexpected_token_41.sts - bad test
610 LogExpectedToken(lexer::TokenType::PUNCTUATOR_COLON);
611 lexer_->NextToken(); // eat ':'
612 } else {
613 // just go to the next token if we missed ':'
614 LogSyntaxError("Unexpected token, expected: ':'.");
615 }
616 } else {
617 lexer_->NextToken(); // eat ':'
618 }
619 return consequent;
620 }
621
CreateBinaryAssignmentExpression(ir::Expression * assignmentExpression,ir::Expression * lhsExpression,lexer::TokenType tokenType)622 ir::Expression *ParserImpl::CreateBinaryAssignmentExpression(ir::Expression *assignmentExpression,
623 ir::Expression *lhsExpression, lexer::TokenType tokenType)
624 {
625 if (assignmentExpression == nullptr) { // Error processing.
626 return nullptr;
627 }
628
629 auto *binaryAssignmentExpression =
630 AllocNode<ir::AssignmentExpression>(lhsExpression, assignmentExpression, tokenType);
631
632 binaryAssignmentExpression->SetRange({lhsExpression->Start(), assignmentExpression->End()});
633 return binaryAssignmentExpression;
634 }
635
ParseAssignmentExpression(ir::Expression * lhsExpression,ExpressionParseFlags flags)636 ir::Expression *ParserImpl::ParseAssignmentExpression(ir::Expression *lhsExpression, ExpressionParseFlags flags)
637 {
638 if (!ValidateGroupedExpression(lhsExpression)) {
639 return nullptr; // Error processing.
640 }
641
642 lexer::TokenType tokenType = lexer_->GetToken().Type();
643 switch (tokenType) {
644 case lexer::TokenType::PUNCTUATOR_QUESTION_MARK: {
645 ir::Expression *consequent = ParseAssignmentExpressionHelper();
646
647 ir::Expression *alternate = ParseExpression();
648 if (consequent == nullptr || alternate == nullptr) { // Error processing.
649 return nullptr;
650 }
651
652 auto *conditionalExpr = AllocNode<ir::ConditionalExpression>(lhsExpression, consequent, alternate);
653 conditionalExpr->SetRange({lhsExpression->Start(), alternate->End()});
654 return conditionalExpr;
655 }
656 case lexer::TokenType::PUNCTUATOR_ARROW:
657 if (lexer_->GetToken().NewLine()) {
658 LogSyntaxError("Uncaught SyntaxError: expected expression, got '=>'");
659 }
660
661 return ParseArrowFunctionExpression(lhsExpression, nullptr, nullptr, false);
662 case lexer::TokenType::PUNCTUATOR_SUBSTITUTION: {
663 ValidateAssignmentTarget(flags, lhsExpression);
664
665 lexer_->NextToken();
666 ir::Expression *assignmentExpression = ParseExpression(CarryPatternFlags(flags));
667 return CreateBinaryAssignmentExpression(assignmentExpression, lhsExpression, tokenType);
668 }
669 case lexer::TokenType::KEYW_AS:
670 if (auto asExpression = ParsePotentialAsExpression(lhsExpression); asExpression != nullptr) {
671 return ParseAssignmentExpression(asExpression);
672 }
673 break;
674 default: {
675 auto expression = ParseAssignmentBinaryExpression(tokenType, lhsExpression, flags);
676 if (expression == nullptr) {
677 expression = ParseAssignmentEqualExpression(tokenType, lhsExpression, flags);
678 }
679
680 if (expression != nullptr) {
681 return expression;
682 }
683
684 break;
685 }
686 }
687
688 return lhsExpression;
689 }
690
ParseAssignmentBinaryExpression(const lexer::TokenType tokenType,ir::Expression * lhsExpression,const ExpressionParseFlags flags)691 ir::Expression *ParserImpl::ParseAssignmentBinaryExpression(const lexer::TokenType tokenType,
692 ir::Expression *lhsExpression,
693 const ExpressionParseFlags flags)
694 {
695 switch (tokenType) {
696 case lexer::TokenType::KEYW_IN: {
697 if ((flags & ExpressionParseFlags::STOP_AT_IN) != 0) {
698 break;
699 }
700
701 [[fallthrough]];
702 }
703 case lexer::TokenType::PUNCTUATOR_NULLISH_COALESCING:
704 case lexer::TokenType::PUNCTUATOR_LOGICAL_OR:
705 case lexer::TokenType::PUNCTUATOR_LOGICAL_AND:
706 case lexer::TokenType::PUNCTUATOR_BITWISE_OR:
707 case lexer::TokenType::PUNCTUATOR_BITWISE_XOR:
708 case lexer::TokenType::PUNCTUATOR_BITWISE_AND:
709 case lexer::TokenType::PUNCTUATOR_EQUAL:
710 case lexer::TokenType::PUNCTUATOR_NOT_EQUAL:
711 case lexer::TokenType::PUNCTUATOR_STRICT_EQUAL:
712 case lexer::TokenType::PUNCTUATOR_NOT_STRICT_EQUAL:
713 case lexer::TokenType::PUNCTUATOR_LESS_THAN:
714 case lexer::TokenType::PUNCTUATOR_LESS_THAN_EQUAL:
715 case lexer::TokenType::PUNCTUATOR_GREATER_THAN:
716 case lexer::TokenType::PUNCTUATOR_GREATER_THAN_EQUAL:
717 case lexer::TokenType::PUNCTUATOR_LEFT_SHIFT:
718 case lexer::TokenType::PUNCTUATOR_RIGHT_SHIFT:
719 case lexer::TokenType::PUNCTUATOR_UNSIGNED_RIGHT_SHIFT:
720 case lexer::TokenType::PUNCTUATOR_PLUS:
721 case lexer::TokenType::PUNCTUATOR_MINUS:
722 case lexer::TokenType::PUNCTUATOR_MULTIPLY:
723 case lexer::TokenType::PUNCTUATOR_DIVIDE:
724 case lexer::TokenType::PUNCTUATOR_MOD:
725 case lexer::TokenType::KEYW_INSTANCEOF:
726 case lexer::TokenType::PUNCTUATOR_EXPONENTIATION: {
727 return ParseAssignmentExpression(ParseBinaryExpression(lhsExpression));
728 }
729 default:
730 break;
731 }
732
733 return nullptr;
734 }
735
ParseAssignmentEqualExpression(const lexer::TokenType tokenType,ir::Expression * lhsExpression,const ExpressionParseFlags flags)736 ir::Expression *ParserImpl::ParseAssignmentEqualExpression(const lexer::TokenType tokenType,
737 ir::Expression *lhsExpression,
738 const ExpressionParseFlags flags)
739 {
740 switch (tokenType) {
741 case lexer::TokenType::PUNCTUATOR_UNSIGNED_RIGHT_SHIFT_EQUAL:
742 case lexer::TokenType::PUNCTUATOR_RIGHT_SHIFT_EQUAL:
743 case lexer::TokenType::PUNCTUATOR_LEFT_SHIFT_EQUAL:
744 case lexer::TokenType::PUNCTUATOR_PLUS_EQUAL:
745 case lexer::TokenType::PUNCTUATOR_MINUS_EQUAL:
746 case lexer::TokenType::PUNCTUATOR_MULTIPLY_EQUAL:
747 case lexer::TokenType::PUNCTUATOR_DIVIDE_EQUAL:
748 case lexer::TokenType::PUNCTUATOR_MOD_EQUAL:
749 case lexer::TokenType::PUNCTUATOR_BITWISE_AND_EQUAL:
750 case lexer::TokenType::PUNCTUATOR_BITWISE_OR_EQUAL:
751 case lexer::TokenType::PUNCTUATOR_BITWISE_XOR_EQUAL:
752 case lexer::TokenType::PUNCTUATOR_EXPONENTIATION_EQUAL: {
753 ValidateLvalueAssignmentTarget(lhsExpression);
754
755 lexer_->NextToken();
756 ir::Expression *assignmentExpression = ParseExpression(CarryPatternFlags(flags));
757
758 auto *binaryAssignmentExpression =
759 AllocNode<ir::AssignmentExpression>(lhsExpression, assignmentExpression, tokenType);
760
761 binaryAssignmentExpression->SetRange({lhsExpression->Start(), assignmentExpression->End()});
762 return binaryAssignmentExpression;
763 }
764 case lexer::TokenType::PUNCTUATOR_LOGICAL_AND_EQUAL:
765 case lexer::TokenType::PUNCTUATOR_LOGICAL_OR_EQUAL:
766 case lexer::TokenType::PUNCTUATOR_LOGICAL_NULLISH_EQUAL: {
767 LogUnexpectedToken(tokenType);
768 lexer_->NextToken(); // eat token
769 ParseExpression(); // Try to parse expression, but skip the result.
770 }
771 default:
772 break;
773 }
774
775 return nullptr;
776 }
777
ParseTemplateLiteral()778 ir::TemplateLiteral *ParserImpl::ParseTemplateLiteral()
779 {
780 lexer::SourcePosition startLoc = lexer_->GetToken().Start();
781
782 ArenaVector<ir::TemplateElement *> quasis(Allocator()->Adapter());
783 ArenaVector<ir::Expression *> expressions(Allocator()->Adapter());
784
785 while (true) {
786 lexer_->ResetTokenEnd();
787 const auto startPos = lexer_->Save();
788 lexer_->ScanString<lexer::LEX_CHAR_BACK_TICK>();
789 const util::StringView cooked = lexer_->GetToken().String();
790 lexer_->Rewind(startPos);
791
792 const auto templateStr = lexer_->ScanTemplateString();
793 if (templateStr.validSequence) {
794 auto *const element = AllocNode<ir::TemplateElement>(templateStr.str.View(), cooked);
795 element->SetRange({lexer::SourcePosition {startPos.Iterator().Index(), startPos.Line()},
796 lexer::SourcePosition {templateStr.end, lexer_->Line()}});
797 quasis.push_back(element);
798 }
799
800 if (!templateStr.scanExpression) {
801 lexer_->ScanTemplateStringEnd();
802 break;
803 }
804
805 ir::Expression *expression = nullptr;
806
807 {
808 lexer::TemplateLiteralParserContext ctx(lexer_);
809 lexer_->PushTemplateContext(&ctx);
810 lexer_->NextToken();
811 expression = ParseExpression();
812 }
813
814 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
815 LogExpectedToken(lexer::TokenType::PUNCTUATOR_RIGHT_BRACE);
816 }
817
818 if (expression != nullptr) { // Error processing.
819 expressions.push_back(expression);
820 }
821 }
822
823 auto *templateNode = AllocNode<ir::TemplateLiteral>(std::move(quasis), std::move(expressions));
824 templateNode->SetRange({startLoc, lexer_->GetToken().End()});
825
826 lexer_->NextToken();
827
828 return templateNode;
829 }
830
ParseNewExpression()831 ir::Expression *ParserImpl::ParseNewExpression()
832 {
833 lexer::SourcePosition start = lexer_->GetToken().Start();
834
835 lexer_->NextToken(); // eat new
836
837 // parse callee part of NewExpression
838 ir::Expression *callee = ParseMemberExpression(true);
839 if (callee == nullptr) { // Error processing.
840 return nullptr;
841 }
842
843 if (callee->IsImportExpression() && !callee->IsGrouped()) {
844 LogSyntaxError("Cannot use new with import(...)");
845 }
846
847 ArenaVector<ir::Expression *> arguments(Allocator()->Adapter());
848
849 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
850 lexer::SourcePosition endLoc = callee->End();
851 auto *newExprNode = AllocNode<ir::NewExpression>(callee, std::move(arguments));
852 newExprNode->SetRange({start, endLoc});
853
854 return newExprNode;
855 }
856
857 lexer_->NextToken(); // eat left parenthesis
858
859 // parse argument part of NewExpression
860 while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
861 util::ErrorRecursionGuard infiniteLoopBlocker(lexer_);
862 ir::Expression *argument = nullptr;
863
864 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD) {
865 argument = ParseSpreadElement();
866 } else {
867 argument = ParseExpression();
868 }
869
870 if (argument != nullptr) { // Error processing.
871 arguments.push_back(argument);
872 }
873
874 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
875 lexer_->NextToken(); // eat comma
876 }
877
878 if (lexer_->GetToken().Type() == lexer::TokenType::EOS) {
879 LogSyntaxError("Unexpected token in argument parsing");
880 break; // All tokens may be exhausted.
881 }
882 }
883
884 auto *newExprNode = AllocNode<ir::NewExpression>(callee, std::move(arguments));
885 newExprNode->SetRange({start, lexer_->GetToken().End()});
886
887 lexer_->NextToken();
888
889 return newExprNode;
890 }
891
ParseLeftHandSideExpression(ExpressionParseFlags flags)892 ir::Expression *ParserImpl::ParseLeftHandSideExpression(ExpressionParseFlags flags)
893 {
894 return ParseMemberExpression(false, flags);
895 }
896
ParsePotentialNewTarget()897 ir::MetaProperty *ParserImpl::ParsePotentialNewTarget()
898 {
899 lexer::SourceRange loc = lexer_->GetToken().Loc();
900
901 if (lexer_->Lookahead() == lexer::LEX_CHAR_DOT) {
902 lexer_->NextToken();
903 lexer_->NextToken();
904
905 if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_TARGET) {
906 if ((context_.Status() & ParserStatus::ALLOW_NEW_TARGET) == 0) {
907 LogSyntaxError("'new.Target' is not allowed here");
908 }
909
910 if ((lexer_->GetToken().Flags() & lexer::TokenFlags::HAS_ESCAPE) != 0) {
911 LogSyntaxError("'new.Target' must not contain escaped characters");
912 }
913
914 auto *metaProperty = AllocNode<ir::MetaProperty>(ir::MetaProperty::MetaPropertyKind::NEW_TARGET);
915 metaProperty->SetRange(loc);
916 lexer_->NextToken();
917 return metaProperty;
918 }
919 }
920
921 return nullptr;
922 }
923
ParsePrimaryExpressionIdent(ExpressionParseFlags flags)924 ir::Identifier *ParserImpl::ParsePrimaryExpressionIdent([[maybe_unused]] ExpressionParseFlags flags)
925 {
926 auto *identNode = AllocNode<ir::Identifier>(lexer_->GetToken().Ident(), Allocator());
927 identNode->SetRange(lexer_->GetToken().Loc());
928
929 lexer_->NextToken();
930 return identNode;
931 }
932
ParseBooleanLiteral()933 ir::BooleanLiteral *ParserImpl::ParseBooleanLiteral()
934 {
935 ASSERT(lexer_->GetToken().Type() == lexer::TokenType::LITERAL_TRUE ||
936 lexer_->GetToken().Type() == lexer::TokenType::LITERAL_FALSE);
937
938 auto *booleanNode = AllocNode<ir::BooleanLiteral>(lexer_->GetToken().Type() == lexer::TokenType::LITERAL_TRUE);
939 booleanNode->SetRange(lexer_->GetToken().Loc());
940
941 lexer_->NextToken();
942 return booleanNode;
943 }
944
ParseNullLiteral()945 ir::NullLiteral *ParserImpl::ParseNullLiteral()
946 {
947 ASSERT(lexer_->GetToken().Type() == lexer::TokenType::LITERAL_NULL);
948 auto *nullNode = AllocNode<ir::NullLiteral>();
949 nullNode->SetRange(lexer_->GetToken().Loc());
950
951 lexer_->NextToken();
952 return nullNode;
953 }
954
ParseNumberLiteral()955 ir::Literal *ParserImpl::ParseNumberLiteral()
956 {
957 ASSERT(lexer_->GetToken().Type() == lexer::TokenType::LITERAL_NUMBER);
958
959 ir::Literal *numberNode {};
960
961 if ((lexer_->GetToken().Flags() & lexer::TokenFlags::NUMBER_BIGINT) != 0U) {
962 numberNode = AllocNode<ir::BigIntLiteral>(lexer_->GetToken().BigInt());
963 } else {
964 numberNode = AllocNode<ir::NumberLiteral>(lexer_->GetToken().GetNumber());
965 }
966
967 numberNode->SetRange(lexer_->GetToken().Loc());
968
969 lexer_->NextToken();
970 return numberNode;
971 }
972
ParseCharLiteral()973 ir::CharLiteral *ParserImpl::ParseCharLiteral()
974 {
975 ASSERT(lexer_->GetToken().Type() == lexer::TokenType::LITERAL_CHAR);
976
977 auto *charNode = AllocNode<ir::CharLiteral>(lexer_->GetToken().Utf16());
978 charNode->SetRange(lexer_->GetToken().Loc());
979
980 lexer_->NextToken();
981 return charNode;
982 }
983
ParseStringLiteral()984 ir::StringLiteral *ParserImpl::ParseStringLiteral()
985 {
986 ASSERT(lexer_->GetToken().Type() == lexer::TokenType::LITERAL_STRING);
987
988 auto *stringNode = AllocNode<ir::StringLiteral>(lexer_->GetToken().String());
989 stringNode->SetRange(lexer_->GetToken().Loc());
990
991 lexer_->NextToken();
992 return stringNode;
993 }
994
ParseUndefinedLiteral()995 ir::UndefinedLiteral *ParserImpl::ParseUndefinedLiteral()
996 {
997 ASSERT(lexer_->GetToken().Type() == lexer::TokenType::KEYW_UNDEFINED);
998 auto *undefinedNode = AllocNode<ir::UndefinedLiteral>();
999 undefinedNode->SetRange(lexer_->GetToken().Loc());
1000
1001 lexer_->NextToken();
1002 return undefinedNode;
1003 }
1004
ParseThisExpression()1005 ir::ThisExpression *ParserImpl::ParseThisExpression()
1006 {
1007 ASSERT(lexer_->GetToken().Type() == lexer::TokenType::KEYW_THIS);
1008
1009 auto *thisExprNode = AllocNode<ir::ThisExpression>();
1010 thisExprNode->SetRange(lexer_->GetToken().Loc());
1011
1012 lexer_->NextToken();
1013 return thisExprNode;
1014 }
1015
ParseRegularExpression()1016 ir::RegExpLiteral *ParserImpl::ParseRegularExpression()
1017 {
1018 ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_DIVIDE ||
1019 lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_DIVIDE_EQUAL);
1020
1021 lexer_->ResetTokenEnd();
1022 auto regexp = lexer_->ScanRegExp();
1023
1024 lexer::RegExpParser reParser(regexp, Allocator(), *this);
1025
1026 reParser.ParsePattern();
1027
1028 auto *regexpNode = AllocNode<ir::RegExpLiteral>(regexp.patternStr, regexp.flags, regexp.flagsStr);
1029 regexpNode->SetRange(lexer_->GetToken().Loc());
1030
1031 lexer_->NextToken();
1032 return regexpNode;
1033 }
1034
ParseSuperExpression()1035 ir::SuperExpression *ParserImpl::ParseSuperExpression()
1036 {
1037 ASSERT(lexer_->GetToken().Type() == lexer::TokenType::KEYW_SUPER);
1038
1039 auto *superExprNode = AllocNode<ir::SuperExpression>();
1040 superExprNode->SetRange(lexer_->GetToken().Loc());
1041
1042 lexer_->NextToken(); // eat super
1043
1044 if ((lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD ||
1045 lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET) &&
1046 (context_.Status() & ParserStatus::ALLOW_SUPER) != 0U) {
1047 return superExprNode;
1048 }
1049
1050 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS &&
1051 (context_.Status() & ParserStatus::ALLOW_SUPER_CALL) != 0U) {
1052 return superExprNode;
1053 }
1054
1055 LogSyntaxError("Unexpected super keyword");
1056 return superExprNode;
1057 }
1058
ParsePrimaryExpressionWithLiterals(ExpressionParseFlags flags)1059 ir::Expression *ParserImpl::ParsePrimaryExpressionWithLiterals(ExpressionParseFlags flags)
1060 {
1061 switch (lexer_->GetToken().Type()) {
1062 case lexer::TokenType::LITERAL_IDENT: {
1063 return ParsePrimaryExpressionIdent(flags);
1064 }
1065 case lexer::TokenType::LITERAL_TRUE:
1066 case lexer::TokenType::LITERAL_FALSE: {
1067 return ParseBooleanLiteral();
1068 }
1069 case lexer::TokenType::LITERAL_NULL: {
1070 return ParseNullLiteral();
1071 }
1072 case lexer::TokenType::KEYW_UNDEFINED: {
1073 return ParseUndefinedLiteral();
1074 }
1075 case lexer::TokenType::LITERAL_NUMBER: {
1076 return ParseNumberLiteral();
1077 }
1078 case lexer::TokenType::LITERAL_STRING: {
1079 return ParseStringLiteral();
1080 }
1081 default: {
1082 break;
1083 }
1084 }
1085
1086 LogUnexpectedToken(lexer_->GetToken().Type());
1087 return nullptr;
1088 }
1089
ParseHashMaskOperator()1090 ir::Expression *ParserImpl::ParseHashMaskOperator()
1091 {
1092 if (!ValidatePrivateIdentifier()) { // Error processing.
1093 return nullptr;
1094 }
1095
1096 auto *privateIdent = AllocNode<ir::Identifier>(lexer_->GetToken().Ident(), Allocator());
1097 privateIdent->SetPrivate(true);
1098 lexer_->NextToken();
1099
1100 if (lexer_->GetToken().Type() != lexer::TokenType::KEYW_IN) {
1101 LogSyntaxError("Unexpected private identifier");
1102 lexer_->GetToken().SetTokenType(lexer::TokenType::KEYW_IN);
1103 }
1104
1105 return privateIdent;
1106 }
1107
ParseClassExpression()1108 ir::Expression *ParserImpl::ParseClassExpression()
1109 {
1110 lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1111 ir::ClassDefinition *classDefinition = ParseClassDefinition(ir::ClassDefinitionModifiers::ID_REQUIRED);
1112
1113 auto *classExpr = AllocNode<ir::ClassExpression>(classDefinition);
1114 classExpr->SetRange({startLoc, classDefinition->End()});
1115
1116 return classExpr;
1117 }
1118
ParsePunctuators(ExpressionParseFlags flags)1119 ir::Expression *ParserImpl::ParsePunctuators(ExpressionParseFlags flags)
1120 {
1121 switch (lexer_->GetToken().Type()) {
1122 case lexer::TokenType::PUNCTUATOR_DIVIDE:
1123 case lexer::TokenType::PUNCTUATOR_DIVIDE_EQUAL: {
1124 return ParseRegularExpression();
1125 }
1126 case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET: {
1127 return ParseArrayExpression(CarryPatternFlags(flags));
1128 }
1129 case lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS: {
1130 return ParseCoverParenthesizedExpressionAndArrowParameterList();
1131 }
1132 case lexer::TokenType::PUNCTUATOR_LEFT_BRACE: {
1133 return ParseObjectExpression(CarryPatternFlags(flags));
1134 }
1135 case lexer::TokenType::PUNCTUATOR_BACK_TICK: {
1136 return ParseTemplateLiteral();
1137 }
1138 case lexer::TokenType::PUNCTUATOR_HASH_MARK: {
1139 return ParseHashMaskOperator();
1140 }
1141 case lexer::TokenType::PUNCTUATOR_LESS_THAN: {
1142 return ParsePrefixAssertionExpression();
1143 }
1144 default: {
1145 UNREACHABLE();
1146 }
1147 }
1148 return nullptr;
1149 }
1150
1151 // NOLINTNEXTLINE(google-default-arguments)
ParsePrimaryExpression(ExpressionParseFlags flags)1152 ir::Expression *ParserImpl::ParsePrimaryExpression(ExpressionParseFlags flags)
1153 {
1154 switch (lexer_->GetToken().Type()) {
1155 case lexer::TokenType::KEYW_IMPORT: {
1156 return ParseImportExpression();
1157 }
1158 case lexer::TokenType::PUNCTUATOR_DIVIDE:
1159 case lexer::TokenType::PUNCTUATOR_DIVIDE_EQUAL:
1160 case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET:
1161 case lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS:
1162 case lexer::TokenType::PUNCTUATOR_LEFT_BRACE:
1163 case lexer::TokenType::PUNCTUATOR_BACK_TICK:
1164 case lexer::TokenType::PUNCTUATOR_HASH_MARK:
1165 case lexer::TokenType::PUNCTUATOR_LESS_THAN: {
1166 return ParsePunctuators(flags);
1167 }
1168 case lexer::TokenType::KEYW_FUNCTION: {
1169 return ParseFunctionExpression();
1170 }
1171 case lexer::TokenType::KEYW_CLASS: {
1172 return ParseClassExpression();
1173 }
1174 case lexer::TokenType::KEYW_THIS: {
1175 return ParseThisExpression();
1176 }
1177 case lexer::TokenType::KEYW_TYPEOF: {
1178 return ParseUnaryOrPrefixUpdateExpression();
1179 }
1180 case lexer::TokenType::KEYW_SUPER: {
1181 return ParseSuperExpression();
1182 }
1183 case lexer::TokenType::KEYW_NEW: {
1184 ir::MetaProperty *newTarget = ParsePotentialNewTarget();
1185
1186 if (newTarget != nullptr) {
1187 return newTarget;
1188 }
1189
1190 return ParseNewExpression();
1191 }
1192 default: {
1193 break;
1194 }
1195 }
1196
1197 return ParsePrimaryExpressionWithLiterals(flags);
1198 }
1199
GetOperatorPrecedenceArithmeticAndComparison(const lexer::TokenType operatorType)1200 static constexpr size_t GetOperatorPrecedenceArithmeticAndComparison(const lexer::TokenType operatorType)
1201 {
1202 switch (operatorType) {
1203 case lexer::TokenType::PUNCTUATOR_EQUAL:
1204 case lexer::TokenType::PUNCTUATOR_NOT_EQUAL:
1205 case lexer::TokenType::PUNCTUATOR_STRICT_EQUAL:
1206 case lexer::TokenType::PUNCTUATOR_NOT_STRICT_EQUAL: {
1207 constexpr auto PRECEDENCE = 8;
1208 return PRECEDENCE;
1209 }
1210 case lexer::TokenType::PUNCTUATOR_LESS_THAN:
1211 case lexer::TokenType::PUNCTUATOR_LESS_THAN_EQUAL:
1212 case lexer::TokenType::PUNCTUATOR_GREATER_THAN:
1213 case lexer::TokenType::PUNCTUATOR_GREATER_THAN_EQUAL:
1214 case lexer::TokenType::KEYW_INSTANCEOF:
1215 case lexer::TokenType::KEYW_IN: {
1216 constexpr auto PRECEDENCE = 9;
1217 return PRECEDENCE;
1218 }
1219 case lexer::TokenType::PUNCTUATOR_PLUS:
1220 case lexer::TokenType::PUNCTUATOR_MINUS: {
1221 constexpr auto PRECEDENCE = 12;
1222 return PRECEDENCE;
1223 }
1224 case lexer::TokenType::PUNCTUATOR_MULTIPLY:
1225 case lexer::TokenType::PUNCTUATOR_DIVIDE:
1226 case lexer::TokenType::PUNCTUATOR_MOD: {
1227 constexpr auto PRECEDENCE = 13;
1228 return PRECEDENCE;
1229 }
1230 default: {
1231 UNREACHABLE();
1232 }
1233 }
1234 }
1235
GetOperatorPrecedence(const lexer::TokenType operatorType)1236 static constexpr size_t GetOperatorPrecedence(const lexer::TokenType operatorType)
1237 {
1238 ASSERT(operatorType == lexer::TokenType::KEYW_AS || lexer::Token::IsBinaryToken(operatorType));
1239
1240 switch (operatorType) {
1241 case lexer::TokenType::PUNCTUATOR_NULLISH_COALESCING: {
1242 constexpr auto PRECEDENCE = 1;
1243 return PRECEDENCE;
1244 }
1245 case lexer::TokenType::PUNCTUATOR_LOGICAL_OR: {
1246 constexpr auto PRECEDENCE = 2;
1247 return PRECEDENCE;
1248 }
1249 case lexer::TokenType::PUNCTUATOR_LOGICAL_AND: {
1250 constexpr auto PRECEDENCE = 4;
1251 return PRECEDENCE;
1252 }
1253 case lexer::TokenType::PUNCTUATOR_BITWISE_OR: {
1254 constexpr auto PRECEDENCE = 5;
1255 return PRECEDENCE;
1256 }
1257 case lexer::TokenType::PUNCTUATOR_BITWISE_XOR: {
1258 constexpr auto PRECEDENCE = 6;
1259 return PRECEDENCE;
1260 }
1261 case lexer::TokenType::PUNCTUATOR_BITWISE_AND: {
1262 constexpr auto PRECEDENCE = 7;
1263 return PRECEDENCE;
1264 }
1265 case lexer::TokenType::PUNCTUATOR_LEFT_SHIFT:
1266 case lexer::TokenType::PUNCTUATOR_RIGHT_SHIFT:
1267 case lexer::TokenType::PUNCTUATOR_UNSIGNED_RIGHT_SHIFT: {
1268 constexpr auto PRECEDENCE = 10;
1269 return PRECEDENCE;
1270 }
1271 case lexer::TokenType::KEYW_AS: {
1272 constexpr auto PRECEDENCE = 11;
1273 return PRECEDENCE;
1274 }
1275 case lexer::TokenType::PUNCTUATOR_EXPONENTIATION: {
1276 constexpr auto PRECEDENCE = 14;
1277 return PRECEDENCE;
1278 }
1279 default: {
1280 return GetOperatorPrecedenceArithmeticAndComparison(operatorType);
1281 }
1282 }
1283 }
1284
ShouldBinaryExpressionBeAmended(const ir::BinaryExpression * const binaryExpression,const lexer::TokenType operatorType)1285 static inline bool ShouldBinaryExpressionBeAmended(const ir::BinaryExpression *const binaryExpression,
1286 const lexer::TokenType operatorType)
1287 {
1288 return GetOperatorPrecedence(binaryExpression->OperatorType()) <= GetOperatorPrecedence(operatorType) &&
1289 !binaryExpression->IsGrouped() &&
1290 (operatorType != lexer::TokenType::PUNCTUATOR_EXPONENTIATION ||
1291 binaryExpression->OperatorType() != lexer::TokenType::PUNCTUATOR_EXPONENTIATION);
1292 }
1293
ShouldAsExpressionBeAmended(const ir::TSAsExpression * const asExpression,const lexer::TokenType operatorType)1294 static inline bool ShouldAsExpressionBeAmended(const ir::TSAsExpression *const asExpression,
1295 const lexer::TokenType operatorType)
1296 {
1297 return GetOperatorPrecedence(lexer::TokenType::KEYW_AS) <= GetOperatorPrecedence(operatorType) &&
1298 !asExpression->IsGrouped() && operatorType != lexer::TokenType::PUNCTUATOR_EXPONENTIATION;
1299 }
1300
ShouldExpressionBeAmended(const ir::Expression * const expression,const lexer::TokenType operatorType)1301 static inline bool ShouldExpressionBeAmended(const ir::Expression *const expression,
1302 const lexer::TokenType operatorType)
1303 {
1304 bool shouldBeAmended = false;
1305
1306 if (expression->IsBinaryExpression()) {
1307 shouldBeAmended = ShouldBinaryExpressionBeAmended(expression->AsBinaryExpression(), operatorType);
1308 } else if (expression->IsTSAsExpression()) {
1309 shouldBeAmended = ShouldAsExpressionBeAmended(expression->AsTSAsExpression(), operatorType);
1310 }
1311
1312 return shouldBeAmended;
1313 }
1314
AreLogicalAndNullishMixedIncorrectly(const ir::Expression * const expression,const lexer::TokenType operatorType)1315 static inline bool AreLogicalAndNullishMixedIncorrectly(const ir::Expression *const expression,
1316 const lexer::TokenType operatorType)
1317 {
1318 return ((operatorType == lexer::TokenType::PUNCTUATOR_LOGICAL_OR ||
1319 operatorType == lexer::TokenType::PUNCTUATOR_LOGICAL_AND) &&
1320 expression->IsBinaryExpression() &&
1321 expression->AsBinaryExpression()->OperatorType() == lexer::TokenType::PUNCTUATOR_NULLISH_COALESCING &&
1322 !expression->IsGrouped()) ||
1323 (operatorType == lexer::TokenType::PUNCTUATOR_NULLISH_COALESCING && expression->IsBinaryExpression() &&
1324 (expression->AsBinaryExpression()->OperatorType() == lexer::TokenType::PUNCTUATOR_LOGICAL_OR ||
1325 expression->AsBinaryExpression()->OperatorType() == lexer::TokenType::PUNCTUATOR_LOGICAL_AND) &&
1326 !expression->IsGrouped());
1327 }
1328
GetAmendedChildExpression(ir::Expression * const expression)1329 static inline ir::Expression *GetAmendedChildExpression(ir::Expression *const expression)
1330 {
1331 ir::Expression *amendedChild = nullptr;
1332
1333 if (expression->IsBinaryExpression()) {
1334 amendedChild = expression->AsBinaryExpression()->Left();
1335 } else if (expression->IsTSAsExpression()) {
1336 amendedChild = expression->AsTSAsExpression()->Expr();
1337 } else {
1338 UNREACHABLE();
1339 }
1340
1341 return amendedChild;
1342 }
1343
SetAmendedChildExpression(ir::Expression * const parent,ir::Expression * const amended)1344 static inline void SetAmendedChildExpression(ir::Expression *const parent, ir::Expression *const amended)
1345 {
1346 if (parent->IsBinaryExpression()) {
1347 parent->AsBinaryExpression()->SetLeft(amended);
1348 amended->SetParent(parent);
1349 } else if (parent->IsTSAsExpression()) {
1350 parent->AsTSAsExpression()->SetExpr(amended);
1351 amended->SetParent(parent);
1352 } else {
1353 UNREACHABLE();
1354 }
1355 }
1356
CreateAmendedBinaryExpression(ir::Expression * const left,ir::Expression * const right,const lexer::TokenType operatorType)1357 void ParserImpl::CreateAmendedBinaryExpression(ir::Expression *const left, ir::Expression *const right,
1358 const lexer::TokenType operatorType)
1359 {
1360 auto *amended = GetAmendedChildExpression(right);
1361
1362 amended->SetParent(nullptr); // Next line overwrite parent
1363 auto *binaryExpr = AllocNode<ir::BinaryExpression>(left, amended, operatorType);
1364
1365 binaryExpr->SetRange({left->Start(), amended->End()});
1366 SetAmendedChildExpression(right, binaryExpr);
1367 }
1368
ParseExpressionOrTypeAnnotation(lexer::TokenType type,ExpressionParseFlags flags)1369 ir::Expression *ParserImpl::ParseExpressionOrTypeAnnotation([[maybe_unused]] lexer::TokenType type,
1370 [[maybe_unused]] ExpressionParseFlags flags)
1371 {
1372 return ParseExpression(ExpressionParseFlags::DISALLOW_YIELD);
1373 }
1374
FindAndAmendChildExpression(ir::Expression * expression,const ir::Expression * left,lexer::TokenType operatorType)1375 static ir::Expression *FindAndAmendChildExpression(ir::Expression *expression, const ir::Expression *left,
1376 lexer::TokenType operatorType)
1377 {
1378 bool shouldBeAmended = true;
1379 ir::Expression *parentExpression = nullptr;
1380 while (shouldBeAmended && GetAmendedChildExpression(expression)->IsBinaryExpression()) {
1381 parentExpression = expression;
1382 parentExpression->SetStart(left->Start());
1383
1384 expression = GetAmendedChildExpression(expression);
1385 shouldBeAmended = ShouldExpressionBeAmended(expression, operatorType);
1386 }
1387
1388 return shouldBeAmended ? expression : parentExpression;
1389 }
1390
ParseBinaryExpression(ir::Expression * left,ExpressionParseFlags flags)1391 ir::Expression *ParserImpl::ParseBinaryExpression(ir::Expression *left, ExpressionParseFlags flags)
1392 {
1393 lexer::TokenType operatorType = lexer_->GetToken().Type();
1394 ASSERT(lexer::Token::IsBinaryToken(operatorType));
1395
1396 if (operatorType == lexer::TokenType::PUNCTUATOR_EXPONENTIATION) {
1397 if ((left->IsUnaryExpression() || left->IsTypeofExpression()) && !left->IsGrouped()) {
1398 LogSyntaxError(
1399 "Illegal expression. Wrap left hand side or entire "
1400 "exponentiation in parentheses.");
1401 }
1402 }
1403
1404 lexer_->NextToken();
1405
1406 ExpressionParseFlags newFlags = ExpressionParseFlags::DISALLOW_YIELD;
1407 if ((operatorType == lexer::TokenType::KEYW_INSTANCEOF) || ((flags & ExpressionParseFlags::INSTANCEOF) != 0)) {
1408 newFlags |= ExpressionParseFlags::INSTANCEOF;
1409 }
1410
1411 ir::Expression *rightExpr = ParseExpressionOrTypeAnnotation(operatorType, ExpressionParseFlags::DISALLOW_YIELD);
1412 ir::ConditionalExpression *conditionalExpr = nullptr;
1413 if (rightExpr == nullptr) { // Error processing.
1414 return nullptr;
1415 }
1416
1417 if (rightExpr->IsConditionalExpression() && !rightExpr->IsGrouped()) {
1418 conditionalExpr = rightExpr->AsConditionalExpression();
1419 rightExpr = conditionalExpr->Test();
1420 }
1421
1422 if (ShouldExpressionBeAmended(rightExpr, operatorType)) {
1423 if (AreLogicalAndNullishMixedIncorrectly(rightExpr, operatorType)) {
1424 LogSyntaxError("Nullish coalescing operator ?? requires parens when mixing with logical operators.");
1425 }
1426
1427 ir::Expression *expression = FindAndAmendChildExpression(rightExpr, left, operatorType);
1428 CreateAmendedBinaryExpression(left, expression, operatorType);
1429 } else {
1430 if (AreLogicalAndNullishMixedIncorrectly(rightExpr, operatorType)) {
1431 LogSyntaxError("Nullish coalescing operator ?? requires parens when mixing with logical operators.");
1432 }
1433 const lexer::SourcePosition &endPos = rightExpr->End();
1434 rightExpr = AllocNode<ir::BinaryExpression>(left, rightExpr, operatorType);
1435 rightExpr->SetRange({left->Start(), endPos});
1436 }
1437
1438 if (conditionalExpr != nullptr) {
1439 conditionalExpr->SetStart(rightExpr->Start());
1440 conditionalExpr->SetTest(rightExpr);
1441 return conditionalExpr;
1442 }
1443
1444 return rightExpr;
1445 }
1446
ParseCallExpressionArguments(bool & trailingComma)1447 ArenaVector<ir::Expression *> ParserImpl::ParseCallExpressionArguments(bool &trailingComma)
1448 {
1449 ArenaVector<ir::Expression *> arguments(Allocator()->Adapter());
1450
1451 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_FORMAT &&
1452 lexer_->Lookahead() == static_cast<char32_t>(ARRAY_FORMAT_NODE)) {
1453 arguments = std::move(ParseExpressionsArrayFormatPlaceholder());
1454 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
1455 LogExpectedToken(lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS);
1456 UNREACHABLE();
1457 }
1458 } else {
1459 while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS &&
1460 lexer_->GetToken().Type() != lexer::TokenType::EOS) {
1461 util::ErrorRecursionGuard infiniteLoopBlocker(lexer_);
1462
1463 trailingComma = false;
1464 ir::Expression *argument {};
1465 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD) {
1466 argument = ParseSpreadElement();
1467 } else {
1468 argument = ParseExpression();
1469 }
1470
1471 if (argument != nullptr) { // Error processing.
1472 arguments.push_back(argument);
1473 }
1474
1475 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
1476 lexer_->NextToken();
1477 trailingComma = true;
1478 } else if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
1479 LogExpectedToken(lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS);
1480 }
1481 }
1482 }
1483
1484 return arguments;
1485 }
1486
ParseCallExpression(ir::Expression * callee,bool isOptionalChain,bool handleEval)1487 ir::CallExpression *ParserImpl::ParseCallExpression(ir::Expression *callee, bool isOptionalChain, bool handleEval)
1488 {
1489 ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS);
1490 bool trailingComma {};
1491
1492 while (true) {
1493 lexer_->NextToken();
1494 ArenaVector<ir::Expression *> arguments = ParseCallExpressionArguments(trailingComma);
1495 ir::CallExpression *callExpr {};
1496
1497 if (!isOptionalChain && handleEval && callee->IsIdentifier() && callee->AsIdentifier()->Name().Is("eval")) {
1498 auto parserStatus = static_cast<uint32_t>(context_.Status() | ParserStatus::DIRECT_EVAL);
1499 callExpr = AllocNode<ir::DirectEvalExpression>(callee, std::move(arguments), nullptr, isOptionalChain,
1500 parserStatus);
1501 } else {
1502 callExpr =
1503 AllocNode<ir::CallExpression>(callee, std::move(arguments), nullptr, isOptionalChain, trailingComma);
1504 }
1505
1506 callExpr->SetRange({callee->Start(), lexer_->GetToken().End()});
1507 isOptionalChain = false;
1508
1509 lexer_->NextToken();
1510
1511 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
1512 ParseTrailingBlock(callExpr);
1513 return callExpr;
1514 }
1515
1516 callee = callExpr;
1517 }
1518
1519 UNREACHABLE();
1520 }
1521
ParseOptionalChain(ir::Expression * leftSideExpr)1522 ir::Expression *ParserImpl::ParseOptionalChain(ir::Expression *leftSideExpr)
1523 {
1524 ir::Expression *returnExpression = nullptr;
1525
1526 bool isPrivate = false;
1527
1528 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_HASH_MARK) {
1529 isPrivate = true;
1530 ValidatePrivateIdentifier();
1531 }
1532
1533 const auto tokenType = lexer_->GetToken().Type();
1534 if (tokenType == lexer::TokenType::LITERAL_IDENT) {
1535 auto *identNode = AllocNode<ir::Identifier>(lexer_->GetToken().Ident(), Allocator());
1536 identNode->SetPrivate(isPrivate);
1537 identNode->SetRange(lexer_->GetToken().Loc());
1538
1539 returnExpression = AllocNode<ir::MemberExpression>(leftSideExpr, identNode,
1540 ir::MemberExpressionKind::PROPERTY_ACCESS, false, true);
1541 returnExpression->SetRange({leftSideExpr->Start(), identNode->End()});
1542 lexer_->NextToken();
1543 }
1544
1545 if (tokenType == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET) {
1546 lexer_->NextToken(); // eat '['
1547 ir::Expression *propertyNode = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
1548
1549 auto endLoc = lexer_->GetToken().End();
1550 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
1551 // test exists for ts extension only
1552 LogExpectedToken(lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET);
1553 }
1554
1555 returnExpression = AllocNode<ir::MemberExpression>(leftSideExpr, propertyNode,
1556 ir::MemberExpressionKind::ELEMENT_ACCESS, true, true);
1557 returnExpression->SetRange({leftSideExpr->Start(), endLoc});
1558 lexer_->NextToken();
1559 }
1560
1561 if (tokenType == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
1562 returnExpression = ParseCallExpression(leftSideExpr, true);
1563 }
1564
1565 // Static semantic
1566 if (tokenType == lexer::TokenType::PUNCTUATOR_BACK_TICK ||
1567 lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_BACK_TICK) {
1568 LogSyntaxError("Tagged Template Literals are not allowed in optionalChain");
1569 }
1570
1571 return returnExpression;
1572 }
1573
ParsePotentialArrowExpression(ir::Expression ** returnExpression,const lexer::SourcePosition & startLoc)1574 ir::ArrowFunctionExpression *ParserImpl::ParsePotentialArrowExpression(ir::Expression **returnExpression,
1575 const lexer::SourcePosition &startLoc)
1576 {
1577 switch (lexer_->GetToken().Type()) {
1578 case lexer::TokenType::KEYW_FUNCTION: {
1579 *returnExpression = ParseFunctionExpression(ParserStatus::ASYNC_FUNCTION);
1580 (*returnExpression)->SetStart(startLoc);
1581 break;
1582 }
1583 case lexer::TokenType::LITERAL_IDENT: {
1584 ir::Expression *identRef = ParsePrimaryExpression();
1585 if (identRef == nullptr) {
1586 return nullptr;
1587 }
1588 ASSERT(identRef->IsIdentifier());
1589
1590 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_ARROW) {
1591 // test exists for js extension only
1592 LogExpectedToken(lexer::TokenType::PUNCTUATOR_ARROW);
1593 }
1594
1595 ir::ArrowFunctionExpression *arrowFuncExpr = ParseArrowFunctionExpression(identRef, nullptr, nullptr, true);
1596 arrowFuncExpr->SetStart(startLoc);
1597
1598 return arrowFuncExpr;
1599 }
1600 case lexer::TokenType::PUNCTUATOR_ARROW: {
1601 ir::ArrowFunctionExpression *arrowFuncExpr =
1602 ParseArrowFunctionExpression(*returnExpression, nullptr, nullptr, true);
1603 arrowFuncExpr->SetStart(startLoc);
1604 return arrowFuncExpr;
1605 }
1606 case lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS: {
1607 ir::CallExpression *callExpression = ParseCallExpression(*returnExpression, false);
1608
1609 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_ARROW) {
1610 ir::ArrowFunctionExpression *arrowFuncExpr =
1611 ParseArrowFunctionExpression(callExpression, nullptr, nullptr, true);
1612 arrowFuncExpr->SetStart(startLoc);
1613
1614 return arrowFuncExpr;
1615 }
1616
1617 *returnExpression = callExpression;
1618 break;
1619 }
1620 default: {
1621 break;
1622 }
1623 }
1624
1625 return nullptr;
1626 }
1627
ParsePotentialGenericFunctionCall(ir::Expression * primaryExpr,ir::Expression ** returnExpression,const lexer::SourcePosition & startLoc,bool ignoreCallExpression)1628 bool ParserImpl::ParsePotentialGenericFunctionCall([[maybe_unused]] ir::Expression *primaryExpr,
1629 [[maybe_unused]] ir::Expression **returnExpression,
1630 [[maybe_unused]] const lexer::SourcePosition &startLoc,
1631 [[maybe_unused]] bool ignoreCallExpression)
1632 {
1633 return true;
1634 }
1635
ParsePotentialNonNullExpression(ir::Expression ** returnExpression,lexer::SourcePosition startLoc)1636 bool ParserImpl::ParsePotentialNonNullExpression([[maybe_unused]] ir::Expression **returnExpression,
1637 [[maybe_unused]] lexer::SourcePosition startLoc)
1638 {
1639 return true;
1640 }
1641
ParsePotentialAsExpression(ir::Expression * primaryExpression)1642 ir::Expression *ParserImpl::ParsePotentialAsExpression([[maybe_unused]] ir::Expression *primaryExpression)
1643 {
1644 return nullptr;
1645 }
1646
ParseElementAccess(ir::Expression * primaryExpr,bool isOptional)1647 ir::MemberExpression *ParserImpl::ParseElementAccess(ir::Expression *primaryExpr, bool isOptional)
1648 {
1649 lexer_->NextToken(); // eat '['
1650 ir::Expression *propertyNode = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
1651 if (propertyNode == nullptr) { // Error processing.
1652 return nullptr;
1653 }
1654
1655 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
1656 LogExpectedToken(lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET);
1657 }
1658
1659 if (propertyNode == nullptr) { // Error processing.
1660 return nullptr;
1661 }
1662
1663 auto *memberExpr = AllocNode<ir::MemberExpression>(primaryExpr, propertyNode,
1664 ir::MemberExpressionKind::ELEMENT_ACCESS, true, isOptional);
1665 memberExpr->SetRange({primaryExpr->Start(), lexer_->GetToken().End()});
1666 lexer_->NextToken();
1667 return memberExpr;
1668 }
1669
ParsePrivatePropertyAccess(ir::Expression * primaryExpr)1670 ir::MemberExpression *ParserImpl::ParsePrivatePropertyAccess(ir::Expression *primaryExpr)
1671 {
1672 ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_HASH_MARK);
1673
1674 lexer::SourcePosition memberStart = lexer_->GetToken().Start();
1675 ValidatePrivateIdentifier();
1676
1677 auto *privateIdent = AllocNode<ir::Identifier>(lexer_->GetToken().Ident(), Allocator());
1678 privateIdent->SetRange({memberStart, lexer_->GetToken().End()});
1679 privateIdent->SetPrivate(true);
1680 lexer_->NextToken();
1681
1682 auto *memberExpr = AllocNode<ir::MemberExpression>(primaryExpr, privateIdent,
1683 ir::MemberExpressionKind::PROPERTY_ACCESS, false, false);
1684 memberExpr->SetRange({primaryExpr->Start(), privateIdent->End()});
1685 return memberExpr;
1686 }
1687
ParsePropertyAccess(ir::Expression * primaryExpr,bool isOptional)1688 ir::MemberExpression *ParserImpl::ParsePropertyAccess(ir::Expression *primaryExpr, bool isOptional)
1689 {
1690 ir::Identifier *ident = ExpectIdentifier(true);
1691 if (ident == nullptr) { // Error processing.
1692 return nullptr;
1693 }
1694
1695 auto *memberExpr = AllocNode<ir::MemberExpression>(primaryExpr, ident, ir::MemberExpressionKind::PROPERTY_ACCESS,
1696 false, isOptional);
1697 memberExpr->SetRange({primaryExpr->Start(), ident->End()});
1698
1699 return memberExpr;
1700 }
1701
ParsePostPrimaryExpression(ir::Expression * primaryExpr,lexer::SourcePosition startLoc,bool ignoreCallExpression,bool * isChainExpression)1702 ir::Expression *ParserImpl::ParsePostPrimaryExpression(ir::Expression *primaryExpr, lexer::SourcePosition startLoc,
1703 bool ignoreCallExpression, bool *isChainExpression)
1704 {
1705 ir::Expression *returnExpr = primaryExpr;
1706 while (true) {
1707 switch (lexer_->GetToken().Type()) {
1708 case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET: {
1709 returnExpr = ParseElementAccess(returnExpr);
1710 continue;
1711 }
1712 case lexer::TokenType::LITERAL_IDENT: {
1713 if (auto *asExpression = ParsePotentialAsExpression(returnExpr); asExpression != nullptr) {
1714 return asExpression;
1715 }
1716 break;
1717 }
1718 case lexer::TokenType::PUNCTUATOR_LEFT_SHIFT:
1719 case lexer::TokenType::PUNCTUATOR_LESS_THAN: {
1720 if (ParsePotentialGenericFunctionCall(primaryExpr, &returnExpr, startLoc, ignoreCallExpression)) {
1721 break;
1722 }
1723 continue;
1724 }
1725 case lexer::TokenType::PUNCTUATOR_BACK_TICK: {
1726 returnExpr = ParsePostPrimaryExpressionBackTick(returnExpr, startLoc);
1727 continue;
1728 }
1729 case lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS: {
1730 if (ignoreCallExpression) {
1731 break;
1732 }
1733 returnExpr = ParseCallExpression(returnExpr, false);
1734 continue;
1735 }
1736 case lexer::TokenType::PUNCTUATOR_EXCLAMATION_MARK: {
1737 if (ParsePotentialNonNullExpression(&returnExpr, startLoc)) {
1738 break;
1739 }
1740 continue;
1741 }
1742 default: {
1743 auto tmp = ParsePostPrimaryExpressionDot(returnExpr, lexer_->GetToken().Type(), isChainExpression);
1744 if (tmp != nullptr) {
1745 returnExpr = tmp;
1746 continue;
1747 }
1748 }
1749 }
1750 break;
1751 }
1752 return returnExpr;
1753 }
1754
ParsePostPrimaryExpressionBackTick(ir::Expression * returnExpression,const lexer::SourcePosition startLoc)1755 ir::Expression *ParserImpl::ParsePostPrimaryExpressionBackTick(ir::Expression *returnExpression,
1756 const lexer::SourcePosition startLoc)
1757 {
1758 ir::TemplateLiteral *propertyNode = ParseTemplateLiteral();
1759 lexer::SourcePosition endLoc = propertyNode->End();
1760
1761 returnExpression = AllocNode<ir::TaggedTemplateExpression>(returnExpression, propertyNode, nullptr);
1762 returnExpression->SetRange({startLoc, endLoc});
1763
1764 return returnExpression;
1765 }
1766
ParsePostPrimaryExpressionDot(ir::Expression * returnExpression,const lexer::TokenType tokenType,bool * isChainExpression)1767 ir::Expression *ParserImpl::ParsePostPrimaryExpressionDot(ir::Expression *returnExpression,
1768 const lexer::TokenType tokenType, bool *isChainExpression)
1769 {
1770 switch (tokenType) {
1771 case lexer::TokenType::PUNCTUATOR_QUESTION_DOT: {
1772 *isChainExpression = true;
1773 lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT); // eat ?.
1774 return ParseOptionalChain(returnExpression);
1775 }
1776 case lexer::TokenType::PUNCTUATOR_PERIOD: {
1777 lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT); // eat period
1778
1779 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_HASH_MARK) {
1780 return ParsePrivatePropertyAccess(returnExpression);
1781 }
1782
1783 return ParsePropertyAccess(returnExpression);
1784 }
1785 default: {
1786 break;
1787 }
1788 }
1789
1790 return nullptr;
1791 }
1792
ValidateUpdateExpression(ir::Expression * returnExpression,bool isChainExpression)1793 void ParserImpl::ValidateUpdateExpression(ir::Expression *returnExpression, bool isChainExpression)
1794 {
1795 if ((!returnExpression->IsMemberExpression() && !returnExpression->IsIdentifier() &&
1796 !returnExpression->IsTSNonNullExpression()) ||
1797 isChainExpression) {
1798 LogSyntaxError("Invalid left-hand side operator.");
1799 }
1800
1801 if (returnExpression->IsIdentifier()) {
1802 const util::StringView &returnExpressionStr = returnExpression->AsIdentifier()->Name();
1803
1804 if (returnExpressionStr.Is("eval")) {
1805 LogSyntaxError("Assigning to 'eval' in strict mode is invalid");
1806 }
1807
1808 if (returnExpressionStr.Is("arguments")) {
1809 LogSyntaxError("Assigning to 'arguments' in strict mode is invalid");
1810 }
1811 }
1812 }
1813
SetupChainExpr(ir::Expression * const top,lexer::SourcePosition startLoc)1814 ir::Expression *ParserImpl::SetupChainExpr(ir::Expression *const top, lexer::SourcePosition startLoc)
1815 {
1816 auto expr = top;
1817 while (expr->IsTSNonNullExpression()) {
1818 expr = expr->AsTSNonNullExpression()->Expr();
1819 }
1820 auto chainParent = expr->Parent();
1821
1822 lexer::SourcePosition endLoc = expr->End();
1823 auto chain = AllocNode<ir::ChainExpression>(expr);
1824 chain->SetRange({startLoc, endLoc});
1825
1826 if (expr == top) {
1827 return chain;
1828 }
1829 chainParent->AsTSNonNullExpression()->SetExpr(chain);
1830 chain->SetParent(chainParent);
1831 return top;
1832 }
1833
ParseMemberExpression(bool ignoreCallExpression,ExpressionParseFlags flags)1834 ir::Expression *ParserImpl::ParseMemberExpression(bool ignoreCallExpression, ExpressionParseFlags flags)
1835 {
1836 bool isAsync = lexer_->GetToken().IsAsyncModifier();
1837 lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1838 ir::Expression *returnExpression = ParsePrimaryExpression(flags);
1839 if (returnExpression == nullptr) { // Error processing.
1840 return nullptr;
1841 }
1842
1843 if (lexer_->GetToken().NewLine() && returnExpression->IsArrowFunctionExpression()) {
1844 return returnExpression;
1845 }
1846
1847 if (isAsync && !lexer_->GetToken().NewLine()) {
1848 context_.Status() |= ParserStatus::ASYNC_FUNCTION;
1849 ir::ArrowFunctionExpression *arrow = ParsePotentialArrowExpression(&returnExpression, startLoc);
1850
1851 if (arrow != nullptr) {
1852 return arrow;
1853 }
1854 }
1855
1856 bool isChainExpression;
1857 ir::Expression *prevExpression;
1858 do {
1859 isChainExpression = false;
1860 prevExpression = returnExpression;
1861 returnExpression =
1862 ParsePostPrimaryExpression(returnExpression, startLoc, ignoreCallExpression, &isChainExpression);
1863 if (returnExpression == nullptr) { // Error processing.
1864 return nullptr;
1865 }
1866
1867 if (isChainExpression) {
1868 returnExpression = SetupChainExpr(returnExpression, startLoc);
1869 }
1870 } while (prevExpression != returnExpression);
1871
1872 if (!lexer_->GetToken().NewLine() && lexer::Token::IsUpdateToken(lexer_->GetToken().Type())) {
1873 lexer::SourcePosition start = returnExpression->Start();
1874
1875 ValidateUpdateExpression(returnExpression, isChainExpression);
1876
1877 returnExpression = AllocNode<ir::UpdateExpression>(returnExpression, lexer_->GetToken().Type(), false);
1878
1879 returnExpression->SetRange({start, lexer_->GetToken().End()});
1880 lexer_->NextToken();
1881 }
1882
1883 return returnExpression;
1884 }
1885
1886 // NOLINTNEXTLINE(google-default-arguments)
ParsePatternElement(ExpressionParseFlags flags,bool allowDefault)1887 ir::Expression *ParserImpl::ParsePatternElement(ExpressionParseFlags flags, bool allowDefault)
1888 {
1889 ir::Expression *returnNode = nullptr;
1890
1891 switch (lexer_->GetToken().Type()) {
1892 case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET: {
1893 returnNode = ParseArrayExpression(ExpressionParseFlags::MUST_BE_PATTERN);
1894 break;
1895 }
1896 case lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD: {
1897 if ((flags & ExpressionParseFlags::IN_REST) != 0) {
1898 LogSyntaxError("Unexpected token");
1899 }
1900 returnNode = ParseSpreadElement(ExpressionParseFlags::MUST_BE_PATTERN);
1901 break;
1902 }
1903 case lexer::TokenType::PUNCTUATOR_LEFT_BRACE: {
1904 returnNode =
1905 ParseObjectExpression(ExpressionParseFlags::MUST_BE_PATTERN | ExpressionParseFlags::OBJECT_PATTERN);
1906 break;
1907 }
1908 case lexer::TokenType::LITERAL_IDENT: {
1909 returnNode = AllocNode<ir::Identifier>(lexer_->GetToken().Ident(), Allocator());
1910 returnNode->SetRange(lexer_->GetToken().Loc());
1911 lexer_->NextToken();
1912 break;
1913 }
1914 default: {
1915 LogSyntaxError("Unexpected token, expected an identifier.");
1916 }
1917 }
1918
1919 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
1920 return returnNode;
1921 }
1922
1923 ParsePatternElementErrorCheck(flags, allowDefault);
1924
1925 ir::Expression *rightNode = ParseExpression();
1926 if (returnNode == nullptr || rightNode == nullptr) { // Error processing.
1927 return nullptr;
1928 }
1929
1930 auto *assignmentExpression = AllocNode<ir::AssignmentExpression>(
1931 ir::AstNodeType::ASSIGNMENT_PATTERN, returnNode, rightNode, lexer::TokenType::PUNCTUATOR_SUBSTITUTION);
1932 assignmentExpression->SetRange({returnNode->Start(), rightNode->End()});
1933
1934 return assignmentExpression;
1935 }
1936
ParsePatternElementErrorCheck(const ExpressionParseFlags flags,const bool allowDefault)1937 void ParserImpl::ParsePatternElementErrorCheck(const ExpressionParseFlags flags, const bool allowDefault)
1938 {
1939 if ((flags & ExpressionParseFlags::IN_REST) != 0) {
1940 // unexpected_token_10.js
1941 LogExpectedToken(lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS);
1942 }
1943
1944 if (!allowDefault) {
1945 LogSyntaxError("Invalid destructuring assignment target");
1946 }
1947
1948 lexer_->NextToken();
1949
1950 if (context_.IsGenerator() && lexer_->GetToken().Type() == lexer::TokenType::KEYW_YIELD) {
1951 LogSyntaxError("Yield is not allowed in generator parameters");
1952 }
1953
1954 if (context_.IsAsync() && lexer_->GetToken().Type() == lexer::TokenType::KEYW_AWAIT) {
1955 LogSyntaxError("Illegal await-expression in formal parameters of async function");
1956 }
1957 }
1958
CheckPropertyKeyAsyncModifier(ParserStatus * methodStatus)1959 void ParserImpl::CheckPropertyKeyAsyncModifier(ParserStatus *methodStatus)
1960 {
1961 const auto asyncPos = lexer_->Save();
1962 lexer_->NextToken();
1963
1964 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS &&
1965 lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COLON &&
1966 lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COMMA &&
1967 lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
1968 if (lexer_->GetToken().NewLine()) {
1969 LogSyntaxError(
1970 "Async methods cannot have a line terminator between "
1971 "'async' and the property name");
1972 }
1973
1974 *methodStatus |= ParserStatus::ASYNC_FUNCTION;
1975 } else {
1976 lexer_->Rewind(asyncPos);
1977 }
1978 }
1979
IsAccessorDelimiter(char32_t cp)1980 static bool IsAccessorDelimiter(char32_t cp)
1981 {
1982 switch (cp) {
1983 case lexer::LEX_CHAR_LEFT_PAREN:
1984 case lexer::LEX_CHAR_COLON:
1985 case lexer::LEX_CHAR_COMMA:
1986 case lexer::LEX_CHAR_RIGHT_BRACE: {
1987 return true;
1988 }
1989 default: {
1990 return false;
1991 }
1992 }
1993 }
1994
IsShorthandDelimiter(char32_t cp)1995 static bool IsShorthandDelimiter(char32_t cp)
1996 {
1997 switch (cp) {
1998 case lexer::LEX_CHAR_EQUALS:
1999 case lexer::LEX_CHAR_COMMA:
2000 case lexer::LEX_CHAR_RIGHT_BRACE: {
2001 return true;
2002 }
2003 default: {
2004 return false;
2005 }
2006 }
2007 }
2008
ValidateAccessor(ExpressionParseFlags flags,lexer::TokenFlags currentTokenFlags)2009 void ParserImpl::ValidateAccessor(ExpressionParseFlags flags, lexer::TokenFlags currentTokenFlags)
2010 {
2011 if ((flags & ExpressionParseFlags::MUST_BE_PATTERN) != 0) {
2012 LogSyntaxError("Unexpected token");
2013 }
2014
2015 if ((currentTokenFlags & lexer::TokenFlags::HAS_ESCAPE) != 0) {
2016 LogSyntaxError("Keyword must not contain escaped characters");
2017 }
2018 }
2019
ParseShorthandProperty(const lexer::LexerPosition * startPos)2020 ir::Property *ParserImpl::ParseShorthandProperty(const lexer::LexerPosition *startPos)
2021 {
2022 char32_t nextCp = lexer_->Lookahead();
2023 lexer::TokenType keywordType = lexer_->GetToken().KeywordType();
2024
2025 /* Rewind the lexer to the beginning of the ident to reparse as common
2026 * identifier */
2027 lexer_->Rewind(*startPos);
2028 lexer_->NextToken();
2029 lexer::SourcePosition start = lexer_->GetToken().Start();
2030
2031 if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
2032 // for now no tests are available since the func is called once
2033 // after checking the same token for the identifier
2034 LogExpectedToken(lexer::TokenType::LITERAL_IDENT);
2035 }
2036
2037 const util::StringView &ident = lexer_->GetToken().Ident();
2038
2039 auto *key = AllocNode<ir::Identifier>(ident, Allocator());
2040 key->SetRange(lexer_->GetToken().Loc());
2041
2042 ir::Expression *value = AllocNode<ir::Identifier>(ident, Allocator());
2043 value->SetRange(lexer_->GetToken().Loc());
2044
2045 lexer::SourcePosition end;
2046
2047 if (nextCp == lexer::LEX_CHAR_EQUALS) {
2048 CheckRestrictedBinding(keywordType);
2049
2050 lexer_->NextToken(); // substitution
2051 lexer_->NextToken(); // eat substitution
2052
2053 ir::Expression *rightNode = ParseExpression();
2054
2055 auto *assignmentExpression = AllocNode<ir::AssignmentExpression>(
2056 ir::AstNodeType::ASSIGNMENT_PATTERN, value, rightNode, lexer::TokenType::PUNCTUATOR_SUBSTITUTION);
2057 assignmentExpression->SetRange({value->Start(), rightNode->End()});
2058 end = rightNode->End();
2059 value = assignmentExpression;
2060 } else {
2061 end = lexer_->GetToken().End();
2062 lexer_->NextToken();
2063 }
2064
2065 auto *returnProperty = AllocNode<ir::Property>(key, value);
2066 returnProperty->SetRange({start, end});
2067
2068 return returnProperty;
2069 }
2070
ParsePropertyModifiers(ExpressionParseFlags flags,ir::PropertyKind * propertyKind,ParserStatus * methodStatus)2071 bool ParserImpl::ParsePropertyModifiers(ExpressionParseFlags flags, ir::PropertyKind *propertyKind,
2072 ParserStatus *methodStatus)
2073 {
2074 if (lexer_->GetToken().IsAsyncModifier()) {
2075 CheckPropertyKeyAsyncModifier(methodStatus);
2076 }
2077
2078 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MULTIPLY) {
2079 if ((flags & ExpressionParseFlags::MUST_BE_PATTERN) != 0) {
2080 LogSyntaxError("Unexpected token");
2081 }
2082
2083 lexer_->NextToken();
2084 *methodStatus |= ParserStatus::GENERATOR_FUNCTION;
2085 }
2086
2087 lexer::TokenFlags currentTokenFlags = lexer_->GetToken().Flags();
2088 char32_t nextCp = lexer_->Lookahead();
2089 lexer::TokenType keywordType = lexer_->GetToken().KeywordType();
2090 // Parse getter property
2091 if (keywordType == lexer::TokenType::KEYW_GET && !IsAccessorDelimiter(nextCp)) {
2092 ValidateAccessor(flags, currentTokenFlags);
2093
2094 *propertyKind = ir::PropertyKind::GET;
2095 lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);
2096
2097 return false;
2098 }
2099
2100 // Parse setter property
2101 if (keywordType == lexer::TokenType::KEYW_SET && !IsAccessorDelimiter(nextCp)) {
2102 ValidateAccessor(flags, currentTokenFlags);
2103
2104 *propertyKind = ir::PropertyKind::SET;
2105 lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);
2106
2107 return false;
2108 }
2109
2110 // Parse shorthand property or assignment pattern
2111 return (IsShorthandDelimiter(nextCp) && (*methodStatus & ParserStatus::ASYNC_FUNCTION) == 0);
2112 }
2113
ParseGeneratorPropertyModifier(ExpressionParseFlags flags,ParserStatus * methodStatus)2114 void ParserImpl::ParseGeneratorPropertyModifier(ExpressionParseFlags flags, ParserStatus *methodStatus)
2115 {
2116 if ((flags & ExpressionParseFlags::MUST_BE_PATTERN) != 0) {
2117 LogSyntaxError("Unexpected token");
2118 }
2119
2120 lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);
2121 *methodStatus |= ParserStatus::GENERATOR_FUNCTION;
2122 }
2123
ParsePropertyKey(ExpressionParseFlags flags)2124 ir::Expression *ParserImpl::ParsePropertyKey(ExpressionParseFlags flags)
2125 {
2126 ir::Expression *key = nullptr;
2127
2128 switch (lexer_->GetToken().Type()) {
2129 case lexer::TokenType::LITERAL_IDENT: {
2130 const util::StringView &ident = lexer_->GetToken().Ident();
2131 key = AllocNode<ir::Identifier>(ident, Allocator());
2132 key->SetRange(lexer_->GetToken().Loc());
2133 break;
2134 }
2135 case lexer::TokenType::LITERAL_STRING: {
2136 const util::StringView &string = lexer_->GetToken().String();
2137 key = AllocNode<ir::StringLiteral>(string);
2138 key->SetRange(lexer_->GetToken().Loc());
2139 break;
2140 }
2141 case lexer::TokenType::LITERAL_NUMBER: {
2142 if ((lexer_->GetToken().Flags() & lexer::TokenFlags::NUMBER_BIGINT) != 0) {
2143 key = AllocNode<ir::BigIntLiteral>(lexer_->GetToken().BigInt());
2144 } else {
2145 key = AllocNode<ir::NumberLiteral>(lexer_->GetToken().GetNumber());
2146 }
2147
2148 key->SetRange(lexer_->GetToken().Loc());
2149 break;
2150 }
2151 case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET: {
2152 lexer_->NextToken(); // eat left square bracket
2153
2154 key = ParseExpression(flags | ExpressionParseFlags::ACCEPT_COMMA);
2155
2156 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
2157 // the same test for ts, sts and js extension
2158 // unexpected_token_52.sts
2159 LogExpectedToken(lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET);
2160 }
2161 break;
2162 }
2163 default: {
2164 LogSyntaxError("Unexpected token in property key");
2165 return nullptr;
2166 }
2167 }
2168
2169 lexer_->NextToken();
2170 return key;
2171 }
2172
ParsePropertyValue(const ir::PropertyKind * propertyKind,const ParserStatus * methodStatus,ExpressionParseFlags flags)2173 ir::Expression *ParserImpl::ParsePropertyValue(const ir::PropertyKind *propertyKind, const ParserStatus *methodStatus,
2174 ExpressionParseFlags flags)
2175 {
2176 bool isMethod = (*methodStatus & ParserStatus::FUNCTION) != 0;
2177 bool inPattern = (flags & ExpressionParseFlags::MUST_BE_PATTERN) != 0;
2178
2179 if (!isMethod && !ir::Property::IsAccessorKind(*propertyKind)) {
2180 // If the actual property is not getter/setter nor method, the following
2181 // token must be ':'
2182 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COLON) {
2183 if (lexer::Token::IsPunctuatorToken(lexer_->GetToken().Type())) {
2184 LogExpectedToken(lexer::TokenType::PUNCTUATOR_COLON);
2185 lexer_->NextToken(); // eat colon
2186 } else {
2187 // we just missed ':'
2188 LogSyntaxError("Unexpected token, expected: ':'.");
2189 }
2190 } else {
2191 lexer_->NextToken(); // eat colon
2192 }
2193
2194 if (!inPattern) {
2195 return ParseExpression(flags);
2196 }
2197
2198 return ParsePatternElement();
2199 }
2200
2201 if (inPattern) {
2202 LogSyntaxError("Object pattern can't contain methods");
2203 }
2204
2205 ParserStatus newStatus = *methodStatus | ParserStatus::FUNCTION | ParserStatus::ALLOW_SUPER;
2206
2207 if (*propertyKind != ir::PropertyKind::SET) {
2208 newStatus |= ParserStatus::NEED_RETURN_TYPE;
2209 }
2210
2211 ir::ScriptFunction *methodDefinitonNode = ParseFunction(newStatus);
2212 methodDefinitonNode->AddFlag(ir::ScriptFunctionFlags::METHOD);
2213
2214 size_t paramsSize = methodDefinitonNode->Params().size();
2215
2216 auto *value = AllocNode<ir::FunctionExpression>(methodDefinitonNode);
2217 value->SetRange(methodDefinitonNode->Range());
2218
2219 if (*propertyKind == ir::PropertyKind::SET && paramsSize != 1) {
2220 LogSyntaxError("Setter must have exactly one formal parameter");
2221 }
2222
2223 if (*propertyKind == ir::PropertyKind::GET && paramsSize != 0) {
2224 LogSyntaxError("Getter must not have formal parameters");
2225 }
2226
2227 return value;
2228 }
2229
2230 // NOLINTNEXTLINE(google-default-arguments)
ParsePropertyDefinition(ExpressionParseFlags flags)2231 ir::Expression *ParserImpl::ParsePropertyDefinition([[maybe_unused]] ExpressionParseFlags flags)
2232 {
2233 ir::PropertyKind propertyKind = ir::PropertyKind::INIT;
2234 ParserStatus methodStatus = ParserStatus::NO_OPTS;
2235
2236 const auto startPos = lexer_->Save();
2237 lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);
2238 lexer::SourcePosition start = lexer_->GetToken().Start();
2239
2240 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD) {
2241 return ParseSpreadElement(flags);
2242 }
2243
2244 if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) {
2245 if (ParsePropertyModifiers(flags, &propertyKind, &methodStatus)) {
2246 return ParseShorthandProperty(&startPos);
2247 }
2248 } else if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MULTIPLY) {
2249 ParseGeneratorPropertyModifier(flags, &methodStatus);
2250 }
2251
2252 bool isComputed = lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET;
2253 ir::Expression *key = ParsePropertyKey(flags);
2254
2255 // Parse method property
2256 if ((lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS ||
2257 lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) &&
2258 !ir::Property::IsAccessorKind(propertyKind)) {
2259 methodStatus |= ParserStatus::FUNCTION | ParserStatus::ALLOW_SUPER;
2260 propertyKind = ir::PropertyKind::INIT;
2261 } else if ((methodStatus & (ParserStatus::GENERATOR_FUNCTION | ParserStatus::ASYNC_FUNCTION)) != 0) {
2262 LogSyntaxError("Unexpected identifier");
2263 }
2264
2265 ir::Expression *value = ParsePropertyValue(&propertyKind, &methodStatus, flags);
2266 if (key == nullptr || value == nullptr) { // Error processing.
2267 return nullptr;
2268 }
2269
2270 lexer::SourcePosition end = value->End();
2271
2272 auto *returnProperty =
2273 AllocNode<ir::Property>(propertyKind, key, value, methodStatus != ParserStatus::NO_OPTS, isComputed);
2274 returnProperty->SetRange({start, end});
2275
2276 return returnProperty;
2277 }
2278
ParsePropertyEndErrorHendler()2279 void ParserImpl::ParsePropertyEndErrorHendler()
2280 {
2281 const auto pos = lexer_->Save();
2282 if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
2283 lexer_->NextToken();
2284 if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) {
2285 // {a. b} -> {a, b}
2286 lexer_->Rewind(pos);
2287 lexer_->GetToken().SetTokenType(lexer::TokenType::PUNCTUATOR_COMMA);
2288 } else {
2289 lexer_->Rewind(pos);
2290 if (lexer::Token::IsPunctuatorToken(lexer_->GetToken().Type())) {
2291 // {a, b) -> {a, b}
2292 lexer_->GetToken().SetTokenType(lexer::TokenType::PUNCTUATOR_RIGHT_BRACE);
2293 }
2294 }
2295 } else {
2296 lexer_->NextToken(); // {a b} -> we just skip the token
2297 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
2298 lexer_->GetToken().SetTokenType(lexer::TokenType::PUNCTUATOR_RIGHT_BRACE);
2299 }
2300 }
2301 }
2302
ParsePropertyEnd()2303 bool ParserImpl::ParsePropertyEnd()
2304 {
2305 // Property definiton must end with ',' or '}' otherwise we report SyntaxError
2306 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COMMA &&
2307 lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
2308 // test_object_literal3.ts
2309 LogSyntaxError("Unexpected token, expected ',' or '}'");
2310 ParsePropertyEndErrorHendler();
2311 }
2312
2313 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA &&
2314 lexer_->Lookahead() == lexer::LEX_CHAR_RIGHT_BRACE) {
2315 lexer_->NextToken();
2316 return true;
2317 }
2318
2319 return false;
2320 }
2321
2322 // NOLINTNEXTLINE(google-default-arguments)
ParseObjectExpression(ExpressionParseFlags flags)2323 ir::ObjectExpression *ParserImpl::ParseObjectExpression(ExpressionParseFlags flags)
2324 {
2325 ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE);
2326 lexer::SourcePosition start = lexer_->GetToken().Start();
2327 ArenaVector<ir::Expression *> properties(Allocator()->Adapter());
2328 bool trailingComma = false;
2329 bool inPattern = (flags & ExpressionParseFlags::MUST_BE_PATTERN) != 0;
2330
2331 if (lexer_->Lookahead() == lexer::LEX_CHAR_RIGHT_BRACE) {
2332 lexer_->NextToken();
2333 }
2334
2335 while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE &&
2336 lexer_->GetToken().Type() != lexer::TokenType::EOS) {
2337 util::ErrorRecursionGuard infiniteLoopBlocker(lexer_);
2338 ir::Expression *property = ParsePropertyDefinition(flags | ExpressionParseFlags::POTENTIALLY_IN_PATTERN);
2339 if (property != nullptr) {
2340 properties.push_back(property);
2341 }
2342
2343 trailingComma = ParsePropertyEnd();
2344 }
2345
2346 auto nodeType = inPattern ? ir::AstNodeType::OBJECT_PATTERN : ir::AstNodeType::OBJECT_EXPRESSION;
2347 auto *objectExpression =
2348 AllocNode<ir::ObjectExpression>(nodeType, Allocator(), std::move(properties), trailingComma);
2349 objectExpression->SetRange({start, lexer_->GetToken().End()});
2350 lexer_->NextToken();
2351
2352 if (inPattern) {
2353 objectExpression->SetDeclaration();
2354 }
2355
2356 if ((flags & ExpressionParseFlags::POTENTIALLY_IN_PATTERN) == 0) {
2357 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION &&
2358 !objectExpression->ConvertibleToObjectPattern()) {
2359 LogSyntaxError("Invalid left-hand side in array destructuring pattern", objectExpression->Start());
2360 } else if (!inPattern && lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
2361 ir::ValidationInfo info = objectExpression->ValidateExpression();
2362 if (info.Fail()) {
2363 LogSyntaxError(info.msg.Utf8(), info.pos);
2364 }
2365 }
2366 }
2367
2368 return objectExpression;
2369 }
2370
ParseSequenceExpression(ir::Expression * startExpr,bool acceptRest)2371 ir::SequenceExpression *ParserImpl::ParseSequenceExpression(ir::Expression *startExpr, bool acceptRest)
2372 {
2373 lexer::SourcePosition start = startExpr->Start();
2374
2375 ArenaVector<ir::Expression *> sequence(Allocator()->Adapter());
2376 sequence.push_back(startExpr);
2377
2378 while (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
2379 lexer_->NextToken();
2380
2381 if (acceptRest && lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD) {
2382 ir::SpreadElement *expr = ParseSpreadElement(ExpressionParseFlags::MUST_BE_PATTERN);
2383 if (expr != nullptr) { // Error processing.
2384 sequence.push_back(expr);
2385 }
2386 break;
2387 }
2388
2389 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS && lexer_->CheckArrow()) {
2390 break;
2391 }
2392
2393 auto expr = ParseExpression();
2394 if (expr != nullptr) { // Error processing.
2395 sequence.push_back(expr);
2396 }
2397 }
2398
2399 lexer::SourcePosition end = sequence.back()->End();
2400 auto *sequenceNode = AllocNode<ir::SequenceExpression>(std::move(sequence));
2401 sequenceNode->SetRange({start, end});
2402
2403 return sequenceNode;
2404 }
2405
2406 // NOLINTNEXTLINE(google-default-arguments)
ParseUnaryOrPrefixUpdateExpression(ExpressionParseFlags flags)2407 ir::Expression *ParserImpl::ParseUnaryOrPrefixUpdateExpression(ExpressionParseFlags flags)
2408 {
2409 if (!lexer_->GetToken().IsUnary()) {
2410 return ParseLeftHandSideExpression(flags);
2411 }
2412
2413 lexer::TokenType operatorType = lexer_->GetToken().Type();
2414 lexer::SourcePosition start = lexer_->GetToken().Start();
2415 lexer_->NextToken();
2416
2417 ir::Expression *argument =
2418 lexer_->GetToken().IsUnary() ? ParseUnaryOrPrefixUpdateExpression() : ParseLeftHandSideExpression();
2419 if (argument == nullptr) { // Error processing.
2420 return nullptr;
2421 }
2422
2423 if (lexer::Token::IsUpdateToken(operatorType)) {
2424 if (!argument->IsIdentifier() && !argument->IsMemberExpression() && !argument->IsTSNonNullExpression()) {
2425 LogSyntaxError("Invalid left-hand side in prefix operation");
2426 }
2427
2428 if (argument->IsIdentifier()) {
2429 const util::StringView &argumentStr = argument->AsIdentifier()->Name();
2430
2431 if (argumentStr.Is("eval")) {
2432 LogSyntaxError("Assigning to 'eval' in strict mode is invalid");
2433 } else if (argumentStr.Is("arguments")) {
2434 LogSyntaxError("Assigning to 'arguments' in strict mode is invalid");
2435 }
2436 }
2437 }
2438
2439 if (operatorType == lexer::TokenType::KEYW_DELETE) {
2440 if (argument->IsIdentifier()) {
2441 LogSyntaxError("Deleting local variable in strict mode");
2442 }
2443
2444 if (argument->IsMemberExpression() && argument->AsMemberExpression()->Property()->IsIdentifier() &&
2445 argument->AsMemberExpression()->Property()->AsIdentifier()->IsPrivateIdent()) {
2446 LogSyntaxError("Private fields can not be deleted");
2447 }
2448 }
2449
2450 lexer::SourcePosition end = argument->End();
2451
2452 ir::Expression *returnExpr = nullptr;
2453
2454 if (lexer::Token::IsUpdateToken(operatorType)) {
2455 returnExpr = AllocNode<ir::UpdateExpression>(argument, operatorType, true);
2456 } else if (operatorType == lexer::TokenType::KEYW_AWAIT) {
2457 returnExpr = AllocNode<ir::AwaitExpression>(argument);
2458 } else if (operatorType == lexer::TokenType::KEYW_TYPEOF) {
2459 returnExpr = AllocNode<ir::TypeofExpression>(argument);
2460 } else {
2461 returnExpr = AllocNode<ir::UnaryExpression>(argument, operatorType);
2462 }
2463
2464 returnExpr->SetRange({start, end});
2465
2466 return returnExpr;
2467 }
2468
ParseImportExpression()2469 ir::Expression *ParserImpl::ParseImportExpression()
2470 {
2471 lexer::SourcePosition startLoc = lexer_->GetToken().Start();
2472 lexer::SourcePosition endLoc = lexer_->GetToken().End();
2473 lexer_->NextToken(); // eat import
2474
2475 // parse import.Meta
2476 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD) {
2477 if (!context_.IsModule()) {
2478 LogSyntaxError("'import.Meta' may appear only with 'sourceType: module'");
2479 } else if (GetOptions().isDirectEval) {
2480 LogSyntaxError("'import.Meta' is not allowed in direct eval in module code.");
2481 }
2482
2483 lexer_->NextToken(); // eat dot
2484
2485 if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT ||
2486 lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_META) {
2487 // js tests only: import_meta_1.js, import_meta_2.js, import_meta_3.js
2488 LogSyntaxError("The only valid meta property for import is import.Meta");
2489
2490 lexer_->GetToken().SetTokenType(lexer::TokenType::KEYW_META);
2491 }
2492
2493 auto *metaProperty = AllocNode<ir::MetaProperty>(ir::MetaProperty::MetaPropertyKind::IMPORT_META);
2494 metaProperty->SetRange({startLoc, endLoc});
2495
2496 lexer_->NextToken();
2497 return metaProperty;
2498 }
2499
2500 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
2501 LogExpectedToken(lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS);
2502 }
2503
2504 lexer_->NextToken(); // eat left parentheses
2505
2506 ir::Expression *source = ParseExpression();
2507
2508 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
2509 // test exists for ts extension only
2510 LogExpectedToken(lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS);
2511 }
2512
2513 lexer::SourcePosition endImportLoc = lexer_->GetToken().End();
2514 lexer_->NextToken(); // eat right paren
2515
2516 if (source == nullptr) { // Error processing.
2517 return nullptr;
2518 }
2519
2520 auto *importExpression = AllocNode<ir::ImportExpression>(source);
2521 importExpression->SetRange({startLoc, endImportLoc});
2522
2523 return importExpression;
2524 }
2525
IsNamedFunctionExpression()2526 bool ParserImpl::IsNamedFunctionExpression()
2527 {
2528 return lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS;
2529 }
2530
ParseFunctionExpression(ParserStatus newStatus)2531 ir::FunctionExpression *ParserImpl::ParseFunctionExpression(ParserStatus newStatus)
2532 {
2533 lexer::SourcePosition startLoc = lexer_->GetToken().Start();
2534 ir::Identifier *ident = nullptr;
2535
2536 if ((newStatus & ParserStatus::ARROW_FUNCTION) == 0) {
2537 ParserStatus savedStatus = context_.Status();
2538 context_.Status() |= static_cast<ParserStatus>(newStatus & ParserStatus::ASYNC_FUNCTION);
2539
2540 lexer_->NextToken();
2541
2542 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MULTIPLY) {
2543 newStatus |= ParserStatus::GENERATOR_FUNCTION;
2544 lexer_->NextToken();
2545 }
2546
2547 if (IsNamedFunctionExpression()) {
2548 CheckRestrictedBinding(lexer_->GetToken().KeywordType());
2549 ident = ExpectIdentifier(false, true);
2550 }
2551
2552 context_.Status() = savedStatus;
2553 }
2554
2555 ir::ScriptFunction *functionNode = ParseFunction(newStatus);
2556 functionNode->SetStart(startLoc);
2557
2558 auto *funcExpr = AllocNode<ir::FunctionExpression>(ident, functionNode);
2559 funcExpr->SetRange(functionNode->Range());
2560
2561 return funcExpr;
2562 }
2563 } // namespace ark::es2panda::parser
2564