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