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
140 bool isConst = false;
141 if (typeAnnotation->IsTSTypeReference() && typeAnnotation->AsTSTypeReference()->TypeName()->IsIdentifier()) {
142 const util::StringView &refName = typeAnnotation->AsTSTypeReference()->TypeName()->AsIdentifier()->Name();
143 if (refName.Is("const")) {
144 isConst = true;
145 }
146 }
147
148 lexer::SourcePosition startLoc = expr->Start();
149 auto *asExpr = AllocNode<ir::TSAsExpression>(expr, typeAnnotation, isConst);
150 asExpr->SetRange({startLoc, lexer_->GetToken().End()});
151
152 if (Extension() == ScriptExtension::TS && lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT &&
153 lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_AS &&
154 !(flags & ExpressionParseFlags::EXP_DISALLOW_AS)) {
155 // Prevent stack overflow caused by nesting too many as. For example: a as Int as Int...
156 CHECK_PARSER_RECURSIVE_DEPTH;
157 return ParseTsAsExpression(asExpr, flags);
158 }
159
160 return asExpr;
161 }
162
ParseTsSatisfiesExpression(ir::Expression * expr)163 ir::TSSatisfiesExpression *ParserImpl::ParseTsSatisfiesExpression(ir::Expression *expr)
164 {
165 lexer_->NextToken(); // eat 'satisfies'
166 TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
167 ir::Expression *typeAnnotation = ParseTsTypeAnnotation(&options);
168
169 lexer::SourcePosition startLoc = expr->Start();
170 auto *satisfiesExpr = AllocNode<ir::TSSatisfiesExpression>(expr, typeAnnotation);
171 satisfiesExpr->SetRange({startLoc, lexer_->GetToken().End()});
172
173 if (Extension() == ScriptExtension::TS && lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT &&
174 lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_SATISFIES) {
175 return ParseTsSatisfiesExpression(satisfiesExpr);
176 }
177
178 return satisfiesExpr;
179 }
180
ParseExpression(ExpressionParseFlags flags)181 ir::Expression *ParserImpl::ParseExpression(ExpressionParseFlags flags)
182 {
183 if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_YIELD && !(flags & ExpressionParseFlags::DISALLOW_YIELD)) {
184 ir::YieldExpression *yieldExpr = ParseYieldExpression();
185
186 return ParsePotentialExpressionSequence(yieldExpr, flags);
187 }
188
189 if (Extension() == ScriptExtension::TS && lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) {
190 const auto startPos = lexer_->Save();
191
192 // TODO(rsipka): ParseTsGenericArrowFunction and ParseTsTypeAssertion might be in a common function
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 lexer::TokenType tokenType = lexer_->GetToken().Type();
744 if (lhsExpression->IsGrouped() && tokenType != lexer::TokenType::PUNCTUATOR_ARROW) {
745 if (lhsExpression->IsSequenceExpression()) {
746 for (auto *seq : lhsExpression->AsSequenceExpression()->Sequence()) {
747 ValidateParenthesizedExpression(seq);
748 }
749 } else {
750 ValidateParenthesizedExpression(lhsExpression);
751 }
752 }
753
754 switch (tokenType) {
755 case lexer::TokenType::PUNCTUATOR_QUESTION_MARK: {
756 lexer_->NextToken();
757 ir::Expression *consequent = ParseExpression();
758
759 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COLON) {
760 ThrowSyntaxError("Unexpected token, expected ':'");
761 }
762
763 lexer_->NextToken();
764 ir::Expression *alternate = ParseExpression();
765
766 auto *conditionalExpr = AllocNode<ir::ConditionalExpression>(lhsExpression, consequent, alternate);
767 conditionalExpr->SetRange({lhsExpression->Start(), alternate->End()});
768 return conditionalExpr;
769 }
770 case lexer::TokenType::PUNCTUATOR_ARROW: {
771 if (lexer_->GetToken().NewLine()) {
772 ThrowSyntaxError("Uncaught SyntaxError: expected expression, got '=>'");
773 }
774
775 return ParseArrowFunctionExpression(lhsExpression, nullptr, nullptr, false);
776 }
777 case lexer::TokenType::KEYW_IN: {
778 if (flags & ExpressionParseFlags::STOP_AT_IN) {
779 break;
780 }
781
782 [[fallthrough]];
783 }
784 case lexer::TokenType::PUNCTUATOR_NULLISH_COALESCING:
785 case lexer::TokenType::PUNCTUATOR_LOGICAL_OR:
786 case lexer::TokenType::PUNCTUATOR_LOGICAL_AND:
787 case lexer::TokenType::PUNCTUATOR_BITWISE_OR:
788 case lexer::TokenType::PUNCTUATOR_BITWISE_XOR:
789 case lexer::TokenType::PUNCTUATOR_BITWISE_AND:
790 case lexer::TokenType::PUNCTUATOR_EQUAL:
791 case lexer::TokenType::PUNCTUATOR_NOT_EQUAL:
792 case lexer::TokenType::PUNCTUATOR_STRICT_EQUAL:
793 case lexer::TokenType::PUNCTUATOR_NOT_STRICT_EQUAL:
794 case lexer::TokenType::PUNCTUATOR_LESS_THAN:
795 case lexer::TokenType::PUNCTUATOR_LESS_THAN_EQUAL:
796 case lexer::TokenType::PUNCTUATOR_GREATER_THAN:
797 case lexer::TokenType::PUNCTUATOR_GREATER_THAN_EQUAL:
798 case lexer::TokenType::PUNCTUATOR_LEFT_SHIFT:
799 case lexer::TokenType::PUNCTUATOR_RIGHT_SHIFT:
800 case lexer::TokenType::PUNCTUATOR_UNSIGNED_RIGHT_SHIFT:
801 case lexer::TokenType::PUNCTUATOR_PLUS:
802 case lexer::TokenType::PUNCTUATOR_MINUS:
803 case lexer::TokenType::PUNCTUATOR_MULTIPLY:
804 case lexer::TokenType::PUNCTUATOR_DIVIDE:
805 case lexer::TokenType::PUNCTUATOR_MOD:
806 case lexer::TokenType::KEYW_INSTANCEOF:
807 case lexer::TokenType::PUNCTUATOR_EXPONENTIATION: {
808 ir::Expression *binaryExpression = ParseBinaryExpression(lhsExpression);
809
810 return ParseAssignmentExpression(binaryExpression);
811 }
812 case lexer::TokenType::PUNCTUATOR_SUBSTITUTION: {
813 ValidateAssignmentTarget(flags, lhsExpression);
814
815 lexer_->NextToken();
816 ir::Expression *assignmentExpression = ParseExpression(CarryPatternFlags(flags));
817
818 auto *binaryAssignmentExpression =
819 AllocNode<ir::AssignmentExpression>(lhsExpression, assignmentExpression, tokenType);
820
821 binaryAssignmentExpression->SetRange({lhsExpression->Start(), assignmentExpression->End()});
822 return binaryAssignmentExpression;
823 }
824 case lexer::TokenType::PUNCTUATOR_UNSIGNED_RIGHT_SHIFT_EQUAL:
825 case lexer::TokenType::PUNCTUATOR_RIGHT_SHIFT_EQUAL:
826 case lexer::TokenType::PUNCTUATOR_LEFT_SHIFT_EQUAL:
827 case lexer::TokenType::PUNCTUATOR_PLUS_EQUAL:
828 case lexer::TokenType::PUNCTUATOR_MINUS_EQUAL:
829 case lexer::TokenType::PUNCTUATOR_MULTIPLY_EQUAL:
830 case lexer::TokenType::PUNCTUATOR_DIVIDE_EQUAL:
831 case lexer::TokenType::PUNCTUATOR_MOD_EQUAL:
832 case lexer::TokenType::PUNCTUATOR_BITWISE_AND_EQUAL:
833 case lexer::TokenType::PUNCTUATOR_BITWISE_OR_EQUAL:
834 case lexer::TokenType::PUNCTUATOR_BITWISE_XOR_EQUAL:
835 case lexer::TokenType::PUNCTUATOR_LOGICAL_AND_EQUAL:
836 case lexer::TokenType::PUNCTUATOR_LOGICAL_OR_EQUAL:
837 case lexer::TokenType::PUNCTUATOR_LOGICAL_NULLISH_EQUAL:
838 case lexer::TokenType::PUNCTUATOR_EXPONENTIATION_EQUAL: {
839 ValidateLvalueAssignmentTarget(lhsExpression);
840
841 lexer_->NextToken();
842 ir::Expression *assignmentExpression = ParseExpression(CarryPatternFlags(flags));
843
844 auto *binaryAssignmentExpression =
845 AllocNode<ir::AssignmentExpression>(lhsExpression, assignmentExpression, tokenType);
846
847 binaryAssignmentExpression->SetRange({lhsExpression->Start(), assignmentExpression->End()});
848 return binaryAssignmentExpression;
849 }
850 case lexer::TokenType::LITERAL_IDENT: {
851 lexer::TokenType keywordType = lexer_->GetToken().KeywordType();
852 if (Extension() == ScriptExtension::TS && keywordType == lexer::TokenType::KEYW_AS &&
853 !(flags & ExpressionParseFlags::EXP_DISALLOW_AS) && !lexer_->GetToken().NewLine()) {
854 ir::Expression *asExpression = ParseTsAsExpression(lhsExpression, flags);
855 return ParseAssignmentExpression(asExpression);
856 } else if (Extension() == ScriptExtension::TS && keywordType == lexer::TokenType::KEYW_SATISFIES &&
857 !lexer_->GetToken().NewLine()) {
858 ir::Expression *satisfiesExpression = ParseTsSatisfiesExpression(lhsExpression);
859 return ParseAssignmentExpression(satisfiesExpression);
860 }
861 break;
862 }
863 default:
864 break;
865 }
866
867 return lhsExpression;
868 }
869
ParseTemplateLiteral(bool isTaggedTemplate)870 ir::TemplateLiteral *ParserImpl::ParseTemplateLiteral(bool isTaggedTemplate)
871 {
872 lexer::SourcePosition startLoc = lexer_->GetToken().Start();
873
874 ArenaVector<ir::TemplateElement *> quasis(Allocator()->Adapter());
875 ArenaVector<ir::Expression *> expressions(Allocator()->Adapter());
876
877 while (true) {
878 lexer_->ResetTokenEnd();
879 const auto startPos = lexer_->Save();
880 if (isTaggedTemplate) {
881 lexer_->AssignTokenTaggedTemplate();
882 }
883 lexer_->ScanString<LEX_CHAR_BACK_TICK>();
884 util::StringView cooked = lexer_->GetToken().String();
885 bool escapeError = lexer_->GetToken().EscapeError();
886
887 lexer_->Rewind(startPos);
888 auto [raw, end, scanExpression] = lexer_->ScanTemplateString();
889
890 auto *element = AllocNode<ir::TemplateElement>(raw.View(), cooked);
891 element->SetEscapeError(escapeError);
892 element->SetRange({lexer::SourcePosition {startPos.iterator.Index(), startPos.line},
893 lexer::SourcePosition {end, lexer_->Line()}});
894 quasis.push_back(element);
895
896 if (!scanExpression) {
897 lexer_->ScanTemplateStringEnd();
898 break;
899 }
900
901 ir::Expression *expression = nullptr;
902
903 {
904 lexer::TemplateLiteralParserContext ctx(lexer_);
905 lexer_->PushTemplateContext(&ctx);
906 lexer_->NextToken();
907 expression = ParseExpression();
908 }
909
910 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
911 ThrowSyntaxError("Unexpected token, expected '}'.");
912 }
913
914 expressions.push_back(expression);
915 }
916
917 auto *templateNode = AllocNode<ir::TemplateLiteral>(std::move(quasis), std::move(expressions));
918 templateNode->SetRange({startLoc, lexer_->GetToken().End()});
919
920 lexer_->NextToken();
921
922 return templateNode;
923 }
924
ParseNewExpression()925 ir::NewExpression *ParserImpl::ParseNewExpression()
926 {
927 lexer::SourcePosition start = lexer_->GetToken().Start();
928
929 lexer_->NextToken(); // eat new
930
931 // parse callee part of NewExpression
932 ir::Expression *callee = ParseMemberExpression(true);
933 if (callee->IsImportExpression() && !callee->IsGrouped()) {
934 ThrowSyntaxError("Cannot use new with import(...)");
935 }
936
937 // parse type params of NewExpression
938 lexer::SourcePosition endLoc = callee->End();
939 ir::TSTypeParameterInstantiation *typeParamInst = nullptr;
940 if (Extension() == ScriptExtension::TS) {
941 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SHIFT) {
942 lexer_->BackwardToken(lexer::TokenType::PUNCTUATOR_LESS_THAN, 1);
943 }
944 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) {
945 typeParamInst = ParseTsTypeParameterInstantiation();
946 if (typeParamInst != nullptr) {
947 endLoc = typeParamInst->End();
948 }
949 }
950 }
951
952 ArenaVector<ir::Expression *> arguments(Allocator()->Adapter());
953
954 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
955 auto *newExprNode = AllocNode<ir::NewExpression>(callee, typeParamInst, std::move(arguments));
956 newExprNode->SetRange({start, endLoc});
957
958 return newExprNode;
959 }
960
961 lexer_->NextToken(); // eat left pranthesis
962
963 // parse argument part of NewExpression
964 while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
965 ir::Expression *argument = nullptr;
966
967 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD) {
968 argument = ParseSpreadElement();
969 } else {
970 argument = ParseExpression();
971 }
972
973 arguments.push_back(argument);
974
975 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
976 lexer_->NextToken(); // eat comma
977 }
978
979 if (lexer_->GetToken().Type() == lexer::TokenType::EOS) {
980 ThrowSyntaxError("Unexpected token in argument parsing");
981 }
982 }
983
984 auto *newExprNode = AllocNode<ir::NewExpression>(callee, typeParamInst, std::move(arguments));
985 newExprNode->SetRange({start, lexer_->GetToken().End()});
986
987 lexer_->NextToken();
988
989 return newExprNode;
990 }
991
ParseLeftHandSideExpression(ExpressionParseFlags flags)992 ir::Expression *ParserImpl::ParseLeftHandSideExpression(ExpressionParseFlags flags)
993 {
994 return ParseMemberExpression(false, flags);
995 }
996
ParsePotentialNewTarget()997 ir::MetaProperty *ParserImpl::ParsePotentialNewTarget()
998 {
999 lexer::SourceRange loc = lexer_->GetToken().Loc();
1000
1001 if (lexer_->Lookahead() == LEX_CHAR_DOT) {
1002 lexer_->NextToken();
1003 lexer_->NextToken();
1004
1005 if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT && lexer_->GetToken().Ident().Is("target")) {
1006 if (!(context_.Status() & ParserStatus::ALLOW_NEW_TARGET)) {
1007 ThrowSyntaxError("'new.Target' is not allowed here");
1008 }
1009
1010 if (lexer_->GetToken().Flags() & lexer::TokenFlags::HAS_ESCAPE) {
1011 ThrowSyntaxError("'new.Target' must not contain escaped characters");
1012 }
1013
1014 auto *metaProperty = AllocNode<ir::MetaProperty>(ir::MetaProperty::MetaPropertyKind::NEW_TARGET);
1015 metaProperty->SetRange(loc);
1016 lexer_->NextToken();
1017 return metaProperty;
1018 }
1019 }
1020
1021 return nullptr;
1022 }
1023
ParsePrimaryExpression(ExpressionParseFlags flags)1024 ir::Expression *ParserImpl::ParsePrimaryExpression(ExpressionParseFlags flags)
1025 {
1026 switch (lexer_->GetToken().Type()) {
1027 case lexer::TokenType::KEYW_IMPORT: {
1028 return ParseImportExpression();
1029 }
1030 case lexer::TokenType::LITERAL_IDENT: {
1031 auto *identNode = AllocNode<ir::Identifier>(lexer_->GetToken().Ident());
1032 identNode->SetReference();
1033 identNode->SetRange(lexer_->GetToken().Loc());
1034
1035 lexer_->NextToken();
1036
1037 if (Extension() == ScriptExtension::TS && (flags & ExpressionParseFlags::ALLOW_TS_PARAM_TOKEN) &&
1038 lexer::Token::IsTsParamToken(lexer_->GetToken().Type(), lexer_->Lookahead())) {
1039 context_.Status() |= ParserStatus::FUNCTION_PARAM;
1040 ParsePotentialTsFunctionParameter(ExpressionParseFlags::NO_OPTS, identNode);
1041 }
1042
1043 return identNode;
1044 }
1045 case lexer::TokenType::LITERAL_TRUE: {
1046 auto *trueNode = AllocNode<ir::BooleanLiteral>(true);
1047 trueNode->SetRange(lexer_->GetToken().Loc());
1048
1049 lexer_->NextToken();
1050 return trueNode;
1051 }
1052 case lexer::TokenType::LITERAL_FALSE: {
1053 auto *falseNode = AllocNode<ir::BooleanLiteral>(false);
1054 falseNode->SetRange(lexer_->GetToken().Loc());
1055
1056 lexer_->NextToken();
1057 return falseNode;
1058 }
1059 case lexer::TokenType::LITERAL_NULL: {
1060 auto *nullNode = AllocNode<ir::NullLiteral>();
1061 nullNode->SetRange(lexer_->GetToken().Loc());
1062
1063 lexer_->NextToken();
1064 return nullNode;
1065 }
1066 case lexer::TokenType::LITERAL_NUMBER: {
1067 ir::Expression *numberNode = nullptr;
1068
1069 if (lexer_->GetToken().Flags() & lexer::TokenFlags::NUMBER_BIGINT) {
1070 numberNode = AllocNode<ir::BigIntLiteral>(lexer_->GetToken().BigInt());
1071 } else {
1072 numberNode = AllocNode<ir::NumberLiteral>(lexer_->GetToken().Number(), lexer_->GetToken().String());
1073 }
1074
1075 numberNode->SetRange(lexer_->GetToken().Loc());
1076
1077 lexer_->NextToken();
1078 return numberNode;
1079 }
1080 case lexer::TokenType::LITERAL_STRING: {
1081 auto *stringNode = AllocNode<ir::StringLiteral>(lexer_->GetToken().String());
1082 stringNode->SetRange(lexer_->GetToken().Loc());
1083
1084 lexer_->NextToken();
1085 return stringNode;
1086 }
1087 case lexer::TokenType::PUNCTUATOR_DIVIDE:
1088 case lexer::TokenType::PUNCTUATOR_DIVIDE_EQUAL: {
1089 lexer_->ResetTokenEnd();
1090 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_DIVIDE_EQUAL) {
1091 lexer_->BackwardToken(lexer::TokenType::PUNCTUATOR_DIVIDE, 1);
1092 }
1093 auto regexp = lexer_->ScanRegExp();
1094
1095 lexer::RegExpParser reParser(regexp, Allocator());
1096
1097 try {
1098 reParser.ParsePattern();
1099 } catch (lexer::RegExpError &e) {
1100 ThrowSyntaxError(e.message.c_str());
1101 }
1102
1103 auto *regexpNode = AllocNode<ir::RegExpLiteral>(regexp.patternStr, regexp.flagsStr);
1104 regexpNode->SetRange(lexer_->GetToken().Loc());
1105
1106 lexer_->NextToken();
1107 return regexpNode;
1108 }
1109 case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET: {
1110 // Prevent stack overflow caused by nesting too many '['. For example: [[[...
1111 CHECK_PARSER_RECURSIVE_DEPTH;
1112 return ParseArrayExpression(CarryAllowTsParamAndPatternFlags(flags));
1113 }
1114 case lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS: {
1115 return ParseCoverParenthesizedExpressionAndArrowParameterList();
1116 }
1117 case lexer::TokenType::PUNCTUATOR_LEFT_BRACE: {
1118 return ParseObjectExpression(CarryAllowTsParamAndPatternFlags(flags));
1119 }
1120 case lexer::TokenType::KEYW_FUNCTION: {
1121 return ParseFunctionExpression();
1122 }
1123 case lexer::TokenType::KEYW_CLASS: {
1124 lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1125 ir::ClassDefinition *classDefinition = ParseClassDefinition(false);
1126
1127 auto *classExpr = AllocNode<ir::ClassExpression>(classDefinition);
1128 classExpr->SetRange({startLoc, classDefinition->End()});
1129
1130 return classExpr;
1131 }
1132 case lexer::TokenType::KEYW_THIS: {
1133 auto *thisExprNode = AllocNode<ir::ThisExpression>();
1134 thisExprNode->SetRange(lexer_->GetToken().Loc());
1135
1136 lexer_->NextToken(); // eat this
1137 return thisExprNode;
1138 }
1139 case lexer::TokenType::KEYW_SUPER: {
1140 auto *superExprNode = AllocNode<ir::SuperExpression>();
1141 superExprNode->SetRange(lexer_->GetToken().Loc());
1142
1143 lexer_->NextToken(); // eat super
1144
1145 if ((lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD ||
1146 lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET) &&
1147 (context_.Status() & ParserStatus::ALLOW_SUPER)) {
1148 return superExprNode;
1149 }
1150
1151 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS &&
1152 (context_.Status() & ParserStatus::ALLOW_SUPER_CALL)) {
1153 return superExprNode;
1154 }
1155
1156 ThrowSyntaxError("Unexpected super keyword");
1157 }
1158 case lexer::TokenType::KEYW_NEW: {
1159 ir::MetaProperty *newTarget = ParsePotentialNewTarget();
1160
1161 if (newTarget) {
1162 return newTarget;
1163 }
1164
1165 return ParseNewExpression();
1166 }
1167 case lexer::TokenType::PUNCTUATOR_BACK_TICK: {
1168 return ParseTemplateLiteral();
1169 }
1170 default: {
1171 break;
1172 }
1173 }
1174
1175 ThrowSyntaxError("Primary expression expected");
1176 return nullptr;
1177 }
1178
GetOperatorPrecedence(lexer::TokenType operatorType)1179 static size_t GetOperatorPrecedence(lexer::TokenType operatorType)
1180 {
1181 ASSERT(lexer::Token::IsBinaryToken(operatorType));
1182
1183 switch (operatorType) {
1184 case lexer::TokenType::PUNCTUATOR_NULLISH_COALESCING: {
1185 constexpr auto precedence = 1;
1186 return precedence;
1187 }
1188 case lexer::TokenType::PUNCTUATOR_LOGICAL_OR: {
1189 constexpr auto precedence = 2;
1190 return precedence;
1191 }
1192 case lexer::TokenType::PUNCTUATOR_LOGICAL_AND:
1193 case lexer::TokenType::PUNCTUATOR_BITWISE_OR: {
1194 constexpr auto precedence = 3;
1195 return precedence;
1196 }
1197 case lexer::TokenType::PUNCTUATOR_BITWISE_XOR: {
1198 constexpr auto precedence = 4;
1199 return precedence;
1200 }
1201 case lexer::TokenType::PUNCTUATOR_BITWISE_AND: {
1202 constexpr auto precedence = 5;
1203 return precedence;
1204 }
1205 case lexer::TokenType::PUNCTUATOR_EQUAL:
1206 case lexer::TokenType::PUNCTUATOR_NOT_EQUAL:
1207 case lexer::TokenType::PUNCTUATOR_STRICT_EQUAL:
1208 case lexer::TokenType::PUNCTUATOR_NOT_STRICT_EQUAL: {
1209 constexpr auto precedence = 6;
1210 return precedence;
1211 }
1212 case lexer::TokenType::PUNCTUATOR_LESS_THAN:
1213 case lexer::TokenType::PUNCTUATOR_LESS_THAN_EQUAL:
1214 case lexer::TokenType::PUNCTUATOR_GREATER_THAN:
1215 case lexer::TokenType::PUNCTUATOR_GREATER_THAN_EQUAL:
1216 case lexer::TokenType::KEYW_INSTANCEOF:
1217 case lexer::TokenType::KEYW_IN: {
1218 constexpr auto precedence = 7;
1219 return precedence;
1220 }
1221 case lexer::TokenType::PUNCTUATOR_LEFT_SHIFT:
1222 case lexer::TokenType::PUNCTUATOR_RIGHT_SHIFT:
1223 case lexer::TokenType::PUNCTUATOR_UNSIGNED_RIGHT_SHIFT: {
1224 constexpr auto precedence = 8;
1225 return precedence;
1226 }
1227 case lexer::TokenType::PUNCTUATOR_PLUS:
1228 case lexer::TokenType::PUNCTUATOR_MINUS: {
1229 constexpr auto precedence = 9;
1230 return precedence;
1231 }
1232 case lexer::TokenType::PUNCTUATOR_MULTIPLY:
1233 case lexer::TokenType::PUNCTUATOR_DIVIDE:
1234 case lexer::TokenType::PUNCTUATOR_MOD: {
1235 const auto precedence = 10;
1236 return precedence;
1237 }
1238 case lexer::TokenType::PUNCTUATOR_EXPONENTIATION: {
1239 constexpr auto precedence = 11;
1240 return precedence;
1241 }
1242 default: {
1243 UNREACHABLE();
1244 }
1245 }
1246 }
1247
ShouldBinaryExpressionBeAmended(ir::BinaryExpression * binaryExpression,lexer::TokenType operatorType)1248 static inline bool ShouldBinaryExpressionBeAmended(ir::BinaryExpression *binaryExpression,
1249 lexer::TokenType operatorType)
1250 {
1251 return GetOperatorPrecedence(binaryExpression->OperatorType()) <= GetOperatorPrecedence(operatorType) &&
1252 !binaryExpression->IsGrouped() &&
1253 (operatorType != lexer::TokenType::PUNCTUATOR_EXPONENTIATION ||
1254 binaryExpression->OperatorType() != lexer::TokenType::PUNCTUATOR_EXPONENTIATION);
1255 }
1256
ParseBinaryExpression(ir::Expression * left)1257 ir::Expression *ParserImpl::ParseBinaryExpression(ir::Expression *left)
1258 {
1259 lexer::TokenType operatorType = lexer_->GetToken().Type();
1260 ASSERT(lexer::Token::IsBinaryToken(operatorType));
1261
1262 if (operatorType == lexer::TokenType::PUNCTUATOR_EXPONENTIATION) {
1263 if (left->IsUnaryExpression() && !left->IsGrouped()) {
1264 ThrowSyntaxError(
1265 "Illegal expression. Wrap left hand side or entire "
1266 "exponentiation in parentheses.");
1267 }
1268 }
1269
1270 lexer_->NextToken();
1271
1272 ir::Expression *rightExprNode = ParseExpression(ExpressionParseFlags::DISALLOW_YIELD);
1273
1274 ir::Expression *rightExpr = rightExprNode;
1275 ir::ConditionalExpression *conditionalExpr = nullptr;
1276
1277 if (rightExpr->IsConditionalExpression() && !rightExpr->IsGrouped()) {
1278 conditionalExpr = rightExpr->AsConditionalExpression();
1279 rightExpr = conditionalExpr->Test();
1280 }
1281
1282 if (rightExpr->IsBinaryExpression() &&
1283 ShouldBinaryExpressionBeAmended(rightExpr->AsBinaryExpression(), operatorType)) {
1284 if ((operatorType == lexer::TokenType::PUNCTUATOR_LOGICAL_OR ||
1285 operatorType == lexer::TokenType::PUNCTUATOR_LOGICAL_AND) &&
1286 rightExpr->AsBinaryExpression()->OperatorType() == lexer::TokenType::PUNCTUATOR_NULLISH_COALESCING) {
1287 ThrowSyntaxError("Nullish coalescing operator ?? requires parens when mixing with logical operators.");
1288 }
1289
1290 bool shouldBeAmended = true;
1291
1292 ir::BinaryExpression *binaryExpression = rightExpr->AsBinaryExpression();
1293 ir::BinaryExpression *parentExpression = nullptr;
1294
1295 while (binaryExpression->Left()->IsBinaryExpression() && shouldBeAmended) {
1296 parentExpression = binaryExpression;
1297 parentExpression->SetStart(left->Start());
1298 binaryExpression = binaryExpression->Left()->AsBinaryExpression();
1299 shouldBeAmended = ShouldBinaryExpressionBeAmended(binaryExpression, operatorType);
1300 }
1301
1302 if (shouldBeAmended) {
1303 auto *leftExprNode = AllocNode<ir::BinaryExpression>(left, binaryExpression->Left(), operatorType);
1304 leftExprNode->SetRange({left->Start(), binaryExpression->Left()->End()});
1305
1306 binaryExpression->SetLeft(leftExprNode);
1307 } else {
1308 // Transfer the parent's left ownership to right_node
1309 ir::Expression *rightNode = parentExpression->Left();
1310
1311 auto *binaryOrLogicalExpressionNode = AllocNode<ir::BinaryExpression>(left, rightNode, operatorType);
1312 binaryOrLogicalExpressionNode->SetRange({left->Start(), rightNode->End()});
1313
1314 parentExpression->SetLeft(binaryOrLogicalExpressionNode);
1315 }
1316 } else {
1317 if (operatorType == lexer::TokenType::PUNCTUATOR_NULLISH_COALESCING && rightExpr->IsBinaryExpression() &&
1318 rightExpr->AsBinaryExpression()->IsLogical() && !rightExpr->IsGrouped()) {
1319 ThrowSyntaxError("Nullish coalescing operator ?? requires parens when mixing with logical operators.");
1320 }
1321 const lexer::SourcePosition &endPos = rightExpr->End();
1322 rightExpr = AllocNode<ir::BinaryExpression>(left, rightExpr, operatorType);
1323 rightExpr->SetRange({left->Start(), endPos});
1324 }
1325
1326 if (conditionalExpr != nullptr) {
1327 conditionalExpr->SetStart(rightExpr->Start());
1328 conditionalExpr->SetTest(rightExpr);
1329 return conditionalExpr;
1330 }
1331
1332 return rightExpr;
1333 }
1334
ParseCallExpression(ir::Expression * callee,bool isOptionalChain,bool isAsync)1335 ir::CallExpression *ParserImpl::ParseCallExpression(ir::Expression *callee, bool isOptionalChain, bool isAsync)
1336 {
1337 ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS);
1338
1339 while (true) {
1340 lexer_->NextToken();
1341 ArenaVector<ir::Expression *> arguments(Allocator()->Adapter());
1342
1343 while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
1344 ir::Expression *argument = nullptr;
1345 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD) {
1346 argument = ParseSpreadElement();
1347 } else {
1348 argument = ParseExpression(isAsync ? ExpressionParseFlags::ALLOW_TS_PARAM_TOKEN
1349 : ExpressionParseFlags::NO_OPTS);
1350 }
1351
1352 arguments.push_back(argument);
1353
1354 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
1355 lexer_->NextToken();
1356 } else if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
1357 ThrowSyntaxError("Expected a ')'");
1358 }
1359 }
1360
1361 auto *callExpr = AllocNode<ir::CallExpression>(callee, std::move(arguments), nullptr, isOptionalChain);
1362 callExpr->SetRange({callee->Start(), lexer_->GetToken().End()});
1363 isOptionalChain = false;
1364
1365 lexer_->NextToken();
1366
1367 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
1368 return callExpr;
1369 }
1370
1371 callee = callExpr;
1372 }
1373
1374 UNREACHABLE();
1375 return nullptr;
1376 }
1377
ParseOptionalChain(ir::Expression * leftSideExpr)1378 ir::Expression *ParserImpl::ParseOptionalChain(ir::Expression *leftSideExpr)
1379 {
1380 lexer::TokenType tokenType = lexer_->GetToken().Type();
1381 ir::Expression *returnExpression = nullptr;
1382
1383 switch (tokenType) {
1384 case lexer::TokenType::PUNCTUATOR_HASH_MARK:
1385 case lexer::TokenType::LITERAL_IDENT:
1386 case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET: {
1387 returnExpression = ParseOptionalMemberExpression(leftSideExpr);
1388 break;
1389 }
1390 case lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS: {
1391 returnExpression = ParseCallExpression(leftSideExpr, true);
1392 break;
1393 }
1394 case lexer::TokenType::PUNCTUATOR_LESS_THAN: {
1395 if (Extension() != ScriptExtension::TS) {
1396 ThrowSyntaxError("Unexpected token");
1397 }
1398
1399 ir::TSTypeParameterInstantiation *typeParams = ParseTsTypeParameterInstantiation(true);
1400
1401 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
1402 ThrowSyntaxError("Expected '('");
1403 }
1404
1405 returnExpression = ParseCallExpression(leftSideExpr, true);
1406 returnExpression->AsCallExpression()->SetTypeParams(typeParams);
1407 break;
1408 }
1409 case lexer::TokenType::PUNCTUATOR_BACK_TICK: {
1410 ThrowSyntaxError("Tagged Template Literals are not allowed in optionalChain");
1411 }
1412 default: {
1413 ThrowSyntaxError("Unexpected token");
1414 }
1415 }
1416
1417 // Static semantic
1418 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_BACK_TICK) {
1419 ThrowSyntaxError("Tagged Template Literals are not allowed in optionalChain");
1420 }
1421
1422 return returnExpression;
1423 }
1424
ParseOptionalMemberExpression(ir::Expression * object)1425 ir::Expression *ParserImpl::ParseOptionalMemberExpression(ir::Expression *object)
1426 {
1427 ir::Expression *property = nullptr;
1428 bool computed = false;
1429 auto kind = ir::MemberExpression::MemberExpressionKind::PROPERTY_ACCESS;
1430
1431 lexer::SourcePosition end;
1432 lexer::TokenType tokenType = lexer_->GetToken().Type();
1433 ASSERT(tokenType == lexer::TokenType::PUNCTUATOR_HASH_MARK || tokenType == lexer::TokenType::LITERAL_IDENT ||
1434 tokenType == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET);
1435
1436 if (tokenType == lexer::TokenType::PUNCTUATOR_HASH_MARK) {
1437 property = ParsePrivateIdentifier();
1438 end = property->End();
1439 } else if (tokenType == lexer::TokenType::LITERAL_IDENT) {
1440 property = AllocNode<ir::Identifier>(lexer_->GetToken().Ident());
1441 property->AsIdentifier()->SetReference();
1442 property->SetRange(lexer_->GetToken().Loc());
1443 end = lexer_->GetToken().End();
1444 lexer_->NextToken();
1445 } else {
1446 computed = true;
1447 kind = ir::MemberExpression::MemberExpressionKind::ELEMENT_ACCESS;
1448 lexer_->NextToken(); // eat '['
1449 property = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
1450
1451 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
1452 ThrowSyntaxError("Expected ']'");
1453 }
1454 end = lexer_->GetToken().End();
1455 lexer_->NextToken();
1456 }
1457
1458 auto *memberExpr = AllocNode<ir::MemberExpression>(object, property, kind, computed, true);
1459 memberExpr->SetRange({object->Start(), end});
1460 return memberExpr;
1461 }
1462
ParsePotentialArrowExpression(ir::Expression ** returnExpression,const lexer::SourcePosition & startLoc,bool ignoreCallExpression)1463 ir::ArrowFunctionExpression *ParserImpl::ParsePotentialArrowExpression(ir::Expression **returnExpression,
1464 const lexer::SourcePosition &startLoc,
1465 bool ignoreCallExpression)
1466 {
1467 ir::TSTypeParameterDeclaration *typeParamDecl = nullptr;
1468
1469 const auto savedPos = lexer_->Save();
1470
1471 switch (lexer_->GetToken().Type()) {
1472 case lexer::TokenType::KEYW_FUNCTION: {
1473 *returnExpression = ParseFunctionExpression(ParserStatus::ASYNC_FUNCTION);
1474 (*returnExpression)->SetStart(startLoc);
1475 break;
1476 }
1477 case lexer::TokenType::LITERAL_IDENT: {
1478 if (!lexer_->CheckArrow()) {
1479 return nullptr;
1480 }
1481
1482 ir::Expression *identRef = ParsePrimaryExpression();
1483 ASSERT(identRef->IsIdentifier());
1484
1485 ir::ArrowFunctionExpression *arrowFuncExpr = ParseArrowFunctionExpression(identRef, nullptr, nullptr, true);
1486 arrowFuncExpr->SetStart(startLoc);
1487
1488 return arrowFuncExpr;
1489 }
1490 case lexer::TokenType::PUNCTUATOR_ARROW: {
1491 ir::ArrowFunctionExpression *arrowFuncExpr =
1492 ParseArrowFunctionExpression(*returnExpression, nullptr, nullptr, true);
1493 arrowFuncExpr->SetStart(startLoc);
1494 return arrowFuncExpr;
1495 }
1496 case lexer::TokenType::PUNCTUATOR_LEFT_SHIFT: {
1497 if (Extension() == ScriptExtension::TS) {
1498 return nullptr;
1499 }
1500
1501 break;
1502 }
1503 case lexer::TokenType::PUNCTUATOR_LESS_THAN: {
1504 if (Extension() != ScriptExtension::TS) {
1505 return nullptr;
1506 }
1507
1508 typeParamDecl = ParseTsTypeParameterDeclaration(false);
1509 if (!typeParamDecl) {
1510 lexer_->Rewind(savedPos);
1511 return nullptr;
1512 }
1513
1514 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
1515 ThrowSyntaxError("'(' expected");
1516 }
1517
1518 [[fallthrough]];
1519 }
1520 case lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS: {
1521 if (ignoreCallExpression) {
1522 lexer_->Rewind(savedPos);
1523 break;
1524 }
1525 ir::CallExpression *callExpression = ParseCallExpression(*returnExpression, false, true);
1526
1527 ir::Expression *returnTypeAnnotation = nullptr;
1528 if (Extension() == ScriptExtension::TS && lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
1529 lexer_->NextToken(); // eat ':'
1530 TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
1531 returnTypeAnnotation = ParseTsTypeAnnotation(&options);
1532 }
1533
1534 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_ARROW) {
1535 ir::ArrowFunctionExpression *arrowFuncExpr =
1536 ParseArrowFunctionExpression(callExpression, typeParamDecl, returnTypeAnnotation, true);
1537 arrowFuncExpr->SetStart(startLoc);
1538
1539 return arrowFuncExpr;
1540 }
1541
1542 if (Extension() == ScriptExtension::TS && (returnTypeAnnotation || typeParamDecl)) {
1543 ThrowSyntaxError("'=>' expected");
1544 }
1545
1546 *returnExpression = callExpression;
1547 break;
1548 }
1549 default: {
1550 break;
1551 }
1552 }
1553
1554 return nullptr;
1555 }
1556
IsGenericInstantiation()1557 bool ParserImpl::IsGenericInstantiation()
1558 {
1559 switch (lexer_->GetToken().Type()) {
1560 case lexer::TokenType::EOS:
1561 case lexer::TokenType::PUNCTUATOR_SEMI_COLON:
1562 case lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS:
1563 case lexer::TokenType::PUNCTUATOR_RIGHT_BRACE:
1564 case lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET:
1565 case lexer::TokenType::PUNCTUATOR_EQUAL:
1566 case lexer::TokenType::PUNCTUATOR_LESS_THAN_EQUAL:
1567 case lexer::TokenType::PUNCTUATOR_NOT_EQUAL:
1568 case lexer::TokenType::PUNCTUATOR_QUESTION_MARK:
1569 case lexer::TokenType::PUNCTUATOR_STRICT_EQUAL:
1570 case lexer::TokenType::PUNCTUATOR_NOT_STRICT_EQUAL:
1571 case lexer::TokenType::PUNCTUATOR_LOGICAL_AND:
1572 case lexer::TokenType::PUNCTUATOR_SUBSTITUTION:
1573 case lexer::TokenType::PUNCTUATOR_LOGICAL_OR:
1574 case lexer::TokenType::PUNCTUATOR_COMMA:
1575 case lexer::TokenType::PUNCTUATOR_NULLISH_COALESCING:
1576 case lexer::TokenType::PUNCTUATOR_LOGICAL_AND_EQUAL:
1577 case lexer::TokenType::PUNCTUATOR_LOGICAL_OR_EQUAL:
1578 case lexer::TokenType::PUNCTUATOR_QUESTION_DOT: {
1579 return true;
1580 }
1581 default: {
1582 return false;
1583 }
1584 }
1585 }
1586
ParsePotentialTsGenericFunctionCall(ir::Expression ** returnExpression,const lexer::SourcePosition & startLoc,bool ignoreCallExpression)1587 bool ParserImpl::ParsePotentialTsGenericFunctionCall(ir::Expression **returnExpression,
1588 const lexer::SourcePosition &startLoc, bool ignoreCallExpression)
1589 {
1590 if (Extension() != ScriptExtension::TS || lexer_->Lookahead() == LEX_CHAR_LESS_THAN) {
1591 return true;
1592 }
1593
1594 const auto savedPos = lexer_->Save();
1595
1596 bool isLeftShift = false;
1597 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SHIFT) {
1598 lexer_->BackwardToken(lexer::TokenType::PUNCTUATOR_LESS_THAN, 1);
1599 isLeftShift = true;
1600 }
1601
1602 ir::TSTypeParameterInstantiation *typeParams;
1603 try {
1604 typeParams = ParseTsTypeParameterInstantiation(false);
1605 } catch (const Error &e) {
1606 if (!isLeftShift) {
1607 throw e;
1608 }
1609 typeParams = nullptr;
1610 }
1611
1612 if (!typeParams) {
1613 lexer_->Rewind(savedPos);
1614 return true;
1615 }
1616
1617 if (IsGenericInstantiation() || lexer_->GetToken().NewLine()) {
1618 *returnExpression = AllocNode<ir::TypeArgumentsExpression>(*returnExpression, typeParams);
1619 lexer::SourcePosition endLoc = typeParams->End();
1620 (*returnExpression)->SetRange({startLoc, endLoc});
1621 return false;
1622 }
1623
1624 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
1625 if (!ignoreCallExpression) {
1626 *returnExpression = ParseCallExpression(*returnExpression, false);
1627 (*returnExpression)->AsCallExpression()->SetTypeParams(typeParams);
1628 return false;
1629 }
1630 }
1631
1632 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_BACK_TICK) {
1633 ir::TemplateLiteral *propertyNode = ParseTemplateLiteral(true);
1634 lexer::SourcePosition endLoc = propertyNode->End();
1635
1636 *returnExpression = AllocNode<ir::TaggedTemplateExpression>(*returnExpression, propertyNode, typeParams);
1637 (*returnExpression)->SetRange({startLoc, endLoc});
1638 return false;
1639 }
1640
1641 lexer_->Rewind(savedPos);
1642 return true;
1643 }
1644
ParsePostPrimaryExpression(ir::Expression * primaryExpr,lexer::SourcePosition startLoc,bool ignoreCallExpression,bool * isChainExpression)1645 ir::Expression *ParserImpl::ParsePostPrimaryExpression(ir::Expression *primaryExpr, lexer::SourcePosition startLoc,
1646 bool ignoreCallExpression, bool *isChainExpression)
1647 {
1648 ir::Expression *returnExpression = primaryExpr;
1649
1650 while (true) {
1651 switch (lexer_->GetToken().Type()) {
1652 case lexer::TokenType::PUNCTUATOR_QUESTION_DOT: {
1653 *isChainExpression = true;
1654 lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT); // eat ?.
1655 returnExpression = ParseOptionalChain(returnExpression);
1656 continue;
1657 }
1658 case lexer::TokenType::PUNCTUATOR_PERIOD: {
1659 lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT); // eat period
1660
1661 ir::Expression *property;
1662 if (program_.TargetApiVersion() > 10 &&
1663 lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_HASH_MARK) {
1664 if (returnExpression->IsSuperExpression()) {
1665 ThrowSyntaxError("Unexpected private property access in super keyword");
1666 }
1667 property = ParsePrivateIdentifier();
1668 } else {
1669 bool isPrivate = false;
1670 lexer::SourcePosition memberStart = lexer_->GetToken().Start();
1671 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_HASH_MARK) {
1672 if (!(context_.Status() & ParserStatus::IN_CLASS_BODY)) {
1673 ThrowSyntaxError("Private identifiers are not allowed outside class bodies.");
1674 }
1675 isPrivate = true;
1676 lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);
1677 }
1678
1679 if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
1680 ThrowSyntaxError("Expected an identifier");
1681 }
1682 auto *identNode = AllocNode<ir::Identifier>(lexer_->GetToken().Ident());
1683 identNode->SetRange(lexer_->GetToken().Loc());
1684 lexer_->NextToken();
1685
1686 if (isPrivate) {
1687 property = AllocNode<ir::TSPrivateIdentifier>(identNode, nullptr, nullptr);
1688 property->SetRange({memberStart, identNode->End()});
1689 } else {
1690 property = identNode;
1691 }
1692 }
1693 const lexer::SourcePosition &startPos = returnExpression->Start();
1694 returnExpression = AllocNode<ir::MemberExpression>(
1695 returnExpression, property, ir::MemberExpression::MemberExpressionKind::PROPERTY_ACCESS, false,
1696 false);
1697 returnExpression->SetRange({startPos, property->End()});
1698 continue;
1699 }
1700 case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET: {
1701 if (context_.Status() & ParserStatus::IN_DECORATOR) {
1702 break;
1703 }
1704
1705 lexer_->NextToken(); // eat '['
1706 ir::Expression *propertyNode = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
1707
1708 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
1709 ThrowSyntaxError("Unexpected token");
1710 }
1711
1712 const lexer::SourcePosition &startPos = returnExpression->Start();
1713 returnExpression = AllocNode<ir::MemberExpression>(
1714 returnExpression, propertyNode, ir::MemberExpression::MemberExpressionKind::ELEMENT_ACCESS, true,
1715 false);
1716 returnExpression->SetRange({startPos, lexer_->GetToken().End()});
1717 lexer_->NextToken();
1718 continue;
1719 }
1720 case lexer::TokenType::PUNCTUATOR_LEFT_SHIFT:
1721 case lexer::TokenType::PUNCTUATOR_LESS_THAN: {
1722 bool shouldBreak =
1723 ParsePotentialTsGenericFunctionCall(&returnExpression, startLoc, ignoreCallExpression);
1724 if (shouldBreak) {
1725 break;
1726 }
1727
1728 continue;
1729 }
1730 case lexer::TokenType::PUNCTUATOR_BACK_TICK: {
1731 ir::TemplateLiteral *propertyNode = ParseTemplateLiteral(true);
1732 lexer::SourcePosition endLoc = propertyNode->End();
1733
1734 returnExpression = AllocNode<ir::TaggedTemplateExpression>(returnExpression, propertyNode, nullptr);
1735 returnExpression->SetRange({startLoc, endLoc});
1736 continue;
1737 }
1738 case lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS: {
1739 if (!ignoreCallExpression) {
1740 returnExpression = ParseCallExpression(returnExpression, false);
1741 continue;
1742 }
1743 break;
1744 }
1745 case lexer::TokenType::PUNCTUATOR_EXCLAMATION_MARK: {
1746 if (Extension() != ScriptExtension::TS || !returnExpression || lexer_->GetToken().NewLine()) {
1747 break;
1748 }
1749
1750 returnExpression = AllocNode<ir::TSNonNullExpression>(returnExpression);
1751 returnExpression->SetRange({startLoc, lexer_->GetToken().End()});
1752 lexer_->NextToken();
1753 continue;
1754 }
1755 default: {
1756 break;
1757 }
1758 }
1759
1760 break;
1761 }
1762
1763 return returnExpression;
1764 }
1765
ValidateUpdateExpression(ir::Expression * returnExpression,bool isChainExpression)1766 void ParserImpl::ValidateUpdateExpression(ir::Expression *returnExpression, bool isChainExpression)
1767 {
1768 if (returnExpression->IsTSAsExpression()) {
1769 ValidateUpdateExpression(returnExpression->AsTSAsExpression()->Expr(), isChainExpression);
1770 return;
1771 }
1772 if (returnExpression->IsTSTypeAssertion()) {
1773 ValidateUpdateExpression(returnExpression->AsTSTypeAssertion()->GetExpression(), isChainExpression);
1774 return;
1775 }
1776
1777 if ((!returnExpression->IsMemberExpression() && !returnExpression->IsIdentifier() &&
1778 !returnExpression->IsTSNonNullExpression()) ||
1779 isChainExpression) {
1780 ThrowSyntaxError("Invalid left-hand side operator.");
1781 }
1782
1783 if (returnExpression->IsIdentifier()) {
1784 const util::StringView &returnExpressionStr = returnExpression->AsIdentifier()->Name();
1785
1786 if (returnExpressionStr.Is("eval")) {
1787 ThrowSyntaxError("Assigning to 'eval' in strict mode is invalid");
1788 }
1789
1790 if (returnExpressionStr.Is("arguments")) {
1791 ThrowSyntaxError("Assigning to 'arguments' in strict mode is invalid");
1792 }
1793 }
1794 }
1795
ParseMemberExpression(bool ignoreCallExpression,ExpressionParseFlags flags)1796 ir::Expression *ParserImpl::ParseMemberExpression(bool ignoreCallExpression, ExpressionParseFlags flags)
1797 {
1798 bool isAsync = lexer_->GetToken().IsAsyncModifier();
1799 lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1800 ir::Expression *returnExpression = ParsePrimaryExpression(flags);
1801
1802 if (lexer_->GetToken().NewLine() && returnExpression->IsArrowFunctionExpression()) {
1803 return returnExpression;
1804 }
1805
1806 if (isAsync && !lexer_->GetToken().NewLine()) {
1807 ir::ArrowFunctionExpression *arrow = ParsePotentialArrowExpression(&returnExpression, startLoc,
1808 ignoreCallExpression);
1809
1810 if (arrow) {
1811 return arrow;
1812 }
1813 }
1814
1815 bool isChainExpression = false;
1816 returnExpression = ParsePostPrimaryExpression(returnExpression, startLoc, ignoreCallExpression, &isChainExpression);
1817
1818 if (!lexer_->GetToken().NewLine() && lexer::Token::IsUpdateToken(lexer_->GetToken().Type())) {
1819 lexer::SourcePosition start = returnExpression->Start();
1820
1821 ValidateUpdateExpression(returnExpression, isChainExpression);
1822
1823 returnExpression = AllocNode<ir::UpdateExpression>(returnExpression, lexer_->GetToken().Type(), false);
1824
1825 returnExpression->SetRange({start, lexer_->GetToken().End()});
1826 lexer_->NextToken();
1827 }
1828
1829 if (isChainExpression) {
1830 lexer::SourcePosition endLoc = returnExpression->End();
1831 returnExpression = AllocNode<ir::ChainExpression>(returnExpression);
1832 returnExpression->SetRange({startLoc, endLoc});
1833 }
1834
1835 return returnExpression;
1836 }
1837
ParsePotentialTsFunctionParameter(ExpressionParseFlags flags,ir::Expression * returnNode,bool isDeclare)1838 void ParserImpl::ParsePotentialTsFunctionParameter(ExpressionParseFlags flags, ir::Expression *returnNode,
1839 bool isDeclare)
1840 {
1841 if (Extension() != ScriptExtension::TS || !(context_.Status() & ParserStatus::FUNCTION_PARAM)) {
1842 return;
1843 }
1844
1845 bool isOptional = false;
1846
1847 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_QUESTION_MARK) {
1848 if (flags & ExpressionParseFlags::IN_REST) {
1849 ThrowSyntaxError("A rest parameter cannot be optional");
1850 }
1851
1852 ASSERT(returnNode->IsIdentifier() || returnNode->IsObjectPattern() || returnNode->IsArrayPattern());
1853 if (returnNode->IsIdentifier()) {
1854 returnNode->AsIdentifier()->SetOptional(true);
1855 } else if (returnNode->IsObjectPattern()) {
1856 returnNode->AsObjectPattern()->SetOptional(true);
1857 } else if (returnNode->IsArrayPattern()) {
1858 returnNode->AsArrayPattern()->SetOptional(true);
1859 }
1860
1861 isOptional = true;
1862 lexer_->NextToken(); // eat '?'
1863 }
1864
1865 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
1866 lexer_->NextToken(); // eat ':'
1867 TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
1868 returnNode->SetTsTypeAnnotation(ParseTsTypeAnnotation(&options));
1869 }
1870
1871 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
1872 return;
1873 }
1874
1875 if (flags & ExpressionParseFlags::IN_REST) {
1876 ThrowSyntaxError("A rest parameter cannot have an initializer");
1877 }
1878
1879 if (returnNode->IsIdentifier() && isOptional) {
1880 ThrowSyntaxError("Parameter cannot have question mark and initializer");
1881 }
1882 }
1883
ParsePatternElement(ExpressionParseFlags flags,bool allowDefault,bool isDeclare)1884 ir::Expression *ParserImpl::ParsePatternElement(ExpressionParseFlags flags, bool allowDefault, bool isDeclare)
1885 {
1886 ir::Expression *returnNode = nullptr;
1887
1888 switch (lexer_->GetToken().Type()) {
1889 case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET: {
1890 returnNode = ParseArrayExpression(ExpressionParseFlags::MUST_BE_PATTERN);
1891 break;
1892 }
1893 case lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD: {
1894 if (flags & ExpressionParseFlags::IN_REST) {
1895 ThrowSyntaxError("Unexpected token");
1896 }
1897
1898 returnNode = ParseSpreadElement(ExpressionParseFlags::MUST_BE_PATTERN);
1899 break;
1900 }
1901 case lexer::TokenType::PUNCTUATOR_LEFT_BRACE: {
1902 returnNode =
1903 ParseObjectExpression(ExpressionParseFlags::MUST_BE_PATTERN | ExpressionParseFlags::OBJECT_PATTERN);
1904 break;
1905 }
1906 case lexer::TokenType::LITERAL_IDENT: {
1907 returnNode = AllocNode<ir::Identifier>(lexer_->GetToken().Ident());
1908 returnNode->AsIdentifier()->SetReference();
1909 returnNode->SetRange(lexer_->GetToken().Loc());
1910 lexer_->NextToken();
1911 break;
1912 }
1913 default: {
1914 ThrowSyntaxError("Unexpected token, expected an identifier.");
1915 }
1916 }
1917
1918 ParsePotentialTsFunctionParameter(flags, returnNode, isDeclare);
1919
1920 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
1921 return returnNode;
1922 }
1923
1924 if (flags & ExpressionParseFlags::IN_REST) {
1925 ThrowSyntaxError("Unexpected token, expected ')'");
1926 }
1927
1928 if (!allowDefault) {
1929 ThrowSyntaxError("Invalid destructuring assignment target");
1930 }
1931
1932 lexer_->NextToken();
1933
1934 if ((context_.Status() & ParserStatus::GENERATOR_FUNCTION) &&
1935 lexer_->GetToken().Type() == lexer::TokenType::KEYW_YIELD) {
1936 ThrowSyntaxError("Yield is not allowed in generator parameters");
1937 }
1938
1939 ir::Expression *rightNode = ParseExpression();
1940
1941 auto *assignmentExpression = AllocNode<ir::AssignmentExpression>(
1942 ir::AstNodeType::ASSIGNMENT_PATTERN, returnNode, rightNode, lexer::TokenType::PUNCTUATOR_SUBSTITUTION);
1943 assignmentExpression->SetRange({returnNode->Start(), rightNode->End()});
1944
1945 return assignmentExpression;
1946 }
1947
CheckPropertyKeyAsycModifier(ParserStatus * methodStatus)1948 void ParserImpl::CheckPropertyKeyAsycModifier(ParserStatus *methodStatus)
1949 {
1950 const auto asyncPos = lexer_->Save();
1951 lexer_->NextToken();
1952
1953 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS &&
1954 lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COLON &&
1955 lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COMMA &&
1956 lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
1957 if (lexer_->GetToken().NewLine()) {
1958 ThrowSyntaxError(
1959 "Async methods cannot have a line terminator between "
1960 "'async' and the property name");
1961 }
1962
1963 *methodStatus |= ParserStatus::ASYNC_FUNCTION;
1964 } else {
1965 lexer_->Rewind(asyncPos);
1966 }
1967 }
1968
IsAccessorDelimiter(char32_t cp)1969 static bool IsAccessorDelimiter(char32_t cp)
1970 {
1971 switch (cp) {
1972 case LEX_CHAR_LEFT_PAREN:
1973 case LEX_CHAR_COLON:
1974 case LEX_CHAR_COMMA:
1975 case LEX_CHAR_RIGHT_BRACE: {
1976 return true;
1977 }
1978 default: {
1979 return false;
1980 }
1981 }
1982 }
1983
IsShorthandDelimiter(char32_t cp)1984 static bool IsShorthandDelimiter(char32_t cp)
1985 {
1986 switch (cp) {
1987 case LEX_CHAR_EQUALS:
1988 case LEX_CHAR_COMMA:
1989 case LEX_CHAR_RIGHT_BRACE: {
1990 return true;
1991 }
1992 default: {
1993 return false;
1994 }
1995 }
1996 }
1997
ValidateAccessor(ExpressionParseFlags flags,lexer::TokenFlags currentTokenFlags)1998 void ParserImpl::ValidateAccessor(ExpressionParseFlags flags, lexer::TokenFlags currentTokenFlags)
1999 {
2000 if (flags & ExpressionParseFlags::MUST_BE_PATTERN) {
2001 ThrowSyntaxError("Unexpected token");
2002 }
2003
2004 if (currentTokenFlags & lexer::TokenFlags::HAS_ESCAPE) {
2005 ThrowSyntaxError("Keyword must not contain escaped characters");
2006 }
2007 }
2008
ParseShorthandProperty(const lexer::LexerPosition * startPos)2009 ir::Property *ParserImpl::ParseShorthandProperty(const lexer::LexerPosition *startPos)
2010 {
2011 char32_t nextCp = lexer_->Lookahead();
2012 lexer::TokenType keywordType = lexer_->GetToken().KeywordType();
2013
2014 /* Rewind the lexer to the beginning of the ident to repase as common
2015 * identifier */
2016 lexer_->Rewind(*startPos);
2017 lexer_->NextToken();
2018 lexer::SourcePosition start = lexer_->GetToken().Start();
2019
2020 if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
2021 ThrowSyntaxError("Expected an identifier");
2022 }
2023
2024 if (lexer_->GetToken().KeywordType() >= lexer::TokenType::KEYW_PRIVATE &&
2025 lexer_->GetToken().KeywordType() <= lexer::TokenType::KEYW_DECLARE) {
2026 ThrowSyntaxError(" Unexpected reserved word", lexer_->GetToken().Start());
2027 }
2028
2029 const util::StringView &ident = lexer_->GetToken().Ident();
2030
2031 auto *key = AllocNode<ir::Identifier>(ident);
2032 key->SetRange(lexer_->GetToken().Loc());
2033
2034 ir::Expression *value = AllocNode<ir::Identifier>(ident);
2035 value->AsIdentifier()->SetReference();
2036 value->SetRange(lexer_->GetToken().Loc());
2037
2038 lexer::SourcePosition end;
2039
2040 if (nextCp == LEX_CHAR_EQUALS) {
2041 if (keywordType == lexer::TokenType::KEYW_EVAL) {
2042 ThrowSyntaxError("eval can't be defined or assigned to in strict mode code");
2043 }
2044
2045 lexer_->NextToken(); // substitution
2046 lexer_->NextToken(); // eat substitution
2047
2048 ir::Expression *rightNode = ParseExpression();
2049
2050 auto *assignmentExpression = AllocNode<ir::AssignmentExpression>(
2051 ir::AstNodeType::ASSIGNMENT_PATTERN, value, rightNode, lexer::TokenType::PUNCTUATOR_SUBSTITUTION);
2052 assignmentExpression->SetRange({value->Start(), rightNode->End()});
2053 end = rightNode->End();
2054 value = assignmentExpression;
2055 } else {
2056 end = lexer_->GetToken().End();
2057 lexer_->NextToken();
2058 }
2059
2060 auto *returnProperty = AllocNode<ir::Property>(key, value);
2061 returnProperty->SetRange({start, end});
2062
2063 return returnProperty;
2064 }
2065
ParsePropertyModifiers(ExpressionParseFlags flags,ir::PropertyKind * propertyKind,ParserStatus * methodStatus)2066 bool ParserImpl::ParsePropertyModifiers(ExpressionParseFlags flags, ir::PropertyKind *propertyKind,
2067 ParserStatus *methodStatus)
2068 {
2069 if (lexer_->GetToken().IsAsyncModifier()) {
2070 CheckPropertyKeyAsycModifier(methodStatus);
2071 }
2072
2073 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MULTIPLY) {
2074 if (flags & ExpressionParseFlags::MUST_BE_PATTERN) {
2075 ThrowSyntaxError("Unexpected token");
2076 }
2077
2078 lexer_->NextToken();
2079 *methodStatus |= ParserStatus::GENERATOR_FUNCTION;
2080 }
2081
2082 lexer::TokenFlags currentTokenFlags = lexer_->GetToken().Flags();
2083 char32_t nextCp = lexer_->Lookahead();
2084 lexer::TokenType keywordType = lexer_->GetToken().KeywordType();
2085 // Parse getter property
2086 if (keywordType == lexer::TokenType::KEYW_GET && !IsAccessorDelimiter(nextCp)) {
2087 ValidateAccessor(flags, currentTokenFlags);
2088
2089 *propertyKind = ir::PropertyKind::GET;
2090 lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);
2091
2092 return false;
2093 }
2094
2095 // Parse setter property
2096 if (keywordType == lexer::TokenType::KEYW_SET && !IsAccessorDelimiter(nextCp)) {
2097 ValidateAccessor(flags, currentTokenFlags);
2098
2099 *propertyKind = ir::PropertyKind::SET;
2100 lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);
2101
2102 return false;
2103 }
2104
2105 // Parse shorthand property or assignment pattern
2106 return (IsShorthandDelimiter(nextCp) && !(*methodStatus & ParserStatus::ASYNC_FUNCTION));
2107 }
2108
ParseGeneratorPropertyModifier(ExpressionParseFlags flags,ParserStatus * methodStatus)2109 void ParserImpl::ParseGeneratorPropertyModifier(ExpressionParseFlags flags, ParserStatus *methodStatus)
2110 {
2111 if (flags & ExpressionParseFlags::MUST_BE_PATTERN) {
2112 ThrowSyntaxError("Unexpected token");
2113 }
2114
2115 lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);
2116 *methodStatus |= ParserStatus::GENERATOR_FUNCTION;
2117 }
2118
ParsePropertyKey(ExpressionParseFlags flags)2119 ir::Expression *ParserImpl::ParsePropertyKey(ExpressionParseFlags flags)
2120 {
2121 ir::Expression *key = nullptr;
2122
2123 switch (lexer_->GetToken().Type()) {
2124 case lexer::TokenType::LITERAL_IDENT: {
2125 const util::StringView &ident = lexer_->GetToken().Ident();
2126 key = AllocNode<ir::Identifier>(ident);
2127 key->SetRange(lexer_->GetToken().Loc());
2128 break;
2129 }
2130 case lexer::TokenType::LITERAL_STRING: {
2131 const util::StringView &string = lexer_->GetToken().String();
2132 key = AllocNode<ir::StringLiteral>(string);
2133 key->SetRange(lexer_->GetToken().Loc());
2134 break;
2135 }
2136 case lexer::TokenType::LITERAL_NUMBER: {
2137 if (lexer_->GetToken().Flags() & lexer::TokenFlags::NUMBER_BIGINT) {
2138 key = AllocNode<ir::BigIntLiteral>(lexer_->GetToken().BigInt());
2139 } else {
2140 key = AllocNode<ir::NumberLiteral>(lexer_->GetToken().Number(), lexer_->GetToken().String());
2141 }
2142
2143 key->SetRange(lexer_->GetToken().Loc());
2144 break;
2145 }
2146 case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET: {
2147 lexer_->NextToken(); // eat left square bracket
2148
2149 key = ParseExpression(flags | ExpressionParseFlags::ACCEPT_COMMA);
2150
2151 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
2152 ThrowSyntaxError("Unexpected token, expected ']'");
2153 }
2154 break;
2155 }
2156 default: {
2157 ThrowSyntaxError("Unexpected token in property key");
2158 }
2159 }
2160
2161 lexer_->NextToken();
2162 return key;
2163 }
2164
ParsePropertyValue(const ir::PropertyKind * propertyKind,const ParserStatus * methodStatus,ExpressionParseFlags flags)2165 ir::Expression *ParserImpl::ParsePropertyValue(const ir::PropertyKind *propertyKind, const ParserStatus *methodStatus,
2166 ExpressionParseFlags flags)
2167 {
2168 bool isMethod = *methodStatus & ParserStatus::FUNCTION;
2169 bool inPattern = (flags & ExpressionParseFlags::MUST_BE_PATTERN);
2170
2171 if (!isMethod && !ir::Property::IsAccessorKind(*propertyKind)) {
2172 // If the actual property is not getter/setter nor method, the following
2173 // token must be ':'
2174 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COLON) {
2175 ThrowSyntaxError("Unexpected token, expected ':'");
2176 }
2177
2178 lexer_->NextToken(); // eat colon
2179
2180 if (!inPattern) {
2181 return ParseExpression(flags);
2182 }
2183
2184 return ParsePatternElement();
2185 }
2186
2187 if (inPattern) {
2188 ThrowSyntaxError("Object pattern can't contain methods");
2189 }
2190
2191 ir::ScriptFunction *methodDefinitonNode =
2192 ParseFunction(*methodStatus | ParserStatus::FUNCTION | ParserStatus::ALLOW_SUPER);
2193 lexer_->NextToken();
2194 methodDefinitonNode->AddFlag(ir::ScriptFunctionFlags::METHOD);
2195
2196 size_t paramsSize = methodDefinitonNode->Params().size();
2197
2198 auto *value = AllocNode<ir::FunctionExpression>(methodDefinitonNode);
2199 value->SetRange(methodDefinitonNode->Range());
2200
2201 if (*propertyKind == ir::PropertyKind::SET && paramsSize != 1) {
2202 ThrowSyntaxError("Setter must have exactly one formal parameter");
2203 }
2204
2205 if (*propertyKind == ir::PropertyKind::GET && paramsSize != 0) {
2206 ThrowSyntaxError("Getter must not have formal parameters");
2207 }
2208
2209 return value;
2210 }
2211
ParsePropertyDefinition(ExpressionParseFlags flags)2212 ir::Expression *ParserImpl::ParsePropertyDefinition(ExpressionParseFlags flags)
2213 {
2214 ir::PropertyKind propertyKind = ir::PropertyKind::INIT;
2215 ParserStatus methodStatus = ParserStatus::NO_OPTS;
2216
2217 const auto startPos = lexer_->Save();
2218 lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);
2219 lexer::SourcePosition start = lexer_->GetToken().Start();
2220
2221 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD) {
2222 return ParseSpreadElement(flags);
2223 }
2224
2225 if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) {
2226 if (ParsePropertyModifiers(flags, &propertyKind, &methodStatus)) {
2227 return ParseShorthandProperty(&startPos);
2228 }
2229 } else if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MULTIPLY) {
2230 ParseGeneratorPropertyModifier(flags, &methodStatus);
2231 }
2232
2233 bool isComputed = lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET;
2234 ir::Expression *key = ParsePropertyKey(flags);
2235
2236 // Parse method property
2237 if ((lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS ||
2238 lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) &&
2239 !ir::Property::IsAccessorKind(propertyKind)) {
2240 methodStatus |= ParserStatus::FUNCTION | ParserStatus::ALLOW_SUPER;
2241 propertyKind = ir::PropertyKind::INIT;
2242 } else if (methodStatus & (ParserStatus::GENERATOR_FUNCTION | ParserStatus::ASYNC_FUNCTION)) {
2243 ThrowSyntaxError("Unexpected identifier");
2244 }
2245
2246 ir::Expression *value = ParsePropertyValue(&propertyKind, &methodStatus, flags);
2247 lexer::SourcePosition end = value->End();
2248
2249 ASSERT(key);
2250 ASSERT(value);
2251
2252 auto *returnProperty =
2253 AllocNode<ir::Property>(propertyKind, key, value, methodStatus != ParserStatus::NO_OPTS, isComputed);
2254 returnProperty->SetRange({start, end});
2255
2256 return returnProperty;
2257 }
2258
ParsePropertyEnd()2259 bool ParserImpl::ParsePropertyEnd()
2260 {
2261 // Property definiton must end with ',' or '}' otherwise we throw SyntaxError
2262 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COMMA &&
2263 lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
2264 ThrowSyntaxError("Unexpected token, expected ',' or '}'");
2265 }
2266
2267 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA &&
2268 lexer_->Lookahead() == LEX_CHAR_RIGHT_BRACE) {
2269 lexer_->NextToken();
2270 return true;
2271 }
2272
2273 return false;
2274 }
2275
ParseObjectExpression(ExpressionParseFlags flags)2276 ir::ObjectExpression *ParserImpl::ParseObjectExpression(ExpressionParseFlags flags)
2277 {
2278 ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE);
2279 lexer::SourcePosition start = lexer_->GetToken().Start();
2280 ArenaVector<ir::Expression *> properties(Allocator()->Adapter());
2281 bool trailingComma = false;
2282 bool inPattern = (flags & ExpressionParseFlags::MUST_BE_PATTERN);
2283
2284 if (lexer_->Lookahead() == LEX_CHAR_RIGHT_BRACE) {
2285 lexer_->NextToken();
2286 }
2287
2288 while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
2289 ir::Expression *property = ParsePropertyDefinition(flags | ExpressionParseFlags::POTENTIALLY_IN_PATTERN);
2290 properties.push_back(property);
2291 trailingComma = ParsePropertyEnd();
2292 }
2293
2294 auto nodeType = inPattern ? ir::AstNodeType::OBJECT_PATTERN : ir::AstNodeType::OBJECT_EXPRESSION;
2295 auto *objectExpression = AllocNode<ir::ObjectExpression>(nodeType, std::move(properties), trailingComma);
2296 objectExpression->SetRange({start, lexer_->GetToken().End()});
2297 lexer_->NextToken();
2298
2299 if (inPattern) {
2300 objectExpression->SetDeclaration();
2301 }
2302
2303 if (Extension() == ScriptExtension::TS && (flags & ExpressionParseFlags::ALLOW_TS_PARAM_TOKEN) &&
2304 lexer::Token::IsTsParamToken(lexer_->GetToken().Type(), lexer_->Lookahead())) {
2305 context_.Status() |= ParserStatus::FUNCTION_PARAM;
2306 ParsePotentialTsFunctionParameter(ExpressionParseFlags::NO_OPTS, objectExpression);
2307 }
2308
2309 if (!(flags & ExpressionParseFlags::POTENTIALLY_IN_PATTERN)) {
2310 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION &&
2311 !objectExpression->ConvertibleToObjectPattern()) {
2312 ThrowSyntaxError("Invalid left-hand side in array destructuring pattern", objectExpression->Start());
2313 } else if (!inPattern && lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
2314 ir::ValidationInfo info = objectExpression->ValidateExpression();
2315 if (info.Fail()) {
2316 ThrowSyntaxError(info.msg.Utf8(), info.pos);
2317 }
2318 }
2319 }
2320
2321 return objectExpression;
2322 }
2323
ParseSequenceExpression(ir::Expression * startExpr,bool acceptRest,bool acceptTsParam,bool acceptPattern)2324 ir::SequenceExpression *ParserImpl::ParseSequenceExpression(ir::Expression *startExpr, bool acceptRest,
2325 bool acceptTsParam, bool acceptPattern)
2326 {
2327 lexer::SourcePosition start = startExpr->Start();
2328
2329 ArenaVector<ir::Expression *> sequence(Allocator()->Adapter());
2330 sequence.push_back(startExpr);
2331
2332 while (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
2333 lexer_->NextToken();
2334
2335 if (acceptRest && lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD) {
2336 ir::SpreadElement *expr = ParseSpreadElement(ExpressionParseFlags::MUST_BE_PATTERN);
2337 sequence.push_back(expr);
2338 break;
2339 }
2340
2341 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS && lexer_->CheckArrow()) {
2342 break;
2343 }
2344
2345 ExpressionParseFlags flags = acceptTsParam ? ExpressionParseFlags::ALLOW_TS_PARAM_TOKEN
2346 : ExpressionParseFlags::NO_OPTS;
2347
2348 sequence.push_back(ParseExpression(acceptPattern ? (ExpressionParseFlags::POTENTIALLY_IN_PATTERN | flags)
2349 : flags));
2350 }
2351
2352 lexer::SourcePosition end = sequence.back()->End();
2353 auto *sequenceNode = AllocNode<ir::SequenceExpression>(std::move(sequence));
2354 sequenceNode->SetRange({start, end});
2355
2356 return sequenceNode;
2357 }
2358
ParseUnaryOrPrefixUpdateExpression(ExpressionParseFlags flags)2359 ir::Expression *ParserImpl::ParseUnaryOrPrefixUpdateExpression(ExpressionParseFlags flags)
2360 {
2361 if (Extension() == ScriptExtension::TS && lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) {
2362 // TODO(rsipka): negative cases are not covered, probably this is not a complete solution yet
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