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 #include "parser/ETSparser.h"
47 #include "util/errorRecovery.h"
48
49 using namespace std::literals::string_literals;
50
51 namespace ark::es2panda::parser {
ParserImpl(Program * program,const CompilerOptions & options,ParserStatus status)52 ParserImpl::ParserImpl(Program *program, const CompilerOptions &options, ParserStatus status)
53 : program_(program), context_(program_, status), options_(options)
54 {
55 }
56
InitLexer(const SourceFile & sourceFile)57 std::unique_ptr<lexer::Lexer> ParserImpl::InitLexer(const SourceFile &sourceFile)
58 {
59 program_->SetSource(sourceFile);
60 std::unique_ptr<lexer::Lexer> lexer = std::make_unique<lexer::Lexer>(&context_, &errorLogger_);
61 lexer_ = lexer.get();
62 return lexer;
63 }
64
ParseScript(const SourceFile & sourceFile,bool genStdLib)65 void ParserImpl::ParseScript(const SourceFile &sourceFile, bool genStdLib)
66 {
67 auto lexer = InitLexer(sourceFile);
68
69 if (sourceFile.isModule) {
70 context_.Status() |= (ParserStatus::MODULE);
71 ParseProgram(ScriptKind::MODULE);
72 } else if (genStdLib) {
73 ParseProgram(ScriptKind::STDLIB);
74 } else {
75 ParseProgram(ScriptKind::SCRIPT);
76 }
77 }
78
ParseProgram(ScriptKind kind)79 void ParserImpl::ParseProgram(ScriptKind kind)
80 {
81 lexer::SourcePosition startLoc = lexer_->GetToken().Start();
82 lexer_->NextToken();
83 program_->SetKind(kind);
84
85 auto statements = ParseStatementList(StatementParsingFlags::STMT_GLOBAL_LEXICAL);
86
87 auto *blockStmt = AllocNode<ir::BlockStatement>(Allocator(), std::move(statements));
88 blockStmt->SetRange({startLoc, lexer_->GetToken().End()});
89
90 program_->SetAst(blockStmt);
91 program_->SetDeclarationModuleInfo();
92 }
93
InAmbientContext()94 bool ParserImpl::InAmbientContext()
95 {
96 return (context_.Status() & ParserStatus::IN_AMBIENT_CONTEXT) != 0;
97 }
98
CarryExpressionParserFlag(ExpressionParseFlags origin,ExpressionParseFlags carry)99 ExpressionParseFlags ParserImpl::CarryExpressionParserFlag(ExpressionParseFlags origin, ExpressionParseFlags carry)
100 {
101 return static_cast<ExpressionParseFlags>(origin & carry);
102 }
103
CarryPatternFlags(ExpressionParseFlags flags)104 ExpressionParseFlags ParserImpl::CarryPatternFlags(ExpressionParseFlags flags)
105 {
106 return CarryExpressionParserFlag(flags, ExpressionParseFlags::POTENTIALLY_IN_PATTERN |
107 ExpressionParseFlags::OBJECT_PATTERN);
108 }
109
GetAccessability(ir::ModifierFlags modifiers)110 ir::ModifierFlags ParserImpl::GetAccessability(ir::ModifierFlags modifiers)
111 {
112 if ((modifiers & ir::ModifierFlags::PUBLIC) != 0) {
113 return ir::ModifierFlags::PUBLIC;
114 }
115
116 if ((modifiers & ir::ModifierFlags::PRIVATE) != 0) {
117 return ir::ModifierFlags::PRIVATE;
118 }
119
120 if ((modifiers & ir::ModifierFlags::PROTECTED) != 0) {
121 return ir::ModifierFlags::PROTECTED;
122 }
123
124 if ((modifiers & ir::ModifierFlags::INTERNAL) != 0) {
125 return ir::ModifierFlags::INTERNAL;
126 }
127
128 return ir::ModifierFlags::NONE;
129 }
130
IsModifierKind(const lexer::Token & token)131 bool ParserImpl::IsModifierKind(const lexer::Token &token)
132 {
133 switch (token.KeywordType()) {
134 case lexer::TokenType::KEYW_STATIC:
135 case lexer::TokenType::KEYW_ASYNC:
136 return true;
137 default:
138 break;
139 }
140
141 return false;
142 }
143
ParseModifiers()144 ir::ModifierFlags ParserImpl::ParseModifiers()
145 {
146 ir::ModifierFlags resultStatus = ir::ModifierFlags::NONE;
147 ir::ModifierFlags prevStatus = ir::ModifierFlags::ALL;
148
149 while (IsModifierKind(lexer_->GetToken())) {
150 char32_t nextCp = lexer_->Lookahead();
151 if (nextCp == lexer::LEX_CHAR_LEFT_PAREN) {
152 return resultStatus;
153 }
154
155 lexer::TokenFlags tokenFlags = lexer_->GetToken().Flags();
156 if ((tokenFlags & lexer::TokenFlags::HAS_ESCAPE) != 0) {
157 LogSyntaxError("Keyword must not contain escaped characters");
158 }
159
160 ir::ModifierFlags actualStatus = ir::ModifierFlags::NONE;
161 ir::ModifierFlags nextStatus = ir::ModifierFlags::NONE;
162
163 switch (lexer_->GetToken().KeywordType()) {
164 case lexer::TokenType::KEYW_STATIC: {
165 actualStatus = ir::ModifierFlags::STATIC;
166 nextStatus = ir::ModifierFlags::ASYNC;
167 break;
168 }
169 case lexer::TokenType::KEYW_ASYNC: {
170 actualStatus = ir::ModifierFlags::ASYNC;
171 nextStatus = ir::ModifierFlags::NONE;
172 break;
173 }
174 default: {
175 break;
176 }
177 }
178
179 if (lexer_->Lookahead() == lexer::LEX_CHAR_COLON || lexer_->Lookahead() == lexer::LEX_CHAR_COMMA ||
180 lexer_->Lookahead() == lexer::LEX_CHAR_RIGHT_PAREN || lexer_->Lookahead() == lexer::LEX_CHAR_QUESTION ||
181 lexer_->Lookahead() == lexer::LEX_CHAR_RIGHT_BRACE || lexer_->Lookahead() == lexer::LEX_CHAR_LESS_THAN) {
182 break;
183 }
184
185 if ((prevStatus & actualStatus) == 0) {
186 LogSyntaxError("Unexpected modifier");
187 }
188
189 if ((resultStatus & actualStatus) != 0) {
190 LogSyntaxError("Duplicated modifier is not allowed");
191 }
192
193 lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);
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 LogSyntaxError("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 LogIfPrivateIdent(desc, "Unexpected identifier");
269
270 if ((lexer_->GetToken().Flags() & lexer::TokenFlags::HAS_ESCAPE) != 0) {
271 LogSyntaxError("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
LogIfPrivateIdent(ClassElementDescriptor * desc,const char * msg)282 void ParserImpl::LogIfPrivateIdent(ClassElementDescriptor *desc, const char *msg)
283 {
284 if (desc->isPrivateIdent) {
285 LogSyntaxError(msg);
286 }
287 }
288
CheckIfStaticConstructor(ir::ModifierFlags flags)289 void ParserImpl::CheckIfStaticConstructor([[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 LogSyntaxError("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 // test-class-constructor3.ts
303 LogSyntaxError("Classes may not have a field named 'constructor'");
304 }
305
306 LogIfPrivateIdent(desc, "Private identifier can not be constructor");
307
308 if ((desc->modifiers & ir::ModifierFlags::STATIC) == 0) {
309 if ((desc->modifiers & ir::ModifierFlags::ASYNC) != 0 ||
310 desc->methodKind == ir::MethodDefinitionKind::GET ||
311 desc->methodKind == ir::MethodDefinitionKind::SET || desc->isGenerator) {
312 LogSyntaxError("Constructor can not be special method");
313 }
314
315 desc->methodKind = ir::MethodDefinitionKind::CONSTRUCTOR;
316 desc->methodStart = lexer_->GetToken().Start();
317 desc->newStatus |= ParserStatus::CONSTRUCTOR_FUNCTION;
318
319 if (desc->hasSuperClass) {
320 desc->newStatus |= ParserStatus::ALLOW_SUPER_CALL;
321 }
322 }
323
324 CheckIfStaticConstructor(desc->modifiers);
325 } else if (propNameStr.Is("prototype") && (desc->modifiers & ir::ModifierFlags::STATIC) != 0) {
326 LogSyntaxError("Classes may not have static property named prototype");
327 }
328 }
329
ParseComputedClassFieldOrIndexSignature(ir::Expression ** propName)330 std::tuple<bool, bool, bool> ParserImpl::ParseComputedClassFieldOrIndexSignature(ir::Expression **propName)
331 {
332 lexer_->NextToken(); // eat left square bracket
333 *propName = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
334
335 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
336 // test exists for js extension only
337 LogExpectedToken(lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET);
338 }
339
340 return {true, false, false};
341 }
342
ParseClassKey(ClassElementDescriptor * desc)343 ir::Expression *ParserImpl::ParseClassKey(ClassElementDescriptor *desc)
344 {
345 ir::Expression *propName = nullptr;
346 if (lexer_->GetToken().IsKeyword()) {
347 lexer_->GetToken().SetTokenType(lexer::TokenType::LITERAL_IDENT);
348 Lexer()->GetToken().SetTokenStr(ERROR_LITERAL);
349 }
350
351 switch (lexer_->GetToken().Type()) {
352 case lexer::TokenType::LITERAL_IDENT: {
353 ValidateClassKey(desc);
354
355 propName = AllocNode<ir::Identifier>(lexer_->GetToken().Ident(), Allocator());
356 propName->SetRange(lexer_->GetToken().Loc());
357 propName->AsIdentifier()->SetPrivate(desc->isPrivateIdent);
358 break;
359 }
360 case lexer::TokenType::LITERAL_STRING: {
361 LogIfPrivateIdent(desc, "Private identifier name can not be string");
362
363 if (lexer_->GetToken().Ident().Is("constructor")) {
364 LogSyntaxError("Classes may not have a field named 'constructor'");
365 }
366
367 if (lexer_->GetToken().Ident().Is("prototype") && (desc->modifiers & ir::ModifierFlags::STATIC) != 0) {
368 LogSyntaxError("Classes may not have a static property named 'prototype'");
369 }
370
371 propName = AllocNode<ir::StringLiteral>(lexer_->GetToken().String());
372 propName->SetRange(lexer_->GetToken().Loc());
373 break;
374 }
375 case lexer::TokenType::LITERAL_NUMBER: {
376 LogIfPrivateIdent(desc, "Private identifier name can not be number");
377
378 if ((lexer_->GetToken().Flags() & lexer::TokenFlags::NUMBER_BIGINT) != 0) {
379 propName = AllocNode<ir::BigIntLiteral>(lexer_->GetToken().BigInt());
380 } else {
381 propName = AllocNode<ir::NumberLiteral>(lexer_->GetToken().GetNumber());
382 }
383
384 propName->SetRange(lexer_->GetToken().Loc());
385 break;
386 }
387 case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET: {
388 LogIfPrivateIdent(desc, "Unexpected character in private identifier");
389 std::tie(desc->isComputed, desc->invalidComputedProperty, desc->isIndexSignature) =
390 ParseComputedClassFieldOrIndexSignature(&propName);
391 break;
392 }
393 default: {
394 LogSyntaxError("Unexpected token in class property");
395 }
396 }
397
398 lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);
399
400 return propName;
401 }
402
ValidateClassMethodStart(ClassElementDescriptor * desc,ir::TypeNode * typeAnnotation)403 void ParserImpl::ValidateClassMethodStart(ClassElementDescriptor *desc, [[maybe_unused]] ir::TypeNode *typeAnnotation)
404 {
405 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
406 return;
407 }
408 desc->classMethod = true;
409
410 if ((desc->modifiers & ir::ModifierFlags::ASYNC) != 0) {
411 desc->newStatus |= ParserStatus::ASYNC_FUNCTION;
412 }
413
414 if (desc->isGenerator) {
415 desc->newStatus |= ParserStatus::GENERATOR_FUNCTION;
416 }
417 }
418
ValidateGetterSetter(ir::MethodDefinitionKind methodDefinition,size_t number)419 void ParserImpl::ValidateGetterSetter(ir::MethodDefinitionKind methodDefinition, size_t number)
420 {
421 if (methodDefinition == ir::MethodDefinitionKind::SET) {
422 if (number != 1) {
423 LogSyntaxError("Setter must have exactly one formal parameter");
424 }
425 } else if (methodDefinition == ir::MethodDefinitionKind::GET) {
426 if (number != 0) {
427 LogSyntaxError("Getter must not have formal parameters");
428 }
429 }
430 }
431
ValidateClassSetter(ClassElementDescriptor * desc,const ArenaVector<ir::AstNode * > & properties,ir::Expression * propName,ir::ScriptFunction * func)432 void ParserImpl::ValidateClassSetter([[maybe_unused]] ClassElementDescriptor *desc,
433 [[maybe_unused]] const ArenaVector<ir::AstNode *> &properties,
434 [[maybe_unused]] ir::Expression *propName, ir::ScriptFunction *func)
435 {
436 ValidateGetterSetter(ir::MethodDefinitionKind::SET, func->Params().size());
437 }
438
ValidateClassGetter(ClassElementDescriptor * desc,const ArenaVector<ir::AstNode * > & properties,ir::Expression * propName,ir::ScriptFunction * func)439 void ParserImpl::ValidateClassGetter([[maybe_unused]] ClassElementDescriptor *desc,
440 [[maybe_unused]] const ArenaVector<ir::AstNode *> &properties,
441 [[maybe_unused]] ir::Expression *propName, ir::ScriptFunction *func)
442 {
443 ValidateGetterSetter(ir::MethodDefinitionKind::GET, func->Params().size());
444 }
445
ParseClassMethod(ClassElementDescriptor * desc,const ArenaVector<ir::AstNode * > & properties,ir::Expression * propName,lexer::SourcePosition * propEnd)446 ir::MethodDefinition *ParserImpl::ParseClassMethod(ClassElementDescriptor *desc,
447 const ArenaVector<ir::AstNode *> &properties,
448 ir::Expression *propName, lexer::SourcePosition *propEnd)
449 {
450 if (desc->methodKind != ir::MethodDefinitionKind::SET &&
451 (desc->newStatus & ParserStatus::CONSTRUCTOR_FUNCTION) == 0) {
452 desc->newStatus |= ParserStatus::NEED_RETURN_TYPE;
453 }
454
455 ir::ScriptFunction *func = ParseFunction(desc->newStatus);
456
457 auto *funcExpr = AllocNode<ir::FunctionExpression>(func);
458 funcExpr->SetRange(func->Range());
459
460 if (desc->methodKind == ir::MethodDefinitionKind::SET) {
461 ValidateClassSetter(desc, properties, propName, func);
462 } else if (desc->methodKind == ir::MethodDefinitionKind::GET) {
463 ValidateClassGetter(desc, properties, propName, func);
464 }
465
466 *propEnd = func->End();
467 func->AddFlag(ir::ScriptFunctionFlags::METHOD);
468
469 auto *ident = !propName->IsArrowFunctionExpression() && !propName->IsFunctionExpression()
470 ? propName->Clone(Allocator(), nullptr)->AsExpression()
471 : propName;
472 auto *method = AllocNode<ir::MethodDefinition>(desc->methodKind, ident, funcExpr, desc->modifiers, Allocator(),
473 desc->isComputed);
474 method->SetRange(funcExpr->Range());
475
476 return method;
477 }
478
ParseClassProperty(ClassElementDescriptor * desc,const ArenaVector<ir::AstNode * > & properties,ir::Expression * propName,ir::TypeNode * typeAnnotation)479 ir::ClassElement *ParserImpl::ParseClassProperty(ClassElementDescriptor *desc,
480 const ArenaVector<ir::AstNode *> &properties, ir::Expression *propName,
481 ir::TypeNode *typeAnnotation)
482 {
483 lexer::SourcePosition propEnd = propName->End();
484 ir::ClassElement *property = nullptr;
485
486 if (desc->classMethod) {
487 if ((desc->modifiers & ir::ModifierFlags::DECLARE) != 0) {
488 LogSyntaxError("'declare modifier cannot appear on class elements of this kind.");
489 }
490
491 property = ParseClassMethod(desc, properties, propName, &propEnd);
492 property->SetRange({desc->propStart, propEnd});
493 return property;
494 }
495
496 ir::Expression *value = nullptr;
497
498 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
499 lexer_->NextToken(); // eat equals
500
501 if (InAmbientContext() || (desc->modifiers & ir::ModifierFlags::DECLARE) != 0) {
502 LogSyntaxError("Initializers are not allowed in ambient contexts.");
503 }
504
505 value = ParseExpression();
506 propEnd = value->End();
507 }
508
509 property =
510 AllocNode<ir::ClassProperty>(propName, value, typeAnnotation, desc->modifiers, Allocator(), desc->isComputed);
511
512 property->SetRange({desc->propStart, propEnd});
513
514 return property;
515 }
516
CheckClassGeneratorMethod(ClassElementDescriptor * desc,char32_t * nextCp)517 void ParserImpl::CheckClassGeneratorMethod(ClassElementDescriptor *desc, char32_t *nextCp)
518 {
519 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_MULTIPLY) {
520 return;
521 }
522
523 desc->isGenerator = true;
524 lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);
525 *nextCp = lexer_->Lookahead();
526 }
527
ValidatePrivateIdentifier()528 bool ParserImpl::ValidatePrivateIdentifier()
529 {
530 size_t iterIdx = lexer_->GetToken().Start().index;
531 lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);
532
533 if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT ||
534 (lexer_->GetToken().Start().index - iterIdx > 1)) {
535 LogSyntaxError("Unexpected token in private field");
536 return false;
537 }
538
539 return true;
540 }
541
ConsumeClassPrivateIdentifier(ClassElementDescriptor * desc,char32_t * nextCp)542 void ParserImpl::ConsumeClassPrivateIdentifier(ClassElementDescriptor *desc, char32_t *nextCp)
543 {
544 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_HASH_MARK) {
545 return;
546 }
547
548 desc->isPrivateIdent = true;
549 ValidatePrivateIdentifier();
550 *nextCp = lexer_->Lookahead();
551 }
552
AddPrivateElement(const ir::ClassElement * elem)553 void ParserImpl::AddPrivateElement(const ir::ClassElement *elem)
554 {
555 if (elem->Id() == nullptr) { // Error processing.
556 return;
557 }
558
559 if (!classPrivateContext_.AddElement(elem)) {
560 LogSyntaxError("Private field has already been declared");
561 }
562 }
563
ParseClassStaticBlock()564 ir::ClassElement *ParserImpl::ParseClassStaticBlock()
565 {
566 const lexer::SourcePosition &startPos = lexer_->GetToken().Start();
567
568 lexer_->NextToken(); // eat 'static'
569
570 SavedParserContext context(this, ParserStatus::ALLOW_SUPER);
571 context_.Status() &= ~(ParserStatus::ASYNC_FUNCTION | ParserStatus::GENERATOR_FUNCTION);
572
573 lexer_->NextToken(); // eat '{'
574
575 ArenaVector<ir::Expression *> params(Allocator()->Adapter());
576
577 ArenaVector<ir::Statement *> statements = ParseStatementList();
578
579 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
580 // redundant check -> we have it in parse statements
581 // we even do not do lexer_->NextToken() trying to eat '}' after
582 LogExpectedToken(lexer::TokenType::PUNCTUATOR_RIGHT_BRACE);
583 }
584
585 auto *body = AllocNode<ir::BlockStatement>(Allocator(), std::move(statements));
586 // clang-format off
587 auto *func = AllocNode<ir::ScriptFunction>(
588 Allocator(), ir::ScriptFunction::ScriptFunctionData {
589 body, ir::FunctionSignature(nullptr, std::move(params), nullptr),
590 ir::ScriptFunctionFlags::EXPRESSION | ir::ScriptFunctionFlags::STATIC_BLOCK,
591 ir::ModifierFlags::STATIC, context_.GetLanguage()});
592 // clang-format on
593
594 auto *funcExpr = AllocNode<ir::FunctionExpression>(func);
595 auto *staticBlock = AllocNode<ir::ClassStaticBlock>(funcExpr, Allocator());
596 staticBlock->SetRange({startPos, lexer_->GetToken().End()});
597
598 lexer_->NextToken(); // eat '}'
599
600 return staticBlock;
601 }
602
ParseClassElement(const ArenaVector<ir::AstNode * > & properties,ir::ClassDefinitionModifiers modifiers,ir::ModifierFlags flags)603 ir::AstNode *ParserImpl::ParseClassElement(const ArenaVector<ir::AstNode *> &properties,
604 ir::ClassDefinitionModifiers modifiers,
605 [[maybe_unused]] ir::ModifierFlags flags)
606 {
607 if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_STATIC &&
608 lexer_->Lookahead() == lexer::LEX_CHAR_LEFT_BRACE) {
609 return ParseClassStaticBlock();
610 }
611
612 ClassElementDescriptor desc(Allocator());
613
614 desc.methodKind = ir::MethodDefinitionKind::METHOD;
615 desc.newStatus = ParserStatus::ALLOW_SUPER;
616 desc.hasSuperClass = (modifiers & ir::ClassDefinitionModifiers::HAS_SUPER) != 0U;
617 desc.propStart = lexer_->GetToken().Start();
618 desc.modifiers = ParseModifiers();
619
620 char32_t nextCp = lexer_->Lookahead();
621 CheckClassGeneratorMethod(&desc, &nextCp);
622 ParseClassAccessor(&desc, &nextCp);
623
624 if ((desc.modifiers & ir::ModifierFlags::STATIC) == 0) {
625 context_.Status() |= ParserStatus::ALLOW_THIS_TYPE;
626 }
627
628 ir::Expression *propName = ParseClassKey(&desc);
629 if (propName == nullptr) { // Error processing.
630 context_.Status() &= ~ParserStatus::ALLOW_THIS_TYPE;
631 return nullptr;
632 }
633
634 ValidateClassMethodStart(&desc, nullptr);
635 ir::ClassElement *property = ParseClassProperty(&desc, properties, propName, nullptr);
636
637 if (property != nullptr && lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON &&
638 lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE &&
639 (lexer_->GetToken().Flags() & lexer::TokenFlags::NEW_LINE) == 0 &&
640 !(property->IsMethodDefinition() &&
641 property->AsMethodDefinition()->Value()->AsFunctionExpression()->Function()->Body() != nullptr)) {
642 // test exists for js extension only
643 LogExpectedToken(lexer::TokenType::PUNCTUATOR_SEMI_COLON);
644 }
645
646 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
647 lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);
648 }
649
650 context_.Status() &= ~ParserStatus::ALLOW_THIS_TYPE;
651
652 if (desc.isPrivateIdent) {
653 AddPrivateElement(property);
654 }
655
656 return property;
657 }
658
BuildImplicitConstructor(ir::ClassDefinitionModifiers modifiers,const lexer::SourcePosition & startLoc)659 ir::MethodDefinition *ParserImpl::BuildImplicitConstructor(ir::ClassDefinitionModifiers modifiers,
660 const lexer::SourcePosition &startLoc)
661 {
662 ArenaVector<ir::Expression *> params(Allocator()->Adapter());
663 ArenaVector<ir::Statement *> statements(Allocator()->Adapter());
664
665 if ((modifiers & ir::ClassDefinitionModifiers::HAS_SUPER) != 0U) {
666 util::StringView argsStr = "args";
667 params.push_back(AllocNode<ir::SpreadElement>(ir::AstNodeType::REST_ELEMENT, Allocator(),
668 AllocNode<ir::Identifier>(argsStr, Allocator())));
669 ArenaVector<ir::Expression *> callArgs(Allocator()->Adapter());
670 auto *superExpr = AllocNode<ir::SuperExpression>();
671 callArgs.push_back(AllocNode<ir::SpreadElement>(ir::AstNodeType::SPREAD_ELEMENT, Allocator(),
672 AllocNode<ir::Identifier>(argsStr, Allocator())));
673
674 auto *callExpr = AllocNode<ir::CallExpression>(superExpr, std::move(callArgs), nullptr, false);
675 statements.push_back(AllocNode<ir::ExpressionStatement>(callExpr));
676 }
677
678 auto *body = AllocNode<ir::BlockStatement>(Allocator(), std::move(statements));
679 auto *func = AllocNode<ir::ScriptFunction>(
680 Allocator(), ir::ScriptFunction::ScriptFunctionData {body,
681 ir::FunctionSignature(nullptr, std::move(params), nullptr),
682 ir::ScriptFunctionFlags::CONSTRUCTOR |
683 ir::ScriptFunctionFlags::IMPLICIT_SUPER_CALL_NEEDED,
684 {},
685 context_.GetLanguage()});
686
687 auto *funcExpr = AllocNode<ir::FunctionExpression>(func);
688 auto *key = AllocNode<ir::Identifier>("constructor", Allocator());
689
690 if ((modifiers & ir::ClassDefinitionModifiers::SET_CTOR_ID) != 0U) {
691 func->SetIdent(key->Clone(Allocator(), nullptr));
692 }
693
694 auto *ctor = AllocNode<ir::MethodDefinition>(ir::MethodDefinitionKind::CONSTRUCTOR, key, funcExpr,
695 ir::ModifierFlags::NONE, Allocator(), false);
696
697 ctor->SetRange({startLoc, lexer_->GetToken().End()});
698
699 return ctor;
700 }
701
CreateImplicitConstructor(ir::MethodDefinition * & ctor,ArenaVector<ir::AstNode * > & properties,ir::ClassDefinitionModifiers modifiers,ir::ModifierFlags flags,const lexer::SourcePosition & startLoc)702 void ParserImpl::CreateImplicitConstructor(ir::MethodDefinition *&ctor,
703 [[maybe_unused]] ArenaVector<ir::AstNode *> &properties,
704 ir::ClassDefinitionModifiers modifiers, ir::ModifierFlags flags,
705 const lexer::SourcePosition &startLoc)
706 {
707 if (ctor != nullptr) {
708 return;
709 }
710
711 ctor = BuildImplicitConstructor(modifiers, startLoc);
712 if ((flags & ir::ModifierFlags::DECLARE) != 0) {
713 ctor->Function()->AddFlag(ir::ScriptFunctionFlags::EXTERNAL);
714 }
715 }
716
ParseClassIdent(ir::ClassDefinitionModifiers modifiers)717 ir::Identifier *ParserImpl::ParseClassIdent(ir::ClassDefinitionModifiers modifiers)
718 {
719 if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) {
720 return ExpectIdentifier();
721 }
722
723 auto idRequired =
724 static_cast<ir::ClassDefinitionModifiers>(modifiers & ir::ClassDefinitionModifiers::DECLARATION_ID_REQUIRED);
725
726 if (idRequired == ir::ClassDefinitionModifiers::DECLARATION_ID_REQUIRED) {
727 LogSyntaxError("Unexpected token, expected an identifier.");
728 }
729
730 return nullptr;
731 }
732
CheckClassElement(ir::AstNode * property,ir::MethodDefinition * & ctor,ArenaVector<ir::AstNode * > & properties)733 bool ParserImpl::CheckClassElement(ir::AstNode *property, ir::MethodDefinition *&ctor,
734 [[maybe_unused]] ArenaVector<ir::AstNode *> &properties)
735 {
736 if (!property->IsMethodDefinition()) {
737 return false;
738 }
739
740 ir::MethodDefinition *def = property->AsMethodDefinition();
741 if (!def->IsConstructor()) {
742 return false;
743 }
744
745 if (ctor != nullptr) {
746 LogSyntaxError("Multiple constructor implementations are not allowed.", property->Start());
747 }
748 ctor = def;
749
750 return true;
751 }
752
ParseSuperClassReference()753 ir::Expression *ParserImpl::ParseSuperClassReference()
754 {
755 if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_EXTENDS) {
756 lexer_->NextToken();
757 return ParseLeftHandSideExpression();
758 }
759
760 return nullptr;
761 }
762
ParseSuperClass()763 std::tuple<ir::Expression *, ir::TSTypeParameterInstantiation *> ParserImpl::ParseSuperClass()
764 {
765 return {ParseSuperClassReference(), nullptr};
766 }
767
768 // NOLINTNEXTLINE(google-default-arguments)
ParseClassDefinition(ir::ClassDefinitionModifiers modifiers,ir::ModifierFlags flags)769 ir::ClassDefinition *ParserImpl::ParseClassDefinition(ir::ClassDefinitionModifiers modifiers, ir::ModifierFlags flags)
770 {
771 ExpectToken(lexer::TokenType::KEYW_CLASS);
772
773 ir::Identifier *identNode = ParseClassIdent(modifiers);
774
775 if (identNode == nullptr && (modifiers & ir::ClassDefinitionModifiers::DECLARATION) != 0U) {
776 LogSyntaxError("Unexpected token, expected an identifier.");
777 return nullptr;
778 }
779
780 varbinder::PrivateBinding privateBinding(Allocator(), classId_++);
781
782 // Parse SuperClass
783 auto [superClass, superTypeParams] = ParseSuperClass();
784
785 if (superClass != nullptr) {
786 modifiers |= ir::ClassDefinitionModifiers::HAS_SUPER;
787 }
788
789 // test exists for js extension only
790 ExpectToken(lexer::TokenType::PUNCTUATOR_LEFT_BRACE, false);
791
792 auto [ctor, properties, bodyRange] = ParseClassBody(modifiers, flags);
793
794 ArenaVector<ir::TSClassImplements *> implements(Allocator()->Adapter());
795 auto *classDefinition = AllocNode<ir::ClassDefinition>(
796 privateBinding.View(), identNode, nullptr, superTypeParams, std::move(implements), ctor, superClass,
797 std::move(properties), modifiers, flags, GetContext().GetLanguage());
798
799 classDefinition->SetRange(bodyRange);
800
801 return classDefinition;
802 }
803
ParseClassBody(ir::ClassDefinitionModifiers modifiers,ir::ModifierFlags flags)804 ParserImpl::ClassBody ParserImpl::ParseClassBody(ir::ClassDefinitionModifiers modifiers, ir::ModifierFlags flags)
805 {
806 auto savedCtx = SavedStatusContext<ParserStatus::IN_CLASS_BODY>(&context_);
807
808 lexer::SourcePosition startLoc = lexer_->GetToken().Start();
809 lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);
810
811 ir::MethodDefinition *ctor = nullptr;
812 ArenaVector<ir::AstNode *> properties(Allocator()->Adapter());
813
814 SavedClassPrivateContext classContext(this);
815
816 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_FORMAT &&
817 lexer_->Lookahead() == static_cast<char32_t>(ARRAY_FORMAT_NODE)) {
818 properties = std::move(ParseAstNodesArrayFormatPlaceholder());
819 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
820 // NOTE(schernykh): add info about LoC
821 LOG(FATAL, ES2PANDA) << "Unexpected " << lexer::TokenToString(lexer_->GetToken().Type())
822 << ", expected '}'.";
823 }
824 } else {
825 while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE &&
826 lexer_->GetToken().Type() != lexer::TokenType::EOS) {
827 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
828 lexer_->NextToken();
829 continue;
830 }
831
832 ir::AstNode *property = ParseClassElement(properties, modifiers, flags);
833 if (property == nullptr) { // Error processing.
834 lexer_->NextToken();
835 continue;
836 }
837
838 if (CheckClassElement(property, ctor, properties)) {
839 continue;
840 }
841
842 properties.push_back(property);
843 }
844 }
845
846 lexer::SourcePosition endLoc = lexer_->GetToken().End();
847 CreateImplicitConstructor(ctor, properties, modifiers, flags, endLoc);
848 lexer_->NextToken();
849
850 return {ctor, std::move(properties), lexer::SourceRange {startLoc, endLoc}};
851 }
852
ValidateRestParameter(ir::Expression * param)853 void ParserImpl::ValidateRestParameter(ir::Expression *param)
854 {
855 if (!param->IsIdentifier()) {
856 context_.Status() |= ParserStatus::HAS_COMPLEX_PARAM;
857 if (!param->IsRestElement()) {
858 return;
859 }
860 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
861 // for now test exists for js extension only
862 LogSyntaxError("Rest parameter must be the last formal parameter.");
863
864 lexer_->GetToken().SetTokenType(lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS);
865 }
866 }
867 }
868
ValidateBreakLabel(util::StringView label)869 bool ParserImpl::ValidateBreakLabel(util::StringView label)
870 {
871 return context_.FindLabel(label) != nullptr;
872 }
873
ValidateContinueLabel(util::StringView label)874 bool ParserImpl::ValidateContinueLabel(util::StringView label)
875 {
876 const ParserContext *labelCtx = context_.FindLabel(label);
877 return labelCtx != nullptr && ((labelCtx->Status() & ParserStatus::IN_ITERATION) != 0);
878 }
879
ParseFunctionParams()880 ArenaVector<ir::Expression *> ParserImpl::ParseFunctionParams()
881 {
882 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
883 lexer_->NextToken(); // eat '('
884 }
885
886 ArenaVector<ir::Expression *> params(Allocator()->Adapter());
887
888 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_FORMAT &&
889 lexer_->Lookahead() == static_cast<char32_t>(ARRAY_FORMAT_NODE)) {
890 params = std::move(ParseExpressionsArrayFormatPlaceholder());
891 } else {
892 while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS &&
893 lexer_->GetToken().Type() != lexer::TokenType::EOS) {
894 util::ErrorRecursionGuard infiniteLoopBlocker(lexer_);
895
896 ir::Expression *parameter = ParseFunctionParameter();
897 if (parameter == nullptr) { // Error processing.
898 continue;
899 }
900
901 ValidateRestParameter(parameter);
902 params.push_back(parameter);
903
904 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
905 lexer_->NextToken();
906 // CC-OFFNXT(G.FMT.06-CPP) project code style
907 } else if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
908 LogSyntaxError("Invalid token: ',' or ')' expected.");
909
910 lexer_->GetToken().SetTokenType(lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS);
911 }
912 }
913 }
914
915 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) { // Error processing.
916 lexer_->NextToken();
917 }
918
919 return params;
920 }
921
CreateParameterThis(ir::TypeNode * typeAnnotation)922 ir::Expression *ParserImpl::CreateParameterThis([[maybe_unused]] ir::TypeNode *typeAnnotation)
923 {
924 LogSyntaxError("Unexpected token, expected function identifier");
925 return nullptr;
926 }
927
ParseFunctionBody(const ArenaVector<ir::Expression * > & params,ParserStatus newStatus,ParserStatus contextStatus)928 std::tuple<bool, ir::BlockStatement *, lexer::SourcePosition, bool> ParserImpl::ParseFunctionBody(
929 // CC-OFFNXT(G.FMT.06-CPP) project code style
930 [[maybe_unused]] const ArenaVector<ir::Expression *> ¶ms, [[maybe_unused]] ParserStatus newStatus,
931 [[maybe_unused]] ParserStatus contextStatus)
932 {
933 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
934 LogExpectedToken(lexer::TokenType::PUNCTUATOR_LEFT_BRACE);
935 }
936
937 ir::BlockStatement *body = ParseBlockStatement();
938
939 return {true, body, body->End(), false};
940 }
941
ParseFunctionSignature(ParserStatus status,ir::TypeNode * typeAnnotation)942 FunctionSignature ParserImpl::ParseFunctionSignature(ParserStatus status, ir::TypeNode *typeAnnotation)
943 {
944 ir::TSTypeParameterDeclaration *typeParamDecl = ParseFunctionTypeParameters();
945
946 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
947 LogExpectedToken(lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS);
948 }
949
950 FunctionParameterContext funcParamContext(&context_);
951
952 ir::Expression *parameterThis = nullptr;
953 if (typeAnnotation != nullptr) {
954 const auto savedPos = Lexer()->Save();
955 lexer_->NextToken(); // eat '('
956 parameterThis = CreateParameterThis(typeAnnotation);
957 Lexer()->Rewind(savedPos);
958 }
959
960 auto params = ParseFunctionParams();
961
962 if (typeAnnotation != nullptr) {
963 params.emplace(params.begin(), parameterThis);
964 }
965
966 ir::TypeNode *returnTypeAnnotation = ParseFunctionReturnType(status);
967 ir::ScriptFunctionFlags throwMarker = ParseFunctionThrowMarker(true);
968
969 auto res = ir::FunctionSignature(typeParamDecl, std::move(params), returnTypeAnnotation);
970 return {std::move(res), throwMarker};
971 }
972
ParseFunction(ParserStatus newStatus)973 ir::ScriptFunction *ParserImpl::ParseFunction(ParserStatus newStatus)
974 {
975 FunctionContext functionContext(this, newStatus | ParserStatus::FUNCTION | ParserStatus::ALLOW_NEW_TARGET);
976
977 lexer::SourcePosition startLoc = lexer_->GetToken().Start();
978
979 auto [signature, throw_marker] = ParseFunctionSignature(newStatus);
980
981 auto [letDeclare, body, endLoc, isOverload] = ParseFunctionBody(signature.Params(), newStatus, context_.Status());
982
983 if (isOverload) {
984 functionContext.AddFlag(ir::ScriptFunctionFlags::OVERLOAD);
985 }
986
987 functionContext.AddFlag(throw_marker);
988 auto *funcNode = AllocNode<ir::ScriptFunction>(
989 Allocator(),
990 ir::ScriptFunction::ScriptFunctionData {body,
991 std::move(signature), // CC-OFFNXT(G.FMT.02-CPP) project code style
992 functionContext.Flags(), // CC-OFFNXT(G.FMT.02-CPP) project code style
993 {}, // CC-OFFNXT(G.FMT.02-CPP) project code style
994 context_.GetLanguage()}); // CC-OFF(G.FMT.02-CPP) project code style
995
996 funcNode->SetRange({startLoc, endLoc});
997
998 return funcNode;
999 }
1000
ParseSpreadElement(ExpressionParseFlags flags)1001 ir::SpreadElement *ParserImpl::ParseSpreadElement(ExpressionParseFlags flags)
1002 {
1003 ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD);
1004 lexer::SourcePosition startLocation = lexer_->GetToken().Start();
1005 bool inPattern = (flags & ExpressionParseFlags::MUST_BE_PATTERN) != 0;
1006 lexer_->NextToken();
1007
1008 ir::Expression *argument {};
1009 if (inPattern) {
1010 argument = ParsePatternElement(ExpressionParseFlags::IN_REST);
1011 if ((flags & ExpressionParseFlags::OBJECT_PATTERN) != 0 && (argument == nullptr || !argument->IsIdentifier())) {
1012 LogSyntaxError("RestParameter must be followed by an identifier in declaration contexts");
1013 }
1014 } else {
1015 argument = ParseExpression(flags);
1016 }
1017
1018 if (argument == nullptr) { // Error processing.
1019 return nullptr;
1020 }
1021
1022 if (inPattern && argument->IsAssignmentExpression()) {
1023 LogSyntaxError("RestParameter does not support an initializer");
1024 }
1025
1026 auto nodeType = inPattern ? ir::AstNodeType::REST_ELEMENT : ir::AstNodeType::SPREAD_ELEMENT;
1027 auto *spreadElementNode = AllocNode<ir::SpreadElement>(nodeType, Allocator(), argument);
1028 spreadElementNode->SetRange({startLocation, argument->End()});
1029 return spreadElementNode;
1030 }
1031
CheckRestrictedBinding()1032 void ParserImpl::CheckRestrictedBinding()
1033 {
1034 ASSERT(lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT);
1035 CheckRestrictedBinding(lexer_->GetToken().KeywordType());
1036 }
1037
CheckRestrictedBinding(lexer::TokenType keywordType)1038 void ParserImpl::CheckRestrictedBinding(lexer::TokenType keywordType)
1039 {
1040 if (keywordType == lexer::TokenType::KEYW_ARGUMENTS || keywordType == lexer::TokenType::KEYW_EVAL) {
1041 LogSyntaxError(
1042 "'eval' or 'arguments' can't be defined or assigned to "
1043 "in strict mode code",
1044 lexer_->GetToken().Start());
1045 }
1046 }
1047
CheckRestrictedBinding(const util::StringView & ident,const lexer::SourcePosition & pos)1048 void ParserImpl::CheckRestrictedBinding(const util::StringView &ident, const lexer::SourcePosition &pos)
1049 {
1050 if (ident.Is("eval") || ident.Is("arguments")) {
1051 LogSyntaxError(
1052 "'eval' or 'arguments' can't be defined or assigned to "
1053 "in strict mode code",
1054 pos);
1055 }
1056 }
1057
ParseFunctionParameter()1058 ir::Expression *ParserImpl::ParseFunctionParameter()
1059 {
1060 ConvertThisKeywordToIdentIfNecessary();
1061
1062 if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) {
1063 CheckRestrictedBinding();
1064 }
1065
1066 return ParsePatternElement(ExpressionParseFlags::NO_OPTS, true);
1067 }
1068
ValidateLvalueAssignmentTarget(ir::Expression * node)1069 void ParserImpl::ValidateLvalueAssignmentTarget(ir::Expression *node)
1070 {
1071 switch (node->Type()) {
1072 case ir::AstNodeType::IDENTIFIER: {
1073 CheckRestrictedBinding(node->AsIdentifier()->Name(), node->Start());
1074 break;
1075 }
1076 case ir::AstNodeType::MEMBER_EXPRESSION: {
1077 break;
1078 }
1079 default: {
1080 LogSyntaxError("Invalid left-hand side in assignment expression");
1081 }
1082 }
1083 }
1084
ValidateAssignmentTarget(ExpressionParseFlags flags,ir::Expression * node)1085 void ParserImpl::ValidateAssignmentTarget(ExpressionParseFlags flags, ir::Expression *node)
1086 {
1087 switch (node->Type()) {
1088 case ir::AstNodeType::ARRAY_PATTERN:
1089 case ir::AstNodeType::OBJECT_PATTERN: {
1090 break;
1091 }
1092 case ir::AstNodeType::ARRAY_EXPRESSION:
1093 case ir::AstNodeType::OBJECT_EXPRESSION: {
1094 if ((flags & ExpressionParseFlags::POTENTIALLY_IN_PATTERN) != 0) {
1095 return;
1096 }
1097
1098 [[fallthrough]];
1099 }
1100 default: {
1101 return ValidateLvalueAssignmentTarget(node);
1102 }
1103 }
1104 }
1105
ValidateArrowParameterBindings(const ir::Expression * node)1106 void ParserImpl::ValidateArrowParameterBindings(const ir::Expression *node)
1107 {
1108 switch (node->Type()) {
1109 case ir::AstNodeType::IDENTIFIER: {
1110 CheckRestrictedBinding(node->AsIdentifier()->Name(), node->Start());
1111 break;
1112 }
1113 case ir::AstNodeType::OMITTED_EXPRESSION: {
1114 break;
1115 }
1116 case ir::AstNodeType::REST_ELEMENT: {
1117 ValidateArrowParameterBindings(node->AsRestElement()->Argument());
1118 break;
1119 }
1120 case ir::AstNodeType::PROPERTY: {
1121 break;
1122 }
1123 case ir::AstNodeType::OBJECT_PATTERN: {
1124 const auto &props = node->AsObjectPattern()->Properties();
1125
1126 for (auto *it : props) {
1127 ValidateArrowParameterBindings(it);
1128 }
1129 break;
1130 }
1131 case ir::AstNodeType::ARRAY_PATTERN: {
1132 const auto &elements = node->AsArrayPattern()->Elements();
1133
1134 for (auto *it : elements) {
1135 ValidateArrowParameterBindings(it);
1136 }
1137 break;
1138 }
1139 case ir::AstNodeType::ASSIGNMENT_PATTERN: {
1140 ValidateArrowParameterBindings(node->AsAssignmentPattern()->Left());
1141 // CC-OFFNXT(G.FMT.06-CPP) project code style
1142 break;
1143 }
1144 default: {
1145 LogSyntaxError("Unexpected ArrowParameter element");
1146 }
1147 }
1148 }
1149
LogParameterModifierError(ir::ModifierFlags status)1150 void ParserImpl::LogParameterModifierError(ir::ModifierFlags status)
1151 {
1152 LogSyntaxError({"'",
1153 (status & ir::ModifierFlags::STATIC) != 0 ? "static"
1154 : (status & ir::ModifierFlags::ASYNC) != 0 ? "async"
1155 : "declare",
1156 "' modifier cannot appear on a parameter."},
1157 lexer_->GetToken().Start());
1158 }
1159
ParseIdentifierFormatPlaceholder(std::optional<NodeFormatType> nodeFormat)1160 ir::Identifier *ParserImpl::ParseIdentifierFormatPlaceholder([[maybe_unused]] std::optional<NodeFormatType> nodeFormat)
1161 {
1162 // NOTE(schernykh): add info about LoC
1163 LOG(FATAL, ES2PANDA) << "Format placeholder with identifier is not supported";
1164 return nullptr;
1165 }
1166
ParseStatementFormatPlaceholder()1167 ir::Statement *ParserImpl::ParseStatementFormatPlaceholder()
1168 {
1169 // NOTE(schernykh): add info about LoC
1170 LOG(FATAL, ES2PANDA) << "Statement with format placeholder is not supported";
1171 return nullptr;
1172 }
1173
ParseTypeParametersFormatPlaceholder()1174 ir::AstNode *ParserImpl::ParseTypeParametersFormatPlaceholder()
1175 {
1176 // NOTE(schernykh): add info about LoC
1177 LOG(FATAL, ES2PANDA) << "Format placeholder with type parameter(s) is not supported";
1178 return nullptr;
1179 }
1180
ParseStatementsArrayFormatPlaceholder()1181 ArenaVector<ir::Statement *> &ParserImpl::ParseStatementsArrayFormatPlaceholder()
1182 {
1183 // NOTE(schernykh): add info about LoC
1184 LOG(FATAL, ES2PANDA) << "Format placeholder from statements array is not supported";
1185 UNREACHABLE();
1186 }
1187
ParseAstNodesArrayFormatPlaceholder()1188 ArenaVector<ir::AstNode *> &ParserImpl::ParseAstNodesArrayFormatPlaceholder()
1189 {
1190 // NOTE(schernykh): add info about LoC
1191 LOG(FATAL, ES2PANDA) << "Format placeholder from AST nodes is not supported";
1192 UNREACHABLE();
1193 }
1194
ParseExpressionsArrayFormatPlaceholder()1195 ArenaVector<ir::Expression *> &ParserImpl::ParseExpressionsArrayFormatPlaceholder()
1196 {
1197 // NOTE(schernykh): add info about LoC
1198 LOG(FATAL, ES2PANDA) << "Format placeholder from expressions array is not supported";
1199 UNREACHABLE();
1200 }
1201
ParseSymbolIteratorIdentifier() const1202 util::StringView ParserImpl::ParseSymbolIteratorIdentifier() const noexcept
1203 {
1204 // Duplicate check - just in case of improper call!
1205 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET) {
1206 return util::StringView {};
1207 }
1208
1209 lexer_->NextToken();
1210 if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT || !lexer_->GetToken().Ident().Is("Symbol")) {
1211 return util::StringView {};
1212 }
1213
1214 lexer_->NextToken();
1215 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_PERIOD) {
1216 return util::StringView {};
1217 }
1218
1219 lexer_->NextToken();
1220 if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT || !lexer_->GetToken().Ident().Is("iterator")) {
1221 return util::StringView {};
1222 }
1223
1224 lexer_->NextToken();
1225 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
1226 return util::StringView {};
1227 }
1228
1229 // Just replace '[Symbol.iterator]` identifier with the standard '$_iterator' name.
1230 return util::StringView {compiler::Signatures::ITERATOR_METHOD};
1231 }
1232
ExpectIdentifier(bool isReference,bool isUserDefinedType)1233 ir::Identifier *ParserImpl::ExpectIdentifier([[maybe_unused]] bool isReference, bool isUserDefinedType)
1234 {
1235 auto const &token = lexer_->GetToken();
1236 auto const tokenType = token.Type();
1237 if (tokenType == lexer::TokenType::PUNCTUATOR_FORMAT) {
1238 return ParseIdentifierFormatPlaceholder(std::nullopt);
1239 }
1240
1241 if (token.IsDefinableTypeName() && isUserDefinedType) {
1242 LogSyntaxError("Cannot be used as user-defined type.");
1243 }
1244
1245 auto const &tokenStart = token.Start();
1246 util::StringView tokenName {};
1247
1248 if (tokenType == lexer::TokenType::LITERAL_IDENT) {
1249 tokenName = token.Ident();
1250 } else if (tokenType == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET) {
1251 // Special case for processing of special '[Symbol.iterator]` identifier using in stdlib.
1252 tokenName = ParseSymbolIteratorIdentifier();
1253 }
1254
1255 if (tokenName.Empty()) {
1256 LogSyntaxError({"Identifier expected, got '", TokenToString(tokenType), "'."}, tokenStart);
1257 tokenName = ERROR_LITERAL;
1258 }
1259
1260 auto *ident = AllocNode<ir::Identifier>(tokenName, Allocator());
1261 // NOTE: here actual token can be changed!
1262 ident->SetRange({tokenStart, lexer_->GetToken().End()});
1263
1264 lexer_->NextToken();
1265
1266 return ident;
1267 }
1268
ExpectToken(lexer::TokenType tokenType,bool consumeToken)1269 void ParserImpl::ExpectToken(lexer::TokenType tokenType, bool consumeToken)
1270 {
1271 if (lexer_->GetToken().Type() == tokenType) {
1272 if (consumeToken) {
1273 lexer_->NextToken();
1274 }
1275 return;
1276 }
1277 LogExpectedToken(tokenType);
1278 if (consumeToken) {
1279 lexer_->NextToken();
1280 }
1281 }
1282
ThrowUnexpectedToken(lexer::TokenType const tokenType) const1283 void ParserImpl::ThrowUnexpectedToken(lexer::TokenType const tokenType) const
1284 {
1285 ThrowSyntaxError("Unexpected token: '"s + TokenToString(tokenType) + "'."s);
1286 }
1287
ThrowSyntaxError(std::string_view const errorMessage) const1288 void ParserImpl::ThrowSyntaxError(std::string_view const errorMessage) const
1289 {
1290 ThrowSyntaxError(errorMessage, lexer_->GetToken().Start());
1291 }
1292
ThrowSyntaxError(std::initializer_list<std::string_view> list) const1293 void ParserImpl::ThrowSyntaxError(std::initializer_list<std::string_view> list) const
1294 {
1295 ThrowSyntaxError(list, lexer_->GetToken().Start());
1296 }
1297
ThrowSyntaxError(std::initializer_list<std::string_view> list,const lexer::SourcePosition & pos) const1298 void ParserImpl::ThrowSyntaxError(std::initializer_list<std::string_view> list, const lexer::SourcePosition &pos) const
1299 {
1300 std::stringstream ss;
1301
1302 for (const auto &it : list) {
1303 ss << it;
1304 }
1305
1306 std::string err = ss.str();
1307
1308 ThrowSyntaxError(std::string_view {err}, pos);
1309 }
1310
ThrowSyntaxError(std::string_view errorMessage,const lexer::SourcePosition & pos) const1311 void ParserImpl::ThrowSyntaxError(std::string_view errorMessage, const lexer::SourcePosition &pos) const
1312 {
1313 lexer::LineIndex index(program_->SourceCode());
1314 lexer::SourceLocation loc = index.GetLocation(pos);
1315
1316 throw Error {ErrorType::SYNTAX, program_->SourceFilePath().Utf8(), errorMessage, loc.line, loc.col};
1317 }
1318
LogUnexpectedToken(lexer::TokenType tokenType)1319 void ParserImpl::LogUnexpectedToken(lexer::TokenType tokenType)
1320 {
1321 LogSyntaxError("Unexpected token: '"s + TokenToString(tokenType) + "'."s);
1322 }
1323
LogExpectedToken(lexer::TokenType tokenType)1324 void ParserImpl::LogExpectedToken(lexer::TokenType tokenType)
1325 {
1326 if (tokenType != lexer::TokenType::LITERAL_IDENT && tokenType != lexer::TokenType::LITERAL_STRING) {
1327 LogSyntaxError("Unexpected token, expected: '"s + TokenToString(tokenType) + "'."s);
1328 } else if (tokenType == lexer::TokenType::LITERAL_IDENT) {
1329 LogSyntaxError("Unexpected token, expected an identifier.");
1330 lexer_->GetToken().SetTokenStr(ERROR_LITERAL);
1331 } else if (tokenType == lexer::TokenType::LITERAL_STRING) {
1332 LogSyntaxError("Unexpected token, expected string literal.");
1333 lexer_->GetToken().SetTokenStr(ERROR_LITERAL);
1334 }
1335 lexer_->GetToken().SetTokenType(tokenType);
1336 }
1337
LogSyntaxError(std::string_view errorMessage,const lexer::SourcePosition & pos)1338 void ParserImpl::LogSyntaxError(std::string_view errorMessage, const lexer::SourcePosition &pos)
1339 {
1340 lexer::LineIndex index(program_->SourceCode());
1341 lexer::SourceLocation loc = index.GetLocation(pos);
1342
1343 errorLogger_.WriteLog(
1344 Error {ErrorType::SYNTAX, program_->SourceFilePath().Utf8(), errorMessage, loc.line, loc.col});
1345 }
1346
LogSyntaxError(std::string_view const errorMessage)1347 void ParserImpl::LogSyntaxError(std::string_view const errorMessage)
1348 {
1349 LogSyntaxError(errorMessage, lexer_->GetToken().Start());
1350 }
1351
LogSyntaxError(std::initializer_list<std::string_view> list)1352 void ParserImpl::LogSyntaxError(std::initializer_list<std::string_view> list)
1353 {
1354 LogSyntaxError(list, lexer_->GetToken().Start());
1355 }
1356
LogSyntaxError(std::initializer_list<std::string_view> list,const lexer::SourcePosition & pos)1357 void ParserImpl::LogSyntaxError(std::initializer_list<std::string_view> list, const lexer::SourcePosition &pos)
1358 {
1359 std::stringstream ss;
1360
1361 for (const auto &it : list) {
1362 ss << it;
1363 }
1364
1365 std::string err = ss.str();
1366
1367 LogSyntaxError(std::string_view {err}, pos);
1368 }
1369
ThrowAllocationError(std::string_view message) const1370 void ParserImpl::ThrowAllocationError(std::string_view message) const
1371 {
1372 throw Error(ErrorType::GENERIC, program_->SourceFilePath().Utf8(), message);
1373 }
1374
Extension() const1375 ScriptExtension ParserImpl::Extension() const
1376 {
1377 return program_->Extension();
1378 }
1379
CheckModuleAsModifier()1380 bool ParserImpl::CheckModuleAsModifier()
1381 {
1382 if (lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_AS) {
1383 return false;
1384 }
1385
1386 if ((lexer_->GetToken().Flags() & lexer::TokenFlags::HAS_ESCAPE) != 0U) {
1387 LogSyntaxError("Escape sequences are not allowed in 'as' keyword");
1388 }
1389
1390 return true;
1391 }
1392
1393 } // namespace ark::es2panda::parser
1394