1/**
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "parserImpl.h"
17#include <functional>
18
19#include <binder/scope.h>
20#include <binder/tsBinding.h>
21#include <util/helpers.h>
22#include <ir/astDump.h>
23#include <ir/astNode.h>
24#include <ir/base/annotation.h>
25#include <ir/base/classDefinition.h>
26#include <ir/base/classProperty.h>
27#include <ir/base/classStaticBlock.h>
28#include <ir/base/decorator.h>
29#include <ir/base/methodDefinition.h>
30#include <ir/base/property.h>
31#include <ir/base/scriptFunction.h>
32#include <ir/base/spreadElement.h>
33#include <ir/expression.h>
34#include <ir/expressions/arrayExpression.h>
35#include <ir/expressions/assignmentExpression.h>
36#include <ir/expressions/callExpression.h>
37#include <ir/expressions/functionExpression.h>
38#include <ir/expressions/identifier.h>
39#include <ir/expressions/literals/bigIntLiteral.h>
40#include <ir/expressions/literals/booleanLiteral.h>
41#include <ir/expressions/literals/nullLiteral.h>
42#include <ir/expressions/literals/numberLiteral.h>
43#include <ir/expressions/literals/stringLiteral.h>
44#include <ir/expressions/memberExpression.h>
45#include <ir/expressions/objectExpression.h>
46#include <ir/expressions/privateIdentifier.h>
47#include <ir/expressions/superExpression.h>
48#include <ir/expressions/templateLiteral.h>
49#include <ir/expressions/typeArgumentsExpression.h>
50#include <ir/module/exportDefaultDeclaration.h>
51#include <ir/module/exportNamedDeclaration.h>
52#include <ir/module/exportSpecifier.h>
53#include <ir/statements/blockStatement.h>
54#include <ir/statements/classDeclaration.h>
55#include <ir/statements/emptyStatement.h>
56#include <ir/statements/expressionStatement.h>
57#include <ir/statements/functionDeclaration.h>
58#include <ir/statements/variableDeclaration.h>
59#include <ir/ts/tsAnyKeyword.h>
60#include <ir/ts/tsArrayType.h>
61#include <ir/ts/tsAsExpression.h>
62#include <ir/ts/tsBigintKeyword.h>
63#include <ir/ts/tsBooleanKeyword.h>
64#include <ir/ts/tsClassImplements.h>
65#include <ir/ts/tsConditionalType.h>
66#include <ir/ts/tsConstructorType.h>
67#include <ir/ts/tsEnumDeclaration.h>
68#include <ir/ts/tsEnumMember.h>
69#include <ir/ts/tsFunctionType.h>
70#include <ir/ts/tsImportType.h>
71#include <ir/ts/tsIndexSignature.h>
72#include <ir/ts/tsIndexedAccessType.h>
73#include <ir/ts/tsInferType.h>
74#include <ir/ts/tsIntersectionType.h>
75#include <ir/ts/tsLiteralType.h>
76#include <ir/ts/tsMappedType.h>
77#include <ir/ts/tsMethodSignature.h>
78#include <ir/ts/tsModuleDeclaration.h>
79#include <ir/ts/tsNamedTupleMember.h>
80#include <ir/ts/tsNeverKeyword.h>
81#include <ir/ts/tsNullKeyword.h>
82#include <ir/ts/tsNumberKeyword.h>
83#include <ir/ts/tsObjectKeyword.h>
84#include <ir/ts/tsOptionalType.h>
85#include <ir/ts/tsParameterProperty.h>
86#include <ir/ts/tsParenthesizedType.h>
87#include <ir/ts/tsPrivateIdentifier.h>
88#include <ir/ts/tsPropertySignature.h>
89#include <ir/ts/tsQualifiedName.h>
90#include <ir/ts/tsRestType.h>
91#include <ir/ts/tsSatisfiesExpression.h>
92#include <ir/ts/tsSignatureDeclaration.h>
93#include <ir/ts/tsStringKeyword.h>
94#include <ir/ts/tsSymbolKeyword.h>
95#include <ir/ts/tsTemplateLiteralType.h>
96#include <ir/ts/tsThisType.h>
97#include <ir/ts/tsTupleType.h>
98#include <ir/ts/tsTypeAssertion.h>
99#include <ir/ts/tsTypeLiteral.h>
100#include <ir/ts/tsTypeOperator.h>
101#include <ir/ts/tsTypeParameterDeclaration.h>
102#include <ir/ts/tsTypeParameterInstantiation.h>
103#include <ir/ts/tsTypePredicate.h>
104#include <ir/ts/tsTypeQuery.h>
105#include <ir/ts/tsTypeReference.h>
106#include <ir/ts/tsUndefinedKeyword.h>
107#include <ir/ts/tsUnionType.h>
108#include <ir/ts/tsUnknownKeyword.h>
109#include <ir/ts/tsVoidKeyword.h>
110#include <ir/ts/tsNonNullExpression.h>
111#include <lexer/lexer.h>
112#include <lexer/token/letters.h>
113#include <lexer/token/sourceLocation.h>
114#include <mem/pool_manager.h>
115
116namespace panda::es2panda::parser {
117
118ParserImpl::ParserImpl(ScriptExtension extension) : program_(extension), context_(&program_) {}
119
120std::unique_ptr<lexer::Lexer> ParserImpl::InitLexer(const std::string &fileName, const std::string &source)
121{
122    bool isDtsFile = false;
123    if (Extension() == ScriptExtension::TS) {
124        isDtsFile = util::Helpers::FileExtensionIs(fileName, ".d.ts");
125    }
126    program_.SetSource(source, fileName, isDtsFile);
127    auto lexer = std::make_unique<lexer::Lexer>(&context_);
128    lexer_ = lexer.get();
129
130    return lexer;
131}
132
133Program ParserImpl::Parse(const SourceFile &sourceFile, const CompilerOptions &options)
134{
135    program_.SetKind(sourceFile.scriptKind);
136    program_.SetRecordName(sourceFile.recordName);
137    program_.SetDebug(options.isDebug);
138    program_.SetTargetApiVersion(options.targetApiVersion);
139    program_.SetTargetApiSubVersion(options.targetApiSubVersion);
140    program_.SetEnableAnnotations(options.enableAnnotations);
141    program_.SetShared(sourceFile.isSharedModule);
142    program_.SetModuleRecordFieldName(options.moduleRecordFieldName);
143    if (Extension() == ScriptExtension::TS) {
144        program_.SetDefineSemantic(options.useDefineSemantic);
145    }
146
147    /*
148     * In order to make the lexer's memory alive, the return value 'lexer' can not be omitted.
149     */
150    auto lexer = InitLexer(sourceFile.fileName, std::string {sourceFile.source});
151    switch (sourceFile.scriptKind) {
152        case ScriptKind::SCRIPT: {
153            ParseScript();
154            break;
155        }
156        case ScriptKind::MODULE: {
157            ParseModule();
158            break;
159        }
160        case ScriptKind::COMMONJS: {
161            ParseCommonjs();
162            break;
163        }
164        default: {
165            UNREACHABLE();
166        }
167    }
168    binder::ResolveBindingFlags bindFlags = binder::ResolveBindingFlags::ALL;
169    if (Extension() == ScriptExtension::TS) {
170        bindFlags = binder::ResolveBindingFlags::TS_BEFORE_TRANSFORM;
171    }
172    Binder()->IdentifierAnalysis(bindFlags);
173    return std::move(program_);
174}
175
176void ParserImpl::ParseScript()
177{
178    ParseProgram(ScriptKind::SCRIPT);
179}
180
181void ParserImpl::ParseModule()
182{
183    context_.Status() |= (ParserStatus::MODULE);
184    ParseProgram(ScriptKind::MODULE);
185}
186
187void ParserImpl::ParseProgram(ScriptKind kind)
188{
189    lexer::SourcePosition startLoc = lexer_->GetToken().Start();
190    lexer_->NextToken();
191
192    auto statements = ParseStatementList(StatementParsingFlags::STMT_GLOBAL_LEXICAL);
193
194    // For close-source har, check 'use shared' when parsing its transformed js code after obfuscation.
195    for (auto statement : statements) {
196        if (program_.IsShared()) {
197            break;
198        }
199        program_.SetShared(util::Helpers::IsUseShared(statement));
200    }
201
202    if (IsDtsFile() && !CheckTopStatementsForRequiredDeclare(statements)) {
203        ThrowSyntaxError(
204            "Top-level declarations in .d.ts files must start with either a 'declare' or 'export' modifier.");
205    }
206
207    auto *blockStmt = AllocNode<ir::BlockStatement>(Binder()->GetScope(), std::move(statements));
208    Binder()->GetScope()->BindNode(blockStmt);
209    blockStmt->SetRange({startLoc, lexer_->GetToken().End()});
210
211    program_.SetAst(blockStmt);
212}
213
214bool ParserImpl::CheckTopStatementsForRequiredDeclare(const ArenaVector<ir::Statement *> &statements)
215{
216    for (auto *statement : statements) {
217        switch (statement->Type()) {
218            case ir::AstNodeType::TS_INTERFACE_DECLARATION:
219            case ir::AstNodeType::TS_TYPE_ALIAS_DECLARATION:
220            case ir::AstNodeType::IMPORT_DECLARATION:
221            case ir::AstNodeType::TS_IMPORT_EQUALS_DECLARATION:
222            case ir::AstNodeType::EXPORT_ALL_DECLARATION:
223            case ir::AstNodeType::EXPORT_DEFAULT_DECLARATION:
224            case ir::AstNodeType::EXPORT_NAMED_DECLARATION:
225            case ir::AstNodeType::TS_NAMESPACE_EXPORT_DECLARATION:
226                continue;
227            case ir::AstNodeType::CLASS_DECLARATION: {
228                if (!statement->AsClassDeclaration()->Definition()->Declare()) {
229                    return false;
230                }
231                break;
232            }
233            case ir::AstNodeType::FUNCTION_DECLARATION: {
234                if (!statement->AsFunctionDeclaration()->Function()->Declare() &&
235                    !statement->AsFunctionDeclaration()->Function()->IsOverload()) {
236                    return false;
237                }
238                break;
239            }
240            case ir::AstNodeType::VARIABLE_DECLARATION: {
241                if (!statement->AsVariableDeclaration()->Declare()) {
242                    return false;
243                }
244                break;
245            }
246            case ir::AstNodeType::TS_MODULE_DECLARATION: {
247                if (!statement->AsTSModuleDeclaration()->Declare()) {
248                    return false;
249                }
250                break;
251            }
252            case ir::AstNodeType::TS_ENUM_DECLARATION: {
253                if (!statement->AsTSEnumDeclaration()->IsDeclare()) {
254                    return false;
255                }
256                break;
257            }
258            default:
259                ThrowSyntaxError("Statements are not allowed in ambient contexts.");
260                UNREACHABLE();
261        }
262    }
263    return true;
264}
265
266/*
267 * Definitions of private methods
268 */
269ExpressionParseFlags ParserImpl::CarryExpressionParserFlag(ExpressionParseFlags origin, ExpressionParseFlags carry)
270{
271    return static_cast<ExpressionParseFlags>(origin & carry);
272}
273
274ExpressionParseFlags ParserImpl::CarryPatternFlags(ExpressionParseFlags flags)
275{
276    return CarryExpressionParserFlag(flags, ExpressionParseFlags::POTENTIALLY_IN_PATTERN |
277                                                ExpressionParseFlags::OBJECT_PATTERN);
278}
279
280ExpressionParseFlags ParserImpl::CarryAllowTsParamAndPatternFlags(ExpressionParseFlags flags)
281{
282    return CarryExpressionParserFlag(flags, ExpressionParseFlags::ALLOW_TS_PARAM_TOKEN |
283                                            ExpressionParseFlags::POTENTIALLY_IN_PATTERN |
284                                            ExpressionParseFlags::OBJECT_PATTERN);
285}
286
287bool ParserImpl::CurrentLiteralIsBasicType()
288{
289    ASSERT(lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT ||
290           lexer_->GetToken().Type() == lexer::TokenType::KEYW_EXTENDS);
291
292    switch (lexer_->GetToken().KeywordType()) {
293        case lexer::TokenType::KEYW_ANY:
294        case lexer::TokenType::KEYW_BOOLEAN:
295        case lexer::TokenType::KEYW_NUMBER:
296        case lexer::TokenType::KEYW_STRING:
297        case lexer::TokenType::KEYW_SYMBOL:
298        case lexer::TokenType::KEYW_UNKNOWN:
299        case lexer::TokenType::KEYW_UNDEFINED:
300        case lexer::TokenType::KEYW_NEVER:
301        case lexer::TokenType::KEYW_OBJECT:
302        case lexer::TokenType::KEYW_BIGINT: {
303            return true;
304        }
305        default: {
306            break;
307        }
308    }
309
310    return false;
311}
312bool ParserImpl::CurrentIsBasicType()
313{
314    switch (lexer_->GetToken().Type()) {
315        case lexer::TokenType::PUNCTUATOR_MINUS:
316        case lexer::TokenType::LITERAL_NUMBER:
317        case lexer::TokenType::LITERAL_STRING:
318        case lexer::TokenType::LITERAL_FALSE:
319        case lexer::TokenType::LITERAL_TRUE:
320        case lexer::TokenType::LITERAL_NULL:
321        case lexer::TokenType::KEYW_VOID: {
322            return true;
323        }
324        case lexer::TokenType::LITERAL_IDENT: {
325            return CurrentLiteralIsBasicType();
326        }
327        default: {
328            break;
329        }
330    }
331
332    return false;
333}
334
335ir::TSTypeReference *ParserImpl::ParseTsConstExpression()
336{
337    auto *identRef = AllocNode<ir::Identifier>(lexer_->GetToken().Ident());
338    identRef->SetReference();
339    identRef->SetRange(lexer_->GetToken().Loc());
340
341    auto *typeReference = AllocNode<ir::TSTypeReference>(identRef, nullptr);
342    typeReference->SetRange(lexer_->GetToken().Loc());
343
344    lexer_->NextToken();
345
346    return typeReference;
347}
348
349ir::Expression *ParserImpl::ParseTsIdentifierReference(TypeAnnotationParsingOptions options)
350{
351    if (CurrentLiteralIsBasicType() && lexer_->Lookahead() != LEX_CHAR_DOT) {
352        return ParseTsBasicType(options);
353    }
354
355    return ParseTsTypeReferenceOrQuery(options, false);
356}
357
358bool ParserImpl::IsStartOfMappedType() const
359{
360    auto pos = lexer_->Save();
361    lexer_->NextToken();
362    bool result = false;
363
364    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MINUS ||
365        lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PLUS) {
366        lexer_->NextToken();
367        result = lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_READONLY;
368        lexer_->Rewind(pos);
369        return result;
370    }
371
372    if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_READONLY) {
373        lexer_->NextToken();
374    }
375
376    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET) {
377        lexer_->Rewind(pos);
378        return false;
379    }
380
381    lexer_->NextToken();
382
383    if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
384        lexer_->Rewind(pos);
385        return false;
386    }
387
388    lexer_->NextToken();
389
390    result = lexer_->GetToken().Type() == lexer::TokenType::KEYW_IN;
391
392    lexer_->Rewind(pos);
393    return result;
394}
395
396bool ParserImpl::IsStartOfTsTypePredicate() const
397{
398    ASSERT(lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT ||
399           lexer_->GetToken().Type() == lexer::TokenType::KEYW_THIS);
400
401    auto pos = lexer_->Save();
402    bool isAsserts = lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_ASSERTS;
403    if (isAsserts) {
404        lexer_->NextToken();
405    }
406
407    if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT &&
408        lexer_->GetToken().Type() != lexer::TokenType::KEYW_THIS) {
409        lexer_->Rewind(pos);
410        return false;
411    }
412
413    if (isAsserts) {
414        lexer_->Rewind(pos);
415        return true;
416    }
417
418    lexer_->NextToken();
419
420    bool result = !lexer_->GetToken().NewLine() && (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_IS);
421    lexer_->Rewind(pos);
422    return result;
423}
424
425bool ParserImpl::IsStartOfAbstractConstructorType() const
426{
427    if (lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_ABSTRACT) {
428        return false;
429    }
430
431    lexer::LexerPosition pos = lexer_->Save();
432    lexer_->NextToken();  // eat 'abstract'
433    bool result = lexer_->GetToken().Type() == lexer::TokenType::KEYW_NEW;
434
435    lexer_->Rewind(pos);
436
437    return result;
438}
439
440ir::Expression *ParserImpl::ParseTsTypeLiteralOrTsMappedType(ir::Expression *typeAnnotation)
441{
442    if (typeAnnotation) {
443        return nullptr;
444    }
445
446    if (IsStartOfMappedType()) {
447        return ParseTsMappedType();
448    }
449
450    lexer::SourcePosition bodyStart = lexer_->GetToken().Start();
451    auto members = ParseTsTypeLiteralOrInterface();
452    lexer::SourcePosition bodyEnd = lexer_->GetToken().End();
453    lexer_->NextToken();
454
455    auto *literalType = AllocNode<ir::TSTypeLiteral>(std::move(members));
456    auto *typeVar = binder::Scope::CreateVar(Allocator(), "__type", binder::VariableFlags::TYPE, literalType);
457    literalType->SetVariable(typeVar);
458    literalType->SetRange({bodyStart, bodyEnd});
459    return literalType;
460}
461
462ir::Expression *ParserImpl::ParseTsTypeReferenceOrTsTypePredicate(ir::Expression *typeAnnotation,
463                                                                  bool canBeTsTypePredicate, bool throwError)
464{
465    if (typeAnnotation) {
466        return nullptr;
467    }
468
469    if (canBeTsTypePredicate && IsStartOfTsTypePredicate()) {
470        return ParseTsTypePredicate();
471    }
472
473    return ParseTsTypeOperatorOrTypeReference(throwError);
474}
475
476ir::Expression *ParserImpl::ParseTsThisTypeOrTsTypePredicate(ir::Expression *typeAnnotation, bool canBeTsTypePredicate,
477                                                             bool throwError)
478{
479    if (typeAnnotation) {
480        return nullptr;
481    }
482
483    if (canBeTsTypePredicate && IsStartOfTsTypePredicate()) {
484        return ParseTsTypePredicate();
485    }
486
487    return ParseTsThisType(throwError);
488}
489
490ir::Expression *ParserImpl::ParseTsTemplateLiteralType(bool throwError)
491{
492    ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_BACK_TICK);
493    lexer::SourcePosition startLoc = lexer_->GetToken().Start();
494
495    ArenaVector<ir::TemplateElement *> quasis(Allocator()->Adapter());
496    ArenaVector<ir::Expression *> references(Allocator()->Adapter());
497
498    while (true) {
499        lexer_->ResetTokenEnd();
500        const auto startPos = lexer_->Save();
501
502        lexer_->ScanString<LEX_CHAR_BACK_TICK>();
503        util::StringView cooked = lexer_->GetToken().String();
504
505        lexer_->Rewind(startPos);
506        auto [raw, end, scanExpression] = lexer_->ScanTemplateString();
507
508        auto *element = AllocNode<ir::TemplateElement>(raw.View(), cooked);
509        element->SetRange({lexer::SourcePosition{startPos.iterator.Index(), startPos.line},
510                           lexer::SourcePosition{end, lexer_->Line()}});
511        quasis.push_back(element);
512
513        if (!scanExpression) {
514            lexer_->ScanTemplateStringEnd();
515            break;
516        }
517
518        ir::Expression *reference = nullptr;
519
520        {
521            lexer::TemplateLiteralParserContext ctx(lexer_);
522            lexer_->PushTemplateContext(&ctx);
523            lexer_->NextToken();
524            TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
525            reference = ParseTsTypeAnnotation(&options);
526        }
527
528        if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
529            if (throwError) {
530                ThrowSyntaxError("Unexpected token, expected '}'.");
531            }
532            return nullptr;
533        }
534
535        references.push_back(reference);
536    }
537
538    ir::Expression *typeAnnotation = AllocNode<ir::TSTemplateLiteralType>(std::move(quasis), std::move(references));
539    typeAnnotation->SetRange({startLoc, lexer_->GetToken().End()});
540
541    lexer_->NextToken();
542
543    return typeAnnotation;
544}
545
546ir::Expression *ParserImpl::ParseTsTypeAnnotationElement(ir::Expression *typeAnnotation,
547                                                         TypeAnnotationParsingOptions *options)
548{
549    switch (lexer_->GetToken().Type()) {
550        case lexer::TokenType::PUNCTUATOR_BITWISE_OR: {
551            if (*options & (TypeAnnotationParsingOptions::IN_MODIFIER | TypeAnnotationParsingOptions::IN_UNION |
552                TypeAnnotationParsingOptions::IN_INTERSECTION)) {
553                break;
554            }
555
556            return ParseTsUnionType(typeAnnotation, *options & TypeAnnotationParsingOptions::RESTRICT_EXTENDS,
557                                    *options & TypeAnnotationParsingOptions::THROW_ERROR);
558        }
559        case lexer::TokenType::PUNCTUATOR_BITWISE_AND: {
560            if (*options & (TypeAnnotationParsingOptions::IN_MODIFIER |
561	        TypeAnnotationParsingOptions::IN_INTERSECTION)) {
562                break;
563            }
564
565            return ParseTsIntersectionType(typeAnnotation, *options & TypeAnnotationParsingOptions::IN_UNION,
566                                           *options & TypeAnnotationParsingOptions::RESTRICT_EXTENDS,
567                                           *options & TypeAnnotationParsingOptions::THROW_ERROR);
568        }
569        case lexer::TokenType::PUNCTUATOR_MINUS:
570        case lexer::TokenType::LITERAL_NUMBER:
571        case lexer::TokenType::LITERAL_STRING:
572        case lexer::TokenType::LITERAL_FALSE:
573        case lexer::TokenType::LITERAL_TRUE:
574        case lexer::TokenType::LITERAL_NULL:
575        case lexer::TokenType::KEYW_VOID: {
576            if (typeAnnotation) {
577                break;
578            }
579
580            return ParseTsBasicType(*options);
581        }
582        case lexer::TokenType::KEYW_TYPEOF: {
583            if (typeAnnotation) {
584                break;
585            }
586
587            return ParseTsTypeReferenceOrQuery(*options, true);
588        }
589        case lexer::TokenType::KEYW_IMPORT: {
590            if (typeAnnotation) {
591                break;
592            }
593
594            lexer::SourcePosition startLoc = lexer_->GetToken().Start();
595            return ParseTsImportType(startLoc);
596        }
597        case lexer::TokenType::KEYW_CONST: {
598            if (!(*options & TypeAnnotationParsingOptions::ALLOW_CONST)) {
599                break;
600            }
601
602            *options &= ~TypeAnnotationParsingOptions::ALLOW_CONST;
603            return ParseTsConstExpression();
604        }
605        case lexer::TokenType::LITERAL_IDENT: {
606            if (IsStartOfAbstractConstructorType()) {
607                return ParseTsParenthesizedOrFunctionType(typeAnnotation,
608                                                          *options & TypeAnnotationParsingOptions::THROW_ERROR);
609            }
610
611            return ParseTsTypeReferenceOrTsTypePredicate(
612                typeAnnotation, *options & TypeAnnotationParsingOptions::CAN_BE_TS_TYPE_PREDICATE,
613                *options & TypeAnnotationParsingOptions::THROW_ERROR);
614        }
615        case lexer::TokenType::KEYW_EXTENDS: {
616            if (*options & (TypeAnnotationParsingOptions::IN_UNION | TypeAnnotationParsingOptions::IN_INTERSECTION)) {
617                break;
618            }
619
620            if (!typeAnnotation) {
621                return ParseTsIdentifierReference(*options);
622            }
623
624            if (InDisallowConditionalTypesContext()) {
625                break;
626            }
627            return ParseTsConditionalType(typeAnnotation, *options & TypeAnnotationParsingOptions::RESTRICT_EXTENDS);
628        }
629        case lexer::TokenType::KEYW_THIS: {
630            return ParseTsThisTypeOrTsTypePredicate(typeAnnotation,
631                                                    *options & TypeAnnotationParsingOptions::CAN_BE_TS_TYPE_PREDICATE,
632                                                    *options & TypeAnnotationParsingOptions::THROW_ERROR);
633        }
634        case lexer::TokenType::PUNCTUATOR_BACK_TICK: {
635            return ParseTsTemplateLiteralType(*options & TypeAnnotationParsingOptions::THROW_ERROR);
636        }
637        default: {
638            auto type = DoOutsideOfDisallowConditinalTypesContext(&ParserImpl::ParsePostfixTypeOrHigher,
639                                                                  typeAnnotation, options);
640            if (type) {
641                return type;
642            }
643        }
644    }
645
646    if (!typeAnnotation && (*options & TypeAnnotationParsingOptions::THROW_ERROR)) {
647        ThrowSyntaxError("Type expected");
648    }
649
650    return nullptr;
651}
652
653ir::Expression *ParserImpl::ParsePostfixTypeOrHigher(ir::Expression *typeAnnotation,
654                                                     TypeAnnotationParsingOptions *options)
655{
656    switch (lexer_->GetToken().Type()) {
657        case lexer::TokenType::PUNCTUATOR_LESS_THAN:
658        case lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS:
659        case lexer::TokenType::KEYW_NEW: {
660            return ParseTsParenthesizedOrFunctionType(typeAnnotation,
661                                                      *options & TypeAnnotationParsingOptions::THROW_ERROR);
662        }
663
664        case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET: {
665            if (typeAnnotation) {
666                if (lexer_->GetToken().NewLine()) {
667                    break;
668                }
669                if (lexer_->Lookahead() == LEX_CHAR_RIGHT_SQUARE) {
670                    return ParseTsArrayType(typeAnnotation);
671                }
672
673                return ParseTsIndexAccessType(typeAnnotation, *options & TypeAnnotationParsingOptions::THROW_ERROR);
674            }
675
676            return ParseTsTupleType();
677        }
678        case lexer::TokenType::PUNCTUATOR_LEFT_BRACE: {
679            return ParseTsTypeLiteralOrTsMappedType(typeAnnotation);
680        }
681        default: {
682            break;
683        }
684    }
685    return nullptr;
686}
687
688ir::TSImportType *ParserImpl::ParseTsImportType(const lexer::SourcePosition &startLoc, bool isTypeof)
689{
690    ASSERT(lexer_->GetToken().Type() == lexer::TokenType::KEYW_IMPORT);
691
692    lexer_->NextToken();
693
694    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
695        ThrowSyntaxError("'(' expected");
696    }
697
698    lexer_->NextToken();
699
700    TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
701    ir::Expression *param = ParseTsTypeAnnotation(&options);
702
703    if (!param->IsTSLiteralType() || !param->AsTSLiteralType()->Literal()->IsStringLiteral()) {
704        ThrowSyntaxError("String literal expected");
705    }
706
707    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
708        ThrowSyntaxError("')' expected");
709    }
710
711    lexer_->NextToken();
712
713    ir::Expression *qualifier = nullptr;
714    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD) {
715        lexer_->NextToken();
716
717        if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
718            ThrowSyntaxError("Identifier expected");
719        }
720
721        qualifier = AllocNode<ir::Identifier>(lexer_->GetToken().Ident());
722        qualifier->SetRange(lexer_->GetToken().Loc());
723
724        lexer_->NextToken();
725
726        if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD) {
727            qualifier = ParseTsQualifiedReference(qualifier);
728        }
729    }
730
731    ir::TSTypeParameterInstantiation *typeParams = nullptr;
732    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SHIFT ||
733        lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) {
734        if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SHIFT) {
735            lexer_->BackwardToken(lexer::TokenType::PUNCTUATOR_LESS_THAN, 1);
736        }
737
738        typeParams = ParseTsTypeParameterInstantiation();
739    }
740
741    auto *importType = AllocNode<ir::TSImportType>(param, typeParams, qualifier, isTypeof);
742
743    importType->SetRange({startLoc, lexer_->GetToken().End()});
744
745    return importType;
746}
747
748ir::Expression *ParserImpl::ParseTsThisType(bool throwError)
749{
750    ASSERT(lexer_->GetToken().Type() == lexer::TokenType::KEYW_THIS);
751
752    if (throwError && !(context_.Status() & ParserStatus::ALLOW_THIS_TYPE)) {
753        ThrowSyntaxError(
754            "A 'this' type is available only in a non-static member "
755            "of a class or interface.");
756    }
757
758    auto *returnType = AllocNode<ir::TSThisType>();
759    returnType->SetRange(lexer_->GetToken().Loc());
760
761    lexer_->NextToken();
762
763    return returnType;
764}
765
766ir::Expression *ParserImpl::ParseTsConditionalType(ir::Expression *checkType, bool restrictExtends)
767{
768    ASSERT(lexer_->GetToken().Type() == lexer::TokenType::KEYW_EXTENDS);
769    if (restrictExtends) {
770        ThrowSyntaxError("'?' expected.");
771    }
772
773    lexer::SourcePosition startLoc = checkType->Start();
774
775    lexer_->NextToken();  // eat 'extends'
776
777    ParserStatus savedStatus = context_.Status();
778    context_.Status() |= ParserStatus::IN_EXTENDS;
779
780    TypeAnnotationParsingOptions options =
781        TypeAnnotationParsingOptions::THROW_ERROR | TypeAnnotationParsingOptions::RESTRICT_EXTENDS;
782
783    ir::Expression *extendsType = DoInsideOfDisallowConditinalTypesContext(&ParserImpl::ParseTsTypeAnnotation,
784                                                                           &options);
785    context_.Status() = savedStatus;
786
787    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_QUESTION_MARK) {
788        ThrowSyntaxError("'?' expected.");
789    }
790
791    lexer_->NextToken();  // eat '?'
792
793    options &= ~TypeAnnotationParsingOptions::RESTRICT_EXTENDS;
794    auto *trueType = DoOutsideOfDisallowConditinalTypesContext(&ParserImpl::ParseTsTypeAnnotation, &options);
795
796    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COLON) {
797        ThrowSyntaxError("':' expected.");
798    }
799
800    lexer_->NextToken();  // eat ':'
801
802    auto *falseType = DoOutsideOfDisallowConditinalTypesContext(&ParserImpl::ParseTsTypeAnnotation, &options);
803
804    lexer::SourcePosition endLoc = falseType->End();
805
806    auto *conditionalType = AllocNode<ir::TSConditionalType>(checkType, extendsType, trueType, falseType);
807
808    conditionalType->SetRange({startLoc, endLoc});
809
810    return conditionalType;
811}
812
813ir::Expression *ParserImpl::ParseTsTypeAnnotation(TypeAnnotationParsingOptions *options)
814{
815    ir::Expression *typeAnnotation = nullptr;
816
817    while (true) {
818        ir::Expression *element = ParseTsTypeAnnotationElement(typeAnnotation, options);
819
820        *options &= ~TypeAnnotationParsingOptions::ALLOW_CONST;
821
822        *options &= ~TypeAnnotationParsingOptions::CAN_BE_TS_TYPE_PREDICATE;
823
824        if (!element) {
825            break;
826        }
827
828        typeAnnotation = element;
829
830        if (((*options & TypeAnnotationParsingOptions::BREAK_AT_NEW_LINE) && lexer_->GetToken().NewLine()) &&
831            !(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_BITWISE_AND ||
832            lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_BITWISE_OR)) {
833            break;
834        }
835    }
836
837    return typeAnnotation;
838}
839
840ir::Expression *ParserImpl::ParseTsTypeOperatorOrTypeReference(bool throwError)
841{
842    TypeAnnotationParsingOptions options = throwError ?
843        TypeAnnotationParsingOptions::THROW_ERROR : TypeAnnotationParsingOptions::NO_OPTS;
844
845    if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_READONLY) {
846        lexer::SourcePosition typeOperatorStart = lexer_->GetToken().Start();
847        lexer_->NextToken();
848
849        options |= TypeAnnotationParsingOptions::IN_MODIFIER;
850        ir::Expression *type = ParseTsTypeAnnotation(&options);
851        ASSERT(type != nullptr);
852
853        if (!type->IsTSArrayType() && !type->IsTSTupleType()) {
854            ThrowSyntaxError(
855                "'readonly' type modifier is only permitted on array "
856                "and tuple literal types.");
857        }
858
859        auto *typeOperator = AllocNode<ir::TSTypeOperator>(type, ir::TSOperatorType::READONLY);
860
861        typeOperator->SetRange({typeOperatorStart, type->End()});
862
863        return typeOperator;
864    }
865
866    if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_KEYOF) {
867        lexer::SourcePosition typeOperatorStart = lexer_->GetToken().Start();
868        lexer_->NextToken();
869
870        options |= TypeAnnotationParsingOptions::IN_MODIFIER;
871        ir::Expression *type = ParseTsTypeAnnotation(&options);
872        ASSERT(type != nullptr);
873
874        auto *typeOperator = AllocNode<ir::TSTypeOperator>(type, ir::TSOperatorType::KEYOF);
875
876        typeOperator->SetRange({typeOperatorStart, type->End()});
877
878        return typeOperator;
879    }
880
881    if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_UNIQUE) {
882        lexer::SourcePosition typeOperatorStart = lexer_->GetToken().Start();
883        lexer_->NextToken();
884
885        ir::Expression *type = ParseTsTypeAnnotation(&options);
886        ASSERT(type != nullptr);
887
888        auto *typeOperator = AllocNode<ir::TSTypeOperator>(type, ir::TSOperatorType::UNIQUE);
889
890        typeOperator->SetRange({typeOperatorStart, type->End()});
891
892        return typeOperator;
893    }
894
895    if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_INFER) {
896        if (!(context_.Status() & ParserStatus::IN_EXTENDS)) {
897            ThrowSyntaxError(
898                "'infer' declarations are only permitted in the "
899                "'extends' clause of a conditional type.");
900        }
901
902        lexer::SourcePosition inferStart = lexer_->GetToken().Start();
903        lexer_->NextToken();
904
905        ir::TSTypeParameter *typeParam = ParseTsTypeParameter(true);
906
907        auto *inferType = AllocNode<ir::TSInferType>(typeParam);
908
909        inferType->SetRange({inferStart, lexer_->GetToken().End()});
910
911        return inferType;
912    }
913
914    return ParseTsIdentifierReference(options);
915}
916
917bool ParserImpl::IsTSNamedTupleMember()
918{
919    if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
920        return false;
921    }
922    const auto savePos = lexer_->Save();
923    bool isNamedMember = false;
924    lexer_->NextToken();
925    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON ||
926        (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_QUESTION_MARK &&
927         lexer_->Lookahead() == LEX_CHAR_COLON)) {
928            isNamedMember = true;
929    }
930    lexer_->Rewind(savePos);
931    return isNamedMember;
932}
933
934void ParserImpl::HandleRestType(ir::AstNodeType elementType, bool *hasRestType) const
935{
936    if (elementType ==  ir::AstNodeType::TS_ARRAY_TYPE && *hasRestType) {
937        ThrowSyntaxError("A rest element cannot follow another rest element");
938    }
939    if (elementType ==  ir::AstNodeType::TS_ARRAY_TYPE) {
940        *hasRestType = true;
941    }
942}
943
944ir::Expression *ParserImpl::ParseTsTupleElement(ir::TSTupleKind *kind, bool *seenOptional, bool *hasRestType)
945{
946    lexer::SourcePosition startPos = lexer_->GetToken().Start();
947    ir::Expression *element = nullptr;
948    bool isRestType = false;
949    TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
950
951    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD) {
952        isRestType = true;
953        lexer_->NextToken();  // eat '...'
954    }
955
956    if (IsTSNamedTupleMember()) {
957        if (*kind == ir::TSTupleKind::DEFAULT) {
958            ThrowSyntaxError("Tuple members must all have or haven't names");
959        }
960        *kind = ir::TSTupleKind::NAMED;
961
962        auto *elementIdent = AllocNode<ir::Identifier>(lexer_->GetToken().Ident());
963        elementIdent->SetRange(lexer_->GetToken().Loc());
964        lexer_->NextToken();  // eat identifier
965
966        bool isOptional = false;
967        if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_QUESTION_MARK) {
968            lexer_->NextToken();  // eat '?'
969            isOptional = true;
970            *seenOptional = true;
971        } else if (*seenOptional && !isRestType) {
972            ThrowSyntaxError("A required element cannot follow an optional element");
973        }
974
975        if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COLON) {
976            ThrowSyntaxError("':' expected");
977        }
978
979        lexer_->NextToken();  // eat ':'
980        auto *elementType = ParseTsTypeAnnotation(&options);
981        CHECK_NOT_NULL(elementType);
982
983        if (elementType && isRestType) {
984            HandleRestType(elementType->Type(), hasRestType);
985        }
986
987        element = AllocNode<ir::TSNamedTupleMember>(elementIdent, elementType, isOptional, isRestType);
988        element->SetRange({startPos, elementType->End()});
989    } else {
990        if (*kind == ir::TSTupleKind::NAMED) {
991            ThrowSyntaxError("Tuple members must all have or haven't names");
992        }
993        *kind = ir::TSTupleKind::DEFAULT;
994
995        element = ParseTsTypeAnnotation(&options);
996        ASSERT(element != nullptr);
997        if (element && isRestType) {
998            HandleRestType(element->Type(), hasRestType);
999            lexer::SourcePosition endPos = element->End();
1000            element = AllocNode<ir::TSRestType>(std::move(element));
1001            element->SetRange({startPos, endPos});
1002        }
1003
1004        if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_QUESTION_MARK) {
1005            lexer::SourcePosition elementStartPos = element->Start();
1006            element = AllocNode<ir::TSOptionalType>(std::move(element));
1007            element->SetRange({elementStartPos, lexer_->GetToken().End()});
1008            lexer_->NextToken();  // eat '?'
1009            *seenOptional = true;
1010        } else if (*seenOptional && !isRestType) {
1011            ThrowSyntaxError("A required element cannot follow an optional element");
1012        }
1013    }
1014    return element;
1015}
1016
1017ir::TSTupleType *ParserImpl::ParseTsTupleType()
1018{
1019    ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET);
1020    lexer::SourcePosition tupleStart = lexer_->GetToken().Start();
1021    ArenaVector<ir::Expression *> elements(Allocator()->Adapter());
1022    ir::TSTupleKind kind = ir::TSTupleKind::NONE;
1023    bool seenOptional = false;
1024    bool hasRestType = false;
1025
1026    lexer_->NextToken();  // eat '['
1027
1028    while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
1029        ir::Expression *element = ParseTsTupleElement(&kind, &seenOptional, &hasRestType);
1030
1031        elements.push_back(element);
1032
1033        if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
1034            break;
1035        }
1036
1037        if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COMMA) {
1038            ThrowSyntaxError("',' expected.");
1039        }
1040
1041        lexer_->NextToken();  // eat ','
1042    }
1043
1044    lexer::SourcePosition tupleEnd = lexer_->GetToken().End();
1045    lexer_->NextToken();  // eat ']'
1046
1047    auto *tupleType = AllocNode<ir::TSTupleType>(std::move(elements));
1048    tupleType->SetRange({tupleStart, tupleEnd});
1049    return tupleType;
1050}
1051
1052ir::Expression *ParserImpl::ParseTsQualifiedReference(ir::Expression *typeName)
1053{
1054    lexer::SourcePosition startLoc = typeName->Start();
1055
1056    do {
1057        lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);  // eat '.'
1058
1059        if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
1060            ThrowSyntaxError("Identifier expected");
1061        }
1062
1063        auto *propName = AllocNode<ir::Identifier>(lexer_->GetToken().Ident());
1064        propName->SetRange(lexer_->GetToken().Loc());
1065
1066        typeName = AllocNode<ir::TSQualifiedName>(typeName, propName);
1067        typeName->SetRange({typeName->AsTSQualifiedName()->Left()->Start(), lexer_->GetToken().End()});
1068
1069        lexer_->NextToken();
1070    } while (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD);
1071
1072    typeName->SetRange({startLoc, lexer_->GetToken().End()});
1073
1074    return typeName;
1075}
1076
1077ir::Expression *ParserImpl::ParseTsIndexAccessType(ir::Expression *typeName, bool throwError)
1078{
1079    TypeAnnotationParsingOptions options = throwError ?
1080        TypeAnnotationParsingOptions::THROW_ERROR : TypeAnnotationParsingOptions::NO_OPTS;
1081
1082    do {
1083        lexer_->NextToken();  // eat '['
1084
1085        ir::Expression *indexType = ParseTsTypeAnnotation(&options);
1086
1087        if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
1088            if (!throwError) {
1089                return nullptr;
1090            }
1091            ThrowSyntaxError("']' expected");
1092        }
1093
1094        lexer_->NextToken();  // eat ']'
1095
1096        typeName = AllocNode<ir::TSIndexedAccessType>(typeName, indexType);
1097        typeName->SetRange({typeName->AsTSIndexedAccessType()->ObjectType()->Start(), lexer_->GetToken().End()});
1098    } while (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET &&
1099             lexer_->Lookahead() != LEX_CHAR_RIGHT_SQUARE);
1100
1101    return typeName;
1102}
1103
1104ir::Expression *ParserImpl::ParseTsTypeReferenceOrQuery(TypeAnnotationParsingOptions options, bool parseQuery)
1105{
1106    lexer::SourcePosition referenceStartLoc = lexer_->GetToken().Start();
1107
1108    if (parseQuery) {
1109        ASSERT(lexer_->GetToken().Type() == lexer::TokenType::KEYW_TYPEOF);
1110        lexer_->NextToken();  // eat 'typeof'
1111
1112        if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_IMPORT) {
1113            lexer::SourcePosition &startLoc = referenceStartLoc;
1114            return ParseTsImportType(startLoc, true);
1115        }
1116
1117        if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT &&
1118            lexer_->GetToken().Type() != lexer::TokenType::KEYW_THIS) {
1119            ThrowSyntaxError("Identifier expected.");
1120        }
1121    }
1122
1123    ASSERT(lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT ||
1124           lexer_->GetToken().Type() == lexer::TokenType::KEYW_THIS ||
1125           lexer_->GetToken().Type() == lexer::TokenType::KEYW_EXTENDS);
1126
1127    ir::Expression *typeName = AllocNode<ir::Identifier>(lexer_->GetToken().Ident());
1128    typeName->SetRange(lexer_->GetToken().Loc());
1129    typeName->AsIdentifier()->SetReference();
1130
1131    if (lexer_->Lookahead() == LEX_CHAR_LESS_THAN) {
1132        lexer_->ForwardToken(lexer::TokenType::PUNCTUATOR_LESS_THAN, 1);
1133    } else {
1134        lexer_->NextToken();
1135    }
1136
1137    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD) {
1138        typeName = ParseTsQualifiedReference(typeName);
1139    }
1140
1141    ir::TSTypeParameterInstantiation *typeParamInst = nullptr;
1142    if (!(lexer_->GetToken().Flags() & lexer::TokenFlags::NEW_LINE) &&
1143        lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) {
1144        typeParamInst = ParseTsTypeParameterInstantiation(options & TypeAnnotationParsingOptions::THROW_ERROR);
1145        if (parseQuery) {
1146            typeName = AllocNode<ir::TypeArgumentsExpression>(typeName, typeParamInst);
1147            lexer::SourcePosition endLoc = typeParamInst->End();
1148            typeName->SetRange({referenceStartLoc, endLoc});
1149        }
1150    }
1151
1152    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET &&
1153        lexer_->Lookahead() != LEX_CHAR_RIGHT_SQUARE) {
1154        if (parseQuery) {
1155            typeName = AllocNode<ir::TSTypeQuery>(typeName);
1156        } else {
1157            typeName = AllocNode<ir::TSTypeReference>(typeName, typeParamInst);
1158        }
1159
1160        typeName->SetRange({referenceStartLoc, lexer_->GetToken().End()});
1161
1162        return ParseTsIndexAccessType(typeName, options & TypeAnnotationParsingOptions::THROW_ERROR);
1163    }
1164
1165    ir::Expression *returnNode = nullptr;
1166
1167    lexer::SourcePosition referenceEndLoc = typeName->End();
1168
1169    if (parseQuery) {
1170        returnNode = AllocNode<ir::TSTypeQuery>(typeName);
1171    } else {
1172        returnNode = AllocNode<ir::TSTypeReference>(typeName, typeParamInst);
1173    }
1174
1175    returnNode->SetRange({referenceStartLoc, referenceEndLoc});
1176
1177    return returnNode;
1178}
1179
1180ir::TSTypeParameter *ParserImpl::ParseTsMappedTypeParameter()
1181{
1182    lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1183
1184    auto *paramName = AllocNode<ir::Identifier>(lexer_->GetToken().Ident());
1185    paramName->SetRange({lexer_->GetToken().Start(), lexer_->GetToken().End()});
1186
1187    lexer_->NextToken();
1188
1189    lexer_->NextToken();  // eat 'in'
1190
1191    TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
1192    ir::Expression *constraint = ParseTsTypeAnnotation(&options);
1193
1194    lexer::SourcePosition endLoc = constraint->End();
1195
1196    auto *typeParameter = AllocNode<ir::TSTypeParameter>(paramName, constraint, nullptr);
1197
1198    typeParameter->SetRange({startLoc, endLoc});
1199
1200    return typeParameter;
1201}
1202
1203ir::MappedOption ParserImpl::ParseMappedOption(lexer::TokenType tokenType)
1204{
1205    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_MINUS &&
1206        lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_PLUS &&
1207        lexer_->GetToken().KeywordType() != tokenType && lexer_->GetToken().Type() != tokenType) {
1208        return ir::MappedOption::NO_OPTS;
1209    }
1210
1211    auto result = lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MINUS ? ir::MappedOption::MINUS
1212                                                                                  : ir::MappedOption::PLUS;
1213
1214    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MINUS ||
1215        lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PLUS) {
1216        lexer_->NextToken();
1217    }
1218
1219    if (lexer_->GetToken().KeywordType() != tokenType && lexer_->GetToken().Type() != tokenType) {
1220        ThrowSyntaxError({"'", TokenToString(tokenType), "' expected."});
1221    }
1222
1223    lexer_->NextToken();
1224
1225    return result;
1226}
1227
1228ir::TSMappedType *ParserImpl::ParseTsMappedType()
1229{
1230    ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE);
1231
1232    lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1233    lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);  // eat '{'
1234
1235    ir::MappedOption readonly = ParseMappedOption(lexer::TokenType::KEYW_READONLY);
1236
1237    lexer_->NextToken();  // eat '['
1238
1239    ir::TSTypeParameter *typeParameter = ParseTsMappedTypeParameter();
1240
1241    ir::Expression *nameKeyType = nullptr;
1242    if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_AS) {
1243        lexer_->NextToken();  // eat 'as'
1244        TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
1245        nameKeyType = ParseTsTypeAnnotation(&options);
1246        ASSERT(nameKeyType != nullptr);
1247    }
1248
1249    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
1250        ThrowSyntaxError("']' expected");
1251    }
1252
1253    lexer_->NextToken();  // eat ']'
1254
1255    ir::MappedOption optional = ParseMappedOption(lexer::TokenType::PUNCTUATOR_QUESTION_MARK);
1256
1257    ir::Expression *typeAnnotation = nullptr;
1258    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
1259        lexer_->NextToken();  // eat ':'
1260        TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
1261        typeAnnotation = ParseTsTypeAnnotation(&options);
1262    }
1263
1264    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON &&
1265        lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
1266        ThrowSyntaxError("';' expected");
1267    }
1268
1269    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
1270        lexer_->NextToken();  // eat ';'
1271    }
1272
1273    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
1274        ThrowSyntaxError("'}' expected");
1275    }
1276
1277    auto *mappedType = AllocNode<ir::TSMappedType>(typeParameter, nameKeyType, typeAnnotation, readonly, optional);
1278
1279    mappedType->SetRange({startLoc, lexer_->GetToken().End()});
1280
1281    lexer_->NextToken();  // eat '}'
1282
1283    return mappedType;
1284}
1285
1286ir::TSTypePredicate *ParserImpl::ParseTsTypePredicate()
1287{
1288    auto pos = lexer_->Save();
1289    lexer::SourcePosition startPos = lexer_->GetToken().Start();
1290    bool isAsserts = lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_ASSERTS;
1291    if (isAsserts) {
1292        lexer_->NextToken();  // eat 'asserts'
1293        if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_IS) {
1294            isAsserts = false;
1295            lexer_->Rewind(pos);
1296        }
1297    }
1298
1299    ir::Expression *parameterName = nullptr;
1300    if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) {
1301        parameterName = AllocNode<ir::Identifier>(lexer_->GetToken().Ident());
1302    } else {
1303        parameterName = AllocNode<ir::TSThisType>();
1304    }
1305
1306    parameterName->SetRange({lexer_->GetToken().Start(), lexer_->GetToken().End()});
1307
1308    lexer_->NextToken();
1309
1310    ir::Expression *typeAnnotation = nullptr;
1311    lexer::SourcePosition endPos;
1312    ir::TSTypePredicate *result = nullptr;
1313
1314    if (isAsserts && lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_IS) {
1315        endPos = parameterName->End();
1316        result = AllocNode<ir::TSTypePredicate>(parameterName, typeAnnotation, isAsserts);
1317        result->SetRange({startPos, endPos});
1318        return result;
1319    }
1320
1321    lexer_->NextToken();  // eat 'is'
1322
1323    TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
1324    typeAnnotation = ParseTsTypeAnnotation(&options);
1325    endPos = typeAnnotation->End();
1326
1327    result = AllocNode<ir::TSTypePredicate>(parameterName, typeAnnotation, isAsserts);
1328
1329    result->SetRange({startPos, endPos});
1330
1331    return result;
1332}
1333
1334ir::Expression *ParserImpl::ParseTsTypeLiteralOrInterfaceKey(bool *computed, bool *signature, bool *isIndexSignature)
1335{
1336    ir::Expression *key = nullptr;
1337
1338    if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT &&
1339        (lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_NEW ||
1340         (lexer_->Lookahead() != LEX_CHAR_LEFT_PAREN && lexer_->Lookahead() != LEX_CHAR_LESS_THAN))) {
1341        key = AllocNode<ir::Identifier>(lexer_->GetToken().Ident());
1342        key->SetRange(lexer_->GetToken().Loc());
1343        lexer_->NextToken();
1344    } else if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_NUMBER) {
1345        if (lexer_->GetToken().Flags() & lexer::TokenFlags::NUMBER_BIGINT) {
1346            key = AllocNode<ir::BigIntLiteral>(lexer_->GetToken().BigInt());
1347        } else {
1348            key = AllocNode<ir::NumberLiteral>(lexer_->GetToken().Number(), lexer_->GetToken().String());
1349        }
1350
1351        key->SetRange(lexer_->GetToken().Loc());
1352        lexer_->NextToken();
1353    } else if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_STRING) {
1354        key = AllocNode<ir::StringLiteral>(lexer_->GetToken().String());
1355        key->SetRange(lexer_->GetToken().Loc());
1356        lexer_->NextToken();
1357    } else if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET) {
1358        *computed = true;
1359        lexer_->NextToken();  // eat '['
1360
1361        if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT && lexer_->Lookahead() == LEX_CHAR_COLON) {
1362            *isIndexSignature = true;
1363            key = AllocNode<ir::Identifier>(lexer_->GetToken().Ident());
1364            key->SetRange(lexer_->GetToken().Loc());
1365
1366            lexer_->NextToken();  // eat param
1367
1368            if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COLON) {
1369                ThrowSyntaxError("':' expected");
1370            }
1371
1372            lexer_->NextToken();  // eat ':'
1373
1374            TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
1375            ir::Expression *typeAnnotation = ParseTsTypeAnnotation(&options);
1376
1377            ValidateIndexSignatureParameterType(typeAnnotation);
1378
1379            key->SetTsTypeAnnotation(typeAnnotation);
1380        } else {
1381            key = ParseExpression();
1382        }
1383
1384        if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
1385            ThrowSyntaxError("']' expected");
1386        }
1387
1388        lexer_->NextToken();  // eat ']'
1389    } else if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS &&
1390               lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LESS_THAN &&
1391               lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_NEW) {
1392        ThrowSyntaxError("Unexpected token");
1393    } else {
1394        *signature = true;
1395    }
1396
1397    return key;
1398}
1399
1400void ParserImpl::ValidateIndexSignatureParameterType(ir::Expression *typeAnnotation)
1401{
1402    // Validation of IndexSignatureParameterType is coarse-grained.
1403    if (!typeAnnotation->IsTSStringKeyword() && !typeAnnotation->IsTSNumberKeyword() &&
1404        !typeAnnotation->IsTSSymbolKeyword() && !typeAnnotation->IsTSTemplateLiteralType() &&
1405        !typeAnnotation->IsTSUnionType() && !typeAnnotation->IsTSTypeReference() &&
1406        !typeAnnotation->IsTSParenthesizedType() && !typeAnnotation->IsTSConditionalType() &&
1407        !typeAnnotation->IsTSIndexedAccessType() && !typeAnnotation->IsTSIntersectionType()) {
1408        ThrowSyntaxError(
1409            "An index signature parameter type must be 'string', 'number', 'symbol', "
1410            "or a template literal type.");
1411    }
1412}
1413
1414void ParserImpl::CreateTSVariableForProperty(ir::AstNode *node, const ir::Expression *key, binder::VariableFlags flags)
1415{
1416    binder::Variable *propVar = nullptr;
1417    bool isMethod = flags & binder::VariableFlags::METHOD;
1418    util::StringView propName = "__computed";
1419
1420    switch (key->Type()) {
1421        case ir::AstNodeType::IDENTIFIER: {
1422            propName = key->AsIdentifier()->Name();
1423            break;
1424        }
1425        case ir::AstNodeType::NUMBER_LITERAL: {
1426            propName = key->AsNumberLiteral()->Str();
1427            flags |= binder::VariableFlags::NUMERIC_NAME;
1428            break;
1429        }
1430        case ir::AstNodeType::STRING_LITERAL: {
1431            propName = key->AsStringLiteral()->Str();
1432            break;
1433        }
1434        default: {
1435            flags |= binder::VariableFlags::COMPUTED;
1436            break;
1437        }
1438    }
1439
1440    propVar = isMethod ? binder::Scope::CreateVar<binder::MethodDecl>(Allocator(), propName, flags, node)
1441                       : binder::Scope::CreateVar<binder::PropertyDecl>(Allocator(), propName, flags, node);
1442
1443    node->SetVariable(propVar);
1444}
1445
1446void ParserImpl::ParseTsTypeLiteralOrInterfaceKeyModifiers(bool *isGetAccessor, bool *isSetAccessor)
1447{
1448    if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
1449        return;
1450    }
1451
1452    char32_t nextCp = lexer_->Lookahead();
1453    if (Extension() == ScriptExtension::TS &&
1454        nextCp != LEX_CHAR_EQUALS && nextCp != LEX_CHAR_SEMICOLON && nextCp != LEX_CHAR_LEFT_PAREN &&
1455        nextCp != LEX_CHAR_LESS_THAN && nextCp != LEX_CHAR_QUESTION && nextCp != LEX_CHAR_COLON &&
1456        nextCp != LEX_CHAR_RIGHT_BRACE && nextCp != LEX_CHAR_COMMA) {
1457        if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_GET) {
1458            if (lexer_->GetToken().Flags() & lexer::TokenFlags::HAS_ESCAPE) {
1459                ThrowSyntaxError("Keyword must not contain escaped characters");
1460            }
1461
1462            *isGetAccessor = true;
1463            lexer_->NextToken();
1464        } else if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_SET) {
1465            if (lexer_->GetToken().Flags() & lexer::TokenFlags::HAS_ESCAPE) {
1466                ThrowSyntaxError("Keyword must not contain escaped characters");
1467            }
1468
1469            *isSetAccessor = true;
1470            lexer_->NextToken();
1471        }
1472    }
1473}
1474
1475ir::Expression *ParserImpl::ParseTsTypeLiteralOrInterfaceMember()
1476{
1477    bool computed = false;
1478    bool optional = false;
1479    bool signature = false;
1480    bool readonly = false;
1481    bool isGetAccessor = false;
1482    bool isSetAccessor = false;
1483    bool isConstructSignature = false;
1484    bool isIndexSignature = false;
1485    lexer::SourcePosition memberStartLoc = lexer_->GetToken().Start();
1486    char32_t nextToken = lexer_->Lookahead();
1487    if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_READONLY && nextToken != LEX_CHAR_LEFT_PAREN &&
1488        nextToken != LEX_CHAR_COLON && nextToken != LEX_CHAR_COMMA && nextToken != LEX_CHAR_LESS_THAN &&
1489        nextToken != LEX_CHAR_SEMICOLON) {
1490        readonly = true;
1491        lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);
1492    }
1493
1494    ParseTsTypeLiteralOrInterfaceKeyModifiers(&isGetAccessor, &isSetAccessor);
1495    ir::Expression *key = ParseTsTypeLiteralOrInterfaceKey(&computed, &signature, &isIndexSignature);
1496
1497    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_QUESTION_MARK) {
1498        if (isIndexSignature) {
1499            ThrowSyntaxError("';' expected");
1500        }
1501
1502        optional = true;
1503        lexer_->NextToken();  // eat '?'
1504    }
1505
1506    if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_NEW && signature) {
1507        lexer_->NextToken();  // eat 'new'
1508
1509        if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS &&
1510            lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LESS_THAN) {
1511            ThrowSyntaxError("'(' expected");
1512        }
1513
1514        isConstructSignature = true;
1515    }
1516
1517    ir::TSTypeParameterDeclaration *typeParamDecl = nullptr;
1518    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) {
1519        if (isIndexSignature) {
1520            ThrowSyntaxError("';' expected");
1521        }
1522
1523        typeParamDecl = ParseTsTypeParameterDeclaration();
1524
1525        if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
1526            ThrowSyntaxError("'(' expected");
1527        }
1528    }
1529
1530    ir::Expression *member = nullptr;
1531    ir::Expression *typeAnnotation = nullptr;
1532    binder::VariableFlags flags = binder::VariableFlags::NONE;
1533
1534    if (optional) {
1535        flags |= binder::VariableFlags::OPTIONAL;
1536    }
1537
1538    if (readonly) {
1539        flags |= binder::VariableFlags::READONLY;
1540    }
1541
1542    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS && !isIndexSignature) {
1543        FunctionParameterContext funcParamContext(&context_, Binder());
1544        auto *funcParamScope = funcParamContext.LexicalScope().GetScope();
1545        ArenaVector<ir::Expression *> params = ParseFunctionParams(true);
1546
1547        if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
1548            lexer_->NextToken();  // eat ':'
1549            TypeAnnotationParsingOptions options =
1550                TypeAnnotationParsingOptions::THROW_ERROR | TypeAnnotationParsingOptions::CAN_BE_TS_TYPE_PREDICATE;
1551            typeAnnotation = ParseTsTypeAnnotation(&options);
1552        }
1553
1554        if (signature) {
1555            auto kind = isConstructSignature
1556                            ? ir::TSSignatureDeclaration::TSSignatureDeclarationKind::CONSTRUCT_SIGNATURE
1557                            : ir::TSSignatureDeclaration::TSSignatureDeclarationKind::CALL_SIGNATURE;
1558            member = AllocNode<ir::TSSignatureDeclaration>(funcParamScope, kind, typeParamDecl, std::move(params),
1559                                                           typeAnnotation);
1560            funcParamScope->BindNode(member);
1561        } else {
1562            member = AllocNode<ir::TSMethodSignature>(funcParamScope, key, typeParamDecl, std::move(params),
1563                                                      typeAnnotation, computed, optional, isGetAccessor, isSetAccessor);
1564            funcParamScope->BindNode(member);
1565            CreateTSVariableForProperty(member, key, flags | binder::VariableFlags::METHOD);
1566        }
1567    } else if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
1568        lexer_->NextToken();  // eat ':'
1569        TypeAnnotationParsingOptions options =
1570            TypeAnnotationParsingOptions::THROW_ERROR | TypeAnnotationParsingOptions::BREAK_AT_NEW_LINE;
1571        typeAnnotation = ParseTsTypeAnnotation(&options);
1572    } else if (isIndexSignature) {
1573        ThrowSyntaxError("An index signature must have a type annotation.", memberStartLoc);
1574    }
1575
1576    if (!member && isIndexSignature) {
1577        member = AllocNode<ir::TSIndexSignature>(key, typeAnnotation, readonly);
1578    } else if (!member) {
1579        member = AllocNode<ir::TSPropertySignature>(key, typeAnnotation, computed, optional, readonly);
1580        CreateTSVariableForProperty(member, key, flags | binder::VariableFlags::PROPERTY);
1581    } else if (readonly) {
1582        ThrowSyntaxError(
1583            "'readonly' modifier can only appear on a property "
1584            "declaration or index signature.",
1585            memberStartLoc);
1586    }
1587
1588    member->SetRange({memberStartLoc, lexer_->GetToken().End()});
1589
1590    return member;
1591}
1592
1593util::StringView GetTSPropertyName(ir::Expression *key)
1594{
1595    switch (key->Type()) {
1596        case ir::AstNodeType::IDENTIFIER: {
1597            return key->AsIdentifier()->Name();
1598        }
1599        case ir::AstNodeType::NUMBER_LITERAL: {
1600            return key->AsNumberLiteral()->Str();
1601        }
1602        case ir::AstNodeType::STRING_LITERAL: {
1603            return key->AsStringLiteral()->Str();
1604        }
1605        default: {
1606            UNREACHABLE();
1607        }
1608    }
1609}
1610
1611void ParserImpl::CheckObjectTypeForDuplicatedProperties(ir::Expression *member,
1612    ArenaVector<ir::Expression *> const &members)
1613{
1614    ir::Expression *key = nullptr;
1615
1616    if (member->IsTSPropertySignature()) {
1617        key = member->AsTSPropertySignature()->Key();
1618    } else if (member->IsTSMethodSignature()) {
1619        key = member->AsTSMethodSignature()->Key();
1620    } else {
1621        return;
1622    }
1623
1624    if (!key->IsIdentifier() && !key->IsNumberLiteral() && !key->IsStringLiteral()) {
1625        return;
1626    }
1627
1628    for (auto *it : members) {
1629        ir::Expression *compare = nullptr;
1630
1631        switch (it->Type()) {
1632            case ir::AstNodeType::TS_PROPERTY_SIGNATURE: {
1633                compare = it->AsTSPropertySignature()->Key();
1634                break;
1635            }
1636            case ir::AstNodeType::TS_METHOD_SIGNATURE: {
1637                compare = it->AsTSMethodSignature()->Key();
1638                break;
1639            }
1640            default: {
1641                continue;
1642            }
1643        }
1644
1645        if (!compare->IsIdentifier() && !compare->IsNumberLiteral() && !compare->IsStringLiteral()) {
1646            continue;
1647        }
1648
1649        if (member->IsTSMethodSignature() && it->Type() == ir::AstNodeType::TS_METHOD_SIGNATURE) {
1650            continue;
1651        }
1652
1653        if (GetTSPropertyName(key) == GetTSPropertyName(compare)) {
1654            ThrowSyntaxError("Duplicated identifier", key->Start());
1655        }
1656    }
1657}
1658
1659ArenaVector<ir::Expression *> ParserImpl::ParseTsTypeLiteralOrInterface()
1660{
1661    ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE);
1662
1663    lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);  // eat '{'
1664
1665    ArenaVector<ir::Expression *> members(Allocator()->Adapter());
1666
1667    while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
1668        ir::Expression *member = ParseTsTypeLiteralOrInterfaceMember();
1669
1670        CheckObjectTypeForDuplicatedProperties(member, members);
1671
1672        members.push_back(member);
1673
1674        if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
1675            break;
1676        }
1677
1678        if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COMMA &&
1679            lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
1680            if (!lexer_->GetToken().NewLine()) {
1681                ThrowSyntaxError("',' expected");
1682            }
1683
1684            if (lexer_->GetToken().IsKeyword()) {
1685                lexer_->GetToken().SetTokenType(lexer::TokenType::LITERAL_IDENT);
1686            }
1687
1688            continue;
1689        }
1690
1691        lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);
1692    }
1693
1694    return members;
1695}
1696
1697ir::TSArrayType *ParserImpl::ParseTsArrayType(ir::Expression *elementType)
1698{
1699    ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET);
1700    lexer_->NextToken();  // eat '['
1701
1702    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
1703        ThrowSyntaxError("']' expected");
1704    }
1705
1706    lexer::SourcePosition endLoc = lexer_->GetToken().End();
1707    lexer_->NextToken();  // eat ']'
1708
1709    lexer::SourcePosition startLoc = elementType->Start();
1710    auto *arrayType = AllocNode<ir::TSArrayType>(elementType);
1711    arrayType->SetRange({startLoc, endLoc});
1712
1713    return arrayType;
1714}
1715
1716ir::TSUnionType *ParserImpl::ParseTsUnionType(ir::Expression *type, bool restrictExtends, bool throwError)
1717{
1718    ArenaVector<ir::Expression *> types(Allocator()->Adapter());
1719    lexer::SourcePosition startLoc;
1720
1721    TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::IN_UNION;
1722    if (throwError) {
1723        options |= TypeAnnotationParsingOptions::THROW_ERROR;
1724    }
1725
1726    if (restrictExtends) {
1727        options |= TypeAnnotationParsingOptions::RESTRICT_EXTENDS;
1728    }
1729
1730    if (type) {
1731        startLoc = type->Start();
1732        types.push_back(type);
1733    } else {
1734        startLoc = lexer_->GetToken().Start();
1735    }
1736
1737    while (true) {
1738        if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_BITWISE_OR) {
1739            break;
1740        }
1741
1742        lexer_->NextToken();  // eat '|'
1743
1744        ir::Expression* unionSuffixType = ParseTsTypeAnnotation(&options);
1745        if (unionSuffixType == nullptr) {
1746            return nullptr;
1747        }
1748
1749        types.push_back(unionSuffixType);
1750    }
1751
1752    lexer::SourcePosition endLoc = types.back()->End();
1753
1754    auto *unionType = AllocNode<ir::TSUnionType>(std::move(types));
1755    auto *typeVar = binder::Scope::CreateVar(Allocator(), "__type", binder::VariableFlags::TYPE, unionType);
1756    unionType->SetVariable(typeVar);
1757    unionType->SetRange({startLoc, endLoc});
1758
1759    return unionType;
1760}
1761
1762ir::TSIntersectionType *ParserImpl::ParseTsIntersectionType(ir::Expression *type, bool inUnion, bool restrictExtends,
1763                                                            bool throwError)
1764{
1765    ArenaVector<ir::Expression *> types(Allocator()->Adapter());
1766    lexer::SourcePosition startLoc;
1767
1768    TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::IN_INTERSECTION;
1769    if (throwError) {
1770        options |= TypeAnnotationParsingOptions::THROW_ERROR;
1771    }
1772
1773    if (restrictExtends) {
1774        options |= TypeAnnotationParsingOptions::RESTRICT_EXTENDS;
1775    }
1776
1777    if (inUnion) {
1778        options |= TypeAnnotationParsingOptions::IN_UNION;
1779    }
1780
1781    if (type) {
1782        startLoc = type->Start();
1783        types.push_back(type);
1784    } else {
1785        startLoc = lexer_->GetToken().Start();
1786    }
1787
1788    while (true) {
1789        if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_BITWISE_AND) {
1790            break;
1791        }
1792
1793        lexer_->NextToken();  // eat '&'
1794
1795        ir::Expression* suffixType = ParseTsTypeAnnotation(&options);
1796        if (suffixType == nullptr) {
1797            return nullptr;
1798        }
1799        types.push_back(suffixType);
1800    }
1801
1802    lexer::SourcePosition endLoc = types.back()->End();
1803
1804    auto *intersectionType = AllocNode<ir::TSIntersectionType>(std::move(types));
1805    auto *typeVar = binder::Scope::CreateVar(Allocator(), "__type", binder::VariableFlags::TYPE, intersectionType);
1806    intersectionType->SetVariable(typeVar);
1807    intersectionType->SetRange({startLoc, endLoc});
1808
1809    return intersectionType;
1810}
1811
1812bool ParserImpl::IsTsFunctionType()
1813{
1814    ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS);
1815    const auto startPos = lexer_->Save();
1816    lexer_->NextToken();  // eat '('
1817    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS ||
1818        lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD) {
1819        lexer_->Rewind(startPos);
1820        return true;
1821    }
1822
1823    try {
1824        ParseModifiers();
1825        if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT ||
1826            (Extension() == ScriptExtension::TS && lexer_->GetToken().Type() == lexer::TokenType::KEYW_THIS)) {
1827            lexer_->NextToken();
1828        } else if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET) {
1829            ParseArrayExpression(ExpressionParseFlags::MUST_BE_PATTERN);
1830        } else if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
1831            ParseObjectExpression(ExpressionParseFlags::MUST_BE_PATTERN | ExpressionParseFlags::OBJECT_PATTERN);
1832        } else {
1833            lexer_->Rewind(startPos);
1834            return false;
1835        }
1836    } catch ([[maybe_unused]] const class Error &e) {
1837        lexer_->Rewind(startPos);
1838        return false;
1839    }
1840
1841    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA ||
1842        lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_QUESTION_MARK ||
1843        lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON ||
1844        lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_EQUAL) {
1845        lexer_->Rewind(startPos);
1846        return true;
1847    }
1848
1849    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
1850        lexer_->NextToken();  // eat ')'
1851        if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_ARROW) {
1852            lexer_->Rewind(startPos);
1853            return true;
1854        }
1855    }
1856    lexer_->Rewind(startPos);
1857    return false;
1858}
1859
1860ir::Expression *ParserImpl::ParseTsParenthesizedOrFunctionType(ir::Expression *typeAnnotation, bool throwError)
1861{
1862    if (typeAnnotation) {
1863        return nullptr;
1864    }
1865
1866    lexer::SourcePosition typeStart = lexer_->GetToken().Start();
1867
1868    bool abstractConstructor = lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_ABSTRACT;
1869    if (abstractConstructor) {
1870        lexer_->NextToken();  // eat 'abstract'
1871    }
1872
1873    bool isConstructionType = false;
1874
1875    if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_NEW) {
1876        lexer_->NextToken();  // eat 'new'
1877        isConstructionType = true;
1878
1879        if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS &&
1880            lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LESS_THAN) {
1881            if (!throwError) {
1882                return nullptr;
1883            }
1884            ThrowSyntaxError("'(' expected");
1885        }
1886    }
1887
1888    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN || isConstructionType) {
1889        return ParseTsFunctionType(typeStart, isConstructionType, throwError, abstractConstructor);
1890    }
1891
1892    if (IsTsFunctionType()) {
1893        return ParseTsFunctionType(typeStart, false, throwError);
1894    }
1895
1896    ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS);
1897    lexer_->NextToken();  // eat '('
1898
1899    TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::NO_OPTS;
1900    ir::Expression *type = ParseTsTypeAnnotation(&options);
1901
1902    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
1903        if (!throwError) {
1904            return nullptr;
1905        }
1906        ThrowSyntaxError("')' expected");
1907    }
1908
1909    lexer::SourcePosition endLoc = lexer_->GetToken().End();
1910    lexer_->NextToken();  // eat ')'
1911
1912    auto *result = AllocNode<ir::TSParenthesizedType>(type);
1913    result->SetRange({typeStart, endLoc});
1914
1915    return result;
1916}
1917
1918ir::Expression *ParserImpl::ParseTsFunctionType(lexer::SourcePosition startLoc, bool isConstructionType,
1919                                                bool throwError, bool abstractConstructor)
1920{
1921    ir::TSTypeParameterDeclaration *typeParamDecl = nullptr;
1922    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) {
1923        typeParamDecl = ParseTsTypeParameterDeclaration(throwError);
1924
1925        if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
1926            if (!throwError) {
1927                return nullptr;
1928            }
1929
1930            ThrowSyntaxError("'(' expected");
1931        }
1932    }
1933
1934    FunctionParameterContext funcParamContext(&context_, Binder());
1935    auto *funcParamScope = funcParamContext.LexicalScope().GetScope();
1936
1937    ArenaVector<ir::Expression *> params(Allocator()->Adapter());
1938    try {
1939        params = ParseFunctionParams(true);
1940    } catch (const Error &e) {
1941        if (!throwError) {
1942            return nullptr;
1943        }
1944        throw e;
1945    }
1946
1947    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_ARROW) {
1948        ThrowSyntaxError("'=>' expected");
1949    }
1950
1951    lexer_->NextToken();  // eat '=>'
1952
1953    TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::CAN_BE_TS_TYPE_PREDICATE;
1954    if (throwError) {
1955        options |= TypeAnnotationParsingOptions::THROW_ERROR;
1956    }
1957
1958    ir::Expression *returnTypeAnnotation = ParseTsTypeAnnotation(&options);
1959
1960    if (returnTypeAnnotation == nullptr) {
1961        return nullptr;
1962    }
1963
1964    ir::Expression *funcType = nullptr;
1965
1966    if (isConstructionType) {
1967        funcType = AllocNode<ir::TSConstructorType>(funcParamScope, std::move(params), typeParamDecl,
1968                                                    returnTypeAnnotation, abstractConstructor);
1969    } else {
1970        funcType =
1971            AllocNode<ir::TSFunctionType>(funcParamScope, std::move(params), typeParamDecl, returnTypeAnnotation);
1972    }
1973
1974    funcType->SetRange({startLoc, returnTypeAnnotation->End()});
1975    funcParamScope->BindNode(funcType);
1976
1977    return funcType;
1978}
1979
1980ir::Expression *ParserImpl::ParseTsBasicType(TypeAnnotationParsingOptions options)
1981{
1982    ir::Expression *typeAnnotation = nullptr;
1983
1984    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MINUS) {
1985        lexer_->NextToken();
1986
1987        if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_NUMBER) {
1988            if (options & TypeAnnotationParsingOptions::THROW_ERROR) {
1989                ThrowSyntaxError("Type expected");
1990            } else {
1991                return nullptr;
1992            }
1993        }
1994    }
1995    if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_NUMBER) {
1996        if (lexer_->GetToken().Flags() & lexer::TokenFlags::NUMBER_BIGINT) {
1997            auto *bigintNode = AllocNode<ir::BigIntLiteral>(lexer_->GetToken().BigInt());
1998            bigintNode->SetRange(lexer_->GetToken().Loc());
1999
2000            typeAnnotation = AllocNode<ir::TSLiteralType>(bigintNode);
2001        } else {
2002            auto *numberNode = AllocNode<ir::NumberLiteral>(lexer_->GetToken().Number(), lexer_->GetToken().String());
2003            numberNode->SetRange(lexer_->GetToken().Loc());
2004
2005            typeAnnotation = AllocNode<ir::TSLiteralType>(numberNode);
2006        }
2007    } else if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_STRING) {
2008        auto *stringNode = AllocNode<ir::StringLiteral>(lexer_->GetToken().String());
2009        stringNode->SetRange(lexer_->GetToken().Loc());
2010
2011        typeAnnotation = AllocNode<ir::TSLiteralType>(stringNode);
2012    } else if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_TRUE) {
2013        auto *booleanLiteral = AllocNode<ir::BooleanLiteral>(true);
2014        booleanLiteral->SetRange(lexer_->GetToken().Loc());
2015
2016        typeAnnotation = AllocNode<ir::TSLiteralType>(booleanLiteral);
2017    } else if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_FALSE) {
2018        auto *booleanLiteral = AllocNode<ir::BooleanLiteral>(false);
2019        booleanLiteral->SetRange(lexer_->GetToken().Loc());
2020
2021        typeAnnotation = AllocNode<ir::TSLiteralType>(booleanLiteral);
2022    } else if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_ANY) {
2023        typeAnnotation = AllocNode<ir::TSAnyKeyword>();
2024    } else if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_BOOLEAN) {
2025        typeAnnotation = AllocNode<ir::TSBooleanKeyword>();
2026    } else if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_NUMBER) {
2027        typeAnnotation = AllocNode<ir::TSNumberKeyword>();
2028    } else if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_STRING) {
2029        typeAnnotation = AllocNode<ir::TSStringKeyword>();
2030    } else if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_UNKNOWN) {
2031        typeAnnotation = AllocNode<ir::TSUnknownKeyword>();
2032    } else if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_VOID) {
2033        typeAnnotation = AllocNode<ir::TSVoidKeyword>();
2034    } else if (lexer_->GetToken().KeywordType() == lexer::TokenType::LITERAL_NULL) {
2035        typeAnnotation = AllocNode<ir::TSNullKeyword>();
2036    } else if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_UNDEFINED) {
2037        typeAnnotation = AllocNode<ir::TSUndefinedKeyword>();
2038    } else if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_NEVER) {
2039        typeAnnotation = AllocNode<ir::TSNeverKeyword>();
2040    } else if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_OBJECT) {
2041        typeAnnotation = AllocNode<ir::TSObjectKeyword>();
2042    } else if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_BIGINT) {
2043        typeAnnotation = AllocNode<ir::TSBigintKeyword>();
2044    } else if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_SYMBOL) {
2045        typeAnnotation = AllocNode<ir::TSSymbolKeyword>();
2046    } else {
2047        ThrowSyntaxError("Unexpected type");
2048    }
2049
2050    typeAnnotation->SetRange(lexer_->GetToken().Loc());
2051
2052    lexer_->NextToken();
2053    return typeAnnotation;
2054}
2055
2056static ir::ModifierFlags GetAccessability(ir::ModifierFlags modifiers)
2057{
2058    if (modifiers & ir::ModifierFlags::PUBLIC) {
2059        return ir::ModifierFlags::PUBLIC;
2060    }
2061
2062    if (modifiers & ir::ModifierFlags::PRIVATE) {
2063        return ir::ModifierFlags::PRIVATE;
2064    }
2065
2066    if (modifiers & ir::ModifierFlags::PROTECTED) {
2067        return ir::ModifierFlags::PROTECTED;
2068    }
2069
2070    return ir::ModifierFlags::NONE;
2071}
2072
2073static bool IsModifierKind(const lexer::Token &token)
2074{
2075    if (token.Type() == lexer::TokenType::LITERAL_IDENT) {
2076        switch (token.KeywordType()) {
2077            case lexer::TokenType::KEYW_PUBLIC:
2078            case lexer::TokenType::KEYW_PRIVATE:
2079            case lexer::TokenType::KEYW_PROTECTED:
2080            case lexer::TokenType::KEYW_STATIC:
2081            case lexer::TokenType::KEYW_ASYNC:
2082            case lexer::TokenType::KEYW_ABSTRACT:
2083            case lexer::TokenType::KEYW_DECLARE:
2084            case lexer::TokenType::KEYW_READONLY:
2085            case lexer::TokenType::KEYW_ACCESSOR:
2086            case lexer::TokenType::KEYW_OVERRIDE:
2087                return true;
2088            default:
2089                return false;
2090        }
2091    }
2092
2093    return false;
2094}
2095
2096ir::ModifierFlags ParserImpl::ParseModifiers()
2097{
2098    ir::ModifierFlags resultStatus = ir::ModifierFlags::NONE;
2099    ir::ModifierFlags prevStatus = ir::ModifierFlags::ALL;
2100
2101    while (IsModifierKind(lexer_->GetToken())) {
2102        char32_t nextCp = lexer_->Lookahead();
2103        if (nextCp == LEX_CHAR_LEFT_PAREN || nextCp == LEX_CHAR_EQUALS || nextCp == LEX_CHAR_SEMICOLON) {
2104            break;
2105        }
2106
2107        lexer::TokenFlags tokenFlags = lexer_->GetToken().Flags();
2108        if (tokenFlags & lexer::TokenFlags::HAS_ESCAPE) {
2109            ThrowSyntaxError("Keyword must not contain escaped characters");
2110        }
2111
2112        ir::ModifierFlags actualStatus = ir::ModifierFlags::NONE;
2113        ir::ModifierFlags nextStatus = ir::ModifierFlags::NONE;
2114
2115        switch (lexer_->GetToken().KeywordType()) {
2116            case lexer::TokenType::KEYW_PUBLIC: {
2117                actualStatus = ir::ModifierFlags::PUBLIC;
2118                nextStatus = ir::ModifierFlags::ASYNC | ir::ModifierFlags::STATIC | ir::ModifierFlags::READONLY |
2119                             ir::ModifierFlags::DECLARE | ir::ModifierFlags::ABSTRACT | ir::ModifierFlags::ACCESSOR |
2120                             ir::ModifierFlags::OVERRIDE;
2121                break;
2122            }
2123            case lexer::TokenType::KEYW_PRIVATE: {
2124                actualStatus = ir::ModifierFlags::PRIVATE;
2125                nextStatus = ir::ModifierFlags::ASYNC | ir::ModifierFlags::STATIC | ir::ModifierFlags::READONLY |
2126                             ir::ModifierFlags::DECLARE | ir::ModifierFlags::ABSTRACT | ir::ModifierFlags::ACCESSOR |
2127                             ir::ModifierFlags::OVERRIDE;
2128                break;
2129            }
2130            case lexer::TokenType::KEYW_PROTECTED: {
2131                actualStatus = ir::ModifierFlags::PROTECTED;
2132                nextStatus = ir::ModifierFlags::ASYNC | ir::ModifierFlags::STATIC | ir::ModifierFlags::READONLY |
2133                             ir::ModifierFlags::DECLARE | ir::ModifierFlags::ABSTRACT | ir::ModifierFlags::ACCESSOR |
2134                             ir::ModifierFlags::OVERRIDE;
2135                break;
2136            }
2137            case lexer::TokenType::KEYW_STATIC: {
2138                actualStatus = ir::ModifierFlags::STATIC;
2139                nextStatus = ir::ModifierFlags::ASYNC | ir::ModifierFlags::READONLY | ir::ModifierFlags::DECLARE |
2140                             ir::ModifierFlags::ABSTRACT | ir::ModifierFlags::ACCESSOR | ir::ModifierFlags::OVERRIDE;
2141                break;
2142            }
2143            case lexer::TokenType::KEYW_ASYNC: {
2144                actualStatus = ir::ModifierFlags::ASYNC;
2145                nextStatus = ir::ModifierFlags::READONLY | ir::ModifierFlags::DECLARE | ir::ModifierFlags::ABSTRACT;
2146                break;
2147            }
2148            case lexer::TokenType::KEYW_ABSTRACT: {
2149                actualStatus = ir::ModifierFlags::ABSTRACT;
2150                nextStatus = ir::ModifierFlags::ACCESS | ir::ModifierFlags::ASYNC | ir::ModifierFlags::STATIC |
2151                             ir::ModifierFlags::READONLY | ir::ModifierFlags::DECLARE | ir::ModifierFlags::OVERRIDE |
2152                             ir::ModifierFlags::ACCESSOR;
2153                break;
2154            }
2155            case lexer::TokenType::KEYW_DECLARE: {
2156                actualStatus = ir::ModifierFlags::DECLARE;
2157                nextStatus = ir::ModifierFlags::ACCESS | ir::ModifierFlags::ASYNC | ir::ModifierFlags::STATIC |
2158                             ir::ModifierFlags::READONLY;
2159                break;
2160            }
2161            case lexer::TokenType::KEYW_READONLY: {
2162                actualStatus = ir::ModifierFlags::READONLY;
2163                nextStatus = ir::ModifierFlags::ASYNC | ir::ModifierFlags::DECLARE | ir::ModifierFlags::ABSTRACT;
2164                break;
2165            }
2166            case lexer::TokenType::KEYW_ACCESSOR: {
2167                actualStatus = ir::ModifierFlags::ACCESSOR;
2168                nextStatus = ir::ModifierFlags::NONE;
2169                break;
2170            }
2171            case lexer::TokenType::KEYW_OVERRIDE: {
2172                actualStatus = ir::ModifierFlags::OVERRIDE;
2173                nextStatus = ir::ModifierFlags::ACCESSOR | ir::ModifierFlags::ASYNC | ir::ModifierFlags::READONLY;
2174                break;
2175            }
2176            default: {
2177                UNREACHABLE();
2178            }
2179        }
2180
2181        if (lexer_->Lookahead() == LEX_CHAR_COLON || lexer_->Lookahead() == LEX_CHAR_COMMA ||
2182            lexer_->Lookahead() == LEX_CHAR_RIGHT_PAREN || lexer_->Lookahead() == LEX_CHAR_QUESTION ||
2183            lexer_->Lookahead() == LEX_CHAR_RIGHT_BRACE || lexer_->Lookahead() == LEX_CHAR_LESS_THAN) {
2184            break;
2185        }
2186
2187        auto pos = lexer_->Save();
2188        lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);
2189
2190        if ((prevStatus & actualStatus) == 0) {
2191            lexer_->Rewind(pos);
2192            ThrowSyntaxError("Unexpected modifier");
2193        }
2194
2195        if ((resultStatus & actualStatus) != 0) {
2196            lexer_->Rewind(pos);
2197            ThrowSyntaxError("Duplicated modifier is not allowed");
2198        }
2199
2200        if ((context_.Status() & ParserStatus::CONSTRUCTOR_FUNCTION) &&
2201            (actualStatus & ~ir::ModifierFlags::ALLOWED_IN_CTOR_PARAMETER)) {
2202            lexer_->Rewind(pos);
2203            ThrowParameterModifierError(actualStatus);
2204        }
2205
2206        resultStatus |= actualStatus;
2207        prevStatus = nextStatus;
2208    }
2209
2210    return resultStatus;
2211}
2212
2213void ParserImpl::CheckAccessorPair(const ArenaVector<ir::Statement *> &properties, const ir::Expression *propName,
2214                                   ir::MethodDefinitionKind methodKind, ir::ModifierFlags access, bool hasDecorator,
2215                                   lexer::SourcePosition errorInfo)
2216{
2217    for (const auto &it : properties) {
2218        if (!it->IsMethodDefinition() || (!hasDecorator && it->AsMethodDefinition()->Kind() != methodKind)) {
2219            continue;
2220        }
2221
2222        const ir::Expression *key = it->AsMethodDefinition()->Key();
2223
2224        if (key->Type() != propName->Type()) {
2225            continue;
2226        }
2227
2228        bool keyIsSame = false;
2229
2230        if (key->IsIdentifier()) {
2231            const util::StringView &strName = propName->AsIdentifier()->Name();
2232            const util::StringView &compareName = (key->AsIdentifier()->Name());
2233
2234            keyIsSame = strName == compareName;
2235        } else if (key->IsNumberLiteral()) {
2236            keyIsSame = *key->AsNumberLiteral() == *propName->AsNumberLiteral();
2237        } else if (key->IsStringLiteral()) {
2238            keyIsSame = *key->AsStringLiteral() == *propName->AsStringLiteral();
2239        }
2240
2241        if (!keyIsSame) {
2242            continue;
2243        }
2244
2245        if (hasDecorator &&
2246            (it->AsMethodDefinition()->Kind() == ir::MethodDefinitionKind::GET ||
2247             it->AsMethodDefinition()->Kind() == ir::MethodDefinitionKind::SET) &&
2248            !it->AsMethodDefinition()->Decorators().empty()) {
2249            ThrowSyntaxError("Decorators cannot be applied to multiple get/set accessors of the same name.", errorInfo);
2250        }
2251
2252        if (it->AsMethodDefinition()->Kind() != methodKind) {
2253            continue;
2254        }
2255
2256        ir::ModifierFlags getAccess = ir::ModifierFlags::NONE;
2257        ir::ModifierFlags setAccess = ir::ModifierFlags::NONE;
2258
2259        if (methodKind == ir::MethodDefinitionKind::GET) {
2260            setAccess = access;
2261            getAccess = GetAccessability(it->AsMethodDefinition()->Modifiers());
2262        } else {
2263            getAccess = access;
2264            setAccess = GetAccessability(it->AsMethodDefinition()->Modifiers());
2265        }
2266
2267        if ((setAccess == ir::ModifierFlags::NONE && getAccess > ir::ModifierFlags::PUBLIC) ||
2268            (setAccess != ir::ModifierFlags::NONE && getAccess > setAccess)) {
2269            ThrowSyntaxError("A get accessor must be at least as accessible as the setter", key->Start());
2270        }
2271    }
2272}
2273
2274void ParserImpl::ParseClassKeyModifiers(ClassElmentDescriptor *desc)
2275{
2276    if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
2277        return;
2278    }
2279
2280    char32_t nextCp = lexer_->Lookahead();
2281
2282    if ((Extension() == ScriptExtension::JS && nextCp != LEX_CHAR_LEFT_PAREN) ||
2283        (Extension() == ScriptExtension::TS &&
2284        nextCp != LEX_CHAR_EQUALS && nextCp != LEX_CHAR_SEMICOLON && nextCp != LEX_CHAR_LEFT_PAREN &&
2285        nextCp != LEX_CHAR_LESS_THAN && nextCp != LEX_CHAR_QUESTION && nextCp != LEX_CHAR_COLON &&
2286        nextCp != LEX_CHAR_RIGHT_BRACE)) {
2287        if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_GET) {
2288            if (lexer_->GetToken().Flags() & lexer::TokenFlags::HAS_ESCAPE) {
2289                ThrowSyntaxError("Keyword must not contain escaped characters");
2290            }
2291
2292            desc->methodKind = ir::MethodDefinitionKind::GET;
2293            desc->methodStart = lexer_->GetToken().Start();
2294
2295            lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);
2296            CheckClassPrivateIdentifier(desc);
2297        } else if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_SET) {
2298            if (lexer_->GetToken().Flags() & lexer::TokenFlags::HAS_ESCAPE) {
2299                ThrowSyntaxError("Keyword must not contain escaped characters");
2300            }
2301
2302            desc->methodKind = ir::MethodDefinitionKind::SET;
2303            desc->methodStart = lexer_->GetToken().Start();
2304
2305            lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);
2306            CheckClassPrivateIdentifier(desc);
2307        }
2308    }
2309}
2310
2311void ParserImpl::ThrowIfPrivateIdent(ClassElmentDescriptor *desc, const char *msg)
2312{
2313    if (desc->isPrivateIdent) {
2314        ThrowSyntaxError(msg);
2315    }
2316}
2317
2318void ParserImpl::ValidateClassKey(ClassElmentDescriptor *desc, bool isDeclare)
2319{
2320    if ((desc->modifiers & ir::ModifierFlags::ASYNC) &&
2321        (desc->methodKind == ir::MethodDefinitionKind::GET || desc->methodKind == ir::MethodDefinitionKind::SET)) {
2322        ThrowSyntaxError("Async method can not be getter nor setter");
2323    }
2324
2325    if (desc->isPrivateIdent) {
2326        if (desc->modifiers & ir::ModifierFlags::ACCESS) {
2327            ThrowSyntaxError("An accessibility modifier cannot be used with a private identifier.");
2328        }
2329
2330        if (desc->modifiers & ir::ModifierFlags::DECLARE) {
2331            ThrowSyntaxError("'declare' modifier cannot be used with a private identifier.");
2332        }
2333
2334        if (desc->modifiers & ir::ModifierFlags::ABSTRACT) {
2335            ThrowSyntaxError("'abstract' modifier cannot be used with a private identifier.");
2336        }
2337    }
2338    //  Check private properties in another method: ParsePrivateIdentifier()
2339    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_HASH_MARK) {
2340        return;
2341    }
2342
2343    const util::StringView &propNameStr = lexer_->GetToken().Ident();
2344
2345    if (propNameStr.Is("constructor")) {
2346        ThrowIfPrivateIdent(desc, "Private identifier can not be constructor");
2347
2348        if (!(desc->modifiers & ir::ModifierFlags::STATIC)) {
2349            if ((desc->modifiers & ir::ModifierFlags::ASYNC) || desc->methodKind == ir::MethodDefinitionKind::GET ||
2350                desc->methodKind == ir::MethodDefinitionKind::SET || desc->isGenerator) {
2351                ThrowSyntaxError("Constructor can not be special method");
2352            }
2353
2354            desc->methodKind = ir::MethodDefinitionKind::CONSTRUCTOR;
2355            desc->methodStart = lexer_->GetToken().Start();
2356            desc->newStatus |= ParserStatus::CONSTRUCTOR_FUNCTION;
2357
2358            if (desc->hasSuperClass) {
2359                desc->newStatus |= ParserStatus::ALLOW_SUPER_CALL;
2360            }
2361        } else if (Extension() == ScriptExtension::TS) {
2362            ThrowSyntaxError("Static modifier can not appear on a constructor");
2363        }
2364    } else if (!isDeclare && propNameStr.Is("prototype") && (desc->modifiers & ir::ModifierFlags::STATIC)) {
2365        ThrowSyntaxError("Classes may not have static property named prototype");
2366    }
2367}
2368
2369ir::Expression *ParserImpl::ParseClassKey(ClassElmentDescriptor *desc, bool isDeclare)
2370{
2371    if (desc->isPrivateIdent && program_.TargetApiVersion() > 10) {
2372        ValidateClassKey(desc, isDeclare);
2373        return ParsePrivateIdentifier();
2374    }
2375
2376    ir::Expression *propName = nullptr;
2377    if (lexer_->GetToken().IsKeyword()) {
2378        lexer_->GetToken().SetTokenType(lexer::TokenType::LITERAL_IDENT);
2379    }
2380
2381    switch (lexer_->GetToken().Type()) {
2382        case lexer::TokenType::LITERAL_IDENT: {
2383            ValidateClassKey(desc, isDeclare);
2384
2385            propName = AllocNode<ir::Identifier>(lexer_->GetToken().Ident());
2386            propName->SetRange(lexer_->GetToken().Loc());
2387            break;
2388        }
2389        case lexer::TokenType::LITERAL_STRING: {
2390            ValidateClassKey(desc, isDeclare);
2391            ThrowIfPrivateIdent(desc, "Private identifier name can not be string");
2392            propName = AllocNode<ir::StringLiteral>(lexer_->GetToken().String());
2393            propName->SetRange(lexer_->GetToken().Loc());
2394            break;
2395        }
2396        case lexer::TokenType::LITERAL_NUMBER: {
2397            ThrowIfPrivateIdent(desc, "Private identifier name can not be number");
2398            if (lexer_->GetToken().Flags() & lexer::TokenFlags::NUMBER_BIGINT) {
2399                propName = AllocNode<ir::BigIntLiteral>(lexer_->GetToken().BigInt());
2400            } else {
2401                propName = AllocNode<ir::NumberLiteral>(lexer_->GetToken().Number(), lexer_->GetToken().String());
2402            }
2403
2404            propName->SetRange(lexer_->GetToken().Loc());
2405            break;
2406        }
2407        case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET: {
2408            ThrowIfPrivateIdent(desc, "Unexpected character in private identifier");
2409            lexer_->NextToken();  // eat left square bracket
2410
2411            if (Extension() == ScriptExtension::TS && lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT &&
2412                lexer_->Lookahead() == LEX_CHAR_COLON) {
2413                desc->isIndexSignature = true;
2414
2415                propName = AllocNode<ir::Identifier>(lexer_->GetToken().Ident());
2416                propName->SetRange(lexer_->GetToken().Loc());
2417
2418                lexer_->NextToken();  // eat param
2419
2420                if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COLON) {
2421                    ThrowSyntaxError("':' expected");
2422                }
2423
2424                lexer_->NextToken();  // eat ':'
2425                TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
2426                ir::Expression *typeAnnotation = ParseTsTypeAnnotation(&options);
2427
2428                ValidateIndexSignatureParameterType(typeAnnotation);
2429
2430                propName->SetTsTypeAnnotation(typeAnnotation);
2431
2432                if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
2433                    ThrowSyntaxError("']' expected");
2434                }
2435
2436                lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);
2437
2438                return propName;
2439            }
2440
2441            desc->isComputed = true;
2442
2443            propName = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
2444
2445            if (Extension() == ScriptExtension::TS) {
2446                // TODO(songqi): Determine whether MemberExpression is a symbol during type check.
2447                desc->invalidComputedProperty = !propName->IsNumberLiteral() &&
2448                    util::Helpers::GetSignedNumberLiteral(propName) == util::SignedNumberLiteral::UNRECOGNIZED &&
2449                    !propName->IsStringLiteral() && !propName->IsMemberExpression() && !propName->IsIdentifier();
2450            }
2451
2452            if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
2453                ThrowSyntaxError("Unexpected token, expected ']'");
2454            }
2455            break;
2456        }
2457        default: {
2458            ThrowSyntaxError("Unexpected token in class property");
2459        }
2460    }
2461
2462    lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);
2463
2464    return propName;
2465}
2466
2467void ParserImpl::ValidateClassMethodStart(ClassElmentDescriptor *desc, ir::Expression *typeAnnotation)
2468{
2469    if (Extension() == ScriptExtension::JS) {
2470        if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
2471            return;
2472        }
2473        desc->classMethod = true;
2474    }
2475
2476    if (Extension() == ScriptExtension::TS) {
2477        if (!typeAnnotation && (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS ||
2478                                lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN)) {
2479            if ((desc->modifiers & (ir::ModifierFlags::DECLARE | ir::ModifierFlags::READONLY))) {
2480                ThrowSyntaxError("Class method can not be declare nor readonly");
2481            }
2482            desc->classMethod = true;
2483        } else {
2484            if ((desc->modifiers & ir::ModifierFlags::ASYNC) || desc->isGenerator) {
2485                ThrowSyntaxError("Expected '('");
2486            }
2487            desc->classField = true;
2488
2489            if (desc->invalidComputedProperty) {
2490                ThrowSyntaxError(
2491                    "Computed property name must refer to a symbol or "
2492                    "literal expression whos value is "
2493                    "number or string");
2494            }
2495        }
2496    }
2497
2498    if (desc->modifiers & ir::ModifierFlags::ASYNC) {
2499        desc->newStatus |= ParserStatus::ASYNC_FUNCTION;
2500    }
2501
2502    if (desc->isGenerator) {
2503        desc->newStatus |= ParserStatus::GENERATOR_FUNCTION;
2504    }
2505}
2506
2507void ParserImpl::ValidateClassSetter(ClassElmentDescriptor *desc, const ArenaVector<ir::Statement *> &properties,
2508                                     ir::Expression *propName, ir::ScriptFunction *func, bool hasDecorator,
2509                                     lexer::SourcePosition errorInfo)
2510{
2511    if (func->Params().size() != 1) {
2512        ThrowSyntaxError("Setter must have exactly one formal parameter");
2513    }
2514
2515    if (Extension() == ScriptExtension::TS && !(desc->modifiers & ir::ModifierFlags::STATIC)) {
2516        ir::ModifierFlags access = GetAccessability(desc->modifiers);
2517        CheckAccessorPair(properties, propName, ir::MethodDefinitionKind::GET, access, hasDecorator, errorInfo);
2518    }
2519}
2520
2521void ParserImpl::ValidateClassGetter(ClassElmentDescriptor *desc, const ArenaVector<ir::Statement *> &properties,
2522                                     ir::Expression *propName, ir::ScriptFunction *func, bool hasDecorator,
2523                                     lexer::SourcePosition errorInfo)
2524{
2525    if (!func->Params().empty()) {
2526        ThrowSyntaxError("Getter must not have formal parameters");
2527    }
2528
2529    if (Extension() == ScriptExtension::TS && !(desc->modifiers & ir::ModifierFlags::STATIC)) {
2530        ir::ModifierFlags access = GetAccessability(desc->modifiers);
2531
2532        CheckAccessorPair(properties, propName, ir::MethodDefinitionKind::SET, access, hasDecorator, errorInfo);
2533    }
2534}
2535
2536void ParserImpl::ValidatePrivateProperty(ir::Statement *stmt, std::unordered_set<util::StringView> &usedPrivateNames,
2537    std::unordered_map<util::StringView, PrivateGetterSetterType> &unusedGetterSetterPairs)
2538{
2539    if (stmt->IsClassProperty()) {
2540        auto *prop = stmt->AsClassProperty();
2541        if (!prop->IsPrivate()) {
2542            return;
2543        }
2544        auto name = prop->Key()->AsPrivateIdentifier()->Name();
2545        if (usedPrivateNames.find(name) != usedPrivateNames.end()) {
2546            ThrowSyntaxError({"Redeclaration of class private property #", name.Utf8()}, prop->Start());
2547        }
2548        usedPrivateNames.insert(name);
2549        return;
2550    }
2551
2552    if (stmt->IsMethodDefinition()) {
2553        auto *methodDef = stmt->AsMethodDefinition();
2554        if (!methodDef->IsPrivate()) {
2555            return;
2556        }
2557        auto name = methodDef->Key()->AsPrivateIdentifier()->Name();
2558
2559        if (methodDef->Kind() == ir::MethodDefinitionKind::METHOD) {
2560            if (usedPrivateNames.find(name) != usedPrivateNames.end()) {
2561                ThrowSyntaxError({"Redeclaration of class private property #", name.Utf8()}, methodDef->Start());
2562            }
2563            usedPrivateNames.insert(name);
2564            return;
2565        }
2566
2567        ASSERT(methodDef->Kind() != ir::MethodDefinitionKind::CONSTRUCTOR);
2568        PrivateGetterSetterType type = (methodDef->Kind() == ir::MethodDefinitionKind::GET) ?
2569                                       PrivateGetterSetterType::GETTER : PrivateGetterSetterType::SETTER;
2570        PrivateGetterSetterType unusedType = (methodDef->Kind() == ir::MethodDefinitionKind::GET) ?
2571                                             PrivateGetterSetterType::SETTER : PrivateGetterSetterType::GETTER;
2572
2573        if (methodDef->IsStatic()) {
2574            type |= PrivateGetterSetterType::STATIC;
2575            unusedType |= PrivateGetterSetterType::STATIC;
2576        }
2577
2578        auto insertRet = usedPrivateNames.insert(name);
2579        if (insertRet.second) {
2580            unusedGetterSetterPairs[name] = unusedType;
2581            return;
2582        }
2583
2584        auto result = unusedGetterSetterPairs.find(name);
2585        if (result == unusedGetterSetterPairs.end() || unusedGetterSetterPairs[name] != type) {
2586            ThrowSyntaxError({"Redeclaration of class private property #", name.Utf8()}, methodDef->Start());
2587        }
2588        unusedGetterSetterPairs.erase(result);
2589    }
2590}
2591
2592ir::MethodDefinition *ParserImpl::ParseClassMethod(ClassElmentDescriptor *desc,
2593                                                   const ArenaVector<ir::Statement *> &properties,
2594                                                   ir::Expression *propName, lexer::SourcePosition *propEnd,
2595                                                   ArenaVector<ir::Decorator *> &&decorators,
2596                                                   ArenaVector<ir::Annotation *> &&annotations, bool isDeclare)
2597{
2598    if (Extension() == ScriptExtension::TS) {
2599        if (desc->methodKind == ir::MethodDefinitionKind::SET || desc->methodKind == ir::MethodDefinitionKind::GET) {
2600            desc->newStatus |= ParserStatus::ACCESSOR_FUNCTION;
2601        }
2602
2603        desc->newStatus |= ParserStatus::IN_METHOD_DEFINITION;
2604    }
2605
2606    if (isDeclare && (desc->newStatus & ParserStatus::ASYNC_FUNCTION)) {
2607        ThrowSyntaxError("'async' modifier cannot be used in an ambient context.");
2608    }
2609
2610    if (isDeclare && desc->isGenerator) {
2611        ThrowSyntaxError("Generators are not allowed in an ambient context.");
2612    }
2613
2614    ArenaVector<ir::ParamDecorators> paramDecorators(Allocator()->Adapter());
2615    ir::ScriptFunction *func = ParseFunction(desc->newStatus, isDeclare, &paramDecorators);
2616    if (func->Body() != nullptr) {
2617        lexer_->NextToken();
2618    }
2619
2620    if (func->IsOverload() && !decorators.empty()) {
2621        ThrowSyntaxError("A decorator can only decorate a method implementation, not an overload.",
2622                         decorators.front()->Start());
2623    }
2624
2625    auto *funcExpr = AllocNode<ir::FunctionExpression>(func);
2626    funcExpr->SetRange(func->Range());
2627
2628    lexer::SourcePosition errorInfo = decorators.empty() ? func->Start() : decorators[0]->Start();
2629
2630    if (desc->methodKind == ir::MethodDefinitionKind::SET) {
2631        ValidateClassSetter(desc, properties, propName, func, !decorators.empty(), errorInfo);
2632    } else if (desc->methodKind == ir::MethodDefinitionKind::GET) {
2633        ValidateClassGetter(desc, properties, propName, func, !decorators.empty(), errorInfo);
2634    }
2635
2636    *propEnd = func->End();
2637    func->AddFlag(ir::ScriptFunctionFlags::METHOD);
2638
2639    ir::MethodDefinition *method = nullptr;
2640
2641    if (desc->isPrivateIdent && Extension() == ScriptExtension::TS && program_.TargetApiVersion() <= 10) {
2642        ir::Expression *privateId = AllocNode<ir::TSPrivateIdentifier>(propName, nullptr, nullptr);
2643        auto privateIdStart = lexer::SourcePosition(propName->Start().index - 1, propName->Start().line);
2644        privateId->SetRange({privateIdStart, propName->End()});
2645        method = AllocNode<ir::MethodDefinition>(desc->methodKind, privateId, funcExpr, desc->modifiers, Allocator(),
2646                                                 std::move(decorators), std::move(annotations),
2647                                                 std::move(paramDecorators), desc->isComputed);
2648        method->SetRange(funcExpr->Range());
2649        return method;
2650    }
2651
2652    method = AllocNode<ir::MethodDefinition>(desc->methodKind, propName, funcExpr, desc->modifiers, Allocator(),
2653                                             std::move(decorators), std::move(annotations), std::move(paramDecorators),
2654                                             desc->isComputed);
2655    method->SetRange(funcExpr->Range());
2656    return method;
2657}
2658
2659ir::ClassStaticBlock *ParserImpl::ParseStaticBlock(ClassElmentDescriptor *desc)
2660{
2661    SavedParserContext ctx(this, desc->newStatus | ParserStatus::ALLOW_NEW_TARGET | ParserStatus::STATIC_BLOCK |
2662                           ParserStatus::DISALLOW_ARGUMENTS);
2663    context_.Status() &= ~ParserStatus::FUNCTION;
2664    auto lexScope = binder::LexicalScope<binder::StaticBlockScope>(Binder());
2665    auto *blockStatement = ParseBlockStatement();
2666    auto *staticBlock = AllocNode<ir::ClassStaticBlock>(lexScope.GetScope(), blockStatement);
2667    staticBlock->SetRange({desc->propStart, blockStatement->End()});
2668    lexScope.GetScope()->BindNode(staticBlock);
2669    return staticBlock;
2670}
2671
2672ir::Statement *ParserImpl::ParseClassProperty(ClassElmentDescriptor *desc,
2673    const ArenaVector<ir::Statement *> &properties, ir::Expression *propName, ir::Expression *typeAnnotation,
2674    ArenaVector<ir::Decorator *> &&decorators, ArenaVector<ir::Annotation *> &&annotations, bool isDeclare,
2675    std::pair<binder::FunctionScope *, binder::FunctionScope *> implicitScopes)
2676{
2677    lexer::SourcePosition propEnd = propName->End();
2678    ir::Statement *property = nullptr;
2679
2680    if (desc->classMethod) {
2681        property = ParseClassMethod(desc, properties, propName, &propEnd, std::move(decorators),
2682                                    std::move(annotations), isDeclare);
2683        property->SetRange({desc->propStart, propEnd});
2684        return property;
2685    }
2686
2687    if (!annotations.empty()) {
2688        ThrowSyntaxError("Annotations can not be used with class properties", annotations.front()->Start());
2689    }
2690
2691    if (!desc->isComputed) {
2692        CheckFieldKey(propName);
2693    }
2694
2695    ir::Expression *value = nullptr;
2696
2697    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
2698        if (Extension() == ScriptExtension::TS && (desc->modifiers & ir::ModifierFlags::ABSTRACT)) {
2699            ThrowSyntaxError("Property cannot have an initializer because it is marked abstract.");
2700        }
2701        context_.Status() |= (ParserStatus::ALLOW_SUPER | ParserStatus::DISALLOW_ARGUMENTS);
2702        lexer_->NextToken();  // eat equals
2703
2704        if (isDeclare) {
2705            ThrowSyntaxError("Initializers are not allowed in ambient contexts.");
2706        }
2707
2708        auto *scope = ((desc->modifiers & ir::ModifierFlags::STATIC) != 0) ? implicitScopes.first :
2709                                                                             implicitScopes.second;
2710        auto scopeCtx = binder::LexicalScope<binder::FunctionScope>::Enter(Binder(), scope);
2711        value = ParseExpression();
2712        context_.Status() &= ~(ParserStatus::ALLOW_SUPER | ParserStatus::DISALLOW_ARGUMENTS);
2713        propEnd = value->End();
2714    }
2715
2716    if (Extension() == ScriptExtension::TS && desc->isPrivateIdent && program_.TargetApiVersion() <= 10) {
2717        auto *privateId = AllocNode<ir::TSPrivateIdentifier>(propName, value, typeAnnotation);
2718        auto privateIdStart = lexer::SourcePosition(propName->Start().index - 1, propName->Start().line);
2719        privateId->SetRange({privateIdStart, propName->End()});
2720        propName = privateId;
2721    }
2722
2723    property = AllocNode<ir::ClassProperty>(propName, value, typeAnnotation,
2724                                            desc->modifiers, std::move(decorators), desc->isComputed,
2725                                            desc->modifiers & ir::ModifierFlags::DEFINITE);
2726
2727    property->SetRange({desc->propStart, propEnd});
2728    return property;
2729}
2730
2731void ParserImpl::CheckClassGeneratorMethod(ClassElmentDescriptor *desc)
2732{
2733    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_MULTIPLY) {
2734        return;
2735    }
2736
2737    desc->isGenerator = true;
2738    lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);
2739}
2740
2741void ParserImpl::CheckClassPrivateIdentifier(ClassElmentDescriptor *desc)
2742{
2743    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_HASH_MARK) {
2744        return;
2745    }
2746
2747    if (Extension() == ScriptExtension::AS) {
2748        return;
2749    }
2750
2751    desc->isPrivateIdent = true;
2752
2753    if (Extension() == ScriptExtension::TS && program_.TargetApiVersion() <= 10) {
2754        lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);
2755    }
2756}
2757
2758void ParserImpl::CheckFieldKey(ir::Expression *propName)
2759{
2760    if (propName->IsNumberLiteral() || propName->IsBigIntLiteral()) {
2761        return;
2762    }
2763
2764    ASSERT(propName->IsIdentifier() || propName->IsStringLiteral() || propName->IsPrivateIdentifier());
2765    const util::StringView &stringView = propName->IsIdentifier() ? propName->AsIdentifier()->Name() :
2766        (propName->IsStringLiteral() ? propName->AsStringLiteral()->Str() : propName->AsPrivateIdentifier()->Name());
2767    if (stringView.Is("constructor")) {
2768        ThrowSyntaxError("Classes may not have field named 'constructor'");
2769    }
2770}
2771
2772ir::Expression *ParserImpl::ParseClassKeyAnnotation()
2773{
2774    if (Extension() == ScriptExtension::TS && lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
2775        lexer_->NextToken();  // eat ':'
2776        TypeAnnotationParsingOptions options =
2777            TypeAnnotationParsingOptions::THROW_ERROR | TypeAnnotationParsingOptions::BREAK_AT_NEW_LINE;
2778        return ParseTsTypeAnnotation(&options);
2779    }
2780
2781    return nullptr;
2782}
2783
2784ir::Statement *ParserImpl::ParseDecoratorAndAnnotation()
2785{
2786    ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_AT);
2787
2788    auto lexPos = lexer_->Save();
2789    lexer::SourcePosition start = lexer_->GetToken().Start();
2790    lexer_->NextToken();  // eat '@'
2791
2792    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_HASH_MARK) {
2793        // Annotation usage case
2794        if (!program_.IsEnableAnnotations()) {
2795            ThrowSyntaxError("Annotations are not enabled");
2796        }
2797        lexer_->NextToken();  // eat '#'
2798        ir::Expression *expr = ParseLeftHandSideExpression();
2799        ir::Statement *resultAnnotation = static_cast<ir::Statement *>(AllocNode<ir::Annotation>(expr));
2800        resultAnnotation->SetRange({start, expr->End()});
2801        return resultAnnotation;
2802    }
2803
2804    ir::Expression *expr = ParseLeftHandSideExpression();
2805    if (expr->IsIdentifier() && expr->AsIdentifier()->Name().Utf8() == ir::Annotation::interfaceString) {
2806        // Annotation declaration case
2807        if (!program_.IsEnableAnnotations()) {
2808            ThrowSyntaxError("Annotations are not enabled");
2809        }
2810        lexer_->Rewind(lexPos);
2811        return nullptr;
2812    }
2813
2814    // Decorator case
2815    ir::Statement *resultDecorator = static_cast<ir::Statement *>(AllocNode<ir::Decorator>(expr));
2816    resultDecorator->SetRange({start, expr->End()});
2817    return resultDecorator;
2818}
2819
2820std::pair<ArenaVector<ir::Decorator *>, ArenaVector<ir::Annotation *>> ParserImpl::ParseDecoratorsAndAnnotations()
2821{
2822    ArenaVector<ir::Decorator *> decorators(Allocator()->Adapter());
2823    ArenaVector<ir::Annotation *> annotations(Allocator()->Adapter());
2824    auto savedStatus = context_.Status();
2825    context_.Status() |= ParserStatus::IN_DECORATOR;
2826
2827    while (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_AT) {
2828        ir::Statement *stmt = ParseDecoratorAndAnnotation();
2829        if (stmt == nullptr) {
2830            // Annotation declaration was encountered and will be processed further in ParseClassDeclaration
2831            context_.Status() = savedStatus;
2832            return {decorators, annotations};
2833        }
2834        if (stmt->IsDecorator()) {
2835            decorators.push_back(stmt->AsDecorator());
2836        } else {
2837            annotations.push_back(stmt->AsAnnotation());
2838        }
2839    }
2840
2841    if (!decorators.empty() && lexer_->GetToken().Type() != lexer::TokenType::KEYW_CLASS &&
2842        (context_.Status() & ParserStatus::IN_CLASS_BODY) == 0 &&
2843        lexer_->GetToken().Type() != lexer::TokenType::KEYW_EXPORT &&
2844        !(lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT &&
2845          (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_DECLARE ||
2846           lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_ABSTRACT))) {
2847        ThrowSyntaxError("Decorators are not valid here.", decorators.front()->Start());
2848    }
2849
2850    context_.Status() = savedStatus;
2851    return {decorators, annotations};
2852}
2853
2854ir::Statement *ParserImpl::ParseClassElement(const ArenaVector<ir::Statement *> &properties,
2855    ArenaVector<ir::TSIndexSignature *> *indexSignatures, bool hasSuperClass, bool isDeclare, bool isAbstractClass,
2856    bool isExtendsFromNull, std::pair<binder::FunctionScope *, binder::FunctionScope *> implicitScopes)
2857{
2858    ClassElmentDescriptor desc;
2859
2860    desc.methodKind = ir::MethodDefinitionKind::METHOD;
2861    desc.newStatus = ParserStatus::ALLOW_SUPER;
2862    desc.hasSuperClass = hasSuperClass;
2863    desc.propStart = lexer_->GetToken().Start();
2864
2865    auto decoratorsAndAnnotations = ParseDecoratorsAndAnnotations();
2866    auto decorators = decoratorsAndAnnotations.first;
2867    auto annotations = decoratorsAndAnnotations.second;
2868
2869    desc.modifiers = ParseModifiers();
2870
2871    if ((desc.modifiers & ir::ModifierFlags::ABSTRACT) && !isAbstractClass) {
2872        ThrowSyntaxError("Abstract methods can only appear within an abstract class.");
2873    }
2874    if (!decorators.empty() && (desc.modifiers & ir::ModifierFlags::ACCESSOR)) {
2875        ThrowSyntaxError("Decorators are not available for auto accessor property now.");
2876    }
2877
2878    if ((desc.modifiers & ir::ModifierFlags::OVERRIDE) && (!desc.hasSuperClass || isExtendsFromNull)) {
2879        ThrowSyntaxError({"This member cannot have an 'override' modifier because its containing class "
2880                          "does not extend another class."});
2881    }
2882
2883    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
2884        if (!(desc.modifiers == ir::ModifierFlags::STATIC)) {
2885            ThrowSyntaxError("Unexpected token '{'");
2886        }
2887
2888        if (!decorators.empty()) {
2889            ThrowSyntaxError("Decorators are not valid here.", decorators.front()->Start());
2890        }
2891        auto scopeCtx = binder::LexicalScope<binder::FunctionScope>::Enter(Binder(), implicitScopes.first);
2892        return ParseStaticBlock(&desc);
2893    }
2894
2895    CheckClassGeneratorMethod(&desc);
2896    ParseClassKeyModifiers(&desc);
2897    CheckClassPrivateIdentifier(&desc);
2898
2899    if (desc.isPrivateIdent && !decorators.empty()) {
2900        ThrowSyntaxError("Decorators are not valid here.", decorators.front()->Start());
2901    }
2902
2903    if (!(desc.modifiers & ir::ModifierFlags::STATIC)) {
2904        context_.Status() |= ParserStatus::ALLOW_THIS_TYPE;
2905    }
2906
2907    ir::Expression *propName = ParseClassKey(&desc, isDeclare);
2908
2909    if (desc.methodKind == ir::MethodDefinitionKind::CONSTRUCTOR && !decorators.empty()) {
2910        ThrowSyntaxError("Decorators are not valid here.", decorators.front()->Start());
2911    }
2912
2913    if (Extension() == ScriptExtension::TS && lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_QUESTION_MARK) {
2914        if (desc.isIndexSignature) {
2915            ThrowSyntaxError("';' expected");
2916        }
2917
2918        if (desc.methodKind == ir::MethodDefinitionKind::CONSTRUCTOR) {
2919            ThrowSyntaxError("'(' expected");
2920        }
2921
2922        if (desc.modifiers & ir::ModifierFlags::ACCESSOR) {
2923            ThrowSyntaxError("An auto accessor property can't be declared optional.");
2924        }
2925
2926        desc.modifiers |= ir::ModifierFlags::OPTIONAL;
2927        lexer_->NextToken();
2928    } else if (Extension() == ScriptExtension::TS &&
2929               lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_EXCLAMATION_MARK) {
2930        if (desc.isIndexSignature || lexer_->Lookahead() != LEX_CHAR_COLON) {
2931            ThrowSyntaxError("';' expected");
2932        }
2933
2934        desc.modifiers |= ir::ModifierFlags::DEFINITE;
2935        lexer_->NextToken();
2936    }
2937
2938    ir::Expression *typeAnnotation = ParseClassKeyAnnotation();
2939
2940    ir::Statement *property = nullptr;
2941    if (desc.isIndexSignature) {
2942        if (!decorators.empty()) {
2943            ThrowSyntaxError("Decorators are not valid here.", decorators.front()->Start());
2944        }
2945
2946        if (!typeAnnotation) {
2947            ThrowSyntaxError("An index signature must have a type annotation");
2948        }
2949
2950        auto *indexSignature =
2951            AllocNode<ir::TSIndexSignature>(propName, typeAnnotation, desc.modifiers & ir::ModifierFlags::READONLY,
2952                                            desc.modifiers & ir::ModifierFlags::STATIC);
2953
2954        indexSignature->SetRange({desc.propStart, indexSignature->TypeAnnotation()->End()});
2955
2956        indexSignatures->push_back(indexSignature);
2957
2958        property = AllocNode<ir::EmptyStatement>();
2959    } else {
2960        ValidateClassMethodStart(&desc, typeAnnotation);
2961        property = ParseClassProperty(&desc, properties, propName, typeAnnotation, std::move(decorators),
2962                                      std::move(annotations), isDeclare ||
2963                                      (desc.modifiers & ir::ModifierFlags::DECLARE), implicitScopes);
2964    }
2965
2966    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON &&
2967        lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE &&
2968        !(lexer_->GetToken().Flags() & lexer::TokenFlags::NEW_LINE) &&
2969        !(property->IsMethodDefinition() && property->AsMethodDefinition()->Value()->Function()->Body())) {
2970        ThrowSyntaxError("';' expected.");
2971    }
2972
2973    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
2974        lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);
2975    }
2976
2977    context_.Status() &= ~ParserStatus::ALLOW_THIS_TYPE;
2978
2979    return property;
2980}
2981
2982static bool IsConstructor(ir::Statement *stmt)
2983{
2984    if (!stmt->IsMethodDefinition()) {
2985        return false;
2986    }
2987
2988    ir::MethodDefinition *def = stmt->AsMethodDefinition();
2989    return def->Kind() == ir::MethodDefinitionKind::CONSTRUCTOR;
2990}
2991
2992ir::Identifier *ParserImpl::GetKeyByFuncFlag(ir::ScriptFunctionFlags funcFlag)
2993{
2994    ir::Identifier *key = nullptr;
2995    switch (funcFlag) {
2996        case ir::ScriptFunctionFlags::CONSTRUCTOR: {
2997            key = AllocNode<ir::Identifier>("constructor");
2998            break;
2999        }
3000        case ir::ScriptFunctionFlags::STATIC_INITIALIZER: {
3001            key = AllocNode<ir::Identifier>("static_initializer");
3002            break;
3003        }
3004        case ir::ScriptFunctionFlags::INSTANCE_INITIALIZER: {
3005            key = AllocNode<ir::Identifier>("instance_initializer");
3006            break;
3007        }
3008        default: {
3009            UNREACHABLE();
3010        }
3011    }
3012    return key;
3013}
3014
3015ir::MethodDefinition *ParserImpl::CreateImplicitMethod(ir::Expression *superClass, bool hasSuperClass,
3016                                                       ir::ScriptFunctionFlags funcFlag, bool isDeclare)
3017{
3018    ArenaVector<ir::Expression *> params(Allocator()->Adapter());
3019    ArenaVector<ir::Statement *> statements(Allocator()->Adapter());
3020
3021    auto *paramScope = Binder()->Allocator()->New<binder::FunctionParamScope>(Allocator(), Binder()->GetScope());
3022    auto *scope = Binder()->Allocator()->New<binder::FunctionScope>(Allocator(), paramScope);
3023    CHECK_NOT_NULL(scope);
3024    CHECK_NOT_NULL(paramScope);
3025
3026    bool isConstructor = (funcFlag == ir::ScriptFunctionFlags::CONSTRUCTOR);
3027    if (isConstructor && hasSuperClass) {
3028        if (Extension() != ScriptExtension::TS || !superClass->IsNullLiteral()) {
3029            util::StringView argsStr = "args";
3030            params.push_back(AllocNode<ir::SpreadElement>(ir::AstNodeType::REST_ELEMENT,
3031                                                          AllocNode<ir::Identifier>(argsStr)));
3032            paramScope->AddParamDecl(Allocator(), params.back());
3033
3034            ArenaVector<ir::Expression *> callArgs(Allocator()->Adapter());
3035            auto *superExpr = AllocNode<ir::SuperExpression>();
3036            callArgs.push_back(AllocNode<ir::SpreadElement>(ir::AstNodeType::SPREAD_ELEMENT,
3037                                                            AllocNode<ir::Identifier>(argsStr)));
3038
3039            auto *callExpr = AllocNode<ir::CallExpression>(superExpr, std::move(callArgs), nullptr, false);
3040            statements.push_back(AllocNode<ir::ExpressionStatement>(callExpr));
3041        }
3042    }
3043
3044    auto *body = AllocNode<ir::BlockStatement>(scope, std::move(statements));
3045    auto *func = AllocNode<ir::ScriptFunction>(scope, std::move(params), nullptr, isDeclare ? nullptr : body, nullptr,
3046                                               funcFlag, isDeclare, Extension() == ScriptExtension::TS);
3047    if (isConstructor) {
3048        func->AddFlag(ir::ScriptFunctionFlags::GENERATED_CONSTRUCTOR);
3049    }
3050    scope->BindNode(func);
3051    paramScope->BindNode(func);
3052    scope->BindParamScope(paramScope);
3053    paramScope->BindFunctionScope(scope);
3054
3055    auto *funcExpr = AllocNode<ir::FunctionExpression>(func);
3056    ir::Identifier *key = GetKeyByFuncFlag(funcFlag);
3057    auto methodKind = isConstructor ? ir::MethodDefinitionKind::CONSTRUCTOR : ir::MethodDefinitionKind::METHOD;
3058
3059    ArenaVector<ir::Decorator *> decorators(Allocator()->Adapter());
3060    ArenaVector<ir::Annotation *> annotations(Allocator()->Adapter());
3061    ArenaVector<ir::ParamDecorators> paramDecorators(Allocator()->Adapter());
3062    auto *method = AllocNode<ir::MethodDefinition>(methodKind, key, funcExpr,
3063                                                 ir::ModifierFlags::NONE, Allocator(), std::move(decorators),
3064                                                 std::move(annotations), std::move(paramDecorators), false);
3065
3066    return method;
3067}
3068
3069bool ParserImpl::IsPropertyKeysAreSame(const ir::Expression *exp1, const ir::Expression *exp2)
3070{
3071    if (exp1->IsIdentifier() && exp2->IsIdentifier()) {
3072        return exp1->AsIdentifier()->Name() == exp2->AsIdentifier()->Name();
3073    }
3074
3075    if (exp1->IsIdentifier() && exp2->IsStringLiteral()) {
3076        return exp1->AsIdentifier()->Name() == exp2->AsStringLiteral()->Str();
3077    }
3078
3079    if (exp1->IsStringLiteral() && exp2->IsStringLiteral()) {
3080        return *exp1->AsStringLiteral() == *exp2->AsStringLiteral();
3081    }
3082
3083    if (exp1->IsStringLiteral() && exp2->IsIdentifier()) {
3084        return exp1->AsStringLiteral()->Str() == exp2->AsIdentifier()->Name();
3085    }
3086
3087    if (exp1->IsStringLiteral() && exp2->IsNumberLiteral()) {
3088        std::string exp2String = std::to_string(exp2->AsNumberLiteral()->Number<double>());
3089        exp2String.erase(exp2String.find_last_not_of('0'), std::string::npos);
3090        return exp1->AsStringLiteral()->Str().Utf8() == exp2String;
3091    }
3092
3093    if (exp1->IsNumberLiteral() && exp2->IsNumberLiteral()) {
3094        return exp1->AsNumberLiteral()->Number<double>() == exp2->AsNumberLiteral()->Number<double>();
3095    }
3096
3097    if (exp1->IsNumberLiteral() && exp2->IsStringLiteral()) {
3098        std::string exp1String = std::to_string(exp1->AsNumberLiteral()->Number<double>());
3099        exp1String.erase(exp1String.find_last_not_of('0'), std::string::npos);
3100        return exp1String == exp2->AsStringLiteral()->Str().Utf8();
3101    }
3102
3103    return false;
3104}
3105
3106bool ParserImpl::IsMemberExpressionsAreSame(const ir::MemberExpression *mExp1, const ir::MemberExpression *mExp2)
3107{
3108    if (!IsPropertyKeysAreSame(mExp1->Property(), mExp2->Property())) {
3109        return false;
3110    }
3111
3112    if (mExp1->Object()->IsMemberExpression() && mExp2->Object()->IsMemberExpression()) {
3113        return IsMemberExpressionsAreSame(mExp1->Object()->AsMemberExpression(), mExp2->Object()->AsMemberExpression());
3114    }
3115
3116    return IsPropertyKeysAreSame(mExp1->Object(), mExp2->Object());
3117}
3118
3119bool ParserImpl::IsMethodDefinitionsAreSame(const ir::MethodDefinition *property, ir::MethodDefinition *overload)
3120{
3121    if (property->Kind() != overload->Kind() || property->IsStatic() != overload->IsStatic()) {
3122        return false;
3123    }
3124
3125    if (property->Key()->IsMemberExpression() && overload->Key()->IsMemberExpression()) {
3126        return IsMemberExpressionsAreSame(property->Key()->AsMemberExpression(), overload->Key()->AsMemberExpression());
3127    }
3128
3129    return IsPropertyKeysAreSame(property->Key(), overload->Key());
3130}
3131
3132ir::Identifier *ParserImpl::SetIdentNodeInClassDefinition(bool isDeclare, binder::ConstDecl **decl)
3133{
3134    if (!isDeclare) {
3135        CheckStrictReservedWord();
3136    }
3137
3138    const util::StringView &identStr = lexer_->GetToken().Ident();
3139
3140    *decl = Binder()->AddDecl<binder::ConstDecl>(lexer_->GetToken().Start(), isDeclare, identStr);
3141
3142    auto *identNode = AllocNode<ir::Identifier>(identStr);
3143    identNode->SetRange(lexer_->GetToken().Loc());
3144
3145    lexer_->NextToken();
3146
3147    return identNode;
3148}
3149
3150ir::ClassDefinition *ParserImpl::ParseClassDefinition(bool isDeclaration, bool idRequired, bool isDeclare,
3151                                                      bool isAbstract)
3152{
3153    isDeclare = isDeclare | (context_.Status() & ParserStatus::IN_AMBIENT_CONTEXT);
3154    lexer::SourcePosition startLoc = lexer_->GetToken().Start();
3155    lexer_->NextToken();
3156
3157    binder::ConstDecl *decl = nullptr;
3158    ir::Identifier *identNode = nullptr;
3159
3160    auto classCtx = binder::LexicalScope<binder::ClassScope>(Binder());
3161
3162    if ((lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT ||
3163        lexer_->GetToken().Type() == lexer::TokenType::KEYW_AWAIT) && (Extension() != ScriptExtension::TS ||
3164        lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_IMPLEMENTS)) {
3165        identNode = SetIdentNodeInClassDefinition(isDeclare, &decl);
3166    } else if (isDeclaration && idRequired) {
3167        ThrowSyntaxError("Unexpected token, expected an identifier.");
3168    }
3169
3170    ir::TSTypeParameterDeclaration *typeParamDecl = nullptr;
3171    if (Extension() == ScriptExtension::TS && lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) {
3172        typeParamDecl = ParseTsTypeParameterDeclaration(true, true);
3173    }
3174
3175    // Parse SuperClass
3176    bool hasSuperClass = false;
3177    bool isExtendsFromNull = false;
3178    ir::Expression *superClass = ParseSuperClass(isDeclare, &hasSuperClass, &isExtendsFromNull);
3179
3180    ir::TSTypeParameterInstantiation *superTypeParams = nullptr;
3181    if (Extension() == ScriptExtension::TS && (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN ||
3182                                               lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SHIFT)) {
3183        if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SHIFT) {
3184            lexer_->BackwardToken(lexer::TokenType::PUNCTUATOR_LESS_THAN, 1);
3185        }
3186
3187        superTypeParams = ParseTsTypeParameterInstantiation();
3188    }
3189
3190    ArenaVector<ir::TSClassImplements *> implements = ParseTSClassImplements(isDeclare);
3191
3192    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
3193        ThrowSyntaxError("Unexpected token, expected '{'");
3194    }
3195
3196    // Parse ClassBody
3197    auto savedStatus = context_.Status();
3198    context_.Status() |= ParserStatus::IN_CLASS_BODY;
3199    context_.Status() &= ~(ParserStatus::CONSTRUCTOR_FUNCTION);
3200    lexer::SourcePosition classBodyStartLoc = lexer_->GetToken().Start();
3201    lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);
3202
3203    ir::MethodDefinition *ctor = nullptr;
3204    ir::MethodDefinition *staticInitializer = CreateImplicitMethod(superClass, hasSuperClass,
3205        ir::ScriptFunctionFlags::STATIC_INITIALIZER, isDeclare);
3206    ir::MethodDefinition *instanceInitializer = CreateImplicitMethod(superClass, hasSuperClass,
3207        ir::ScriptFunctionFlags::INSTANCE_INITIALIZER, isDeclare);
3208    ArenaVector<ir::Statement *> properties(Allocator()->Adapter());
3209    ArenaVector<ir::TSIndexSignature *> indexSignatures(Allocator()->Adapter());
3210    bool hasConstructorFuncBody = false;
3211    bool isCtorContinuousDefined = true;
3212
3213    auto *static_scope  = staticInitializer->Function()->Scope();
3214    auto *instance_scope = instanceInitializer->Function()->Scope();
3215
3216    std::unordered_set<util::StringView> usedPrivateNames;
3217    std::unordered_map<util::StringView, PrivateGetterSetterType> unusedGetterSetterPairs;
3218
3219    while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
3220        if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
3221            lexer_->NextToken();
3222            continue;
3223        }
3224
3225        ir::Statement *property = ParseClassElement(properties, &indexSignatures, hasSuperClass, isDeclare, isAbstract,
3226                                                    isExtendsFromNull, std::make_pair(static_scope, instance_scope));
3227
3228        if (property->IsEmptyStatement()) {
3229            continue;
3230        }
3231
3232        if (IsConstructor(property)) {
3233            if (!isDeclare && !isCtorContinuousDefined) {
3234                ThrowSyntaxError("Constructor implementation is missing.", property->Start());
3235            }
3236
3237            if (hasConstructorFuncBody) {
3238                ThrowSyntaxError("Multiple constructor implementations are not allowed.", property->Start());
3239            }
3240            ctor = property->AsMethodDefinition();
3241            hasConstructorFuncBody = ctor->Value()->Function()->Body() != nullptr;
3242            continue;
3243        }
3244        isCtorContinuousDefined = ctor == nullptr;
3245        ValidatePrivateProperty(property, usedPrivateNames, unusedGetterSetterPairs);
3246        properties.push_back(property);
3247    }
3248
3249    context_.Status() = savedStatus;
3250
3251    lexer::SourcePosition classBodyEndLoc = lexer_->GetToken().End();
3252    if (ctor == nullptr) {
3253        ctor = CreateImplicitMethod(superClass, hasSuperClass, ir::ScriptFunctionFlags::CONSTRUCTOR, isDeclare);
3254        ctor->SetRange({startLoc, classBodyEndLoc});
3255        hasConstructorFuncBody = !isDeclare;
3256    }
3257
3258    lexer_->NextToken();
3259
3260    ValidateClassConstructor(ctor, properties, isDeclare, hasConstructorFuncBody, hasSuperClass, isExtendsFromNull);
3261
3262    auto *classDefinition = AllocNode<ir::ClassDefinition>(
3263        classCtx.GetScope(), identNode, typeParamDecl, superTypeParams, std::move(implements), ctor, staticInitializer,
3264        instanceInitializer, superClass, std::move(properties), std::move(indexSignatures), isDeclare, isAbstract);
3265
3266    classDefinition->SetRange({classBodyStartLoc, classBodyEndLoc});
3267    if (decl != nullptr) {
3268        decl->BindNode(classDefinition);
3269    }
3270
3271    classCtx.GetScope()->BindNode(classDefinition);
3272    return classDefinition;
3273}
3274
3275ir::Expression *ParserImpl::ParseSuperClass(bool isDeclare, bool *hasSuperClass, bool *isExtendsFromNull)
3276{
3277    ir::Expression *superClass = nullptr;
3278    if (lexer_->GetToken().Type() != lexer::TokenType::KEYW_EXTENDS) {
3279        return nullptr;
3280    }
3281
3282    lexer_->NextToken();
3283    if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_AWAIT && isDeclare) {
3284        lexer_->GetToken().SetTokenType(lexer::TokenType::LITERAL_IDENT);
3285    }
3286
3287    *hasSuperClass = true;
3288    superClass = ParseLeftHandSideExpression();
3289    ASSERT(superClass != nullptr);
3290    *isExtendsFromNull = superClass->IsNullLiteral();
3291
3292    return superClass;
3293}
3294
3295ArenaVector<ir::TSClassImplements *> ParserImpl::ParseTSClassImplements(bool isDeclare)
3296{
3297    ArenaVector<ir::TSClassImplements *> implements(Allocator()->Adapter());
3298
3299    if (Extension() != ScriptExtension::TS || lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_IMPLEMENTS) {
3300        return implements;
3301    }
3302
3303    lexer_->NextToken();
3304    while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
3305        lexer::SourcePosition implStart = lexer_->GetToken().Start();
3306        if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT &&
3307            !(lexer_->GetToken().Type() == lexer::TokenType::KEYW_AWAIT && isDeclare)) {
3308            ThrowSyntaxError("Identifier expected");
3309        }
3310        ir::Expression *expr = AllocNode<ir::Identifier>(lexer_->GetToken().Ident());
3311        expr->SetRange(lexer_->GetToken().Loc());
3312        expr->AsIdentifier()->SetReference();
3313        lexer_->NextToken();
3314        if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD) {
3315            expr = ParseTsQualifiedReference(expr);
3316        }
3317        ir::TSTypeParameterInstantiation *implTypeParams = nullptr;
3318        if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SHIFT) {
3319            lexer_->BackwardToken(lexer::TokenType::PUNCTUATOR_LESS_THAN, 1);
3320        }
3321        if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN ||
3322            lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SHIFT) {
3323            implTypeParams = ParseTsTypeParameterInstantiation();
3324        }
3325        auto *impl = AllocNode<ir::TSClassImplements>(expr, implTypeParams);
3326        impl->SetRange({implStart, lexer_->GetToken().End()});
3327        implements.push_back(impl);
3328        if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
3329            lexer_->NextToken();
3330            continue;
3331        }
3332        if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
3333            ThrowSyntaxError("',' expected");
3334        }
3335    }
3336    if (implements.empty()) {
3337        ThrowSyntaxError("Implements clause can not be empty");
3338    }
3339
3340    return implements;
3341}
3342
3343void ParserImpl::ValidateClassConstructor(const ir::MethodDefinition *ctor,
3344                                          const ArenaVector<ir::Statement *> &properties,
3345                                          bool isDeclare, bool hasConstructorFuncBody,
3346                                          bool hasSuperClass, bool isExtendsFromNull)
3347{
3348    if (!hasConstructorFuncBody) {
3349        if (isDeclare) {
3350            return;
3351        }
3352        ThrowSyntaxError("Constructor implementation is missing.", ctor->Start());
3353    }
3354
3355    if (Extension() != ScriptExtension::TS || !hasSuperClass) {
3356        return;
3357    }
3358
3359    bool hasSuperCall = false;
3360    FindSuperCall(ctor->Function()->Body()->AsBlockStatement(), &hasSuperCall);
3361    if (hasSuperCall) {
3362        if (isExtendsFromNull) {
3363            ThrowSyntaxError("A constructor cannot contain a super call when its class extends null.", ctor->Start());
3364        }
3365
3366        ValidateSuperCallLocation(ctor, SuperCallShouldBeRootLevel(ctor, properties));
3367    } else {
3368        if (!isExtendsFromNull) {
3369            ThrowSyntaxError("Constructors for derived classes must contain a super call.", ctor->Start());
3370        }
3371    }
3372}
3373
3374void ParserImpl::FindSuperCall(const ir::AstNode *parent, bool *hasSuperCall)
3375{
3376    parent->Iterate([this, hasSuperCall](auto *childNode) {
3377        FindSuperCallInCtorChildNode(childNode, hasSuperCall);
3378    });
3379}
3380
3381void ParserImpl::FindSuperCallInCtorChildNode(const ir::AstNode *childNode, bool *hasSuperCall)
3382{
3383    if (*hasSuperCall) {
3384        return;
3385    }
3386    switch (childNode->Type()) {
3387        case ir::AstNodeType::CALL_EXPRESSION: {
3388            if (childNode->AsCallExpression()->Callee()->IsSuperExpression()) {
3389                *hasSuperCall = true;
3390                return;
3391            }
3392            break;
3393        }
3394        case ir::AstNodeType::CLASS_DEFINITION:
3395        case ir::AstNodeType::FUNCTION_DECLARATION:
3396        case ir::AstNodeType::FUNCTION_EXPRESSION:
3397        case ir::AstNodeType::ARROW_FUNCTION_EXPRESSION: {
3398            break;
3399        }
3400        default: {
3401            FindSuperCall(childNode, hasSuperCall);
3402            break;
3403        }
3404    }
3405}
3406
3407bool ParserImpl::SuperCallShouldBeRootLevel(const ir::MethodDefinition *ctor,
3408                                            const ArenaVector<ir::Statement *> &properties)
3409{
3410    for (const auto *property : properties) {
3411        if (property->IsClassProperty()) {
3412            auto *classProperty = property->AsClassProperty();
3413            bool isPrivateProperty = program_.TargetApiVersion() > 10 ?
3414                classProperty->Key()->IsPrivateIdentifier() : classProperty->Key()->IsTSPrivateIdentifier();
3415            if (classProperty->Value() != nullptr || isPrivateProperty) {
3416                return true;
3417            }
3418        }
3419    }
3420
3421    for (const auto &param : ctor->Function()->Params()) {
3422        if (param->IsTSParameterProperty() &&
3423            (param->AsTSParameterProperty()->Accessibility() != ir::AccessibilityOption::NO_OPTS ||
3424            param->AsTSParameterProperty()->Readonly())) {
3425            return true;
3426        }
3427    }
3428    return false;
3429}
3430
3431void ParserImpl::ValidateSuperCallLocation(const ir::MethodDefinition *ctor, bool superCallShouldBeRootLevel)
3432{
3433    bool hasThisOrSuperReferenceBeforeSuperCall = false;
3434    const ir::BlockStatement *blockStat = ctor->Function()->Body()->AsBlockStatement();
3435
3436    if (superCallShouldBeRootLevel) {
3437        bool superCallInRootLevel = false;
3438        for (auto iter = blockStat->Statements().begin(); iter != blockStat->Statements().end(); iter++) {
3439            if ((*iter)->IsExpressionStatement() &&
3440                (*iter)->AsExpressionStatement()->GetExpression()->IsCallExpression() &&
3441                (*iter)->AsExpressionStatement()->GetExpression()->AsCallExpression()->Callee()->IsSuperExpression()) {
3442                superCallInRootLevel = true;
3443                break;
3444            }
3445            if (!hasThisOrSuperReferenceBeforeSuperCall) {
3446                FindThisOrSuperReferenceInChildNode(*iter, &hasThisOrSuperReferenceBeforeSuperCall);
3447            }
3448        }
3449
3450        if (!superCallInRootLevel) {
3451            ThrowSyntaxError("A super call must be a root-level statement within a constructor of a derived class "
3452                             "that contains initialized properties, parameter properties, or private identifiers.",
3453                             ctor->Start());
3454        }
3455    } else {
3456        for (auto iter = blockStat->Statements().begin(); iter != blockStat->Statements().end(); iter++) {
3457            bool superCallInStatement = false;
3458            FindSuperCallInCtorChildNode(*iter, &superCallInStatement);
3459            if (superCallInStatement) {
3460                break;
3461            }
3462            if (!hasThisOrSuperReferenceBeforeSuperCall) {
3463                FindThisOrSuperReferenceInChildNode(*iter, &hasThisOrSuperReferenceBeforeSuperCall);
3464            }
3465        }
3466    }
3467
3468    if (hasThisOrSuperReferenceBeforeSuperCall) {
3469        ThrowSyntaxError("super() must be called before this/super access.", ctor->Start());
3470    }
3471}
3472
3473void ParserImpl::FindThisOrSuperReference(const ir::AstNode *parent, bool *hasThisOrSuperReference)
3474{
3475    parent->Iterate([this, hasThisOrSuperReference](auto *childNode) {
3476        FindThisOrSuperReferenceInChildNode(childNode, hasThisOrSuperReference);
3477    });
3478}
3479
3480void ParserImpl::FindThisOrSuperReferenceInChildNode(const ir::AstNode *childNode, bool *hasThisOrSuperReference)
3481{
3482    if (*hasThisOrSuperReference) {
3483        return;
3484    }
3485
3486    // The logic for finding ThisOrSuperReference is coarse-grained and may miss some cases.
3487    switch (childNode->Type()) {
3488        case ir::AstNodeType::THIS_EXPRESSION:
3489        case ir::AstNodeType::SUPER_EXPRESSION: {
3490            *hasThisOrSuperReference = true;
3491            break;
3492        }
3493        case ir::AstNodeType::CLASS_DEFINITION:
3494        case ir::AstNodeType::FUNCTION_DECLARATION:
3495        case ir::AstNodeType::FUNCTION_EXPRESSION:
3496        case ir::AstNodeType::ARROW_FUNCTION_EXPRESSION: {
3497            break;
3498        }
3499        default: {
3500            FindThisOrSuperReference(childNode, hasThisOrSuperReference);
3501            break;
3502        }
3503    }
3504}
3505
3506ir::Expression *ParserImpl::ParseEnumComputedPropertyKey(binder::EnumDecl *&decl,
3507                                                         const lexer::SourcePosition &keyStartLoc, bool isDeclare)
3508{
3509    ir::Expression *memberKey = nullptr;
3510    lexer_->NextToken();
3511
3512    if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_STRING) {
3513        memberKey = AllocNode<ir::StringLiteral>(lexer_->GetToken().String());
3514        decl = Binder()->AddDecl<binder::EnumDecl>(keyStartLoc, isDeclare, lexer_->GetToken().String());
3515        memberKey->SetRange(lexer_->GetToken().Loc());
3516        lexer_->NextToken();
3517    } else if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_BACK_TICK) {
3518        lexer_->ResetTokenEnd();
3519        const auto startPos = lexer_->Save();
3520        lexer_->ScanString<LEX_CHAR_BACK_TICK>();
3521        util::StringView cooked = lexer_->GetToken().String();
3522        lexer_->Rewind(startPos);
3523
3524        memberKey = ParsePrimaryExpression();
3525        ArenaVector<ir::Expression *> expressions = memberKey->AsTemplateLiteral()->Expressions();
3526        if (!expressions.empty()) {
3527            ThrowSyntaxError("Computed property names are not allowed in enums");
3528        }
3529
3530        decl = Binder()->AddDecl<binder::EnumDecl>(keyStartLoc, isDeclare, cooked);
3531        memberKey->SetRange(lexer_->GetToken().Loc());
3532    } else {
3533        ThrowSyntaxError("Unexpected token in enum member");
3534    }
3535
3536    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
3537        ThrowSyntaxError("Unexpected token, expected ']'");
3538    }
3539
3540    lexer_->NextToken();
3541    return memberKey;
3542}
3543
3544
3545ir::TSEnumDeclaration *ParserImpl::ParseEnumMembers(ir::Identifier *key, const lexer::SourcePosition &enumStart,
3546                                                    bool isExport, bool isDeclare, bool isConst)
3547{
3548    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
3549        ThrowSyntaxError("'{' expected");
3550    }
3551
3552    ArenaVector<ir::TSEnumMember *> members(Allocator()->Adapter());
3553    lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);  // eat '{'
3554
3555    while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
3556        ir::Expression *memberKey = nullptr;
3557        const auto &keyStartLoc = lexer_->GetToken().Start();
3558        binder::EnumDecl *decl {};
3559
3560        if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) {
3561            memberKey = AllocNode<ir::Identifier>(lexer_->GetToken().Ident());
3562            decl = Binder()->AddDecl<binder::EnumDecl>(keyStartLoc, isDeclare, lexer_->GetToken().Ident());
3563            memberKey->SetRange(lexer_->GetToken().Loc());
3564            lexer_->NextToken();
3565        } else if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_STRING) {
3566            memberKey = AllocNode<ir::StringLiteral>(lexer_->GetToken().String());
3567            decl = Binder()->AddDecl<binder::EnumDecl>(keyStartLoc, isDeclare, lexer_->GetToken().String());
3568            memberKey->SetRange(lexer_->GetToken().Loc());
3569            lexer_->NextToken();
3570        } else if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET) {
3571            memberKey = ParseEnumComputedPropertyKey(decl, keyStartLoc, isDeclare);
3572        } else {
3573            ThrowSyntaxError("Unexpected token in enum member");
3574        }
3575
3576        ir::Expression *memberInit = nullptr;
3577        lexer::SourcePosition initStart = lexer_->GetToken().Start();
3578
3579        if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
3580            lexer_->NextToken();  // eat '='
3581            initStart = lexer_->GetToken().Start();
3582            memberInit = ParseExpression();
3583        }
3584
3585        auto *member = AllocNode<ir::TSEnumMember>(memberKey, memberInit);
3586        decl->BindNode(member);
3587        member->SetRange({initStart, lexer_->GetToken().End()});
3588        members.push_back(member);
3589
3590        if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
3591            lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);  // eat ','
3592        }
3593    }
3594
3595    auto *enumDeclaration = AllocNode<ir::TSEnumDeclaration>(
3596        Binder()->GetScope()->AsTSEnumScope(), key, std::move(members), isExport, isDeclare, isConst);
3597    enumDeclaration->SetRange({enumStart, lexer_->GetToken().End()});
3598    Binder()->GetScope()->BindNode(enumDeclaration);
3599    lexer_->NextToken();  // eat '}'
3600
3601    return enumDeclaration;
3602}
3603
3604ir::TSEnumDeclaration *ParserImpl::ParseEnumDeclaration(bool isExport, bool isDeclare, bool isConst)
3605{
3606    ASSERT(lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_ENUM);
3607    lexer::SourcePosition enumStart = lexer_->GetToken().Start();
3608    lexer_->NextToken();  // eat enum keyword
3609
3610    if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT &&
3611        lexer_->GetToken().Type() != lexer::TokenType::KEYW_AWAIT) {
3612        ThrowSyntaxError("Identifier expected");
3613    }
3614
3615    const util::StringView &ident = lexer_->GetToken().Ident();
3616    auto *currentScope = Binder()->GetScope();
3617    binder::Variable *res = currentScope->FindLocalTSVariable<binder::TSBindingType::ENUMLITERAL>(ident);
3618    if (res == nullptr && isExport && currentScope->IsTSModuleScope()) {
3619        res = currentScope->AsTSModuleScope()->FindExportTSVariable<binder::TSBindingType::ENUMLITERAL>(ident);
3620        if (res != nullptr) {
3621            currentScope->AddLocalTSVariable<binder::TSBindingType::ENUMLITERAL>(ident, res);
3622        }
3623    }
3624    if (res == nullptr) {
3625        Binder()->AddTsDecl<binder::EnumLiteralDecl>(lexer_->GetToken().Start(), isDeclare,
3626                                                     Allocator(), ident, isExport, isConst);
3627        res = currentScope->FindLocalTSVariable<binder::TSBindingType::ENUMLITERAL>(ident);
3628        if (isExport && currentScope->IsTSModuleScope()) {
3629            currentScope->AsTSModuleScope()->AddExportTSVariable<binder::TSBindingType::ENUMLITERAL>(ident, res);
3630        }
3631        res->AsEnumLiteralVariable()->SetEnumMembers(Allocator()->New<binder::VariableMap>(Allocator()->Adapter()));
3632    }
3633    binder::VariableMap *enumMemberBindings = res->AsEnumLiteralVariable()->GetEnumMembers();
3634
3635    auto *key = AllocNode<ir::Identifier>(ident);
3636    key->SetRange(lexer_->GetToken().Loc());
3637    key->SetReference();
3638    lexer_->NextToken();
3639
3640    if (!res->Declaration()->IsEnumLiteralDecl() ||
3641        (isConst ^ res->Declaration()->AsEnumLiteralDecl()->IsConst())) {
3642        Binder()->ThrowRedeclaration(lexer_->GetToken().Start(), ident);
3643    }
3644
3645    auto enumCtx = binder::LexicalScope<binder::TSEnumScope>(Binder(), enumMemberBindings);
3646    auto *enumDeclaration = ParseEnumMembers(key, enumStart, isExport, isDeclare, isConst);
3647    res->Declaration()->AsEnumLiteralDecl()->Add(enumDeclaration);
3648    res->Declaration()->BindNode(enumDeclaration);
3649
3650    return enumDeclaration;
3651}
3652
3653void ParserImpl::ValidateFunctionParam(const ArenaVector<ir::Expression *> &params, const ir::Expression *parameter,
3654                                       bool *seenOptional)
3655{
3656    if (!parameter->IsIdentifier()) {
3657        context_.Status() |= ParserStatus::HAS_COMPLEX_PARAM;
3658        if (!parameter->IsRestElement()) {
3659            return;
3660        }
3661
3662        if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
3663            const char *msg = (Extension() == ScriptExtension::JS ? "Rest parameter must be last formal parameter"
3664                                                                  : "A rest parameter must be last in parameter list");
3665            ThrowSyntaxError(msg);
3666        }
3667        return;
3668    }
3669
3670    if (Extension() != ScriptExtension::TS) {
3671        return;
3672    }
3673
3674    bool currentIsOptinal = parameter->AsIdentifier()->IsOptional();
3675    if (*seenOptional && !currentIsOptinal) {
3676        ThrowSyntaxError("A required parameter cannot follow an optional parameter");
3677    }
3678
3679    *seenOptional |= currentIsOptinal;
3680    const util::StringView &paramName = parameter->AsIdentifier()->Name();
3681
3682    if (paramName.Is("this")) {
3683        if (!params.empty()) {
3684            ThrowSyntaxError("A 'this' parameter must be the first parameter");
3685        }
3686
3687        if (context_.Status() & ParserStatus::CONSTRUCTOR_FUNCTION) {
3688            ThrowSyntaxError("A constructor cannot have a 'this' parameter");
3689        }
3690
3691        if (context_.Status() & ParserStatus::ARROW_FUNCTION) {
3692            ThrowSyntaxError("An arrow function cannot have a 'this' parameter");
3693        }
3694
3695        if (context_.Status() & ParserStatus::ACCESSOR_FUNCTION) {
3696            ThrowSyntaxError("'get' and 'set' accessors cannot declare 'this' parameters");
3697        }
3698    }
3699
3700    if (paramName.Is("constructor") && (context_.Status() & ParserStatus::CONSTRUCTOR_FUNCTION)) {
3701        ThrowSyntaxError("'constructor' cannot be used as a parameter property name");
3702    }
3703}
3704
3705ArenaVector<ir::Expression *> ParserImpl::ParseFunctionParams(bool isDeclare,
3706                                                              ArenaVector<ir::ParamDecorators> *paramDecorators)
3707{
3708    ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS);
3709    lexer_->NextToken();
3710
3711    ArenaVector<ir::Expression *> params(Allocator()->Adapter());
3712    bool seenOptional = false;
3713
3714    size_t index = 0;
3715    while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
3716        if (context_.Status() & ParserStatus::IN_METHOD_DEFINITION) {
3717            auto decoratorsAndAnnotations = ParseDecoratorsAndAnnotations();
3718            auto decorators = decoratorsAndAnnotations.first;
3719            auto annotations = decoratorsAndAnnotations.second;
3720            if (!annotations.empty()) {
3721                ThrowSyntaxError("Annotations can not be used with function parameters", annotations.front()->Start());
3722            }
3723
3724            if (!decorators.empty()) {
3725                ASSERT(paramDecorators != nullptr);
3726                paramDecorators->push_back({index, std::move(decorators)});
3727            }
3728        }
3729
3730        ir::Expression *parameter = ParseFunctionParameter(isDeclare);
3731        ValidateFunctionParam(params, parameter, &seenOptional);
3732
3733        params.push_back(parameter);
3734
3735        if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COMMA &&
3736            lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
3737            ThrowSyntaxError(", expected");
3738        }
3739
3740        if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
3741            lexer_->NextToken();
3742        }
3743
3744        index++;
3745    }
3746
3747    ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS);
3748    lexer_->NextToken();
3749
3750    return params;
3751}
3752
3753bool ParserImpl::CheckTypeNameIsReserved(const util::StringView &paramName)
3754{
3755    return paramName.Is("number") || paramName.Is("any") || paramName.Is("unknown") || paramName.Is("never") ||
3756           paramName.Is("bigint") || paramName.Is("boolean") || paramName.Is("string") || paramName.Is("string") ||
3757           paramName.Is("void") || paramName.Is("object");
3758}
3759
3760bool ParserImpl::CheckOutIsIdentInTypeParameter()
3761{
3762    auto pos = lexer_->Save();
3763    lexer_->NextToken();
3764
3765    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_GREATER_THAN ||
3766        lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
3767        lexer_->Rewind(pos);
3768        return true;
3769    }
3770
3771    lexer_->Rewind(pos);
3772    return false;
3773}
3774
3775void ParserImpl::ParseTypeModifier(bool &isTypeIn, bool &isTypeOut, bool &isAllowInOut)
3776{
3777    if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_IN) {
3778        if (!isAllowInOut) {
3779            ThrowSyntaxError("'in' modifier can only appear on a type parameter of a class, interface or type alias");
3780        }
3781        isTypeIn = true;
3782        lexer_->NextToken();
3783        if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_IN) {
3784            ThrowSyntaxError("'in' modifier already seen.");
3785        }
3786
3787        if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_OUT && !CheckOutIsIdentInTypeParameter()) {
3788            isTypeOut = true;
3789            lexer_->NextToken();
3790            if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_OUT && !CheckOutIsIdentInTypeParameter()) {
3791                ThrowSyntaxError("'out' modifier already seen.");
3792            }
3793        }
3794    } else if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_OUT && !CheckOutIsIdentInTypeParameter()) {
3795        if (!isAllowInOut) {
3796            ThrowSyntaxError("'out' modifier can only appear on a type parameter of a class, interface or type alias");
3797        }
3798
3799        isTypeOut = true;
3800        lexer_->NextToken();
3801
3802        if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_IN) {
3803            ThrowSyntaxError("'in' modifier must precede 'out' modifier.");
3804        }
3805
3806        if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_OUT && !CheckOutIsIdentInTypeParameter()) {
3807            ThrowSyntaxError("'out' modifier already seen.");
3808        }
3809    }
3810}
3811
3812ir::TSTypeParameter *ParserImpl::ParseTsTypeParameter(bool throwError, bool addBinding, bool isAllowInOut)
3813{
3814    lexer::SourcePosition startLoc = lexer_->GetToken().Start();
3815
3816    bool isTypeIn = false;
3817    bool isTypeOut = false;
3818    ParseTypeModifier(isTypeIn, isTypeOut, isAllowInOut);
3819
3820    if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
3821        if (!throwError) {
3822            return nullptr;
3823        }
3824
3825        ThrowSyntaxError("Type parameter declaration expected");
3826    }
3827
3828    const auto &ident = lexer_->GetToken().Ident();
3829
3830    if (CheckTypeNameIsReserved(ident)) {
3831        if (!throwError) {
3832            return nullptr;
3833        }
3834
3835        ThrowSyntaxError("Invalid type parameter name");
3836    }
3837
3838    auto *paramIdent = AllocNode<ir::Identifier>(ident);
3839
3840    if (addBinding) {
3841        Binder()->AddDecl<binder::LetDecl>(lexer_->GetToken().Start(), false, ident);
3842    }
3843
3844    paramIdent->SetRange({lexer_->GetToken().Start(), lexer_->GetToken().End()});
3845
3846    lexer_->NextToken();
3847
3848    TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::NO_OPTS;
3849
3850    if (throwError) {
3851        options |= TypeAnnotationParsingOptions::THROW_ERROR;
3852    }
3853
3854    ir::Expression *constraint = TryParseConstraintOfInferType(&options);
3855
3856    ir::Expression *defaultType = nullptr;
3857    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
3858        lexer_->NextToken();
3859        defaultType = ParseTsTypeAnnotation(&options);
3860    }
3861
3862    auto *typeParam = AllocNode<ir::TSTypeParameter>(paramIdent, constraint, defaultType, isTypeIn, isTypeOut);
3863
3864    typeParam->SetRange({startLoc, lexer_->GetToken().End()});
3865
3866    return typeParam;
3867}
3868
3869ir::Expression *ParserImpl::TryParseConstraintOfInferType(TypeAnnotationParsingOptions *options)
3870{
3871    ir::Expression *constraint = nullptr;
3872    if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_EXTENDS) {
3873        auto savedPos = lexer_->Save();
3874        lexer_->NextToken(); // eat 'extends'
3875        constraint = DoInsideOfDisallowConditinalTypesContext(&ParserImpl::ParseTsTypeAnnotation, options);
3876        if (!InDisallowConditionalTypesContext() &&
3877            lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_QUESTION_MARK) {
3878            constraint = nullptr;
3879            lexer_->Rewind(savedPos); // go back to 'extends'
3880        }
3881    }
3882    return constraint;
3883}
3884
3885ir::TSTypeParameterDeclaration *ParserImpl::ParseTsTypeParameterDeclaration(bool throwError, bool isAllowInOut)
3886{
3887    ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN);
3888
3889    auto localCtx = binder::LexicalScope<binder::LocalScope>(Binder());
3890
3891    lexer::SourcePosition startLoc = lexer_->GetToken().Start();
3892    ArenaVector<ir::TSTypeParameter *> params(Allocator()->Adapter());
3893    bool seenDefault = false;
3894    size_t requiredParams = 0;
3895    lexer_->NextToken();  // eat '<'
3896
3897    while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_GREATER_THAN) {
3898        ir::TSTypeParameter *currentParam = ParseTsTypeParameter(throwError, true, isAllowInOut);
3899
3900        if (!currentParam) {
3901            ASSERT(!throwError);
3902            return nullptr;
3903        }
3904
3905        if (currentParam->DefaultType()) {
3906            seenDefault = true;
3907        } else if (seenDefault) {
3908            ThrowSyntaxError("Required type parameters may not follow optional type parameters.");
3909        } else {
3910            requiredParams++;
3911        }
3912
3913        params.push_back(currentParam);
3914
3915        if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
3916            lexer_->NextToken();
3917            continue;
3918        }
3919
3920        if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_GREATER_THAN) {
3921            if (!throwError) {
3922                return nullptr;
3923            }
3924
3925            ThrowSyntaxError("'>' expected");
3926        }
3927    }
3928
3929    if (params.empty()) {
3930        ThrowSyntaxError("Type parameter list cannot be empty.");
3931    }
3932
3933    lexer::SourcePosition endLoc = lexer_->GetToken().End();
3934    lexer_->NextToken();  // eat '>'
3935
3936    auto *typeParamDecl =
3937        AllocNode<ir::TSTypeParameterDeclaration>(localCtx.GetScope(), std::move(params), requiredParams);
3938    typeParamDecl->SetRange({startLoc, endLoc});
3939    localCtx.GetScope()->BindNode(typeParamDecl);
3940
3941    return typeParamDecl;
3942}
3943
3944ir::TSTypeParameterInstantiation *ParserImpl::ParseTsTypeParameterInstantiation(bool throwError)
3945{
3946    ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN);
3947    lexer::SourcePosition startLoc = lexer_->GetToken().Start();
3948    ArenaVector<ir::Expression *> params(Allocator()->Adapter());
3949    lexer_->NextToken();  // eat '<'
3950
3951    while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_GREATER_THAN) {
3952        TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::NO_OPTS;
3953
3954        if (throwError) {
3955            options |= TypeAnnotationParsingOptions::THROW_ERROR;
3956        }
3957
3958        ir::Expression *currentParam = ParseTsTypeAnnotation(&options);
3959
3960        if (!currentParam) {
3961            return nullptr;
3962        }
3963
3964        params.push_back(currentParam);
3965
3966        switch (lexer_->GetToken().Type()) {
3967            case lexer::TokenType::PUNCTUATOR_COMMA: {
3968                lexer_->NextToken();
3969                continue;
3970            }
3971            case lexer::TokenType::PUNCTUATOR_RIGHT_SHIFT: {
3972                lexer_->BackwardToken(lexer::TokenType::PUNCTUATOR_GREATER_THAN, 1);
3973                break;
3974            }
3975            case lexer::TokenType::PUNCTUATOR_UNSIGNED_RIGHT_SHIFT: {
3976                lexer_->BackwardToken(lexer::TokenType::PUNCTUATOR_GREATER_THAN, 2);
3977                break;
3978            }
3979            case lexer::TokenType::PUNCTUATOR_GREATER_THAN: {
3980                break;
3981            }
3982            default: {
3983                if (throwError) {
3984                    ThrowSyntaxError("'>' expected");
3985                }
3986
3987                return nullptr;
3988            }
3989        }
3990    }
3991
3992    lexer::SourcePosition endLoc = lexer_->GetToken().End();
3993    lexer_->NextToken();
3994
3995    auto *typeParamInst = AllocNode<ir::TSTypeParameterInstantiation>(std::move(params));
3996
3997    typeParamInst->SetRange({startLoc, endLoc});
3998
3999    return typeParamInst;
4000}
4001
4002ir::ScriptFunction *ParserImpl::ParseFunction(ParserStatus newStatus,
4003                                              bool isDeclare,
4004                                              ArenaVector<ir::ParamDecorators> *paramDecorators)
4005{
4006    FunctionContext functionContext(this, newStatus | ParserStatus::FUNCTION | ParserStatus::ALLOW_NEW_TARGET);
4007
4008    FunctionParameterContext funcParamContext(&context_, Binder());
4009    auto *funcParamScope = funcParamContext.LexicalScope().GetScope();
4010
4011    lexer::SourcePosition startLoc = lexer_->GetToken().Start();
4012
4013    ir::TSTypeParameterDeclaration *typeParamDecl = nullptr;
4014    if (Extension() == ScriptExtension::TS && lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) {
4015        typeParamDecl = ParseTsTypeParameterDeclaration();
4016    }
4017
4018    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
4019        ThrowSyntaxError("Unexpected token, expected '('");
4020    }
4021
4022    if ((newStatus & (ParserStatus::ASYNC_FUNCTION | ParserStatus::FUNCTION_DECLARATION)) | context_.IsModule()) {
4023        context_.Status() |= ParserStatus::DISALLOW_AWAIT;
4024    }
4025
4026    ArenaVector<ir::Expression *> params = ParseFunctionParams(isDeclare, paramDecorators);
4027
4028    ir::Expression *returnTypeAnnotation = nullptr;
4029
4030    if (Extension() == ScriptExtension::TS && lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
4031        lexer_->NextToken();  // eat ':'
4032        TypeAnnotationParsingOptions options =
4033            TypeAnnotationParsingOptions::THROW_ERROR | TypeAnnotationParsingOptions::CAN_BE_TS_TYPE_PREDICATE;
4034        returnTypeAnnotation = ParseTsTypeAnnotation(&options);
4035    }
4036
4037    auto functionCtx = binder::LexicalScope<binder::FunctionScope>(Binder());
4038    auto *functionScope = functionCtx.GetScope();
4039    functionScope->BindParamScope(funcParamScope);
4040    funcParamScope->BindFunctionScope(functionScope);
4041
4042    ir::BlockStatement *body = nullptr;
4043    lexer::SourcePosition endLoc = lexer_->GetToken().End();
4044    bool letDeclare = true;
4045
4046    if (newStatus & ParserStatus::ASYNC_FUNCTION) {
4047        context_.Status() &= ~ParserStatus::DISALLOW_AWAIT;
4048    } else {
4049        context_.Status() |= ParserStatus::DISALLOW_AWAIT;
4050    }
4051
4052    if (newStatus & ParserStatus::GENERATOR_FUNCTION) {
4053        context_.Status() |= ParserStatus::ALLOW_YIELD;
4054    }
4055
4056    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
4057        if (Extension() == ScriptExtension::TS && (newStatus & ParserStatus::FUNCTION_DECLARATION)) {
4058            ValidateTsFunctionOverloadParams(params);
4059            functionContext.AddFlag(ir::ScriptFunctionFlags::OVERLOAD);
4060        } else if (!isDeclare && !(context_.Status() & ParserStatus::IN_METHOD_DEFINITION)) {
4061            ThrowSyntaxError("Unexpected token, expected '{'");
4062        } else {
4063            letDeclare = false;
4064            functionContext.AddFlag(ir::ScriptFunctionFlags::OVERLOAD);
4065        }
4066    } else if (isDeclare) {
4067        ThrowSyntaxError("An implementation cannot be declared in ambient contexts.");
4068    } else {
4069        body = ParseBlockStatement(functionScope);
4070        endLoc = body->End();
4071    }
4072
4073    auto *funcNode =
4074        AllocNode<ir::ScriptFunction>(functionScope, std::move(params), typeParamDecl, body, returnTypeAnnotation,
4075                                      functionContext.Flags(), isDeclare && letDeclare,
4076                                      Extension() == ScriptExtension::TS);
4077    functionScope->BindNode(funcNode);
4078    funcParamScope->BindNode(funcNode);
4079    funcNode->SetRange({startLoc, endLoc});
4080
4081    return funcNode;
4082}
4083
4084void ParserImpl::ValidateTsFunctionOverloadParams(const ArenaVector<ir::Expression *> &params)
4085{
4086    for (auto *it : params) {
4087        if (it->IsAssignmentPattern()) {
4088            ThrowSyntaxError(
4089                "A parameter initializer is only allowed in a function "
4090                "or constructor implementation.",
4091                it->Start());
4092        }
4093    }
4094}
4095
4096ir::SpreadElement *ParserImpl::ParseSpreadElement(ExpressionParseFlags flags)
4097{
4098    ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD);
4099    lexer::SourcePosition startLocation = lexer_->GetToken().Start();
4100    bool inPattern = (flags & ExpressionParseFlags::MUST_BE_PATTERN);
4101    lexer_->NextToken();
4102
4103    ir::Expression *argument {};
4104    if (inPattern) {
4105        argument = ParsePatternElement(ExpressionParseFlags::IN_REST);
4106        if ((flags & ExpressionParseFlags::OBJECT_PATTERN) && !argument->IsIdentifier()) {
4107            ThrowSyntaxError("RestParameter must be followed by an identifier in declaration contexts");
4108        }
4109    } else {
4110        argument = ParseExpression(flags);
4111    }
4112
4113    ir::Expression *typeAnnotation = nullptr;
4114
4115    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
4116        lexer_->NextToken();  // eat ':'
4117        TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
4118        typeAnnotation = ParseTsTypeAnnotation(&options);
4119    }
4120
4121    if (inPattern && argument->IsAssignmentExpression()) {
4122        ThrowSyntaxError("RestParameter does not support an initializer");
4123    }
4124
4125    lexer::SourcePosition endLoc = typeAnnotation ? typeAnnotation->End() : argument->End();
4126
4127    auto nodeType = inPattern ? ir::AstNodeType::REST_ELEMENT : ir::AstNodeType::SPREAD_ELEMENT;
4128    auto *spreadElementNode = AllocNode<ir::SpreadElement>(nodeType, argument);
4129    spreadElementNode->SetRange({startLocation, endLoc});
4130
4131    if (typeAnnotation) {
4132        spreadElementNode->SetTsTypeAnnotation(typeAnnotation);
4133    }
4134
4135    return spreadElementNode;
4136}
4137
4138ir::TSParameterProperty *ParserImpl::CreateTsParameterProperty(ir::Expression *parameter, ir::ModifierFlags modifiers)
4139{
4140    auto accessibility = ir::AccessibilityOption::NO_OPTS;
4141    bool readonly = false;
4142    bool isOverride = false;
4143    bool isStatic = false;
4144    bool isExport = false;
4145
4146    if (modifiers & ir::ModifierFlags::PRIVATE) {
4147        accessibility = ir::AccessibilityOption::PRIVATE;
4148    } else if ((modifiers & ir::ModifierFlags::PUBLIC)) {
4149        accessibility = ir::AccessibilityOption::PUBLIC;
4150    } else if (modifiers & ir::ModifierFlags::PROTECTED) {
4151        accessibility = ir::AccessibilityOption::PROTECTED;
4152    }
4153
4154    if (modifiers & ir::ModifierFlags::READONLY) {
4155        readonly = true;
4156    }
4157
4158    if (modifiers & ir::ModifierFlags::OVERRIDE) {
4159        isOverride = true;
4160    }
4161
4162    if (modifiers & ir::ModifierFlags::STATIC) {
4163        isStatic = true;
4164    }
4165
4166    return AllocNode<ir::TSParameterProperty>(accessibility, parameter, readonly, isOverride, isStatic, isExport);
4167}
4168
4169ir::Expression *ParserImpl::ParseFunctionParameter(bool isDeclare)
4170{
4171    if (Extension() == ScriptExtension::TS && lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_THIS) {
4172        lexer_->GetToken().SetTokenType(lexer::TokenType::LITERAL_IDENT);
4173    }
4174
4175    lexer::SourcePosition parameterStart = lexer_->GetToken().Start();
4176    ir::ModifierFlags modifiers = ParseModifiers();
4177    if (!(context_.Status() & ParserStatus::CONSTRUCTOR_FUNCTION) && modifiers != ir::ModifierFlags::NONE) {
4178        ThrowSyntaxError("A parameter property is only allowed in a constructor implementation.", parameterStart);
4179    }
4180
4181    lexer::TokenType tokenType = lexer_->GetToken().Type();
4182    if (tokenType == lexer::TokenType::LITERAL_IDENT &&
4183        (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_ARGUMENTS ||
4184         lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_EVAL)) {
4185        ThrowSyntaxError(
4186            "'eval' or 'arguments' can't be defined or assigned to "
4187            "in strict mode code",
4188            lexer_->GetToken().Start());
4189    }
4190
4191    ir::Expression *functionParameter = ParsePatternElement(ExpressionParseFlags::NO_OPTS, true, isDeclare);
4192
4193    if (modifiers != ir::ModifierFlags::NONE && functionParameter->IsRestElement()) {
4194        ThrowSyntaxError("A parameter property cannot be declared using a rest parameter.", parameterStart);
4195    }
4196
4197    if (modifiers != ir::ModifierFlags::NONE &&
4198        (functionParameter->IsArrayPattern() || functionParameter->IsObjectPattern() ||
4199         (functionParameter->IsAssignmentPattern() &&
4200          (functionParameter->AsAssignmentPattern()->Left()->IsArrayPattern() ||
4201           functionParameter->AsAssignmentPattern()->Left()->IsObjectPattern())))) {
4202        ThrowSyntaxError("A parameter property may not be declared using a binding pattern.", parameterStart);
4203    }
4204
4205    if (modifiers != ir::ModifierFlags::NONE) {
4206        functionParameter = CreateTsParameterProperty(functionParameter, modifiers);
4207        functionParameter->SetRange({parameterStart, functionParameter->AsTSParameterProperty()->Parameter()->End()});
4208    }
4209
4210    Binder()->AddParamDecl(functionParameter);
4211
4212    return functionParameter;
4213}
4214
4215void ParserImpl::ValidateLvalueAssignmentTarget(ir::Expression *node) const
4216{
4217    switch (node->Type()) {
4218        case ir::AstNodeType::IDENTIFIER: {
4219            // Check the prevoius ident name
4220            if (node->AsIdentifier()->Name().Is("arguments")) {
4221                ThrowSyntaxError("Assigning to 'arguments' in strict mode is invalid");
4222            } else if (node->AsIdentifier()->Name().Is("eval")) {
4223                ThrowSyntaxError("Assigning to 'eval' in strict mode is invalid");
4224            }
4225            break;
4226        }
4227        case ir::AstNodeType::MEMBER_EXPRESSION: {
4228            break;
4229        }
4230        case ir::AstNodeType::TS_AS_EXPRESSION: {
4231            ValidateLvalueAssignmentTarget(node->AsTSAsExpression()->Expr());
4232            break;
4233        }
4234        case ir::AstNodeType::TS_SATISFIES_EXPRESSION: {
4235            ValidateLvalueAssignmentTarget(node->AsTSSatisfiesExpression()->Expr());
4236            break;
4237        }
4238        case ir::AstNodeType::TS_TYPE_ASSERTION: {
4239            ValidateLvalueAssignmentTarget(node->AsTSTypeAssertion()->GetExpression());
4240            break;
4241        }
4242        case ir::AstNodeType::TS_NON_NULL_EXPRESSION: {
4243            ValidateLvalueAssignmentTarget(node->AsTSNonNullExpression()->Expr());
4244            break;
4245        }
4246        default: {
4247            ThrowSyntaxError("Invalid left-hand side in assignment expression");
4248        }
4249    }
4250}
4251
4252void ParserImpl::ValidateAssignmentTarget(ExpressionParseFlags flags, ir::Expression *node)
4253{
4254    switch (node->Type()) {
4255        case ir::AstNodeType::ARRAY_PATTERN:
4256        case ir::AstNodeType::OBJECT_PATTERN: {
4257            break;
4258        }
4259        case ir::AstNodeType::ARRAY_EXPRESSION:
4260        case ir::AstNodeType::OBJECT_EXPRESSION: {
4261            if (flags & ExpressionParseFlags::POTENTIALLY_IN_PATTERN) {
4262                return;
4263            }
4264
4265            [[fallthrough]];
4266        }
4267        default: {
4268            return ValidateLvalueAssignmentTarget(node);
4269        }
4270    }
4271}
4272
4273void ParserImpl::ValidateArrowParameterBindings(const ir::Expression *node)
4274{
4275    switch (node->Type()) {
4276        case ir::AstNodeType::IDENTIFIER: {
4277            const util::StringView &identifier = node->AsIdentifier()->Name();
4278
4279            if (context_.IsAsync() && identifier.Is("await")) {
4280                ThrowSyntaxError("'await' in formal parameter is invalid.", node->Start());
4281            }
4282            break;
4283        }
4284        case ir::AstNodeType::OMITTED_EXPRESSION: {
4285            break;
4286        }
4287        case ir::AstNodeType::REST_ELEMENT: {
4288            ValidateArrowParameterBindings(node->AsRestElement()->Argument());
4289            break;
4290        }
4291        case ir::AstNodeType::PROPERTY: {
4292            break;
4293        }
4294        case ir::AstNodeType::OBJECT_PATTERN: {
4295            const auto &props = node->AsObjectPattern()->Properties();
4296
4297            for (auto *it : props) {
4298                ValidateArrowParameterBindings(it);
4299            }
4300            break;
4301        }
4302        case ir::AstNodeType::ARRAY_PATTERN: {
4303            const auto &elements = node->AsArrayPattern()->Elements();
4304
4305            for (auto *it : elements) {
4306                ValidateArrowParameterBindings(it);
4307            }
4308            break;
4309        }
4310        case ir::AstNodeType::ASSIGNMENT_PATTERN: {
4311            ValidateArrowParameterBindings(node->AsAssignmentPattern()->Left());
4312            break;
4313        }
4314        default: {
4315            ThrowSyntaxError("Unexpected ArrowParameter element");
4316        }
4317    }
4318}
4319
4320bool ParserImpl::CurrentTokenIsModifier(char32_t nextCp) const
4321{
4322    return (Extension() == ScriptExtension::TS &&
4323            (nextCp != LEX_CHAR_EQUALS || nextCp != LEX_CHAR_SEMICOLON || nextCp != LEX_CHAR_LEFT_PAREN));
4324}
4325
4326void ParserImpl::ThrowParameterModifierError(ir::ModifierFlags status) const
4327{
4328    ThrowSyntaxError(
4329        {"'",
4330         (status & ir::ModifierFlags::STATIC) ? "static" : ((status & ir::ModifierFlags::ASYNC) ? "async" : "declare"),
4331         "' modifier cannot appear on a parameter."},
4332        lexer_->GetToken().Start());
4333}
4334
4335void ParserImpl::ThrowSyntaxError(std::string_view errorMessage) const
4336{
4337    ThrowSyntaxError(errorMessage, lexer_->GetToken().Start());
4338}
4339
4340void ParserImpl::ThrowSyntaxError(std::initializer_list<std::string_view> list) const
4341{
4342    ThrowSyntaxError(list, lexer_->GetToken().Start());
4343}
4344
4345void ParserImpl::ThrowSyntaxError(std::initializer_list<std::string_view> list, const lexer::SourcePosition &pos) const
4346{
4347    std::stringstream ss;
4348
4349    for (const auto &it : list) {
4350        ss << it;
4351    }
4352
4353    std::string err = ss.str();
4354
4355    ThrowSyntaxError(std::string_view {err}, pos);
4356}
4357
4358void ParserImpl::ThrowSyntaxError(std::string_view errorMessage, const lexer::SourcePosition &pos) const
4359{
4360    lexer::LineIndex index(program_.SourceCode());
4361    lexer::SourceLocation loc = index.GetLocation(pos);
4362
4363    throw Error {ErrorType::SYNTAX, errorMessage, loc.line, loc.col};
4364}
4365
4366ScriptExtension ParserImpl::Extension() const
4367{
4368    return program_.Extension();
4369}
4370
4371parser::SourceTextModuleRecord *ParserImpl::GetSourceTextModuleRecord()
4372{
4373    return Binder()->Program()->ModuleRecord();
4374}
4375
4376parser::SourceTextModuleRecord *ParserImpl::GetSourceTextTypeModuleRecord()
4377{
4378    return Binder()->Program()->TypeModuleRecord();
4379}
4380
4381void ParserImpl::AddPatchFixHelper(util::PatchFix *patchFixHelper)
4382{
4383    program_.AddPatchFixHelper(patchFixHelper);
4384}
4385
4386bool ParserImpl::IsDtsFile() const
4387{
4388    return program_.IsDtsFile();
4389}
4390
4391void ParserImpl::CheckStrictReservedWord() const
4392{
4393    if (Extension() == ScriptExtension::JS) {
4394        if (lexer_->GetToken().IsJsStrictReservedWord()) {
4395            ThrowSyntaxError("Unexpected reserved word in strict mode.");
4396        }
4397    } else {
4398        if (lexer_->GetToken().KeywordType() >= lexer::TokenType::KEYW_ARGUMENTS) {
4399            ThrowSyntaxError("Unexpected reserved word in strict mode.");
4400        }
4401    }
4402
4403    if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_AWAIT &&
4404        context_.IsModule() && !context_.IsTsModule()) {
4405        ThrowSyntaxError("Unexpected reserved word");
4406    }
4407}
4408
4409template<typename Function, typename... Args>
4410ir::Expression* ParserImpl::DoOutsideOfDisallowConditinalTypesContext(Function func, Args &&... args)
4411{
4412    ParserStatus status = ParserStatus::DISALLOW_CONDITIONAL_TYPES;
4413    auto inDisallowConditionalTypesContext = InDisallowConditionalTypesContext();
4414    ir::Expression *result = nullptr;
4415    if (inDisallowConditionalTypesContext) {
4416        RemoveFlagToStatus(status);
4417        result = (this->*func)(std::forward<Args>(args)...);
4418        AddFlagToStatus(status);
4419        return result;
4420    }
4421    result = (this->*func)(std::forward<Args>(args)...);
4422    return result;
4423}
4424
4425template<typename Function, typename... Args>
4426ir::Expression* ParserImpl::DoInsideOfDisallowConditinalTypesContext(Function func, Args &&... args)
4427{
4428    ParserStatus status = ParserStatus::DISALLOW_CONDITIONAL_TYPES;
4429    auto inAllowConditionalTypesContext = status & ~context_.Status();
4430    ir::Expression *result = nullptr;
4431    if (inAllowConditionalTypesContext) {
4432        AddFlagToStatus(status);
4433        result = (this->*func)(std::forward<Args>(args)...);
4434        RemoveFlagToStatus(status);
4435        return result;
4436    }
4437    result = (this->*func)(std::forward<Args>(args)...);
4438    return result;
4439}
4440
4441bool ParserImpl::InDisallowConditionalTypesContext()
4442{
4443    return InContext(ParserStatus::DISALLOW_CONDITIONAL_TYPES);
4444}
4445
4446bool ParserImpl::InContext(ParserStatus status)
4447{
4448    return context_.Status() & status;
4449}
4450
4451void ParserImpl::AddFlagToStatus(ParserStatus status)
4452{
4453    context_.Status() |= status;
4454}
4455
4456void ParserImpl::RemoveFlagToStatus(ParserStatus status)
4457{
4458    context_.Status() &= ~status;
4459}
4460
4461void ParserImpl::RecursiveDepthException()
4462{
4463    auto pos = lexer_->GetToken().Start();
4464    lexer::LineIndex index(program_.SourceCode());
4465    lexer::SourceLocation loc = index.GetLocation(pos);
4466    throw Error(ErrorType::GENERIC, "Too many nested expressions/statemnets/declarations", loc.line, loc.col);
4467}
4468}  // namespace panda::es2panda::parser
4469