1 /**
2 * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "parserImpl.h"
17 #include "parserStatusContext.h"
18
19 #include "varbinder/privateBinding.h"
20 #include "ir/astNode.h"
21 #include "ir/base/classDefinition.h"
22 #include "ir/base/classProperty.h"
23 #include "ir/base/classStaticBlock.h"
24 #include "ir/base/methodDefinition.h"
25 #include "ir/base/scriptFunction.h"
26 #include "ir/base/spreadElement.h"
27 #include "ir/expression.h"
28 #include "ir/expressions/arrayExpression.h"
29 #include "ir/expressions/assignmentExpression.h"
30 #include "ir/expressions/callExpression.h"
31 #include "ir/expressions/functionExpression.h"
32 #include "ir/expressions/identifier.h"
33 #include "ir/expressions/literals/bigIntLiteral.h"
34 #include "ir/expressions/literals/numberLiteral.h"
35 #include "ir/expressions/literals/stringLiteral.h"
36 #include "ir/expressions/objectExpression.h"
37 #include "ir/expressions/superExpression.h"
38 #include "ir/module/exportNamedDeclaration.h"
39 #include "ir/module/exportSpecifier.h"
40 #include "ir/statements/blockStatement.h"
41 #include "ir/statements/expressionStatement.h"
42 #include "ir/statements/functionDeclaration.h"
43 #include "lexer/lexer.h"
44 #include "lexer/token/letters.h"
45 #include "lexer/token/sourceLocation.h"
46
47 using namespace std::literals::string_literals;
48
49 namespace ark::es2panda::parser {
ParserImpl(Program * program,const CompilerOptions & options,ParserStatus status)50 ParserImpl::ParserImpl(Program *program, const CompilerOptions &options, ParserStatus status)
51 : program_(program), context_(program_, status), options_(options)
52 {
53 }
54
InitLexer(const SourceFile & sourceFile)55 std::unique_ptr<lexer::Lexer> ParserImpl::InitLexer(const SourceFile &sourceFile)
56 {
57 program_->SetSource(sourceFile);
58 std::unique_ptr<lexer::Lexer> lexer = std::make_unique<lexer::Lexer>(&context_);
59 lexer_ = lexer.get();
60 return lexer;
61 }
62
ParseScript(const SourceFile & sourceFile,bool genStdLib)63 void ParserImpl::ParseScript(const SourceFile &sourceFile, bool genStdLib)
64 {
65 auto lexer = InitLexer(sourceFile);
66
67 if (sourceFile.isModule) {
68 context_.Status() |= (ParserStatus::MODULE);
69 ParseProgram(ScriptKind::MODULE);
70 } else if (genStdLib) {
71 ParseProgram(ScriptKind::STDLIB);
72 } else {
73 ParseProgram(ScriptKind::SCRIPT);
74 }
75 }
76
ParseProgram(ScriptKind kind)77 void ParserImpl::ParseProgram(ScriptKind kind)
78 {
79 lexer::SourcePosition startLoc = lexer_->GetToken().Start();
80 lexer_->NextToken();
81 program_->SetKind(kind);
82
83 auto statements = ParseStatementList(StatementParsingFlags::STMT_GLOBAL_LEXICAL);
84
85 auto *blockStmt = AllocNode<ir::BlockStatement>(Allocator(), std::move(statements));
86 blockStmt->SetRange({startLoc, lexer_->GetToken().End()});
87
88 program_->SetAst(blockStmt);
89 }
90
InAmbientContext()91 bool ParserImpl::InAmbientContext()
92 {
93 return (context_.Status() & ParserStatus::IN_AMBIENT_CONTEXT) != 0;
94 }
95
CarryExpressionParserFlag(ExpressionParseFlags origin,ExpressionParseFlags carry)96 ExpressionParseFlags ParserImpl::CarryExpressionParserFlag(ExpressionParseFlags origin, ExpressionParseFlags carry)
97 {
98 return static_cast<ExpressionParseFlags>(origin & carry);
99 }
100
CarryPatternFlags(ExpressionParseFlags flags)101 ExpressionParseFlags ParserImpl::CarryPatternFlags(ExpressionParseFlags flags)
102 {
103 return CarryExpressionParserFlag(flags, ExpressionParseFlags::POTENTIALLY_IN_PATTERN |
104 ExpressionParseFlags::OBJECT_PATTERN);
105 }
106
GetAccessability(ir::ModifierFlags modifiers)107 ir::ModifierFlags ParserImpl::GetAccessability(ir::ModifierFlags modifiers)
108 {
109 if ((modifiers & ir::ModifierFlags::PUBLIC) != 0) {
110 return ir::ModifierFlags::PUBLIC;
111 }
112
113 if ((modifiers & ir::ModifierFlags::PRIVATE) != 0) {
114 return ir::ModifierFlags::PRIVATE;
115 }
116
117 if ((modifiers & ir::ModifierFlags::PROTECTED) != 0) {
118 return ir::ModifierFlags::PROTECTED;
119 }
120
121 if ((modifiers & ir::ModifierFlags::INTERNAL) != 0) {
122 return ir::ModifierFlags::INTERNAL;
123 }
124
125 return ir::ModifierFlags::NONE;
126 }
127
IsModifierKind(const lexer::Token & token)128 bool ParserImpl::IsModifierKind(const lexer::Token &token)
129 {
130 switch (token.KeywordType()) {
131 case lexer::TokenType::KEYW_STATIC:
132 case lexer::TokenType::KEYW_ASYNC:
133 return true;
134 default:
135 break;
136 }
137
138 return false;
139 }
140
ParseModifiers()141 ir::ModifierFlags ParserImpl::ParseModifiers()
142 {
143 ir::ModifierFlags resultStatus = ir::ModifierFlags::NONE;
144 ir::ModifierFlags prevStatus = ir::ModifierFlags::ALL;
145
146 while (IsModifierKind(lexer_->GetToken())) {
147 char32_t nextCp = lexer_->Lookahead();
148 if (nextCp == lexer::LEX_CHAR_LEFT_PAREN) {
149 return resultStatus;
150 }
151
152 lexer::TokenFlags tokenFlags = lexer_->GetToken().Flags();
153 if ((tokenFlags & lexer::TokenFlags::HAS_ESCAPE) != 0) {
154 ThrowSyntaxError("Keyword must not contain escaped characters");
155 }
156
157 ir::ModifierFlags actualStatus = ir::ModifierFlags::NONE;
158 ir::ModifierFlags nextStatus = ir::ModifierFlags::NONE;
159
160 switch (lexer_->GetToken().KeywordType()) {
161 case lexer::TokenType::KEYW_STATIC: {
162 actualStatus = ir::ModifierFlags::STATIC;
163 nextStatus = ir::ModifierFlags::ASYNC;
164 break;
165 }
166 case lexer::TokenType::KEYW_ASYNC: {
167 actualStatus = ir::ModifierFlags::ASYNC;
168 nextStatus = ir::ModifierFlags::NONE;
169 break;
170 }
171 default: {
172 break;
173 }
174 }
175
176 if (lexer_->Lookahead() == lexer::LEX_CHAR_COLON || lexer_->Lookahead() == lexer::LEX_CHAR_COMMA ||
177 lexer_->Lookahead() == lexer::LEX_CHAR_RIGHT_PAREN || lexer_->Lookahead() == lexer::LEX_CHAR_QUESTION ||
178 lexer_->Lookahead() == lexer::LEX_CHAR_RIGHT_BRACE || lexer_->Lookahead() == lexer::LEX_CHAR_LESS_THAN) {
179 break;
180 }
181
182 auto pos = lexer_->Save();
183 lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);
184
185 if ((prevStatus & actualStatus) == 0) {
186 lexer_->Rewind(pos);
187 ThrowSyntaxError("Unexpected modifier");
188 }
189
190 if ((resultStatus & actualStatus) != 0) {
191 lexer_->Rewind(pos);
192 ThrowSyntaxError("Duplicated modifier is not allowed");
193 }
194
195 resultStatus |= actualStatus;
196 prevStatus = nextStatus;
197 }
198
199 return resultStatus;
200 }
201
CheckAccessorPair(const ArenaVector<ir::AstNode * > & properties,const ir::Expression * propName,ir::MethodDefinitionKind methodKind,ir::ModifierFlags access)202 void ParserImpl::CheckAccessorPair(const ArenaVector<ir::AstNode *> &properties, const ir::Expression *propName,
203 ir::MethodDefinitionKind methodKind, ir::ModifierFlags access)
204 {
205 for (const auto &it : properties) {
206 if (!it->IsMethodDefinition() || it->AsMethodDefinition()->Kind() != methodKind) {
207 continue;
208 }
209
210 const ir::Expression *key = it->AsMethodDefinition()->Key();
211
212 if (key->Type() != propName->Type()) {
213 continue;
214 }
215
216 bool keyIsSame = false;
217
218 if (key->IsIdentifier()) {
219 const util::StringView &strName = propName->AsIdentifier()->Name();
220 const util::StringView &compareName = (key->AsIdentifier()->Name());
221
222 keyIsSame = strName == compareName;
223 } else if (key->IsNumberLiteral()) {
224 keyIsSame =
225 key->AsNumberLiteral()->Number().GetDouble() == propName->AsNumberLiteral()->Number().GetDouble();
226 } else if (key->IsStringLiteral()) {
227 keyIsSame = *key->AsStringLiteral() == *propName->AsStringLiteral();
228 }
229
230 if (!keyIsSame) {
231 continue;
232 }
233
234 ir::ModifierFlags getAccess;
235 ir::ModifierFlags setAccess;
236
237 if (methodKind == ir::MethodDefinitionKind::GET) {
238 setAccess = access;
239 getAccess = GetAccessability(it->Modifiers());
240 } else {
241 getAccess = access;
242 setAccess = GetAccessability(it->Modifiers());
243 }
244
245 if ((setAccess == ir::ModifierFlags::NONE && getAccess > ir::ModifierFlags::PUBLIC) ||
246 (setAccess != ir::ModifierFlags::NONE && getAccess > setAccess)) {
247 ThrowSyntaxError("A get accessor must be at least as accessible as the setter", key->Start());
248 }
249 }
250 }
251
ParseClassAccessor(ClassElementDescriptor * desc,char32_t * nextCp)252 void ParserImpl::ParseClassAccessor(ClassElementDescriptor *desc, char32_t *nextCp)
253 {
254 ConsumeClassPrivateIdentifier(desc, nextCp);
255
256 if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
257 return;
258 }
259
260 auto keywordType = lexer_->GetToken().KeywordType();
261 if ((keywordType != lexer::TokenType::KEYW_GET && keywordType != lexer::TokenType::KEYW_SET) ||
262 (*nextCp == lexer::LEX_CHAR_EQUALS || *nextCp == lexer::LEX_CHAR_SEMICOLON ||
263 *nextCp == lexer::LEX_CHAR_LEFT_PAREN || *nextCp == lexer::LEX_CHAR_COLON ||
264 *nextCp == lexer::LEX_CHAR_LESS_THAN)) {
265 return;
266 }
267
268 ThrowIfPrivateIdent(desc, "Unexpected identifier");
269
270 if ((lexer_->GetToken().Flags() & lexer::TokenFlags::HAS_ESCAPE) != 0) {
271 ThrowSyntaxError("Keyword must not contain escaped characters");
272 }
273
274 desc->methodKind =
275 keywordType == lexer::TokenType::KEYW_GET ? ir::MethodDefinitionKind::GET : ir::MethodDefinitionKind::SET;
276 desc->methodStart = lexer_->GetToken().Start();
277
278 lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);
279 ConsumeClassPrivateIdentifier(desc, nextCp);
280 }
281
ThrowIfPrivateIdent(ClassElementDescriptor * desc,const char * msg)282 void ParserImpl::ThrowIfPrivateIdent(ClassElementDescriptor *desc, const char *msg)
283 {
284 if (desc->isPrivateIdent) {
285 ThrowSyntaxError(msg);
286 }
287 }
288
ThrowErrorIfStaticConstructor(ir::ModifierFlags flags)289 void ParserImpl::ThrowErrorIfStaticConstructor([[maybe_unused]] ir::ModifierFlags flags) {}
290
ValidateClassKey(ClassElementDescriptor * desc)291 void ParserImpl::ValidateClassKey(ClassElementDescriptor *desc)
292 {
293 if (((desc->modifiers & ir::ModifierFlags::ASYNC) != 0 || desc->isGenerator) &&
294 (desc->methodKind == ir::MethodDefinitionKind::GET || desc->methodKind == ir::MethodDefinitionKind::SET)) {
295 ThrowSyntaxError("Invalid accessor");
296 }
297
298 const util::StringView &propNameStr = lexer_->GetToken().Ident();
299
300 if (propNameStr.Is("constructor")) {
301 if (lexer_->Lookahead() != lexer::LEX_CHAR_LEFT_PAREN) {
302 ThrowSyntaxError("Classes may not have a field named 'constructor'");
303 }
304
305 ThrowIfPrivateIdent(desc, "Private identifier can not be constructor");
306
307 if ((desc->modifiers & ir::ModifierFlags::STATIC) == 0) {
308 if ((desc->modifiers & ir::ModifierFlags::ASYNC) != 0 ||
309 desc->methodKind == ir::MethodDefinitionKind::GET ||
310 desc->methodKind == ir::MethodDefinitionKind::SET || desc->isGenerator) {
311 ThrowSyntaxError("Constructor can not be special method");
312 }
313
314 desc->methodKind = ir::MethodDefinitionKind::CONSTRUCTOR;
315 desc->methodStart = lexer_->GetToken().Start();
316 desc->newStatus |= ParserStatus::CONSTRUCTOR_FUNCTION;
317
318 if (desc->hasSuperClass) {
319 desc->newStatus |= ParserStatus::ALLOW_SUPER_CALL;
320 }
321 }
322
323 ThrowErrorIfStaticConstructor(desc->modifiers);
324 } else if (propNameStr.Is("prototype") && (desc->modifiers & ir::ModifierFlags::STATIC) != 0) {
325 ThrowSyntaxError("Classes may not have static property named prototype");
326 }
327 }
328
ParseComputedClassFieldOrIndexSignature(ir::Expression ** propName)329 std::tuple<bool, bool, bool> ParserImpl::ParseComputedClassFieldOrIndexSignature(ir::Expression **propName)
330 {
331 lexer_->NextToken(); // eat left square bracket
332
333 *propName = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
334
335 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
336 ThrowSyntaxError("Unexpected token, expected ']'");
337 }
338
339 return {true, false, false};
340 }
341
ParseClassKey(ClassElementDescriptor * desc)342 ir::Expression *ParserImpl::ParseClassKey(ClassElementDescriptor *desc)
343 {
344 ir::Expression *propName = nullptr;
345 if (lexer_->GetToken().IsKeyword()) {
346 lexer_->GetToken().SetTokenType(lexer::TokenType::LITERAL_IDENT);
347 }
348
349 switch (lexer_->GetToken().Type()) {
350 case lexer::TokenType::LITERAL_IDENT: {
351 ValidateClassKey(desc);
352
353 propName = AllocNode<ir::Identifier>(lexer_->GetToken().Ident(), Allocator());
354 propName->SetRange(lexer_->GetToken().Loc());
355 propName->AsIdentifier()->SetPrivate(desc->isPrivateIdent);
356 break;
357 }
358 case lexer::TokenType::LITERAL_STRING: {
359 ThrowIfPrivateIdent(desc, "Private identifier name can not be string");
360
361 if (lexer_->GetToken().Ident().Is("constructor")) {
362 ThrowSyntaxError("Classes may not have a field named 'constructor'");
363 }
364
365 if (lexer_->GetToken().Ident().Is("prototype") && (desc->modifiers & ir::ModifierFlags::STATIC) != 0) {
366 ThrowSyntaxError("Classes may not have a static property named 'prototype'");
367 }
368
369 propName = AllocNode<ir::StringLiteral>(lexer_->GetToken().String());
370 propName->SetRange(lexer_->GetToken().Loc());
371 break;
372 }
373 case lexer::TokenType::LITERAL_NUMBER: {
374 ThrowIfPrivateIdent(desc, "Private identifier name can not be number");
375
376 if ((lexer_->GetToken().Flags() & lexer::TokenFlags::NUMBER_BIGINT) != 0) {
377 propName = AllocNode<ir::BigIntLiteral>(lexer_->GetToken().BigInt());
378 } else {
379 propName = AllocNode<ir::NumberLiteral>(lexer_->GetToken().GetNumber());
380 }
381
382 propName->SetRange(lexer_->GetToken().Loc());
383 break;
384 }
385 case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET: {
386 ThrowIfPrivateIdent(desc, "Unexpected character in private identifier");
387 std::tie(desc->isComputed, desc->invalidComputedProperty, desc->isIndexSignature) =
388 ParseComputedClassFieldOrIndexSignature(&propName);
389 break;
390 }
391 default: {
392 ThrowSyntaxError("Unexpected token in class property");
393 }
394 }
395
396 lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);
397
398 return propName;
399 }
400
ValidateClassMethodStart(ClassElementDescriptor * desc,ir::TypeNode * typeAnnotation)401 void ParserImpl::ValidateClassMethodStart(ClassElementDescriptor *desc, [[maybe_unused]] ir::TypeNode *typeAnnotation)
402 {
403 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
404 return;
405 }
406 desc->classMethod = true;
407
408 if ((desc->modifiers & ir::ModifierFlags::ASYNC) != 0) {
409 desc->newStatus |= ParserStatus::ASYNC_FUNCTION;
410 }
411
412 if (desc->isGenerator) {
413 desc->newStatus |= ParserStatus::GENERATOR_FUNCTION;
414 }
415 }
416
ValidateClassSetter(ClassElementDescriptor * desc,const ArenaVector<ir::AstNode * > & properties,ir::Expression * propName,ir::ScriptFunction * func)417 void ParserImpl::ValidateClassSetter([[maybe_unused]] ClassElementDescriptor *desc,
418 [[maybe_unused]] const ArenaVector<ir::AstNode *> &properties,
419 [[maybe_unused]] ir::Expression *propName, ir::ScriptFunction *func)
420 {
421 if (func->Params().size() != 1) {
422 ThrowSyntaxError("Setter must have exactly one formal parameter");
423 }
424 }
425
ValidateClassGetter(ClassElementDescriptor * desc,const ArenaVector<ir::AstNode * > & properties,ir::Expression * propName,ir::ScriptFunction * func)426 void ParserImpl::ValidateClassGetter([[maybe_unused]] ClassElementDescriptor *desc,
427 [[maybe_unused]] const ArenaVector<ir::AstNode *> &properties,
428 [[maybe_unused]] ir::Expression *propName, ir::ScriptFunction *func)
429 {
430 if (!func->Params().empty()) {
431 ThrowSyntaxError("Getter must not have formal parameters");
432 }
433 }
434
ParseClassMethod(ClassElementDescriptor * desc,const ArenaVector<ir::AstNode * > & properties,ir::Expression * propName,lexer::SourcePosition * propEnd)435 ir::MethodDefinition *ParserImpl::ParseClassMethod(ClassElementDescriptor *desc,
436 const ArenaVector<ir::AstNode *> &properties,
437 ir::Expression *propName, lexer::SourcePosition *propEnd)
438 {
439 if (desc->methodKind != ir::MethodDefinitionKind::SET &&
440 (desc->newStatus & ParserStatus::CONSTRUCTOR_FUNCTION) == 0) {
441 desc->newStatus |= ParserStatus::NEED_RETURN_TYPE;
442 }
443
444 ir::ScriptFunction *func = ParseFunction(desc->newStatus);
445
446 auto *funcExpr = AllocNode<ir::FunctionExpression>(func);
447 funcExpr->SetRange(func->Range());
448
449 if (desc->methodKind == ir::MethodDefinitionKind::SET) {
450 ValidateClassSetter(desc, properties, propName, func);
451 } else if (desc->methodKind == ir::MethodDefinitionKind::GET) {
452 ValidateClassGetter(desc, properties, propName, func);
453 }
454
455 *propEnd = func->End();
456 func->AddFlag(ir::ScriptFunctionFlags::METHOD);
457
458 auto *ident = !propName->IsArrowFunctionExpression() && !propName->IsFunctionExpression()
459 ? propName->Clone(Allocator(), nullptr)->AsExpression()
460 : propName;
461 auto *method = AllocNode<ir::MethodDefinition>(desc->methodKind, ident, funcExpr, desc->modifiers, Allocator(),
462 desc->isComputed);
463 method->SetRange(funcExpr->Range());
464
465 return method;
466 }
467
ParseClassProperty(ClassElementDescriptor * desc,const ArenaVector<ir::AstNode * > & properties,ir::Expression * propName,ir::TypeNode * typeAnnotation)468 ir::ClassElement *ParserImpl::ParseClassProperty(ClassElementDescriptor *desc,
469 const ArenaVector<ir::AstNode *> &properties, ir::Expression *propName,
470 ir::TypeNode *typeAnnotation)
471 {
472 lexer::SourcePosition propEnd = propName->End();
473 ir::ClassElement *property = nullptr;
474
475 if (desc->classMethod) {
476 if ((desc->modifiers & ir::ModifierFlags::DECLARE) != 0) {
477 ThrowSyntaxError("'declare modifier cannot appear on class elements of this kind.");
478 }
479
480 property = ParseClassMethod(desc, properties, propName, &propEnd);
481 property->SetRange({desc->propStart, propEnd});
482 return property;
483 }
484
485 ir::Expression *value = nullptr;
486
487 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
488 lexer_->NextToken(); // eat equals
489
490 if (InAmbientContext() || (desc->modifiers & ir::ModifierFlags::DECLARE) != 0) {
491 ThrowSyntaxError("Initializers are not allowed in ambient contexts.");
492 }
493
494 value = ParseExpression();
495 propEnd = value->End();
496 }
497
498 property =
499 AllocNode<ir::ClassProperty>(propName, value, typeAnnotation, desc->modifiers, Allocator(), desc->isComputed);
500
501 property->SetRange({desc->propStart, propEnd});
502
503 return property;
504 }
505
CheckClassGeneratorMethod(ClassElementDescriptor * desc,char32_t * nextCp)506 void ParserImpl::CheckClassGeneratorMethod(ClassElementDescriptor *desc, char32_t *nextCp)
507 {
508 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_MULTIPLY) {
509 return;
510 }
511
512 desc->isGenerator = true;
513 lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);
514 *nextCp = lexer_->Lookahead();
515 }
516
ValidatePrivateIdentifier()517 void ParserImpl::ValidatePrivateIdentifier()
518 {
519 size_t iterIdx = lexer_->GetToken().Start().index;
520 lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);
521
522 if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT ||
523 (lexer_->GetToken().Start().index - iterIdx > 1)) {
524 ThrowSyntaxError("Unexpected token in private field");
525 }
526 }
527
ConsumeClassPrivateIdentifier(ClassElementDescriptor * desc,char32_t * nextCp)528 void ParserImpl::ConsumeClassPrivateIdentifier(ClassElementDescriptor *desc, char32_t *nextCp)
529 {
530 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_HASH_MARK) {
531 return;
532 }
533
534 desc->isPrivateIdent = true;
535 ValidatePrivateIdentifier();
536 *nextCp = lexer_->Lookahead();
537 }
538
AddPrivateElement(const ir::ClassElement * elem)539 void ParserImpl::AddPrivateElement(const ir::ClassElement *elem)
540 {
541 if (!classPrivateContext_.AddElement(elem)) {
542 ThrowSyntaxError("Private field has already been declared");
543 }
544 }
545
ParseClassStaticBlock()546 ir::ClassElement *ParserImpl::ParseClassStaticBlock()
547 {
548 const lexer::SourcePosition &startPos = lexer_->GetToken().Start();
549
550 lexer_->NextToken(); // eat 'static'
551
552 SavedParserContext context(this, ParserStatus::ALLOW_SUPER);
553 context_.Status() &= ~(ParserStatus::ASYNC_FUNCTION | ParserStatus::GENERATOR_FUNCTION);
554
555 lexer_->NextToken(); // eat '{'
556
557 ArenaVector<ir::Expression *> params(Allocator()->Adapter());
558
559 ArenaVector<ir::Statement *> statements = ParseStatementList();
560
561 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
562 ThrowSyntaxError("Expected a '}'");
563 }
564
565 auto *body = AllocNode<ir::BlockStatement>(Allocator(), std::move(statements));
566 // clang-format off
567 auto *func = AllocNode<ir::ScriptFunction>(
568 Allocator(), ir::ScriptFunction::ScriptFunctionData {
569 body, ir::FunctionSignature(nullptr, std::move(params), nullptr),
570 ir::ScriptFunctionFlags::EXPRESSION | ir::ScriptFunctionFlags::STATIC_BLOCK,
571 ir::ModifierFlags::STATIC, false, context_.GetLanguage()});
572 // clang-format on
573
574 auto *funcExpr = AllocNode<ir::FunctionExpression>(func);
575 auto *staticBlock = AllocNode<ir::ClassStaticBlock>(funcExpr, Allocator());
576 staticBlock->SetRange({startPos, lexer_->GetToken().End()});
577
578 lexer_->NextToken(); // eat '}'
579
580 return staticBlock;
581 }
582
ParseClassElement(const ArenaVector<ir::AstNode * > & properties,ir::ClassDefinitionModifiers modifiers,ir::ModifierFlags flags)583 ir::AstNode *ParserImpl::ParseClassElement(const ArenaVector<ir::AstNode *> &properties,
584 ir::ClassDefinitionModifiers modifiers,
585 [[maybe_unused]] ir::ModifierFlags flags)
586 {
587 if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_STATIC &&
588 lexer_->Lookahead() == lexer::LEX_CHAR_LEFT_BRACE) {
589 return ParseClassStaticBlock();
590 }
591
592 ClassElementDescriptor desc(Allocator());
593
594 desc.methodKind = ir::MethodDefinitionKind::METHOD;
595 desc.newStatus = ParserStatus::ALLOW_SUPER;
596 desc.hasSuperClass = (modifiers & ir::ClassDefinitionModifiers::HAS_SUPER) != 0U;
597 desc.propStart = lexer_->GetToken().Start();
598 desc.modifiers = ParseModifiers();
599
600 char32_t nextCp = lexer_->Lookahead();
601 CheckClassGeneratorMethod(&desc, &nextCp);
602 ParseClassAccessor(&desc, &nextCp);
603
604 if ((desc.modifiers & ir::ModifierFlags::STATIC) == 0) {
605 context_.Status() |= ParserStatus::ALLOW_THIS_TYPE;
606 }
607
608 ir::Expression *propName = ParseClassKey(&desc);
609 ValidateClassMethodStart(&desc, nullptr);
610 ir::ClassElement *property = ParseClassProperty(&desc, properties, propName, nullptr);
611
612 if (property != nullptr && lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON &&
613 lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE &&
614 (lexer_->GetToken().Flags() & lexer::TokenFlags::NEW_LINE) == 0 &&
615 !(property->IsMethodDefinition() &&
616 property->AsMethodDefinition()->Value()->AsFunctionExpression()->Function()->Body() != nullptr)) {
617 ThrowSyntaxError("';' expected.");
618 }
619
620 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
621 lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);
622 }
623
624 context_.Status() &= ~ParserStatus::ALLOW_THIS_TYPE;
625
626 if (desc.isPrivateIdent) {
627 AddPrivateElement(property);
628 }
629
630 return property;
631 }
632
BuildImplicitConstructor(ir::ClassDefinitionModifiers modifiers,const lexer::SourcePosition & startLoc)633 ir::MethodDefinition *ParserImpl::BuildImplicitConstructor(ir::ClassDefinitionModifiers modifiers,
634 const lexer::SourcePosition &startLoc)
635 {
636 ArenaVector<ir::Expression *> params(Allocator()->Adapter());
637 ArenaVector<ir::Statement *> statements(Allocator()->Adapter());
638
639 if ((modifiers & ir::ClassDefinitionModifiers::HAS_SUPER) != 0U) {
640 util::StringView argsStr = "args";
641 params.push_back(AllocNode<ir::SpreadElement>(ir::AstNodeType::REST_ELEMENT, Allocator(),
642 AllocNode<ir::Identifier>(argsStr, Allocator())));
643 ArenaVector<ir::Expression *> callArgs(Allocator()->Adapter());
644 auto *superExpr = AllocNode<ir::SuperExpression>();
645 callArgs.push_back(AllocNode<ir::SpreadElement>(ir::AstNodeType::SPREAD_ELEMENT, Allocator(),
646 AllocNode<ir::Identifier>(argsStr, Allocator())));
647
648 auto *callExpr = AllocNode<ir::CallExpression>(superExpr, std::move(callArgs), nullptr, false);
649 statements.push_back(AllocNode<ir::ExpressionStatement>(callExpr));
650 }
651
652 auto *body = AllocNode<ir::BlockStatement>(Allocator(), std::move(statements));
653 auto *func = AllocNode<ir::ScriptFunction>(
654 Allocator(), ir::ScriptFunction::ScriptFunctionData {body,
655 ir::FunctionSignature(nullptr, std::move(params), nullptr),
656 ir::ScriptFunctionFlags::CONSTRUCTOR |
657 ir::ScriptFunctionFlags::IMPLICIT_SUPER_CALL_NEEDED,
658 {},
659 false,
660 context_.GetLanguage()});
661
662 auto *funcExpr = AllocNode<ir::FunctionExpression>(func);
663 auto *key = AllocNode<ir::Identifier>("constructor", Allocator());
664
665 if ((modifiers & ir::ClassDefinitionModifiers::SET_CTOR_ID) != 0U) {
666 func->SetIdent(key->Clone(Allocator(), nullptr));
667 }
668
669 auto *ctor = AllocNode<ir::MethodDefinition>(ir::MethodDefinitionKind::CONSTRUCTOR, key, funcExpr,
670 ir::ModifierFlags::NONE, Allocator(), false);
671
672 ctor->SetRange({startLoc, lexer_->GetToken().End()});
673
674 return ctor;
675 }
676
CreateImplicitConstructor(ir::MethodDefinition * & ctor,ArenaVector<ir::AstNode * > & properties,ir::ClassDefinitionModifiers modifiers,const lexer::SourcePosition & startLoc)677 void ParserImpl::CreateImplicitConstructor(ir::MethodDefinition *&ctor,
678 [[maybe_unused]] ArenaVector<ir::AstNode *> &properties,
679 ir::ClassDefinitionModifiers modifiers,
680 const lexer::SourcePosition &startLoc)
681 {
682 if (ctor != nullptr) {
683 return;
684 }
685
686 ctor = BuildImplicitConstructor(modifiers, startLoc);
687 }
688
ParseClassIdent(ir::ClassDefinitionModifiers modifiers)689 ir::Identifier *ParserImpl::ParseClassIdent(ir::ClassDefinitionModifiers modifiers)
690 {
691 if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) {
692 return ExpectIdentifier();
693 }
694
695 auto idRequired =
696 static_cast<ir::ClassDefinitionModifiers>(modifiers & ir::ClassDefinitionModifiers::DECLARATION_ID_REQUIRED);
697
698 if (idRequired == ir::ClassDefinitionModifiers::DECLARATION_ID_REQUIRED) {
699 ThrowSyntaxError("Unexpected token, expected an identifier.");
700 }
701
702 return nullptr;
703 }
704
CheckClassElement(ir::AstNode * property,ir::MethodDefinition * & ctor,ArenaVector<ir::AstNode * > & properties)705 bool ParserImpl::CheckClassElement(ir::AstNode *property, ir::MethodDefinition *&ctor,
706 [[maybe_unused]] ArenaVector<ir::AstNode *> &properties)
707 {
708 if (!property->IsMethodDefinition()) {
709 return false;
710 }
711
712 ir::MethodDefinition *def = property->AsMethodDefinition();
713 if (!def->IsConstructor()) {
714 return false;
715 }
716
717 if (ctor != nullptr) {
718 ThrowSyntaxError("Multiple constructor implementations are not allowed.", property->Start());
719 }
720 ctor = def;
721
722 return true;
723 }
724
ParseSuperClassReference()725 ir::Expression *ParserImpl::ParseSuperClassReference()
726 {
727 if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_EXTENDS) {
728 lexer_->NextToken();
729 return ParseLeftHandSideExpression();
730 }
731
732 return nullptr;
733 }
734
ParseSuperClass()735 std::tuple<ir::Expression *, ir::TSTypeParameterInstantiation *> ParserImpl::ParseSuperClass()
736 {
737 return {ParseSuperClassReference(), nullptr};
738 }
739
740 // NOLINTNEXTLINE(google-default-arguments)
ParseClassDefinition(ir::ClassDefinitionModifiers modifiers,ir::ModifierFlags flags)741 ir::ClassDefinition *ParserImpl::ParseClassDefinition(ir::ClassDefinitionModifiers modifiers, ir::ModifierFlags flags)
742 {
743 lexer_->NextToken();
744
745 ir::Identifier *identNode = ParseClassIdent(modifiers);
746
747 if (identNode == nullptr && (modifiers & ir::ClassDefinitionModifiers::DECLARATION) != 0U) {
748 ThrowSyntaxError("Unexpected token, expected an identifier.");
749 }
750
751 varbinder::PrivateBinding privateBinding(Allocator(), classId_++);
752
753 // Parse SuperClass
754 auto [superClass, superTypeParams] = ParseSuperClass();
755
756 if (superClass != nullptr) {
757 modifiers |= ir::ClassDefinitionModifiers::HAS_SUPER;
758 }
759
760 ExpectToken(lexer::TokenType::PUNCTUATOR_LEFT_BRACE, false);
761
762 auto [ctor, properties, bodyRange] = ParseClassBody(modifiers, flags);
763
764 ArenaVector<ir::TSClassImplements *> implements(Allocator()->Adapter());
765 auto *classDefinition = AllocNode<ir::ClassDefinition>(
766 privateBinding.View(), identNode, nullptr, superTypeParams, std::move(implements), ctor, superClass,
767 std::move(properties), modifiers, flags, GetContext().GetLanguage());
768
769 classDefinition->SetRange(bodyRange);
770
771 return classDefinition;
772 }
773
ParseClassBody(ir::ClassDefinitionModifiers modifiers,ir::ModifierFlags flags)774 ParserImpl::ClassBody ParserImpl::ParseClassBody(ir::ClassDefinitionModifiers modifiers, ir::ModifierFlags flags)
775 {
776 auto savedCtx = SavedStatusContext<ParserStatus::IN_CLASS_BODY>(&context_);
777
778 lexer::SourcePosition startLoc = lexer_->GetToken().Start();
779 lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);
780
781 ir::MethodDefinition *ctor = nullptr;
782 ArenaVector<ir::AstNode *> properties(Allocator()->Adapter());
783
784 SavedClassPrivateContext classContext(this);
785
786 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_FORMAT &&
787 lexer_->Lookahead() == static_cast<char32_t>(ARRAY_FORMAT_NODE)) {
788 properties = std::move(ParseAstNodesArrayFormatPlaceholder());
789 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
790 ThrowSyntaxError("Expected a '}'");
791 }
792 } else {
793 while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
794 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
795 lexer_->NextToken();
796 continue;
797 }
798
799 ir::AstNode *property = ParseClassElement(properties, modifiers, flags);
800
801 if (CheckClassElement(property, ctor, properties)) {
802 continue;
803 }
804
805 properties.push_back(property);
806 }
807 }
808
809 lexer::SourcePosition endLoc = lexer_->GetToken().End();
810 CreateImplicitConstructor(ctor, properties, modifiers, endLoc);
811 lexer_->NextToken();
812
813 return {ctor, std::move(properties), lexer::SourceRange {startLoc, endLoc}};
814 }
815
ValidateRestParameter(ir::Expression * param)816 void ParserImpl::ValidateRestParameter(ir::Expression *param)
817 {
818 if (!param->IsIdentifier()) {
819 context_.Status() |= ParserStatus::HAS_COMPLEX_PARAM;
820 if (!param->IsRestElement()) {
821 return;
822 }
823
824 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
825 ThrowSyntaxError("Rest parameter must be last formal parameter.");
826 }
827 }
828 }
829
ValidateBreakLabel(util::StringView label)830 bool ParserImpl::ValidateBreakLabel(util::StringView label)
831 {
832 return context_.FindLabel(label) != nullptr;
833 }
834
ValidateContinueLabel(util::StringView label)835 bool ParserImpl::ValidateContinueLabel(util::StringView label)
836 {
837 const ParserContext *labelCtx = context_.FindLabel(label);
838 return labelCtx != nullptr && ((labelCtx->Status() & ParserStatus::IN_ITERATION) != 0);
839 }
840
ParseFunctionParams()841 ArenaVector<ir::Expression *> ParserImpl::ParseFunctionParams()
842 {
843 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
844 lexer_->NextToken(); // eat '('
845 }
846
847 ArenaVector<ir::Expression *> params(Allocator()->Adapter());
848
849 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_FORMAT &&
850 lexer_->Lookahead() == static_cast<char32_t>(ARRAY_FORMAT_NODE)) {
851 params = std::move(ParseExpressionsArrayFormatPlaceholder());
852 } else {
853 while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
854 ir::Expression *parameter = ParseFunctionParameter();
855 ValidateRestParameter(parameter);
856
857 params.push_back(parameter);
858
859 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
860 lexer_->NextToken();
861 } else if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
862 ThrowSyntaxError("Invalid token: comma or right parenthesis expected.");
863 }
864 }
865 }
866
867 ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS);
868 lexer_->NextToken();
869 return params;
870 }
871
CreateParameterThis(util::StringView className)872 ir::Expression *ParserImpl::CreateParameterThis([[maybe_unused]] util::StringView className)
873 {
874 ThrowSyntaxError({"Unexpected token: ", className.Utf8()});
875 }
876
ParseFunctionBody(const ArenaVector<ir::Expression * > & params,ParserStatus newStatus,ParserStatus contextStatus)877 std::tuple<bool, ir::BlockStatement *, lexer::SourcePosition, bool> ParserImpl::ParseFunctionBody(
878 [[maybe_unused]] const ArenaVector<ir::Expression *> ¶ms, [[maybe_unused]] ParserStatus newStatus,
879 [[maybe_unused]] ParserStatus contextStatus)
880 {
881 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
882 ThrowSyntaxError("Unexpected token, expected '{'");
883 }
884
885 ir::BlockStatement *body = ParseBlockStatement();
886
887 return {true, body, body->End(), false};
888 }
889
ParseFunctionSignature(ParserStatus status,ir::Identifier * className)890 FunctionSignature ParserImpl::ParseFunctionSignature(ParserStatus status, ir::Identifier *className)
891 {
892 ir::TSTypeParameterDeclaration *typeParamDecl = ParseFunctionTypeParameters();
893
894 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
895 ThrowSyntaxError("Unexpected token, expected '('");
896 }
897
898 FunctionParameterContext funcParamContext(&context_);
899
900 ir::Expression *parameterThis = nullptr;
901 if (className != nullptr) {
902 const auto savedPos = Lexer()->Save();
903 lexer_->NextToken(); // eat '('
904 parameterThis = CreateParameterThis(className->Name());
905 Lexer()->Rewind(savedPos);
906 }
907
908 auto params = ParseFunctionParams();
909
910 if (className != nullptr) {
911 params.emplace(params.begin(), parameterThis);
912 }
913
914 ir::TypeNode *returnTypeAnnotation = ParseFunctionReturnType(status);
915 ir::ScriptFunctionFlags throwMarker = ParseFunctionThrowMarker(true);
916
917 auto res = ir::FunctionSignature(typeParamDecl, std::move(params), returnTypeAnnotation);
918 return {std::move(res), throwMarker};
919 }
920
ParseFunction(ParserStatus newStatus)921 ir::ScriptFunction *ParserImpl::ParseFunction(ParserStatus newStatus)
922 {
923 FunctionContext functionContext(this, newStatus | ParserStatus::FUNCTION | ParserStatus::ALLOW_NEW_TARGET);
924
925 bool isDeclare = InAmbientContext();
926
927 lexer::SourcePosition startLoc = lexer_->GetToken().Start();
928
929 auto [signature, throw_marker] = ParseFunctionSignature(newStatus);
930
931 auto [letDeclare, body, endLoc, isOverload] = ParseFunctionBody(signature.Params(), newStatus, context_.Status());
932
933 if (isOverload) {
934 functionContext.AddFlag(ir::ScriptFunctionFlags::OVERLOAD);
935 }
936
937 functionContext.AddFlag(throw_marker);
938 auto *funcNode = AllocNode<ir::ScriptFunction>(
939 Allocator(),
940 ir::ScriptFunction::ScriptFunctionData {
941 body, std::move(signature), functionContext.Flags(), {}, isDeclare && letDeclare, context_.GetLanguage()});
942 funcNode->SetRange({startLoc, endLoc});
943
944 return funcNode;
945 }
946
ParseSpreadElement(ExpressionParseFlags flags)947 ir::SpreadElement *ParserImpl::ParseSpreadElement(ExpressionParseFlags flags)
948 {
949 ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD);
950 lexer::SourcePosition startLocation = lexer_->GetToken().Start();
951 bool inPattern = (flags & ExpressionParseFlags::MUST_BE_PATTERN) != 0;
952 lexer_->NextToken();
953
954 ir::Expression *argument {};
955 if (inPattern) {
956 argument = ParsePatternElement(ExpressionParseFlags::IN_REST);
957 if ((flags & ExpressionParseFlags::OBJECT_PATTERN) != 0 && !argument->IsIdentifier()) {
958 ThrowSyntaxError("RestParameter must be followed by an identifier in declaration contexts");
959 }
960 } else {
961 argument = ParseExpression(flags);
962 }
963
964 if (inPattern && argument->IsAssignmentExpression()) {
965 ThrowSyntaxError("RestParameter does not support an initializer");
966 }
967
968 auto nodeType = inPattern ? ir::AstNodeType::REST_ELEMENT : ir::AstNodeType::SPREAD_ELEMENT;
969 auto *spreadElementNode = AllocNode<ir::SpreadElement>(nodeType, Allocator(), argument);
970 spreadElementNode->SetRange({startLocation, argument->End()});
971 return spreadElementNode;
972 }
973
CheckRestrictedBinding() const974 void ParserImpl::CheckRestrictedBinding() const
975 {
976 ASSERT(lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT);
977 CheckRestrictedBinding(lexer_->GetToken().KeywordType());
978 }
979
CheckRestrictedBinding(lexer::TokenType keywordType) const980 void ParserImpl::CheckRestrictedBinding(lexer::TokenType keywordType) const
981 {
982 if (keywordType == lexer::TokenType::KEYW_ARGUMENTS || keywordType == lexer::TokenType::KEYW_EVAL) {
983 ThrowSyntaxError(
984 "'eval' or 'arguments' can't be defined or assigned to "
985 "in strict mode code",
986 lexer_->GetToken().Start());
987 }
988 }
989
CheckRestrictedBinding(const util::StringView & ident,const lexer::SourcePosition & pos) const990 void ParserImpl::CheckRestrictedBinding(const util::StringView &ident, const lexer::SourcePosition &pos) const
991 {
992 if (ident.Is("eval") || ident.Is("arguments")) {
993 ThrowSyntaxError(
994 "'eval' or 'arguments' can't be defined or assigned to "
995 "in strict mode code",
996 pos);
997 }
998 }
999
ParseFunctionParameter()1000 ir::Expression *ParserImpl::ParseFunctionParameter()
1001 {
1002 ConvertThisKeywordToIdentIfNecessary();
1003
1004 if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) {
1005 CheckRestrictedBinding();
1006 }
1007
1008 return ParsePatternElement(ExpressionParseFlags::NO_OPTS, true);
1009 }
1010
ValidateLvalueAssignmentTarget(ir::Expression * node)1011 void ParserImpl::ValidateLvalueAssignmentTarget(ir::Expression *node)
1012 {
1013 switch (node->Type()) {
1014 case ir::AstNodeType::IDENTIFIER: {
1015 CheckRestrictedBinding(node->AsIdentifier()->Name(), node->Start());
1016 break;
1017 }
1018 case ir::AstNodeType::MEMBER_EXPRESSION: {
1019 break;
1020 }
1021 default: {
1022 ThrowSyntaxError("Invalid left-hand side in assignment expression");
1023 }
1024 }
1025 }
1026
ValidateAssignmentTarget(ExpressionParseFlags flags,ir::Expression * node)1027 void ParserImpl::ValidateAssignmentTarget(ExpressionParseFlags flags, ir::Expression *node)
1028 {
1029 switch (node->Type()) {
1030 case ir::AstNodeType::ARRAY_PATTERN:
1031 case ir::AstNodeType::OBJECT_PATTERN: {
1032 break;
1033 }
1034 case ir::AstNodeType::ARRAY_EXPRESSION:
1035 case ir::AstNodeType::OBJECT_EXPRESSION: {
1036 if ((flags & ExpressionParseFlags::POTENTIALLY_IN_PATTERN) != 0) {
1037 return;
1038 }
1039
1040 [[fallthrough]];
1041 }
1042 default: {
1043 return ValidateLvalueAssignmentTarget(node);
1044 }
1045 }
1046 }
1047
ValidateArrowParameterBindings(const ir::Expression * node)1048 void ParserImpl::ValidateArrowParameterBindings(const ir::Expression *node)
1049 {
1050 switch (node->Type()) {
1051 case ir::AstNodeType::IDENTIFIER: {
1052 CheckRestrictedBinding(node->AsIdentifier()->Name(), node->Start());
1053 break;
1054 }
1055 case ir::AstNodeType::OMITTED_EXPRESSION: {
1056 break;
1057 }
1058 case ir::AstNodeType::REST_ELEMENT: {
1059 ValidateArrowParameterBindings(node->AsRestElement()->Argument());
1060 break;
1061 }
1062 case ir::AstNodeType::PROPERTY: {
1063 break;
1064 }
1065 case ir::AstNodeType::OBJECT_PATTERN: {
1066 const auto &props = node->AsObjectPattern()->Properties();
1067
1068 for (auto *it : props) {
1069 ValidateArrowParameterBindings(it);
1070 }
1071 break;
1072 }
1073 case ir::AstNodeType::ARRAY_PATTERN: {
1074 const auto &elements = node->AsArrayPattern()->Elements();
1075
1076 for (auto *it : elements) {
1077 ValidateArrowParameterBindings(it);
1078 }
1079 break;
1080 }
1081 case ir::AstNodeType::ASSIGNMENT_PATTERN: {
1082 ValidateArrowParameterBindings(node->AsAssignmentPattern()->Left());
1083 break;
1084 }
1085 default: {
1086 ThrowSyntaxError("Unexpected ArrowParameter element");
1087 }
1088 }
1089 }
1090
ThrowParameterModifierError(ir::ModifierFlags status) const1091 void ParserImpl::ThrowParameterModifierError(ir::ModifierFlags status) const
1092 {
1093 ThrowSyntaxError({"'",
1094 (status & ir::ModifierFlags::STATIC) != 0 ? "static"
1095 : (status & ir::ModifierFlags::ASYNC) != 0 ? "async"
1096 : "declare",
1097 "' modifier cannot appear on a parameter."},
1098 lexer_->GetToken().Start());
1099 }
1100
ParseIdentifierFormatPlaceholder(std::optional<NodeFormatType> nodeFormat) const1101 ir::Identifier *ParserImpl::ParseIdentifierFormatPlaceholder(
1102 [[maybe_unused]] std::optional<NodeFormatType> nodeFormat) const
1103 {
1104 ThrowSyntaxError("Identifier expected.");
1105 }
1106
ParseStatementFormatPlaceholder() const1107 ir::Statement *ParserImpl::ParseStatementFormatPlaceholder() const
1108 {
1109 ThrowSyntaxError("Statement expected.");
1110 }
1111
ParseTypeParametersFormatPlaceholder() const1112 ir::AstNode *ParserImpl::ParseTypeParametersFormatPlaceholder() const
1113 {
1114 ThrowSyntaxError("Type parameter(s) expected.");
1115 }
1116
ParseStatementsArrayFormatPlaceholder() const1117 ArenaVector<ir::Statement *> &ParserImpl::ParseStatementsArrayFormatPlaceholder() const
1118 {
1119 ThrowSyntaxError("ArenaVector of ir::Statement *'s expected.");
1120 }
1121
ParseAstNodesArrayFormatPlaceholder() const1122 ArenaVector<ir::AstNode *> &ParserImpl::ParseAstNodesArrayFormatPlaceholder() const
1123 {
1124 ThrowSyntaxError("ArenaVector of ir::AstNode *'s expected.");
1125 }
1126
ParseExpressionsArrayFormatPlaceholder() const1127 ArenaVector<ir::Expression *> &ParserImpl::ParseExpressionsArrayFormatPlaceholder() const
1128 {
1129 ThrowSyntaxError("ArenaVector of ir::Expression *'s expected.");
1130 }
1131
ParseSymbolIteratorIdentifier() const1132 util::StringView ParserImpl::ParseSymbolIteratorIdentifier() const noexcept
1133 {
1134 // Duplicate check - just in case of improper call!
1135 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET) {
1136 return util::StringView {};
1137 }
1138
1139 lexer_->NextToken();
1140 if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT || !lexer_->GetToken().Ident().Is("Symbol")) {
1141 return util::StringView {};
1142 }
1143
1144 lexer_->NextToken();
1145 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_PERIOD) {
1146 return util::StringView {};
1147 }
1148
1149 lexer_->NextToken();
1150 if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT || !lexer_->GetToken().Ident().Is("iterator")) {
1151 return util::StringView {};
1152 }
1153
1154 lexer_->NextToken();
1155 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
1156 return util::StringView {};
1157 }
1158
1159 // Just replace '[Symbol.iterator]` identifier with the standard '$_iterator' name.
1160 return util::StringView {compiler::Signatures::ITERATOR_METHOD};
1161 }
1162
ExpectIdentifier(bool isReference,bool isUserDefinedType)1163 ir::Identifier *ParserImpl::ExpectIdentifier(bool isReference, bool isUserDefinedType)
1164 {
1165 auto const &token = lexer_->GetToken();
1166 auto const tokenType = token.Type();
1167 if (tokenType == lexer::TokenType::PUNCTUATOR_FORMAT) {
1168 return ParseIdentifierFormatPlaceholder(std::nullopt);
1169 }
1170
1171 if (token.IsDefinableTypeName() && isUserDefinedType) {
1172 ThrowSyntaxError("Cannot be used as user-defined type.");
1173 }
1174
1175 auto const &tokenStart = token.Start();
1176 util::StringView tokenName {};
1177
1178 if (tokenType == lexer::TokenType::LITERAL_IDENT) {
1179 tokenName = token.Ident();
1180 } else if (tokenType == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET) {
1181 // Special case for processing of special '[Symbol.iterator]` identifier using in stdlib.
1182 tokenName = ParseSymbolIteratorIdentifier();
1183 }
1184
1185 if (tokenName.Empty()) {
1186 ThrowSyntaxError("Identifier expected.", tokenStart);
1187 }
1188
1189 auto *ident = AllocNode<ir::Identifier>(tokenName, Allocator());
1190 ident->SetReference(isReference);
1191 // NOTE: here actual token can be changed!
1192 ident->SetRange({tokenStart, lexer_->GetToken().End()});
1193
1194 lexer_->NextToken();
1195
1196 return ident;
1197 }
1198
ExpectToken(lexer::TokenType tokenType,bool consumeToken)1199 void ParserImpl::ExpectToken(lexer::TokenType tokenType, bool consumeToken)
1200 {
1201 if (lexer_->GetToken().Type() == tokenType) {
1202 if (consumeToken) {
1203 lexer_->NextToken();
1204 }
1205 return;
1206 }
1207 ThrowExpectedToken(tokenType);
1208 }
1209
ThrowUnexpectedToken(lexer::TokenType const tokenType) const1210 void ParserImpl::ThrowUnexpectedToken(lexer::TokenType const tokenType) const
1211 {
1212 ThrowSyntaxError("Unexpected token: '"s + TokenToString(tokenType) + "'."s);
1213 }
1214
ThrowExpectedToken(lexer::TokenType const tokenType) const1215 void ParserImpl::ThrowExpectedToken(lexer::TokenType const tokenType) const
1216 {
1217 ThrowSyntaxError("Unexpected token, expected: '"s + TokenToString(tokenType) + "'."s);
1218 }
1219
ThrowSyntaxError(std::string_view const errorMessage) const1220 void ParserImpl::ThrowSyntaxError(std::string_view const errorMessage) const
1221 {
1222 ThrowSyntaxError(errorMessage, lexer_->GetToken().Start());
1223 }
1224
ThrowSyntaxError(std::initializer_list<std::string_view> list) const1225 void ParserImpl::ThrowSyntaxError(std::initializer_list<std::string_view> list) const
1226 {
1227 ThrowSyntaxError(list, lexer_->GetToken().Start());
1228 }
1229
ThrowSyntaxError(std::initializer_list<std::string_view> list,const lexer::SourcePosition & pos) const1230 void ParserImpl::ThrowSyntaxError(std::initializer_list<std::string_view> list, const lexer::SourcePosition &pos) const
1231 {
1232 std::stringstream ss;
1233
1234 for (const auto &it : list) {
1235 ss << it;
1236 }
1237
1238 std::string err = ss.str();
1239
1240 ThrowSyntaxError(std::string_view {err}, pos);
1241 }
1242
ThrowSyntaxError(std::string_view errorMessage,const lexer::SourcePosition & pos) const1243 void ParserImpl::ThrowSyntaxError(std::string_view errorMessage, const lexer::SourcePosition &pos) const
1244 {
1245 lexer::LineIndex index(program_->SourceCode());
1246 lexer::SourceLocation loc = index.GetLocation(pos);
1247
1248 throw Error {ErrorType::SYNTAX, program_->SourceFilePath().Utf8(), errorMessage, loc.line, loc.col};
1249 }
1250
ThrowAllocationError(std::string_view message) const1251 void ParserImpl::ThrowAllocationError(std::string_view message) const
1252 {
1253 throw Error(ErrorType::GENERIC, program_->SourceFilePath().Utf8(), message);
1254 }
1255
Extension() const1256 ScriptExtension ParserImpl::Extension() const
1257 {
1258 return program_->Extension();
1259 }
1260
CheckModuleAsModifier()1261 bool ParserImpl::CheckModuleAsModifier()
1262 {
1263 if (lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_AS) {
1264 return false;
1265 }
1266
1267 if ((lexer_->GetToken().Flags() & lexer::TokenFlags::HAS_ESCAPE) != 0U) {
1268 ThrowSyntaxError("Escape sequences are not allowed in 'as' keyword");
1269 }
1270
1271 return true;
1272 }
1273
1274 } // namespace ark::es2panda::parser
1275