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