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