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