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