• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
18 #include <binder/scope.h>
19 #include <binder/tsBinding.h>
20 #include <ir/astDump.h>
21 #include <ir/astNode.h>
22 #include <ir/base/classDefinition.h>
23 #include <ir/base/classProperty.h>
24 #include <ir/base/decorator.h>
25 #include <ir/base/methodDefinition.h>
26 #include <ir/base/property.h>
27 #include <ir/base/scriptFunction.h>
28 #include <ir/base/spreadElement.h>
29 #include <ir/expression.h>
30 #include <ir/expressions/arrayExpression.h>
31 #include <ir/expressions/assignmentExpression.h>
32 #include <ir/expressions/callExpression.h>
33 #include <ir/expressions/functionExpression.h>
34 #include <ir/expressions/identifier.h>
35 #include <ir/expressions/literals/bigIntLiteral.h>
36 #include <ir/expressions/literals/booleanLiteral.h>
37 #include <ir/expressions/literals/nullLiteral.h>
38 #include <ir/expressions/literals/numberLiteral.h>
39 #include <ir/expressions/literals/stringLiteral.h>
40 #include <ir/expressions/memberExpression.h>
41 #include <ir/expressions/objectExpression.h>
42 #include <ir/expressions/superExpression.h>
43 #include <ir/module/exportDefaultDeclaration.h>
44 #include <ir/module/exportNamedDeclaration.h>
45 #include <ir/module/exportSpecifier.h>
46 #include <ir/statements/blockStatement.h>
47 #include <ir/statements/emptyStatement.h>
48 #include <ir/statements/expressionStatement.h>
49 #include <ir/statements/functionDeclaration.h>
50 #include <ir/ts/tsAnyKeyword.h>
51 #include <ir/ts/tsArrayType.h>
52 #include <ir/ts/tsBigintKeyword.h>
53 #include <ir/ts/tsBooleanKeyword.h>
54 #include <ir/ts/tsClassImplements.h>
55 #include <ir/ts/tsConditionalType.h>
56 #include <ir/ts/tsConstructorType.h>
57 #include <ir/ts/tsEnumDeclaration.h>
58 #include <ir/ts/tsEnumMember.h>
59 #include <ir/ts/tsFunctionType.h>
60 #include <ir/ts/tsImportType.h>
61 #include <ir/ts/tsIndexSignature.h>
62 #include <ir/ts/tsIndexedAccessType.h>
63 #include <ir/ts/tsInferType.h>
64 #include <ir/ts/tsIntersectionType.h>
65 #include <ir/ts/tsLiteralType.h>
66 #include <ir/ts/tsMappedType.h>
67 #include <ir/ts/tsMethodSignature.h>
68 #include <ir/ts/tsNamedTupleMember.h>
69 #include <ir/ts/tsNeverKeyword.h>
70 #include <ir/ts/tsNullKeyword.h>
71 #include <ir/ts/tsNumberKeyword.h>
72 #include <ir/ts/tsObjectKeyword.h>
73 #include <ir/ts/tsOptionalType.h>
74 #include <ir/ts/tsParameterProperty.h>
75 #include <ir/ts/tsParenthesizedType.h>
76 #include <ir/ts/tsPrivateIdentifier.h>
77 #include <ir/ts/tsPropertySignature.h>
78 #include <ir/ts/tsQualifiedName.h>
79 #include <ir/ts/tsRestType.h>
80 #include <ir/ts/tsSignatureDeclaration.h>
81 #include <ir/ts/tsStringKeyword.h>
82 #include <ir/ts/tsSymbolKeyword.h>
83 #include <ir/ts/tsTemplateLiteralType.h>
84 #include <ir/ts/tsThisType.h>
85 #include <ir/ts/tsTupleType.h>
86 #include <ir/ts/tsTypeLiteral.h>
87 #include <ir/ts/tsTypeOperator.h>
88 #include <ir/ts/tsTypeParameterDeclaration.h>
89 #include <ir/ts/tsTypeParameterInstantiation.h>
90 #include <ir/ts/tsTypePredicate.h>
91 #include <ir/ts/tsTypeQuery.h>
92 #include <ir/ts/tsTypeReference.h>
93 #include <ir/ts/tsUndefinedKeyword.h>
94 #include <ir/ts/tsUnionType.h>
95 #include <ir/ts/tsUnknownKeyword.h>
96 #include <ir/ts/tsVoidKeyword.h>
97 #include <lexer/lexer.h>
98 #include <lexer/token/letters.h>
99 #include <lexer/token/sourceLocation.h>
100 #include <mem/pool_manager.h>
101 
102 namespace panda::es2panda::parser {
103 
ParserImpl(ScriptExtension extension)104 ParserImpl::ParserImpl(ScriptExtension extension) : program_(extension), context_(&program_) {}
105 
106 template <class T>
IsSuffix(T const & filename,T const & suffix)107 bool IsSuffix(T const &filename, T const &suffix)
108 {
109     return (filename.length() > suffix.length()) &&
110         (filename.rfind(suffix) == (filename.length() - suffix.length()));
111 }
112 
InitLexer(const std::string & fileName,const std::string & source)113 std::unique_ptr<lexer::Lexer> ParserImpl::InitLexer(const std::string &fileName, const std::string &source)
114 {
115     bool isDtsFile = false;
116     if (Extension() == ScriptExtension::TS) {
117         isDtsFile = IsSuffix(fileName, std::string(".d.ts"));
118     }
119     program_.SetSource(source, fileName, isDtsFile);
120     auto lexer = std::make_unique<lexer::Lexer>(&context_);
121     lexer_ = lexer.get();
122 
123     return lexer;
124 }
125 
Parse(const std::string & fileName,const std::string & source,const std::string & recordName,ScriptKind kind)126 Program ParserImpl::Parse(const std::string &fileName, const std::string &source,
127                           const std::string &recordName, ScriptKind kind)
128 {
129     program_.SetKind(kind);
130     program_.SetRecordName(recordName);
131 
132     /*
133      * In order to make the lexer's memory alive, the return value 'lexer' can not be omitted.
134      */
135     auto lexer = InitLexer(fileName, source);
136     switch (kind) {
137         case ScriptKind::SCRIPT: {
138             ParseScript();
139             break;
140         }
141         case ScriptKind::MODULE: {
142             ParseModule();
143             break;
144         }
145         case ScriptKind::COMMONJS: {
146             ParseCommonjs();
147             break;
148         }
149         default: {
150             UNREACHABLE();
151         }
152     }
153     binder::ResolveBindingFlags bindFlags = binder::ResolveBindingFlags::ALL;
154     if (Extension() == ScriptExtension::TS) {
155         bindFlags = binder::ResolveBindingFlags::TS_BEFORE_TRANSFORM;
156     }
157     Binder()->IdentifierAnalysis(bindFlags);
158     return std::move(program_);
159 }
160 
ParseScript()161 void ParserImpl::ParseScript()
162 {
163     ParseProgram(ScriptKind::SCRIPT);
164 }
165 
ParseModule()166 void ParserImpl::ParseModule()
167 {
168     context_.Status() |= (ParserStatus::MODULE);
169     ParseProgram(ScriptKind::MODULE);
170 }
171 
ParseProgram(ScriptKind kind)172 void ParserImpl::ParseProgram(ScriptKind kind)
173 {
174     lexer::SourcePosition startLoc = lexer_->GetToken().Start();
175     lexer_->NextToken();
176 
177     auto statements = ParseStatementList(StatementParsingFlags::STMT_GLOBAL_LEXICAL);
178 
179     auto *blockStmt = AllocNode<ir::BlockStatement>(Binder()->GetScope(), std::move(statements));
180     Binder()->GetScope()->BindNode(blockStmt);
181     blockStmt->SetRange({startLoc, lexer_->GetToken().End()});
182 
183     program_.SetAst(blockStmt);
184 }
185 
186 /*
187  * Definitions of private methods
188  */
CarryExpressionParserFlag(ExpressionParseFlags origin,ExpressionParseFlags carry)189 ExpressionParseFlags ParserImpl::CarryExpressionParserFlag(ExpressionParseFlags origin, ExpressionParseFlags carry)
190 {
191     return static_cast<ExpressionParseFlags>(origin & carry);
192 }
193 
CarryPatternFlags(ExpressionParseFlags flags)194 ExpressionParseFlags ParserImpl::CarryPatternFlags(ExpressionParseFlags flags)
195 {
196     return CarryExpressionParserFlag(flags, ExpressionParseFlags::POTENTIALLY_IN_PATTERN |
197                                                 ExpressionParseFlags::OBJECT_PATTERN);
198 }
199 
CurrentLiteralIsBasicType()200 bool ParserImpl::CurrentLiteralIsBasicType()
201 {
202     ASSERT(lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT ||
203            lexer_->GetToken().Type() == lexer::TokenType::KEYW_EXTENDS);
204 
205     switch (lexer_->GetToken().KeywordType()) {
206         case lexer::TokenType::KEYW_ANY:
207         case lexer::TokenType::KEYW_BOOLEAN:
208         case lexer::TokenType::KEYW_NUMBER:
209         case lexer::TokenType::KEYW_STRING:
210         case lexer::TokenType::KEYW_SYMBOL:
211         case lexer::TokenType::KEYW_UNKNOWN:
212         case lexer::TokenType::KEYW_UNDEFINED:
213         case lexer::TokenType::KEYW_NEVER:
214         case lexer::TokenType::KEYW_OBJECT:
215         case lexer::TokenType::KEYW_BIGINT: {
216             return true;
217         }
218         default: {
219             break;
220         }
221     }
222 
223     return false;
224 }
CurrentIsBasicType()225 bool ParserImpl::CurrentIsBasicType()
226 {
227     switch (lexer_->GetToken().Type()) {
228         case lexer::TokenType::PUNCTUATOR_MINUS:
229         case lexer::TokenType::LITERAL_NUMBER:
230         case lexer::TokenType::LITERAL_STRING:
231         case lexer::TokenType::LITERAL_FALSE:
232         case lexer::TokenType::LITERAL_TRUE:
233         case lexer::TokenType::LITERAL_NULL:
234         case lexer::TokenType::KEYW_VOID: {
235             return true;
236         }
237         case lexer::TokenType::LITERAL_IDENT: {
238             return CurrentLiteralIsBasicType();
239         }
240         default: {
241             break;
242         }
243     }
244 
245     return false;
246 }
247 
ParseTsConstExpression()248 ir::TSTypeReference *ParserImpl::ParseTsConstExpression()
249 {
250     auto *identRef = AllocNode<ir::Identifier>(lexer_->GetToken().Ident(), Allocator());
251     identRef->SetReference();
252     identRef->SetRange(lexer_->GetToken().Loc());
253 
254     auto *typeReference = AllocNode<ir::TSTypeReference>(identRef, nullptr);
255     typeReference->SetRange(lexer_->GetToken().Loc());
256 
257     lexer_->NextToken();
258 
259     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COMMA &&
260         lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON &&
261         lexer_->GetToken().Type() != lexer::TokenType::EOS &&
262         lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET &&
263         !(lexer_->GetToken().Flags() & lexer::TokenFlags::NEW_LINE)) {
264         ThrowSyntaxError("Unexpected token.");
265     }
266 
267     return typeReference;
268 }
269 
ParseTsIdentifierReference()270 ir::Expression *ParserImpl::ParseTsIdentifierReference()
271 {
272     if (CurrentLiteralIsBasicType() && lexer_->Lookahead() != LEX_CHAR_DOT) {
273         return ParseTsBasicType();
274     }
275 
276     return ParseTsTypeReferenceOrQuery();
277 }
278 
IsStartOfMappedType() const279 bool ParserImpl::IsStartOfMappedType() const
280 {
281     auto pos = lexer_->Save();
282     lexer_->NextToken();
283     bool result = false;
284 
285     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MINUS ||
286         lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PLUS) {
287         lexer_->NextToken();
288         result = lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_READONLY;
289         lexer_->Rewind(pos);
290         return result;
291     }
292 
293     if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_READONLY) {
294         lexer_->NextToken();
295     }
296 
297     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET) {
298         lexer_->Rewind(pos);
299         return false;
300     }
301 
302     lexer_->NextToken();
303 
304     if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
305         lexer_->Rewind(pos);
306         return false;
307     }
308 
309     lexer_->NextToken();
310 
311     result = lexer_->GetToken().Type() == lexer::TokenType::KEYW_IN;
312 
313     lexer_->Rewind(pos);
314     return result;
315 }
316 
IsStartOfTsTypePredicate() const317 bool ParserImpl::IsStartOfTsTypePredicate() const
318 {
319     ASSERT(lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT ||
320            lexer_->GetToken().Type() == lexer::TokenType::KEYW_THIS);
321 
322     auto pos = lexer_->Save();
323     bool isAsserts = lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_ASSERTS;
324     if (isAsserts) {
325         lexer_->NextToken();
326     }
327 
328     if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT &&
329         lexer_->GetToken().Type() != lexer::TokenType::KEYW_THIS) {
330         lexer_->Rewind(pos);
331         return false;
332     }
333 
334     if (isAsserts) {
335         lexer_->Rewind(pos);
336         return true;
337     }
338 
339     lexer_->NextToken();
340 
341     bool result = !lexer_->GetToken().NewLine() && (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_IS);
342     lexer_->Rewind(pos);
343     return result;
344 }
345 
IsStartOfAbstractConstructorType() const346 bool ParserImpl::IsStartOfAbstractConstructorType() const
347 {
348     if (lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_ABSTRACT) {
349         return false;
350     }
351 
352     lexer::LexerPosition pos = lexer_->Save();
353     lexer_->NextToken();  // eat 'abstract'
354     bool result = lexer_->GetToken().Type() == lexer::TokenType::KEYW_NEW;
355 
356     lexer_->Rewind(pos);
357 
358     return result;
359 }
360 
ParseTsTypeLiteralOrTsMappedType(ir::Expression * typeAnnotation)361 ir::Expression *ParserImpl::ParseTsTypeLiteralOrTsMappedType(ir::Expression *typeAnnotation)
362 {
363     if (typeAnnotation) {
364         return nullptr;
365     }
366 
367     if (IsStartOfMappedType()) {
368         return ParseTsMappedType();
369     }
370 
371     lexer::SourcePosition bodyStart = lexer_->GetToken().Start();
372     auto members = ParseTsTypeLiteralOrInterface();
373     lexer::SourcePosition bodyEnd = lexer_->GetToken().End();
374     lexer_->NextToken();
375 
376     auto *literalType = AllocNode<ir::TSTypeLiteral>(std::move(members));
377     auto *typeVar = binder::Scope::CreateVar(Allocator(), "__type", binder::VariableFlags::TYPE, literalType);
378     literalType->SetVariable(typeVar);
379     literalType->SetRange({bodyStart, bodyEnd});
380     return literalType;
381 }
382 
ParseTsTypeReferenceOrTsTypePredicate(ir::Expression * typeAnnotation,bool canBeTsTypePredicate)383 ir::Expression *ParserImpl::ParseTsTypeReferenceOrTsTypePredicate(ir::Expression *typeAnnotation,
384                                                                   bool canBeTsTypePredicate)
385 {
386     if (typeAnnotation) {
387         return nullptr;
388     }
389 
390     if (canBeTsTypePredicate && IsStartOfTsTypePredicate()) {
391         return ParseTsTypePredicate();
392     }
393 
394     return ParseTsTypeOperatorOrTypeReference();
395 }
396 
ParseTsThisTypeOrTsTypePredicate(ir::Expression * typeAnnotation,bool canBeTsTypePredicate,bool throwError)397 ir::Expression *ParserImpl::ParseTsThisTypeOrTsTypePredicate(ir::Expression *typeAnnotation, bool canBeTsTypePredicate,
398                                                              bool throwError)
399 {
400     if (typeAnnotation) {
401         return nullptr;
402     }
403 
404     if (canBeTsTypePredicate && IsStartOfTsTypePredicate()) {
405         return ParseTsTypePredicate();
406     }
407 
408     return ParseTsThisType(throwError);
409 }
410 
ParseTsTemplateLiteralType()411 ir::Expression *ParserImpl::ParseTsTemplateLiteralType()
412 {
413     ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_BACK_TICK);
414     lexer::SourcePosition startLoc = lexer_->GetToken().Start();
415 
416     ArenaVector<ir::TemplateElement *> quasis(Allocator()->Adapter());
417     ArenaVector<ir::Expression *> references(Allocator()->Adapter());
418 
419     while (true) {
420         lexer_->ResetTokenEnd();
421         const auto startPos = lexer_->Save();
422 
423         lexer_->ScanString<LEX_CHAR_BACK_TICK>();
424         util::StringView cooked = lexer_->GetToken().String();
425 
426         lexer_->Rewind(startPos);
427         auto [raw, end, scanExpression] = lexer_->ScanTemplateString();
428 
429         auto *element = AllocNode<ir::TemplateElement>(raw.View(), cooked);
430         element->SetRange({lexer::SourcePosition{startPos.iterator.Index(), startPos.line},
431                            lexer::SourcePosition{end, lexer_->Line()}});
432         quasis.push_back(element);
433 
434         if (!scanExpression) {
435             lexer_->ScanTemplateStringEnd();
436             break;
437         }
438 
439         ir::Expression *reference = nullptr;
440 
441         {
442             lexer::TemplateLiteralParserContext ctx(lexer_);
443             lexer_->PushTemplateContext(&ctx);
444             lexer_->NextToken();
445             TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
446             reference = ParseTsTypeAnnotation(&options);
447         }
448 
449         if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
450             ThrowSyntaxError("Unexpected token, expected '}'.");
451         }
452 
453         references.push_back(reference);
454     }
455 
456     ir::Expression *typeAnnotation = AllocNode<ir::TSTemplateLiteralType>(std::move(quasis), std::move(references));
457     typeAnnotation->SetRange({startLoc, lexer_->GetToken().End()});
458 
459     lexer_->NextToken();
460 
461     return typeAnnotation;
462 }
463 
ParseTsTypeAnnotationElement(ir::Expression * typeAnnotation,TypeAnnotationParsingOptions * options)464 ir::Expression *ParserImpl::ParseTsTypeAnnotationElement(ir::Expression *typeAnnotation,
465                                                          TypeAnnotationParsingOptions *options)
466 {
467     switch (lexer_->GetToken().Type()) {
468         case lexer::TokenType::PUNCTUATOR_BITWISE_OR: {
469             if (*options & (TypeAnnotationParsingOptions::IN_MODIFIER | TypeAnnotationParsingOptions::IN_UNION |
470                 TypeAnnotationParsingOptions::IN_INTERSECTION)) {
471                 break;
472             }
473 
474             return ParseTsUnionType(typeAnnotation, *options & TypeAnnotationParsingOptions::RESTRICT_EXTENDS);
475         }
476         case lexer::TokenType::PUNCTUATOR_BITWISE_AND: {
477             if (*options & (TypeAnnotationParsingOptions::IN_MODIFIER |
478 	        TypeAnnotationParsingOptions::IN_INTERSECTION)) {
479                 break;
480             }
481 
482             return ParseTsIntersectionType(typeAnnotation, *options & TypeAnnotationParsingOptions::IN_UNION,
483                                            *options & TypeAnnotationParsingOptions::RESTRICT_EXTENDS);
484         }
485         case lexer::TokenType::PUNCTUATOR_LESS_THAN:
486         case lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS:
487         case lexer::TokenType::KEYW_NEW: {
488             return ParseTsParenthesizedOrFunctionType(typeAnnotation,
489                                                       *options & TypeAnnotationParsingOptions::THROW_ERROR);
490         }
491         case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET: {
492             if (typeAnnotation) {
493                 if (lexer_->Lookahead() == LEX_CHAR_RIGHT_SQUARE) {
494                     return ParseTsArrayType(typeAnnotation);
495                 }
496 
497                 return ParseTsIndexAccessType(typeAnnotation);
498             }
499 
500             return ParseTsTupleType();
501         }
502         case lexer::TokenType::PUNCTUATOR_LEFT_BRACE: {
503             return ParseTsTypeLiteralOrTsMappedType(typeAnnotation);
504         }
505         case lexer::TokenType::PUNCTUATOR_MINUS:
506         case lexer::TokenType::LITERAL_NUMBER:
507         case lexer::TokenType::LITERAL_STRING:
508         case lexer::TokenType::LITERAL_FALSE:
509         case lexer::TokenType::LITERAL_TRUE:
510         case lexer::TokenType::LITERAL_NULL:
511         case lexer::TokenType::KEYW_VOID: {
512             if (typeAnnotation) {
513                 break;
514             }
515 
516             return ParseTsBasicType();
517         }
518         case lexer::TokenType::KEYW_TYPEOF: {
519             if (typeAnnotation) {
520                 break;
521             }
522 
523             return ParseTsTypeReferenceOrQuery(true);
524         }
525         case lexer::TokenType::KEYW_IMPORT: {
526             if (typeAnnotation) {
527                 break;
528             }
529 
530             lexer::SourcePosition startLoc = lexer_->GetToken().Start();
531             return ParseTsImportType(startLoc);
532         }
533         case lexer::TokenType::KEYW_CONST: {
534             if (!(*options & TypeAnnotationParsingOptions::ALLOW_CONST)) {
535                 break;
536             }
537 
538             *options &= ~TypeAnnotationParsingOptions::ALLOW_CONST;
539             return ParseTsConstExpression();
540         }
541         case lexer::TokenType::LITERAL_IDENT: {
542             if (IsStartOfAbstractConstructorType()) {
543                 return ParseTsParenthesizedOrFunctionType(typeAnnotation,
544                                                           *options & TypeAnnotationParsingOptions::THROW_ERROR);
545             }
546 
547             return ParseTsTypeReferenceOrTsTypePredicate(
548                 typeAnnotation, *options & TypeAnnotationParsingOptions::CAN_BE_TS_TYPE_PREDICATE);
549         }
550         case lexer::TokenType::KEYW_EXTENDS: {
551             if (*options & (TypeAnnotationParsingOptions::IN_UNION | TypeAnnotationParsingOptions::IN_INTERSECTION)) {
552                 break;
553             }
554 
555             if (!typeAnnotation) {
556                 return ParseTsIdentifierReference();
557             }
558 
559             return ParseTsConditionalType(typeAnnotation, *options & TypeAnnotationParsingOptions::RESTRICT_EXTENDS);
560         }
561         case lexer::TokenType::KEYW_THIS: {
562             return ParseTsThisTypeOrTsTypePredicate(typeAnnotation,
563                                                     *options & TypeAnnotationParsingOptions::CAN_BE_TS_TYPE_PREDICATE,
564                                                     *options & TypeAnnotationParsingOptions::THROW_ERROR);
565         }
566         case lexer::TokenType::PUNCTUATOR_BACK_TICK: {
567             return ParseTsTemplateLiteralType();
568         }
569         default: {
570             break;
571         }
572     }
573 
574     if (!typeAnnotation && (*options & TypeAnnotationParsingOptions::THROW_ERROR)) {
575         ThrowSyntaxError("Type expected");
576     }
577 
578     return nullptr;
579 }
580 
ParseTsImportType(const lexer::SourcePosition & startLoc,bool isTypeof)581 ir::TSImportType *ParserImpl::ParseTsImportType(const lexer::SourcePosition &startLoc, bool isTypeof)
582 {
583     ASSERT(lexer_->GetToken().Type() == lexer::TokenType::KEYW_IMPORT);
584 
585     lexer_->NextToken();
586 
587     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
588         ThrowSyntaxError("'(' expected");
589     }
590 
591     lexer_->NextToken();
592 
593     TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
594     ir::Expression *param = ParseTsTypeAnnotation(&options);
595 
596     if (!param->IsTSLiteralType() || !param->AsTSLiteralType()->Literal()->IsStringLiteral()) {
597         ThrowSyntaxError("String literal expected");
598     }
599 
600     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
601         ThrowSyntaxError("')' expected");
602     }
603 
604     lexer_->NextToken();
605 
606     ir::Expression *qualifier = nullptr;
607     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD) {
608         lexer_->NextToken();
609 
610         if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
611             ThrowSyntaxError("Identifier expected");
612         }
613 
614         qualifier = AllocNode<ir::Identifier>(lexer_->GetToken().Ident(), Allocator());
615         qualifier->SetRange(lexer_->GetToken().Loc());
616 
617         lexer_->NextToken();
618 
619         if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD) {
620             qualifier = ParseTsQualifiedReference(qualifier);
621         }
622     }
623 
624     ir::TSTypeParameterInstantiation *typeParams = nullptr;
625     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SHIFT ||
626         lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) {
627         if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SHIFT) {
628             lexer_->BackwardToken(lexer::TokenType::PUNCTUATOR_LESS_THAN, 1);
629         }
630 
631         typeParams = ParseTsTypeParameterInstantiation();
632     }
633 
634     auto *importType = AllocNode<ir::TSImportType>(param, typeParams, qualifier, isTypeof);
635 
636     importType->SetRange({startLoc, lexer_->GetToken().End()});
637 
638     return importType;
639 }
640 
ParseTsThisType(bool throwError)641 ir::Expression *ParserImpl::ParseTsThisType(bool throwError)
642 {
643     ASSERT(lexer_->GetToken().Type() == lexer::TokenType::KEYW_THIS);
644 
645     if (throwError && !(context_.Status() & ParserStatus::ALLOW_THIS_TYPE)) {
646         ThrowSyntaxError(
647             "A 'this' type is available only in a non-static member "
648             "of a class or interface.");
649     }
650 
651     auto *returnType = AllocNode<ir::TSThisType>();
652     returnType->SetRange(lexer_->GetToken().Loc());
653 
654     lexer_->NextToken();
655 
656     return returnType;
657 }
658 
ParseTsConditionalType(ir::Expression * checkType,bool restrictExtends)659 ir::Expression *ParserImpl::ParseTsConditionalType(ir::Expression *checkType, bool restrictExtends)
660 {
661     ASSERT(lexer_->GetToken().Type() == lexer::TokenType::KEYW_EXTENDS);
662     if (restrictExtends) {
663         ThrowSyntaxError("'?' expected.");
664     }
665 
666     lexer::SourcePosition startLoc = checkType->Start();
667 
668     lexer_->NextToken();  // eat 'extends'
669 
670     ParserStatus savedStatus = context_.Status();
671     context_.Status() |= ParserStatus::IN_EXTENDS;
672 
673     TypeAnnotationParsingOptions options =
674         TypeAnnotationParsingOptions::THROW_ERROR | TypeAnnotationParsingOptions::RESTRICT_EXTENDS;
675     auto *extendsType = ParseTsTypeAnnotation(&options);
676 
677     context_.Status() = savedStatus;
678 
679     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_QUESTION_MARK) {
680         ThrowSyntaxError("'?' expected.");
681     }
682 
683     lexer_->NextToken();  // eat '?'
684 
685     options &= ~TypeAnnotationParsingOptions::RESTRICT_EXTENDS;
686     auto *trueType = ParseTsTypeAnnotation(&options);
687 
688     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COLON) {
689         ThrowSyntaxError("':' expected.");
690     }
691 
692     lexer_->NextToken();  // eat ':'
693 
694     auto *falseType = ParseTsTypeAnnotation(&options);
695 
696     lexer::SourcePosition endLoc = falseType->End();
697 
698     auto *conditionalType = AllocNode<ir::TSConditionalType>(checkType, extendsType, trueType, falseType);
699 
700     conditionalType->SetRange({startLoc, endLoc});
701 
702     return conditionalType;
703 }
704 
ParseTsTypeAnnotation(TypeAnnotationParsingOptions * options)705 ir::Expression *ParserImpl::ParseTsTypeAnnotation(TypeAnnotationParsingOptions *options)
706 {
707     ir::Expression *typeAnnotation = nullptr;
708 
709     while (true) {
710         ir::Expression *element = ParseTsTypeAnnotationElement(typeAnnotation, options);
711 
712         *options &= ~TypeAnnotationParsingOptions::CAN_BE_TS_TYPE_PREDICATE;
713 
714         if (!element) {
715             break;
716         }
717 
718         typeAnnotation = element;
719 
720         if ((*options & TypeAnnotationParsingOptions::BREAK_AT_NEW_LINE) && lexer_->GetToken().NewLine()) {
721             break;
722         }
723     }
724 
725     return typeAnnotation;
726 }
727 
ParseTsTypeOperatorOrTypeReference()728 ir::Expression *ParserImpl::ParseTsTypeOperatorOrTypeReference()
729 {
730     TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
731 
732     if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_READONLY) {
733         lexer::SourcePosition typeOperatorStart = lexer_->GetToken().Start();
734         lexer_->NextToken();
735 
736         options |= TypeAnnotationParsingOptions::IN_MODIFIER;
737         ir::Expression *type = ParseTsTypeAnnotation(&options);
738         ASSERT(type != nullptr);
739 
740         if (!type->IsTSArrayType() && !type->IsTSTupleType()) {
741             ThrowSyntaxError(
742                 "'readonly' type modifier is only permitted on array "
743                 "and tuple literal types.");
744         }
745 
746         auto *typeOperator = AllocNode<ir::TSTypeOperator>(type, ir::TSOperatorType::READONLY);
747 
748         typeOperator->SetRange({typeOperatorStart, type->End()});
749 
750         return typeOperator;
751     }
752 
753     if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_KEYOF) {
754         lexer::SourcePosition typeOperatorStart = lexer_->GetToken().Start();
755         lexer_->NextToken();
756 
757         options |= TypeAnnotationParsingOptions::IN_MODIFIER;
758         ir::Expression *type = ParseTsTypeAnnotation(&options);
759         ASSERT(type != nullptr);
760 
761         auto *typeOperator = AllocNode<ir::TSTypeOperator>(type, ir::TSOperatorType::KEYOF);
762 
763         typeOperator->SetRange({typeOperatorStart, type->End()});
764 
765         return typeOperator;
766     }
767 
768     if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_UNIQUE) {
769         lexer::SourcePosition typeOperatorStart = lexer_->GetToken().Start();
770         lexer_->NextToken();
771 
772         ir::Expression *type = ParseTsTypeAnnotation(&options);
773         ASSERT(type != nullptr);
774 
775         auto *typeOperator = AllocNode<ir::TSTypeOperator>(type, ir::TSOperatorType::UNIQUE);
776 
777         typeOperator->SetRange({typeOperatorStart, type->End()});
778 
779         return typeOperator;
780     }
781 
782     if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_INFER) {
783         if (!(context_.Status() & ParserStatus::IN_EXTENDS)) {
784             ThrowSyntaxError(
785                 "'infer' declarations are only permitted in the "
786                 "'extends' clause of a conditional type.");
787         }
788 
789         lexer::SourcePosition inferStart = lexer_->GetToken().Start();
790         lexer_->NextToken();
791 
792         ir::TSTypeParameter *typeParam = ParseTsTypeParameter(true);
793 
794         auto *inferType = AllocNode<ir::TSInferType>(typeParam);
795 
796         inferType->SetRange({inferStart, lexer_->GetToken().End()});
797 
798         return inferType;
799     }
800 
801     return ParseTsIdentifierReference();
802 }
803 
IsTSNamedTupleMember()804 bool ParserImpl::IsTSNamedTupleMember()
805 {
806     if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
807         return false;
808     }
809     const auto savePos = lexer_->Save();
810     bool isNamedMember = false;
811     lexer_->NextToken();
812     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON ||
813         (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_QUESTION_MARK &&
814          lexer_->Lookahead() == LEX_CHAR_COLON)) {
815             isNamedMember = true;
816     }
817     lexer_->Rewind(savePos);
818     return isNamedMember;
819 }
820 
ParseTsTupleElement(ir::TSTupleKind * kind,bool * seenOptional)821 ir::Expression *ParserImpl::ParseTsTupleElement(ir::TSTupleKind *kind, bool *seenOptional)
822 {
823     lexer::SourcePosition startPos = lexer_->GetToken().Start();
824     ir::Expression *element = nullptr;
825     bool isOptional = false;
826     bool isRestType = false;
827     TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
828 
829     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD) {
830         isRestType = true;
831         lexer_->NextToken();  // eat '...'
832     }
833 
834     if (IsTSNamedTupleMember()) {
835         if (*kind == ir::TSTupleKind::DEFAULT) {
836             ThrowSyntaxError("Tuple members must all have or haven't names");
837         }
838         *kind = ir::TSTupleKind::NAMED;
839 
840         auto *elementIdent = AllocNode<ir::Identifier>(lexer_->GetToken().Ident(), Allocator());
841         elementIdent->SetRange(lexer_->GetToken().Loc());
842         lexer_->NextToken();  // eat identifier
843 
844         if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_QUESTION_MARK) {
845             lexer_->NextToken();  // eat '?'
846             isOptional = true;
847             *seenOptional = true;
848         } else if (*seenOptional) {
849             ThrowSyntaxError("A required element cannot follow an optional element");
850         }
851 
852         if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COLON) {
853             ThrowSyntaxError("':' expected");
854         }
855 
856         lexer_->NextToken();  // eat ':'
857         auto *elementType = ParseTsTypeAnnotation(&options);
858         ASSERT(elementType != nullptr);
859 
860         element = AllocNode<ir::TSNamedTupleMember>(elementIdent, elementType, isOptional, isRestType);
861         element->SetRange({startPos, elementType->End()});
862     } else {
863         if (*kind == ir::TSTupleKind::NAMED) {
864             ThrowSyntaxError("Tuple members must all have or haven't names");
865         }
866         *kind = ir::TSTupleKind::DEFAULT;
867 
868         element = ParseTsTypeAnnotation(&options);
869         ASSERT(element != nullptr);
870         if (element && isRestType) {
871             lexer::SourcePosition endPos = element->End();
872             element = AllocNode<ir::TSRestType>(std::move(element));
873             element->SetRange({startPos, endPos});
874         }
875 
876         if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_QUESTION_MARK) {
877             lexer::SourcePosition elementStartPos = element->Start();
878             element = AllocNode<ir::TSOptionalType>(std::move(element));
879             element->SetRange({elementStartPos, lexer_->GetToken().End()});
880             lexer_->NextToken();  // eat '?'
881         }
882     }
883     return element;
884 }
885 
ParseTsTupleType()886 ir::TSTupleType *ParserImpl::ParseTsTupleType()
887 {
888     ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET);
889     lexer::SourcePosition tupleStart = lexer_->GetToken().Start();
890     ArenaVector<ir::Expression *> elements(Allocator()->Adapter());
891     ir::TSTupleKind kind = ir::TSTupleKind::NONE;
892     bool seenOptional = false;
893 
894     lexer_->NextToken();  // eat '['
895 
896     while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
897         ir::Expression *element = ParseTsTupleElement(&kind, &seenOptional);
898 
899         elements.push_back(element);
900 
901         if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
902             break;
903         }
904 
905         if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COMMA) {
906             ThrowSyntaxError("',' expected.");
907         }
908 
909         lexer_->NextToken();  // eat ','
910     }
911 
912     lexer::SourcePosition tupleEnd = lexer_->GetToken().End();
913     lexer_->NextToken();  // eat ']'
914 
915     auto *tupleType = AllocNode<ir::TSTupleType>(std::move(elements));
916     tupleType->SetRange({tupleStart, tupleEnd});
917     return tupleType;
918 }
919 
ParseTsQualifiedReference(ir::Expression * typeName)920 ir::Expression *ParserImpl::ParseTsQualifiedReference(ir::Expression *typeName)
921 {
922     lexer::SourcePosition startLoc = typeName->Start();
923 
924     do {
925         lexer_->NextToken();  // eat '.'
926 
927         if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
928             ThrowSyntaxError("Identifier expected");
929         }
930 
931         auto *propName = AllocNode<ir::Identifier>(lexer_->GetToken().Ident(), Allocator());
932         propName->SetRange(lexer_->GetToken().Loc());
933 
934         typeName = AllocNode<ir::TSQualifiedName>(typeName, propName);
935         typeName->SetRange({typeName->AsTSQualifiedName()->Left()->Start(), lexer_->GetToken().End()});
936 
937         lexer_->NextToken();
938     } while (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD);
939 
940     typeName->SetRange({startLoc, lexer_->GetToken().End()});
941 
942     return typeName;
943 }
944 
ParseTsIndexAccessType(ir::Expression * typeName)945 ir::Expression *ParserImpl::ParseTsIndexAccessType(ir::Expression *typeName)
946 {
947     TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
948 
949     do {
950         lexer_->NextToken();  // eat '['
951 
952         ir::Expression *indexType = ParseTsTypeAnnotation(&options);
953 
954         if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
955             ThrowSyntaxError("']' exprected");
956         }
957 
958         lexer_->NextToken();  // eat ']'
959 
960         typeName = AllocNode<ir::TSIndexedAccessType>(typeName, indexType);
961         typeName->SetRange({typeName->AsTSIndexedAccessType()->ObjectType()->Start(), lexer_->GetToken().End()});
962     } while (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET &&
963              lexer_->Lookahead() != LEX_CHAR_RIGHT_SQUARE);
964 
965     return typeName;
966 }
967 
ParseTsTypeReferenceOrQuery(bool parseQuery)968 ir::Expression *ParserImpl::ParseTsTypeReferenceOrQuery(bool parseQuery)
969 {
970     lexer::SourcePosition referenceStartLoc = lexer_->GetToken().Start();
971 
972     if (parseQuery) {
973         ASSERT(lexer_->GetToken().Type() == lexer::TokenType::KEYW_TYPEOF);
974         lexer_->NextToken();  // eat 'typeof'
975 
976         if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_IMPORT) {
977             lexer::SourcePosition &startLoc = referenceStartLoc;
978             return ParseTsImportType(startLoc, true);
979         }
980 
981         if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
982             ThrowSyntaxError("Identifier expected.");
983         }
984     }
985 
986     ASSERT(lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT ||
987            lexer_->GetToken().Type() == lexer::TokenType::KEYW_EXTENDS);
988 
989     ir::Expression *typeName = AllocNode<ir::Identifier>(lexer_->GetToken().Ident(), Allocator());
990     typeName->SetRange(lexer_->GetToken().Loc());
991     typeName->AsIdentifier()->SetReference();
992 
993     if (lexer_->Lookahead() == LEX_CHAR_LESS_THAN) {
994         lexer_->ForwardToken(lexer::TokenType::PUNCTUATOR_LESS_THAN, 1);
995     } else {
996         lexer_->NextToken();
997     }
998 
999     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD) {
1000         typeName = ParseTsQualifiedReference(typeName);
1001     }
1002 
1003     ir::TSTypeParameterInstantiation *typeParamInst = nullptr;
1004     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) {
1005         if (parseQuery) {
1006             ThrowSyntaxError("Unexpected token.");
1007         }
1008 
1009         typeParamInst = ParseTsTypeParameterInstantiation();
1010     }
1011 
1012     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET &&
1013         lexer_->Lookahead() != LEX_CHAR_RIGHT_SQUARE) {
1014         if (parseQuery) {
1015             typeName = AllocNode<ir::TSTypeQuery>(typeName);
1016         } else {
1017             typeName = AllocNode<ir::TSTypeReference>(typeName, typeParamInst);
1018         }
1019 
1020         typeName->SetRange({referenceStartLoc, lexer_->GetToken().End()});
1021 
1022         return ParseTsIndexAccessType(typeName);
1023     }
1024 
1025     ir::Expression *returnNode = nullptr;
1026 
1027     lexer::SourcePosition referenceEndLoc = typeName->End();
1028 
1029     if (parseQuery) {
1030         returnNode = AllocNode<ir::TSTypeQuery>(typeName);
1031     } else {
1032         returnNode = AllocNode<ir::TSTypeReference>(typeName, typeParamInst);
1033     }
1034 
1035     returnNode->SetRange({referenceStartLoc, referenceEndLoc});
1036 
1037     return returnNode;
1038 }
1039 
ParseTsMappedTypeParameter()1040 ir::TSTypeParameter *ParserImpl::ParseTsMappedTypeParameter()
1041 {
1042     lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1043 
1044     auto *paramName = AllocNode<ir::Identifier>(lexer_->GetToken().Ident(), Allocator());
1045     paramName->SetRange({lexer_->GetToken().Start(), lexer_->GetToken().End()});
1046 
1047     lexer_->NextToken();
1048 
1049     lexer_->NextToken();  // eat 'in'
1050 
1051     TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
1052     ir::Expression *constraint = ParseTsTypeAnnotation(&options);
1053 
1054     lexer::SourcePosition endLoc = constraint->End();
1055 
1056     auto *typeParameter = AllocNode<ir::TSTypeParameter>(paramName, constraint, nullptr);
1057 
1058     typeParameter->SetRange({startLoc, endLoc});
1059 
1060     return typeParameter;
1061 }
1062 
ParseMappedOption(lexer::TokenType tokenType)1063 ir::MappedOption ParserImpl::ParseMappedOption(lexer::TokenType tokenType)
1064 {
1065     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_MINUS &&
1066         lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_PLUS &&
1067         lexer_->GetToken().KeywordType() != tokenType && lexer_->GetToken().Type() != tokenType) {
1068         return ir::MappedOption::NO_OPTS;
1069     }
1070 
1071     auto result = lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MINUS ? ir::MappedOption::MINUS
1072                                                                                   : ir::MappedOption::PLUS;
1073 
1074     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MINUS ||
1075         lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PLUS) {
1076         lexer_->NextToken();
1077     }
1078 
1079     if (lexer_->GetToken().KeywordType() != tokenType && lexer_->GetToken().Type() != tokenType) {
1080         ThrowSyntaxError({"'", TokenToString(tokenType), "' expected."});
1081     }
1082 
1083     lexer_->NextToken();
1084 
1085     return result;
1086 }
1087 
ParseTsMappedType()1088 ir::TSMappedType *ParserImpl::ParseTsMappedType()
1089 {
1090     ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE);
1091 
1092     lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1093     lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);  // eat '{'
1094 
1095     ir::MappedOption readonly = ParseMappedOption(lexer::TokenType::KEYW_READONLY);
1096 
1097     lexer_->NextToken();  // eat '['
1098 
1099     ir::TSTypeParameter *typeParameter = ParseTsMappedTypeParameter();
1100 
1101     ir::Expression *nameKeyType = nullptr;
1102     if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_AS) {
1103         lexer_->NextToken();  // eat 'as'
1104         TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
1105         nameKeyType = ParseTsTypeAnnotation(&options);
1106         ASSERT(nameKeyType != nullptr);
1107     }
1108 
1109     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
1110         ThrowSyntaxError("']' expected");
1111     }
1112 
1113     lexer_->NextToken();  // eat ']'
1114 
1115     ir::MappedOption optional = ParseMappedOption(lexer::TokenType::PUNCTUATOR_QUESTION_MARK);
1116 
1117     ir::Expression *typeAnnotation = nullptr;
1118     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
1119         lexer_->NextToken();  // eat ':'
1120         TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
1121         typeAnnotation = ParseTsTypeAnnotation(&options);
1122     }
1123 
1124     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON &&
1125         lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
1126         ThrowSyntaxError("';' expected");
1127     }
1128 
1129     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
1130         lexer_->NextToken();  // eat ';'
1131     }
1132 
1133     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
1134         ThrowSyntaxError("'}' expected");
1135     }
1136 
1137     auto *mappedType = AllocNode<ir::TSMappedType>(typeParameter, nameKeyType, typeAnnotation, readonly, optional);
1138 
1139     mappedType->SetRange({startLoc, lexer_->GetToken().End()});
1140 
1141     lexer_->NextToken();  // eat '}'
1142 
1143     return mappedType;
1144 }
1145 
ParseTsTypePredicate()1146 ir::TSTypePredicate *ParserImpl::ParseTsTypePredicate()
1147 {
1148     auto pos = lexer_->Save();
1149     lexer::SourcePosition startPos = lexer_->GetToken().Start();
1150     bool isAsserts = lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_ASSERTS;
1151     if (isAsserts) {
1152         lexer_->NextToken();  // eat 'asserts'
1153         if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_IS) {
1154             isAsserts = false;
1155             lexer_->Rewind(pos);
1156         }
1157     }
1158 
1159     ir::Expression *parameterName = nullptr;
1160     if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) {
1161         parameterName = AllocNode<ir::Identifier>(lexer_->GetToken().Ident(), Allocator());
1162     } else {
1163         parameterName = AllocNode<ir::TSThisType>();
1164     }
1165 
1166     parameterName->SetRange({lexer_->GetToken().Start(), lexer_->GetToken().End()});
1167 
1168     lexer_->NextToken();
1169 
1170     ir::Expression *typeAnnotation = nullptr;
1171     lexer::SourcePosition endPos;
1172     ir::TSTypePredicate *result = nullptr;
1173 
1174     if (isAsserts && lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_IS) {
1175         endPos = parameterName->End();
1176         result = AllocNode<ir::TSTypePredicate>(parameterName, typeAnnotation, isAsserts);
1177         result->SetRange({startPos, endPos});
1178         return result;
1179     }
1180 
1181     lexer_->NextToken();  // eat 'is'
1182 
1183     TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
1184     typeAnnotation = ParseTsTypeAnnotation(&options);
1185     endPos = typeAnnotation->End();
1186 
1187     result = AllocNode<ir::TSTypePredicate>(parameterName, typeAnnotation, isAsserts);
1188 
1189     result->SetRange({startPos, endPos});
1190 
1191     return result;
1192 }
1193 
ParseTsTypeLiteralOrInterfaceKey(bool * computed,bool * signature,bool * isIndexSignature)1194 ir::Expression *ParserImpl::ParseTsTypeLiteralOrInterfaceKey(bool *computed, bool *signature, bool *isIndexSignature)
1195 {
1196     ir::Expression *key = nullptr;
1197 
1198     if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT &&
1199         (lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_NEW ||
1200          (lexer_->Lookahead() != LEX_CHAR_LEFT_PAREN && lexer_->Lookahead() != LEX_CHAR_LESS_THAN))) {
1201         key = AllocNode<ir::Identifier>(lexer_->GetToken().Ident(), Allocator());
1202         key->SetRange(lexer_->GetToken().Loc());
1203         lexer_->NextToken();
1204     } else if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_NUMBER) {
1205         if (lexer_->GetToken().Flags() & lexer::TokenFlags::NUMBER_BIGINT) {
1206             key = AllocNode<ir::BigIntLiteral>(lexer_->GetToken().BigInt());
1207         } else {
1208             key = AllocNode<ir::NumberLiteral>(lexer_->GetToken().Number(), lexer_->GetToken().String());
1209         }
1210 
1211         key->SetRange(lexer_->GetToken().Loc());
1212         lexer_->NextToken();
1213     } else if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_STRING) {
1214         key = AllocNode<ir::StringLiteral>(lexer_->GetToken().String());
1215         key->SetRange(lexer_->GetToken().Loc());
1216         lexer_->NextToken();
1217     } else if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET) {
1218         *computed = true;
1219         lexer_->NextToken();  // eat '['
1220 
1221         if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT && lexer_->Lookahead() == LEX_CHAR_COLON) {
1222             *isIndexSignature = true;
1223             key = AllocNode<ir::Identifier>(lexer_->GetToken().Ident(), Allocator());
1224             key->SetRange(lexer_->GetToken().Loc());
1225 
1226             lexer_->NextToken();  // eat param
1227 
1228             if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COLON) {
1229                 ThrowSyntaxError("':' expected");
1230             }
1231 
1232             lexer_->NextToken();  // eat ':'
1233 
1234             TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
1235             ir::Expression *typeAnnotation = ParseTsTypeAnnotation(&options);
1236 
1237             if (!typeAnnotation->IsTSNumberKeyword() && !typeAnnotation->IsTSStringKeyword()) {
1238                 ThrowSyntaxError(
1239                     "An index signature parameter type must be either "
1240                     "'string' or 'number'");
1241             }
1242 
1243             key->SetTsTypeAnnotation(typeAnnotation);
1244         } else {
1245             key = ParseExpression();
1246         }
1247 
1248         if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
1249             ThrowSyntaxError("']' expected");
1250         }
1251 
1252         lexer_->NextToken();  // eat ']'
1253     } else if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS &&
1254                lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LESS_THAN &&
1255                lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_NEW) {
1256         ThrowSyntaxError("Unexpected token");
1257     } else {
1258         *signature = true;
1259     }
1260 
1261     return key;
1262 }
1263 
CreateTSVariableForProperty(ir::AstNode * node,const ir::Expression * key,binder::VariableFlags flags)1264 void ParserImpl::CreateTSVariableForProperty(ir::AstNode *node, const ir::Expression *key, binder::VariableFlags flags)
1265 {
1266     binder::Variable *propVar = nullptr;
1267     bool isMethod = flags & binder::VariableFlags::METHOD;
1268     util::StringView propName = "__computed";
1269 
1270     switch (key->Type()) {
1271         case ir::AstNodeType::IDENTIFIER: {
1272             propName = key->AsIdentifier()->Name();
1273             break;
1274         }
1275         case ir::AstNodeType::NUMBER_LITERAL: {
1276             propName = key->AsNumberLiteral()->Str();
1277             flags |= binder::VariableFlags::NUMERIC_NAME;
1278             break;
1279         }
1280         case ir::AstNodeType::STRING_LITERAL: {
1281             propName = key->AsStringLiteral()->Str();
1282             break;
1283         }
1284         default: {
1285             flags |= binder::VariableFlags::COMPUTED;
1286             break;
1287         }
1288     }
1289 
1290     propVar = isMethod ? binder::Scope::CreateVar<binder::MethodDecl>(Allocator(), propName, flags, node)
1291                        : binder::Scope::CreateVar<binder::PropertyDecl>(Allocator(), propName, flags, node);
1292 
1293     node->SetVariable(propVar);
1294 }
1295 
ParseTsTypeLiteralOrInterfaceMember()1296 ir::Expression *ParserImpl::ParseTsTypeLiteralOrInterfaceMember()
1297 {
1298     bool computed = false;
1299     bool optional = false;
1300     bool signature = false;
1301     bool readonly = false;
1302     bool isConstructSignature = false;
1303     bool isIndexSignature = false;
1304     lexer::SourcePosition memberStartLoc = lexer_->GetToken().Start();
1305     char32_t nextToken = lexer_->Lookahead();
1306     if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_READONLY && nextToken != LEX_CHAR_LEFT_PAREN &&
1307         nextToken != LEX_CHAR_COLON && nextToken != LEX_CHAR_COMMA && nextToken != LEX_CHAR_LESS_THAN &&
1308         nextToken != LEX_CHAR_SEMICOLON) {
1309         readonly = true;
1310         lexer_->NextToken();
1311     }
1312 
1313     ir::Expression *key = ParseTsTypeLiteralOrInterfaceKey(&computed, &signature, &isIndexSignature);
1314 
1315     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_QUESTION_MARK) {
1316         if (isIndexSignature) {
1317             ThrowSyntaxError("';' expected");
1318         }
1319 
1320         optional = true;
1321         lexer_->NextToken();  // eat '?'
1322     }
1323 
1324     if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_NEW && signature) {
1325         lexer_->NextToken();  // eat 'new'
1326 
1327         if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS &&
1328             lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LESS_THAN) {
1329             ThrowSyntaxError("'(' expected");
1330         }
1331 
1332         isConstructSignature = true;
1333     }
1334 
1335     ir::TSTypeParameterDeclaration *typeParamDecl = nullptr;
1336     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) {
1337         if (isIndexSignature) {
1338             ThrowSyntaxError("';' expected");
1339         }
1340 
1341         typeParamDecl = ParseTsTypeParameterDeclaration();
1342 
1343         if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
1344             ThrowSyntaxError("'(' expected");
1345         }
1346     }
1347 
1348     ir::Expression *member = nullptr;
1349     ir::Expression *typeAnnotation = nullptr;
1350     binder::VariableFlags flags = binder::VariableFlags::NONE;
1351 
1352     if (optional) {
1353         flags |= binder::VariableFlags::OPTIONAL;
1354     }
1355 
1356     if (readonly) {
1357         flags |= binder::VariableFlags::READONLY;
1358     }
1359 
1360     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS && !isIndexSignature) {
1361         FunctionParameterContext funcParamContext(&context_, Binder());
1362         auto *funcParamScope = funcParamContext.LexicalScope().GetScope();
1363         ArenaVector<ir::Expression *> params = ParseFunctionParams(true);
1364 
1365         if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
1366             lexer_->NextToken();  // eat ':'
1367             TypeAnnotationParsingOptions options =
1368                 TypeAnnotationParsingOptions::THROW_ERROR | TypeAnnotationParsingOptions::CAN_BE_TS_TYPE_PREDICATE;
1369             typeAnnotation = ParseTsTypeAnnotation(&options);
1370         }
1371 
1372         if (signature) {
1373             auto kind = isConstructSignature
1374                             ? ir::TSSignatureDeclaration::TSSignatureDeclarationKind::CONSTRUCT_SIGNATURE
1375                             : ir::TSSignatureDeclaration::TSSignatureDeclarationKind::CALL_SIGNATURE;
1376             member = AllocNode<ir::TSSignatureDeclaration>(funcParamScope, kind, typeParamDecl, std::move(params),
1377                                                            typeAnnotation);
1378             funcParamScope->BindNode(member);
1379         } else {
1380             member = AllocNode<ir::TSMethodSignature>(funcParamScope, key, typeParamDecl, std::move(params),
1381                                                       typeAnnotation, computed, optional);
1382             funcParamScope->BindNode(member);
1383             CreateTSVariableForProperty(member, key, flags | binder::VariableFlags::METHOD);
1384         }
1385     } else if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
1386         lexer_->NextToken();  // eat ':'
1387         TypeAnnotationParsingOptions options =
1388             TypeAnnotationParsingOptions::THROW_ERROR | TypeAnnotationParsingOptions::BREAK_AT_NEW_LINE;
1389         typeAnnotation = ParseTsTypeAnnotation(&options);
1390     } else if (isIndexSignature) {
1391         ThrowSyntaxError("An index signature must have a type annotation.", memberStartLoc);
1392     }
1393 
1394     if (!member && isIndexSignature) {
1395         member = AllocNode<ir::TSIndexSignature>(key, typeAnnotation, readonly);
1396     } else if (!member) {
1397         member = AllocNode<ir::TSPropertySignature>(key, typeAnnotation, computed, optional, readonly);
1398         CreateTSVariableForProperty(member, key, flags | binder::VariableFlags::PROPERTY);
1399     } else if (readonly) {
1400         ThrowSyntaxError(
1401             "'readonly' modifier can only appear on a property "
1402             "declaration or index signature.",
1403             memberStartLoc);
1404     }
1405 
1406     member->SetRange({memberStartLoc, lexer_->GetToken().End()});
1407 
1408     return member;
1409 }
1410 
GetTSPropertyName(ir::Expression * key)1411 util::StringView GetTSPropertyName(ir::Expression *key)
1412 {
1413     switch (key->Type()) {
1414         case ir::AstNodeType::IDENTIFIER: {
1415             return key->AsIdentifier()->Name();
1416         }
1417         case ir::AstNodeType::NUMBER_LITERAL: {
1418             return key->AsNumberLiteral()->Str();
1419         }
1420         case ir::AstNodeType::STRING_LITERAL: {
1421             return key->AsStringLiteral()->Str();
1422         }
1423         default: {
1424             UNREACHABLE();
1425         }
1426     }
1427 }
1428 
CheckObjectTypeForDuplicatedProperties(ir::Expression * member,ArenaVector<ir::Expression * > const & members)1429 void ParserImpl::CheckObjectTypeForDuplicatedProperties(ir::Expression *member, ArenaVector<ir::Expression *> const &members)
1430 {
1431     ir::Expression *key = nullptr;
1432 
1433     if (member->IsTSPropertySignature()) {
1434         key = member->AsTSPropertySignature()->Key();
1435     } else if (member->IsTSMethodSignature()) {
1436         key = member->AsTSMethodSignature()->Key();
1437     } else {
1438         return;
1439     }
1440 
1441     if (!key->IsIdentifier() && !key->IsNumberLiteral() && !key->IsStringLiteral()) {
1442         return;
1443     }
1444 
1445     for (auto *it : members) {
1446         ir::Expression *compare = nullptr;
1447 
1448         switch (it->Type()) {
1449             case ir::AstNodeType::TS_PROPERTY_SIGNATURE: {
1450                 compare = it->AsTSPropertySignature()->Key();
1451                 break;
1452             }
1453             case ir::AstNodeType::TS_METHOD_SIGNATURE: {
1454                 compare = it->AsTSMethodSignature()->Key();
1455                 break;
1456             }
1457             default: {
1458                 continue;
1459             }
1460         }
1461 
1462         if (!compare->IsIdentifier() && !compare->IsNumberLiteral() && !compare->IsStringLiteral()) {
1463             continue;
1464         }
1465 
1466         if (member->IsTSMethodSignature() && it->Type() == ir::AstNodeType::TS_METHOD_SIGNATURE) {
1467             continue;
1468         }
1469 
1470         if (GetTSPropertyName(key) == GetTSPropertyName(compare)) {
1471             ThrowSyntaxError("Duplicated identifier", key->Start());
1472         }
1473     }
1474 }
1475 
ParseTsTypeLiteralOrInterface()1476 ArenaVector<ir::Expression *> ParserImpl::ParseTsTypeLiteralOrInterface()
1477 {
1478     ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE);
1479 
1480     lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);  // eat '{'
1481 
1482     ArenaVector<ir::Expression *> members(Allocator()->Adapter());
1483 
1484     while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
1485         ir::Expression *member = ParseTsTypeLiteralOrInterfaceMember();
1486 
1487         CheckObjectTypeForDuplicatedProperties(member, members);
1488 
1489         members.push_back(member);
1490 
1491         if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
1492             break;
1493         }
1494 
1495         if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COMMA &&
1496             lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
1497             if (!lexer_->GetToken().NewLine()) {
1498                 ThrowSyntaxError("',' expected");
1499             }
1500 
1501             if (lexer_->GetToken().IsKeyword()) {
1502                 lexer_->GetToken().SetTokenType(lexer::TokenType::LITERAL_IDENT);
1503             }
1504 
1505             continue;
1506         }
1507 
1508         lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);
1509     }
1510 
1511     return members;
1512 }
1513 
ParseTsArrayType(ir::Expression * elementType)1514 ir::TSArrayType *ParserImpl::ParseTsArrayType(ir::Expression *elementType)
1515 {
1516     ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET);
1517     lexer_->NextToken();  // eat '['
1518 
1519     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
1520         ThrowSyntaxError("']' expected");
1521     }
1522 
1523     lexer::SourcePosition endLoc = lexer_->GetToken().End();
1524     lexer_->NextToken();  // eat ']'
1525 
1526     lexer::SourcePosition startLoc = elementType->Start();
1527     auto *arrayType = AllocNode<ir::TSArrayType>(elementType);
1528     arrayType->SetRange({startLoc, endLoc});
1529 
1530     return arrayType;
1531 }
1532 
ParseTsUnionType(ir::Expression * type,bool restrictExtends)1533 ir::TSUnionType *ParserImpl::ParseTsUnionType(ir::Expression *type, bool restrictExtends)
1534 {
1535     ArenaVector<ir::Expression *> types(Allocator()->Adapter());
1536     lexer::SourcePosition startLoc;
1537 
1538     TypeAnnotationParsingOptions options =
1539         TypeAnnotationParsingOptions::THROW_ERROR | TypeAnnotationParsingOptions::IN_UNION;
1540 
1541     if (restrictExtends) {
1542         options |= TypeAnnotationParsingOptions::RESTRICT_EXTENDS;
1543     }
1544 
1545     if (type) {
1546         startLoc = type->Start();
1547         types.push_back(type);
1548     } else {
1549         startLoc = lexer_->GetToken().Start();
1550     }
1551 
1552     while (true) {
1553         if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_BITWISE_OR) {
1554             break;
1555         }
1556 
1557         lexer_->NextToken();  // eat '|'
1558 
1559         types.push_back(ParseTsTypeAnnotation(&options));
1560     }
1561 
1562     lexer::SourcePosition endLoc = types.back()->End();
1563 
1564     auto *unionType = AllocNode<ir::TSUnionType>(std::move(types));
1565     auto *typeVar = binder::Scope::CreateVar(Allocator(), "__type", binder::VariableFlags::TYPE, unionType);
1566     unionType->SetVariable(typeVar);
1567     unionType->SetRange({startLoc, endLoc});
1568 
1569     return unionType;
1570 }
1571 
ParseTsIntersectionType(ir::Expression * type,bool inUnion,bool restrictExtends)1572 ir::TSIntersectionType *ParserImpl::ParseTsIntersectionType(ir::Expression *type, bool inUnion, bool restrictExtends)
1573 {
1574     ArenaVector<ir::Expression *> types(Allocator()->Adapter());
1575     lexer::SourcePosition startLoc;
1576 
1577     TypeAnnotationParsingOptions options =
1578         TypeAnnotationParsingOptions::THROW_ERROR | TypeAnnotationParsingOptions::IN_INTERSECTION;
1579 
1580     if (restrictExtends) {
1581         options |= TypeAnnotationParsingOptions::RESTRICT_EXTENDS;
1582     }
1583 
1584     if (inUnion) {
1585         options |= TypeAnnotationParsingOptions::IN_UNION;
1586     }
1587 
1588     if (type) {
1589         startLoc = type->Start();
1590         types.push_back(type);
1591     } else {
1592         startLoc = lexer_->GetToken().Start();
1593     }
1594 
1595     while (true) {
1596         if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_BITWISE_AND) {
1597             break;
1598         }
1599 
1600         lexer_->NextToken();  // eat '&'
1601 
1602         types.push_back(ParseTsTypeAnnotation(&options));
1603     }
1604 
1605     lexer::SourcePosition endLoc = types.back()->End();
1606 
1607     auto *intersectionType = AllocNode<ir::TSIntersectionType>(std::move(types));
1608     auto *typeVar = binder::Scope::CreateVar(Allocator(), "__type", binder::VariableFlags::TYPE, intersectionType);
1609     intersectionType->SetVariable(typeVar);
1610     intersectionType->SetRange({startLoc, endLoc});
1611 
1612     return intersectionType;
1613 }
1614 
ParseTsParenthesizedOrFunctionType(ir::Expression * typeAnnotation,bool throwError)1615 ir::Expression *ParserImpl::ParseTsParenthesizedOrFunctionType(ir::Expression *typeAnnotation, bool throwError)
1616 {
1617     if (typeAnnotation) {
1618         return nullptr;
1619     }
1620 
1621     lexer::SourcePosition typeStart = lexer_->GetToken().Start();
1622 
1623     bool abstractConstructor = lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_ABSTRACT;
1624     if (abstractConstructor) {
1625         lexer_->NextToken();  // eat 'abstract'
1626     }
1627 
1628     bool isConstructionType = false;
1629 
1630     if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_NEW) {
1631         lexer_->NextToken();  // eat 'new'
1632         isConstructionType = true;
1633 
1634         if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS &&
1635             lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LESS_THAN) {
1636             ThrowSyntaxError("'(' expected");
1637         }
1638     }
1639 
1640     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN || isConstructionType) {
1641         return ParseTsFunctionType(typeStart, isConstructionType, throwError, abstractConstructor);
1642     }
1643 
1644     const auto startPos = lexer_->Save();
1645     ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS);
1646     lexer_->NextToken();  // eat '('
1647 
1648     TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::NO_OPTS;
1649     ir::Expression *type = ParseTsTypeAnnotation(&options);
1650 
1651     if (!type) {
1652         lexer_->Rewind(startPos);
1653         return ParseTsFunctionType(typeStart, false, throwError);
1654     }
1655 
1656     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA ||
1657         lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_QUESTION_MARK ||
1658         lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
1659         lexer_->Rewind(startPos);
1660         return ParseTsFunctionType(typeStart, false, throwError);
1661     }
1662 
1663     if (throwError && lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
1664         ThrowSyntaxError("')' expected");
1665     }
1666 
1667     lexer::SourcePosition endLoc = lexer_->GetToken().End();
1668     lexer_->NextToken();  // eat ')'
1669 
1670     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_ARROW) {
1671         lexer_->Rewind(startPos);
1672 
1673         return ParseTsFunctionType(typeStart, false, throwError);
1674     }
1675 
1676     auto *result = AllocNode<ir::TSParenthesizedType>(type);
1677     result->SetRange({typeStart, endLoc});
1678 
1679     return result;
1680 }
1681 
ParseTsFunctionType(lexer::SourcePosition startLoc,bool isConstructionType,bool throwError,bool abstractConstructor)1682 ir::Expression *ParserImpl::ParseTsFunctionType(lexer::SourcePosition startLoc, bool isConstructionType,
1683                                                 bool throwError, bool abstractConstructor)
1684 {
1685     ir::TSTypeParameterDeclaration *typeParamDecl = nullptr;
1686     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) {
1687         typeParamDecl = ParseTsTypeParameterDeclaration(throwError);
1688 
1689         if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
1690             if (!throwError) {
1691                 return nullptr;
1692             }
1693 
1694             ThrowSyntaxError("'(' expected");
1695         }
1696     }
1697 
1698     FunctionParameterContext funcParamContext(&context_, Binder());
1699     auto *funcParamScope = funcParamContext.LexicalScope().GetScope();
1700     ArenaVector<ir::Expression *> params = ParseFunctionParams(true);
1701 
1702     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_ARROW) {
1703         ThrowSyntaxError("'=>' expected");
1704     }
1705 
1706     lexer_->NextToken();  // eat '=>'
1707 
1708     TypeAnnotationParsingOptions options =
1709         TypeAnnotationParsingOptions::THROW_ERROR | TypeAnnotationParsingOptions::CAN_BE_TS_TYPE_PREDICATE;
1710     ir::Expression *returnTypeAnnotation = ParseTsTypeAnnotation(&options);
1711 
1712     ir::Expression *funcType = nullptr;
1713 
1714     if (isConstructionType) {
1715         funcType = AllocNode<ir::TSConstructorType>(funcParamScope, std::move(params), typeParamDecl,
1716                                                     returnTypeAnnotation, abstractConstructor);
1717     } else {
1718         funcType =
1719             AllocNode<ir::TSFunctionType>(funcParamScope, std::move(params), typeParamDecl, returnTypeAnnotation);
1720     }
1721 
1722     funcType->SetRange({startLoc, returnTypeAnnotation->End()});
1723     funcParamScope->BindNode(funcType);
1724 
1725     return funcType;
1726 }
1727 
ParseTsBasicType()1728 ir::Expression *ParserImpl::ParseTsBasicType()
1729 {
1730     ir::Expression *typeAnnotation = nullptr;
1731 
1732     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MINUS) {
1733         lexer_->NextToken();
1734 
1735         if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_NUMBER) {
1736             ThrowSyntaxError("Type expected");
1737         }
1738     }
1739     if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_NUMBER) {
1740         if (lexer_->GetToken().Flags() & lexer::TokenFlags::NUMBER_BIGINT) {
1741             auto *bigintNode = AllocNode<ir::BigIntLiteral>(lexer_->GetToken().BigInt());
1742             bigintNode->SetRange(lexer_->GetToken().Loc());
1743 
1744             typeAnnotation = AllocNode<ir::TSLiteralType>(bigintNode);
1745         } else {
1746             auto *numberNode = AllocNode<ir::NumberLiteral>(lexer_->GetToken().Number(), lexer_->GetToken().String());
1747             numberNode->SetRange(lexer_->GetToken().Loc());
1748 
1749             typeAnnotation = AllocNode<ir::TSLiteralType>(numberNode);
1750         }
1751     } else if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_STRING) {
1752         auto *stringNode = AllocNode<ir::StringLiteral>(lexer_->GetToken().String());
1753         stringNode->SetRange(lexer_->GetToken().Loc());
1754 
1755         typeAnnotation = AllocNode<ir::TSLiteralType>(stringNode);
1756     } else if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_TRUE) {
1757         auto *booleanLiteral = AllocNode<ir::BooleanLiteral>(true);
1758         booleanLiteral->SetRange(lexer_->GetToken().Loc());
1759 
1760         typeAnnotation = AllocNode<ir::TSLiteralType>(booleanLiteral);
1761     } else if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_FALSE) {
1762         auto *booleanLiteral = AllocNode<ir::BooleanLiteral>(false);
1763         booleanLiteral->SetRange(lexer_->GetToken().Loc());
1764 
1765         typeAnnotation = AllocNode<ir::TSLiteralType>(booleanLiteral);
1766     } else if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_ANY) {
1767         typeAnnotation = AllocNode<ir::TSAnyKeyword>();
1768     } else if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_BOOLEAN) {
1769         typeAnnotation = AllocNode<ir::TSBooleanKeyword>();
1770     } else if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_NUMBER) {
1771         typeAnnotation = AllocNode<ir::TSNumberKeyword>();
1772     } else if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_STRING) {
1773         typeAnnotation = AllocNode<ir::TSStringKeyword>();
1774     } else if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_UNKNOWN) {
1775         typeAnnotation = AllocNode<ir::TSUnknownKeyword>();
1776     } else if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_VOID) {
1777         typeAnnotation = AllocNode<ir::TSVoidKeyword>();
1778     } else if (lexer_->GetToken().KeywordType() == lexer::TokenType::LITERAL_NULL) {
1779         typeAnnotation = AllocNode<ir::TSNullKeyword>();
1780     } else if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_UNDEFINED) {
1781         typeAnnotation = AllocNode<ir::TSUndefinedKeyword>();
1782     } else if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_NEVER) {
1783         typeAnnotation = AllocNode<ir::TSNeverKeyword>();
1784     } else if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_OBJECT) {
1785         typeAnnotation = AllocNode<ir::TSObjectKeyword>();
1786     } else if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_BIGINT) {
1787         typeAnnotation = AllocNode<ir::TSBigintKeyword>();
1788     } else if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_SYMBOL) {
1789         typeAnnotation = AllocNode<ir::TSSymbolKeyword>();
1790     } else {
1791         ThrowSyntaxError("Unexpected type");
1792     }
1793 
1794     typeAnnotation->SetRange(lexer_->GetToken().Loc());
1795 
1796     lexer_->NextToken();
1797     return typeAnnotation;
1798 }
1799 
GetAccessability(ir::ModifierFlags modifiers)1800 static ir::ModifierFlags GetAccessability(ir::ModifierFlags modifiers)
1801 {
1802     if (modifiers & ir::ModifierFlags::PUBLIC) {
1803         return ir::ModifierFlags::PUBLIC;
1804     }
1805 
1806     if (modifiers & ir::ModifierFlags::PRIVATE) {
1807         return ir::ModifierFlags::PRIVATE;
1808     }
1809 
1810     if (modifiers & ir::ModifierFlags::PROTECTED) {
1811         return ir::ModifierFlags::PROTECTED;
1812     }
1813 
1814     return ir::ModifierFlags::NONE;
1815 }
1816 
IsModifierKind(const lexer::Token & token)1817 static bool IsModifierKind(const lexer::Token &token)
1818 {
1819     if (token.Type() == lexer::TokenType::LITERAL_IDENT) {
1820         switch (token.KeywordType()) {
1821             case lexer::TokenType::KEYW_PUBLIC:
1822             case lexer::TokenType::KEYW_PRIVATE:
1823             case lexer::TokenType::KEYW_PROTECTED:
1824             case lexer::TokenType::KEYW_STATIC:
1825             case lexer::TokenType::KEYW_ASYNC:
1826             case lexer::TokenType::KEYW_ABSTRACT:
1827             case lexer::TokenType::KEYW_DECLARE:
1828             case lexer::TokenType::KEYW_READONLY:
1829                 return true;
1830             default:
1831                 return false;
1832         }
1833     }
1834 
1835     return false;
1836 }
1837 
ParseModifiers()1838 ir::ModifierFlags ParserImpl::ParseModifiers()
1839 {
1840     ir::ModifierFlags resultStatus = ir::ModifierFlags::NONE;
1841     ir::ModifierFlags prevStatus = ir::ModifierFlags::ALL;
1842 
1843     while (IsModifierKind(lexer_->GetToken())) {
1844         char32_t nextCp = lexer_->Lookahead();
1845         if (!((Extension() == ScriptExtension::JS && nextCp != LEX_CHAR_LEFT_PAREN) ||
1846               (Extension() == ScriptExtension::TS && nextCp != LEX_CHAR_EQUALS && nextCp != LEX_CHAR_SEMICOLON &&
1847                nextCp != LEX_CHAR_COMMA && nextCp != LEX_CHAR_LEFT_PAREN))) {
1848             break;
1849         }
1850 
1851         lexer::TokenFlags tokenFlags = lexer_->GetToken().Flags();
1852         if (tokenFlags & lexer::TokenFlags::HAS_ESCAPE) {
1853             ThrowSyntaxError("Keyword must not contain escaped characters");
1854         }
1855 
1856         ir::ModifierFlags actualStatus = ir::ModifierFlags::NONE;
1857         ir::ModifierFlags nextStatus = ir::ModifierFlags::NONE;
1858 
1859         switch (lexer_->GetToken().KeywordType()) {
1860             case lexer::TokenType::KEYW_PUBLIC: {
1861                 actualStatus = ir::ModifierFlags::PUBLIC;
1862                 nextStatus = ir::ModifierFlags::ASYNC | ir::ModifierFlags::STATIC | ir::ModifierFlags::READONLY |
1863                              ir::ModifierFlags::DECLARE | ir::ModifierFlags::ABSTRACT;
1864                 break;
1865             }
1866             case lexer::TokenType::KEYW_PRIVATE: {
1867                 actualStatus = ir::ModifierFlags::PRIVATE;
1868                 nextStatus = ir::ModifierFlags::ASYNC | ir::ModifierFlags::STATIC | ir::ModifierFlags::READONLY |
1869                              ir::ModifierFlags::DECLARE | ir::ModifierFlags::ABSTRACT;
1870                 break;
1871             }
1872             case lexer::TokenType::KEYW_PROTECTED: {
1873                 actualStatus = ir::ModifierFlags::PROTECTED;
1874                 nextStatus = ir::ModifierFlags::ASYNC | ir::ModifierFlags::STATIC | ir::ModifierFlags::READONLY |
1875                              ir::ModifierFlags::DECLARE | ir::ModifierFlags::ABSTRACT;
1876                 break;
1877             }
1878             case lexer::TokenType::KEYW_STATIC: {
1879                 actualStatus = ir::ModifierFlags::STATIC;
1880                 nextStatus = ir::ModifierFlags::ASYNC | ir::ModifierFlags::READONLY | ir::ModifierFlags::DECLARE |
1881                              ir::ModifierFlags::ABSTRACT;
1882                 break;
1883             }
1884             case lexer::TokenType::KEYW_ASYNC: {
1885                 actualStatus = ir::ModifierFlags::ASYNC;
1886                 nextStatus = ir::ModifierFlags::READONLY | ir::ModifierFlags::DECLARE | ir::ModifierFlags::ABSTRACT;
1887                 break;
1888             }
1889             case lexer::TokenType::KEYW_ABSTRACT: {
1890                 actualStatus = ir::ModifierFlags::ABSTRACT;
1891                 nextStatus = ir::ModifierFlags::ACCESS | ir::ModifierFlags::ASYNC | ir::ModifierFlags::STATIC |
1892                              ir::ModifierFlags::READONLY | ir::ModifierFlags::DECLARE;
1893                 break;
1894             }
1895             case lexer::TokenType::KEYW_DECLARE: {
1896                 actualStatus = ir::ModifierFlags::DECLARE;
1897                 nextStatus = ir::ModifierFlags::ACCESS | ir::ModifierFlags::ASYNC | ir::ModifierFlags::STATIC |
1898                              ir::ModifierFlags::READONLY;
1899                 break;
1900             }
1901             case lexer::TokenType::KEYW_READONLY: {
1902                 actualStatus = ir::ModifierFlags::READONLY;
1903                 nextStatus = ir::ModifierFlags::ASYNC | ir::ModifierFlags::DECLARE | ir::ModifierFlags::ABSTRACT;
1904                 break;
1905             }
1906             default: {
1907                 UNREACHABLE();
1908             }
1909         }
1910 
1911         if (lexer_->Lookahead() == LEX_CHAR_COLON || lexer_->Lookahead() == LEX_CHAR_COMMA ||
1912             lexer_->Lookahead() == LEX_CHAR_RIGHT_PAREN || lexer_->Lookahead() == LEX_CHAR_QUESTION ||
1913             lexer_->Lookahead() == LEX_CHAR_RIGHT_BRACE || lexer_->Lookahead() == LEX_CHAR_LESS_THAN) {
1914             break;
1915         }
1916 
1917         auto pos = lexer_->Save();
1918         lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);
1919 
1920         if ((prevStatus & actualStatus) == 0) {
1921             lexer_->Rewind(pos);
1922             ThrowSyntaxError("Unexpected modifier");
1923         }
1924 
1925         if ((resultStatus & actualStatus) != 0) {
1926             lexer_->Rewind(pos);
1927             ThrowSyntaxError("Duplicated modifier is not allowed");
1928         }
1929 
1930         if ((context_.Status() & ParserStatus::CONSTRUCTOR_FUNCTION) &&
1931             (actualStatus & ~ir::ModifierFlags::ALLOWED_IN_CTOR_PARAMETER)) {
1932             lexer_->Rewind(pos);
1933             ThrowParameterModifierError(actualStatus);
1934         }
1935 
1936         resultStatus |= actualStatus;
1937         prevStatus = nextStatus;
1938     }
1939 
1940     return resultStatus;
1941 }
1942 
CheckAccessorPair(const ArenaVector<ir::Statement * > & properties,const ir::Expression * propName,ir::MethodDefinitionKind methodKind,ir::ModifierFlags access,bool hasDecorator,lexer::SourcePosition errorInfo)1943 void ParserImpl::CheckAccessorPair(const ArenaVector<ir::Statement *> &properties, const ir::Expression *propName,
1944                                    ir::MethodDefinitionKind methodKind, ir::ModifierFlags access, bool hasDecorator,
1945                                    lexer::SourcePosition errorInfo)
1946 {
1947     for (const auto &it : properties) {
1948         if (!it->IsMethodDefinition() || (!hasDecorator && it->AsMethodDefinition()->Kind() != methodKind)) {
1949             continue;
1950         }
1951 
1952         const ir::Expression *key = it->AsMethodDefinition()->Key();
1953 
1954         if (key->Type() != propName->Type()) {
1955             continue;
1956         }
1957 
1958         bool keyIsSame = false;
1959 
1960         if (key->IsIdentifier()) {
1961             const util::StringView &strName = propName->AsIdentifier()->Name();
1962             const util::StringView &compareName = (key->AsIdentifier()->Name());
1963 
1964             keyIsSame = strName == compareName;
1965         } else if (key->IsNumberLiteral()) {
1966             keyIsSame = *key->AsNumberLiteral() == *propName->AsNumberLiteral();
1967         } else if (key->IsStringLiteral()) {
1968             keyIsSame = *key->AsStringLiteral() == *propName->AsStringLiteral();
1969         }
1970 
1971         if (!keyIsSame) {
1972             continue;
1973         }
1974 
1975         if (hasDecorator &&
1976             (it->AsMethodDefinition()->Kind() == ir::MethodDefinitionKind::GET ||
1977              it->AsMethodDefinition()->Kind() == ir::MethodDefinitionKind::SET) &&
1978             !it->AsMethodDefinition()->Decorators().empty()) {
1979             ThrowSyntaxError("Decorators cannot be applied to multiple get/set accessors of the same name.", errorInfo);
1980         }
1981 
1982         if (it->AsMethodDefinition()->Kind() != methodKind) {
1983             continue;
1984         }
1985 
1986         ir::ModifierFlags getAccess = ir::ModifierFlags::NONE;
1987         ir::ModifierFlags setAccess = ir::ModifierFlags::NONE;
1988 
1989         if (methodKind == ir::MethodDefinitionKind::GET) {
1990             setAccess = access;
1991             getAccess = GetAccessability(it->AsMethodDefinition()->Modifiers());
1992         } else {
1993             getAccess = access;
1994             setAccess = GetAccessability(it->AsMethodDefinition()->Modifiers());
1995         }
1996 
1997         if ((setAccess == ir::ModifierFlags::NONE && getAccess > ir::ModifierFlags::PUBLIC) ||
1998             (setAccess != ir::ModifierFlags::NONE && getAccess > setAccess)) {
1999             ThrowSyntaxError("A get accessor must be at least as accessible as the setter", key->Start());
2000         }
2001     }
2002 }
2003 
ParseClassKeyModifiers(ClassElmentDescriptor * desc)2004 void ParserImpl::ParseClassKeyModifiers(ClassElmentDescriptor *desc)
2005 {
2006     if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
2007         return;
2008     }
2009 
2010     char32_t nextCp = lexer_->Lookahead();
2011 
2012     if ((Extension() == ScriptExtension::JS && nextCp != LEX_CHAR_LEFT_PAREN) ||
2013         (Extension() == ScriptExtension::TS && nextCp != LEX_CHAR_EQUALS && nextCp != LEX_CHAR_SEMICOLON &&
2014          nextCp != LEX_CHAR_LEFT_PAREN)) {
2015         if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_GET) {
2016             if (desc->isPrivateIdent) {
2017                 ThrowSyntaxError("Private identifier can not be getter");
2018             }
2019 
2020             if (lexer_->GetToken().Flags() & lexer::TokenFlags::HAS_ESCAPE) {
2021                 ThrowSyntaxError("Keyword must not contain escaped characters");
2022             }
2023 
2024             desc->methodKind = ir::MethodDefinitionKind::GET;
2025             desc->methodStart = lexer_->GetToken().Start();
2026 
2027             lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);
2028         } else if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_SET) {
2029             if (desc->isPrivateIdent) {
2030                 ThrowSyntaxError("Private identifier can not be setter");
2031             }
2032 
2033             if (lexer_->GetToken().Flags() & lexer::TokenFlags::HAS_ESCAPE) {
2034                 ThrowSyntaxError("Keyword must not contain escaped characters");
2035             }
2036 
2037             desc->methodKind = ir::MethodDefinitionKind::SET;
2038             desc->methodStart = lexer_->GetToken().Start();
2039 
2040             lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);
2041         }
2042     }
2043 }
2044 
ThrowIfPrivateIdent(ClassElmentDescriptor * desc,const char * msg)2045 void ParserImpl::ThrowIfPrivateIdent(ClassElmentDescriptor *desc, const char *msg)
2046 {
2047     if (desc->isPrivateIdent) {
2048         ThrowSyntaxError(msg);
2049     }
2050 }
2051 
ValidateClassKey(ClassElmentDescriptor * desc,bool isDeclare)2052 void ParserImpl::ValidateClassKey(ClassElmentDescriptor *desc, bool isDeclare)
2053 {
2054     if ((desc->modifiers & ir::ModifierFlags::ASYNC) &&
2055         (desc->methodKind == ir::MethodDefinitionKind::GET || desc->methodKind == ir::MethodDefinitionKind::SET)) {
2056         ThrowSyntaxError("Async method can not be getter nor setter");
2057     }
2058 
2059     const util::StringView &propNameStr = lexer_->GetToken().Ident();
2060 
2061     if (propNameStr.Is("constructor")) {
2062         ThrowIfPrivateIdent(desc, "Private identifier can not be constructor");
2063 
2064         if (!(desc->modifiers & ir::ModifierFlags::STATIC)) {
2065             if ((desc->modifiers & ir::ModifierFlags::ASYNC) || desc->methodKind == ir::MethodDefinitionKind::GET ||
2066                 desc->methodKind == ir::MethodDefinitionKind::SET || desc->isGenerator) {
2067                 ThrowSyntaxError("Constructor can not be special method");
2068             }
2069 
2070             desc->methodKind = ir::MethodDefinitionKind::CONSTRUCTOR;
2071             desc->methodStart = lexer_->GetToken().Start();
2072             desc->newStatus |= ParserStatus::CONSTRUCTOR_FUNCTION;
2073 
2074             if (desc->hasSuperClass) {
2075                 desc->newStatus |= ParserStatus::ALLOW_SUPER_CALL;
2076             }
2077         } else if (Extension() == ScriptExtension::TS) {
2078             ThrowSyntaxError("Static modifier can not appear on a constructor");
2079         }
2080     } else if (!isDeclare && propNameStr.Is("prototype") && (desc->modifiers & ir::ModifierFlags::STATIC)) {
2081         ThrowSyntaxError("Classes may not have static property named prototype");
2082     }
2083 }
2084 
ParseClassKey(ClassElmentDescriptor * desc,bool isDeclare)2085 ir::Expression *ParserImpl::ParseClassKey(ClassElmentDescriptor *desc, bool isDeclare)
2086 {
2087     ir::Expression *propName = nullptr;
2088     if (lexer_->GetToken().IsKeyword()) {
2089         lexer_->GetToken().SetTokenType(lexer::TokenType::LITERAL_IDENT);
2090     }
2091 
2092     switch (lexer_->GetToken().Type()) {
2093         case lexer::TokenType::LITERAL_IDENT: {
2094             ValidateClassKey(desc, isDeclare);
2095 
2096             propName = AllocNode<ir::Identifier>(lexer_->GetToken().Ident(), Allocator());
2097             propName->SetRange(lexer_->GetToken().Loc());
2098             break;
2099         }
2100         case lexer::TokenType::LITERAL_STRING: {
2101             ThrowIfPrivateIdent(desc, "Private identifier name can not be string");
2102 
2103             propName = AllocNode<ir::StringLiteral>(lexer_->GetToken().String());
2104             propName->SetRange(lexer_->GetToken().Loc());
2105             break;
2106         }
2107         case lexer::TokenType::LITERAL_NUMBER: {
2108             ThrowIfPrivateIdent(desc, "Private identifier name can not be number");
2109 
2110             if (lexer_->GetToken().Flags() & lexer::TokenFlags::NUMBER_BIGINT) {
2111                 propName = AllocNode<ir::BigIntLiteral>(lexer_->GetToken().BigInt());
2112             } else {
2113                 propName = AllocNode<ir::NumberLiteral>(lexer_->GetToken().Number(), lexer_->GetToken().String());
2114             }
2115 
2116             propName->SetRange(lexer_->GetToken().Loc());
2117             break;
2118         }
2119         case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET: {
2120             ThrowIfPrivateIdent(desc, "Unexpected character in private identifier");
2121 
2122             lexer_->NextToken();  // eat left square bracket
2123 
2124             if (Extension() == ScriptExtension::TS && lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT &&
2125                 lexer_->Lookahead() == LEX_CHAR_COLON) {
2126                 desc->isIndexSignature = true;
2127 
2128                 propName = AllocNode<ir::Identifier>(lexer_->GetToken().Ident(), Allocator());
2129                 propName->SetRange(lexer_->GetToken().Loc());
2130 
2131                 lexer_->NextToken();  // eat param
2132 
2133                 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COLON) {
2134                     ThrowSyntaxError("':' expected");
2135                 }
2136 
2137                 lexer_->NextToken();  // eat ':'
2138                 TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
2139                 ir::Expression *typeAnnotation = ParseTsTypeAnnotation(&options);
2140 
2141                 if (!typeAnnotation->IsTSNumberKeyword() && !typeAnnotation->IsTSStringKeyword()) {
2142                     ThrowSyntaxError(
2143                         "An index signature parameter type must be either "
2144                         "'string' or 'number'");
2145                 }
2146 
2147                 propName->SetTsTypeAnnotation(typeAnnotation);
2148 
2149                 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
2150                     ThrowSyntaxError("']' expected");
2151                 }
2152 
2153                 lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);
2154 
2155                 return propName;
2156             }
2157 
2158             desc->isComputed = true;
2159 
2160             propName = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
2161 
2162             if (Extension() == ScriptExtension::TS) {
2163                 desc->invalidComputedProperty =
2164                     !propName->IsNumberLiteral() && !propName->IsStringLiteral() &&
2165                     !(propName->IsMemberExpression() && propName->AsMemberExpression()->Object()->IsIdentifier() &&
2166                       propName->AsMemberExpression()->Object()->AsIdentifier()->Name().Is("Symbol")) &&
2167                     !propName->IsIdentifier();
2168             }
2169 
2170             if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
2171                 ThrowSyntaxError("Unexpected token, expected ']'");
2172             }
2173             break;
2174         }
2175         default: {
2176             ThrowSyntaxError("Unexpected token in class property");
2177         }
2178     }
2179 
2180     lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);
2181 
2182     return propName;
2183 }
2184 
ValidateClassMethodStart(ClassElmentDescriptor * desc,ir::Expression * typeAnnotation)2185 void ParserImpl::ValidateClassMethodStart(ClassElmentDescriptor *desc, ir::Expression *typeAnnotation)
2186 {
2187     if (Extension() == ScriptExtension::JS) {
2188         if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
2189             return;
2190         }
2191         desc->classMethod = true;
2192     }
2193 
2194     if (Extension() == ScriptExtension::TS &&
2195         lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS && desc->isPrivateIdent) {
2196         ThrowSyntaxError("A method cannot be named with a private identifier");
2197     }
2198 
2199     if (Extension() == ScriptExtension::TS) {
2200         if (!typeAnnotation && (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS ||
2201                                 lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN)) {
2202             if ((desc->modifiers & (ir::ModifierFlags::DECLARE | ir::ModifierFlags::READONLY))) {
2203                 ThrowSyntaxError("Class method can not be declare nor readonly");
2204             }
2205             desc->classMethod = true;
2206         } else {
2207             if ((desc->modifiers & ir::ModifierFlags::ASYNC) || desc->isGenerator) {
2208                 ThrowSyntaxError("Expected '('");
2209             }
2210             desc->classField = true;
2211 
2212             if (desc->invalidComputedProperty) {
2213                 ThrowSyntaxError(
2214                     "Computed property name must refer to a symbol or "
2215                     "literal expression whos value is "
2216                     "number or string");
2217             }
2218         }
2219     }
2220 
2221     if (desc->modifiers & ir::ModifierFlags::ASYNC) {
2222         desc->newStatus |= ParserStatus::ASYNC_FUNCTION;
2223     }
2224 
2225     if (desc->isGenerator) {
2226         desc->newStatus |= ParserStatus::GENERATOR_FUNCTION;
2227     }
2228 }
2229 
ValidateClassSetter(ClassElmentDescriptor * desc,const ArenaVector<ir::Statement * > & properties,ir::Expression * propName,ir::ScriptFunction * func,bool hasDecorator,lexer::SourcePosition errorInfo)2230 void ParserImpl::ValidateClassSetter(ClassElmentDescriptor *desc, const ArenaVector<ir::Statement *> &properties,
2231                                      ir::Expression *propName, ir::ScriptFunction *func, bool hasDecorator,
2232                                      lexer::SourcePosition errorInfo)
2233 {
2234     if (func->Params().size() != 1) {
2235         ThrowSyntaxError("Setter must have exactly one formal parameter");
2236     }
2237 
2238     if (Extension() == ScriptExtension::TS && !(desc->modifiers & ir::ModifierFlags::STATIC)) {
2239         ir::ModifierFlags access = GetAccessability(desc->modifiers);
2240         CheckAccessorPair(properties, propName, ir::MethodDefinitionKind::GET, access, hasDecorator, errorInfo);
2241     }
2242 }
2243 
ValidateClassGetter(ClassElmentDescriptor * desc,const ArenaVector<ir::Statement * > & properties,ir::Expression * propName,ir::ScriptFunction * func,bool hasDecorator,lexer::SourcePosition errorInfo)2244 void ParserImpl::ValidateClassGetter(ClassElmentDescriptor *desc, const ArenaVector<ir::Statement *> &properties,
2245                                      ir::Expression *propName, ir::ScriptFunction *func, bool hasDecorator,
2246                                      lexer::SourcePosition errorInfo)
2247 {
2248     if (!func->Params().empty()) {
2249         ThrowSyntaxError("Getter must not have formal parameters");
2250     }
2251 
2252     if (Extension() == ScriptExtension::TS && !(desc->modifiers & ir::ModifierFlags::STATIC)) {
2253         ir::ModifierFlags access = GetAccessability(desc->modifiers);
2254 
2255         CheckAccessorPair(properties, propName, ir::MethodDefinitionKind::SET, access, hasDecorator, errorInfo);
2256     }
2257 }
2258 
ParseClassMethod(ClassElmentDescriptor * desc,const ArenaVector<ir::Statement * > & properties,ir::Expression * propName,lexer::SourcePosition * propEnd,ArenaVector<ir::Decorator * > && decorators,bool isDeclare)2259 ir::MethodDefinition *ParserImpl::ParseClassMethod(ClassElmentDescriptor *desc,
2260                                                    const ArenaVector<ir::Statement *> &properties,
2261                                                    ir::Expression *propName, lexer::SourcePosition *propEnd,
2262                                                    ArenaVector<ir::Decorator *> &&decorators, bool isDeclare)
2263 {
2264     if (Extension() == ScriptExtension::TS) {
2265         if (desc->methodKind == ir::MethodDefinitionKind::SET || desc->methodKind == ir::MethodDefinitionKind::GET) {
2266             desc->newStatus |= ParserStatus::ACCESSOR_FUNCTION;
2267         }
2268 
2269         desc->newStatus |= ParserStatus::IN_METHOD_DEFINITION;
2270     }
2271 
2272     if (isDeclare && (desc->newStatus & ParserStatus::ASYNC_FUNCTION)) {
2273         ThrowSyntaxError("'async' modifier cannot be used in an ambient context.");
2274     }
2275 
2276     if (isDeclare && desc->isGenerator) {
2277         ThrowSyntaxError("Generators are not allowed in an ambient context.");
2278     }
2279 
2280     ir::ScriptFunction *func = ParseFunction(desc->newStatus, isDeclare);
2281     if (func->Body() != nullptr) {
2282         lexer_->NextToken();
2283     }
2284 
2285     if (func->IsOverload() && !decorators.empty()) {
2286         ThrowSyntaxError("A decorator can only decorate a method implementation, not an overload.",
2287                          decorators.front()->Start());
2288     }
2289 
2290     auto *funcExpr = AllocNode<ir::FunctionExpression>(func);
2291     funcExpr->SetRange(func->Range());
2292 
2293     lexer::SourcePosition errorInfo = decorators.empty() ? func->Start() : decorators[0]->Start();
2294 
2295     if (desc->methodKind == ir::MethodDefinitionKind::SET) {
2296         ValidateClassSetter(desc, properties, propName, func, !decorators.empty(), errorInfo);
2297     } else if (desc->methodKind == ir::MethodDefinitionKind::GET) {
2298         ValidateClassGetter(desc, properties, propName, func, !decorators.empty(), errorInfo);
2299     }
2300 
2301     *propEnd = func->End();
2302     func->AddFlag(ir::ScriptFunctionFlags::METHOD);
2303     auto *method = AllocNode<ir::MethodDefinition>(desc->methodKind, propName, funcExpr, desc->modifiers, Allocator(),
2304                                                    std::move(decorators), desc->isComputed);
2305     method->SetRange(funcExpr->Range());
2306     return method;
2307 }
2308 
ParseClassProperty(ClassElmentDescriptor * desc,const ArenaVector<ir::Statement * > & properties,ir::Expression * propName,ir::Expression * typeAnnotation,ArenaVector<ir::Decorator * > && decorators,bool isDeclare)2309 ir::Statement *ParserImpl::ParseClassProperty(ClassElmentDescriptor *desc,
2310                                               const ArenaVector<ir::Statement *> &properties, ir::Expression *propName,
2311                                               ir::Expression *typeAnnotation, ArenaVector<ir::Decorator *> &&decorators,
2312                                               bool isDeclare)
2313 {
2314     lexer::SourcePosition propEnd = propName->End();
2315     ir::Statement *property = nullptr;
2316 
2317     if (desc->classMethod) {
2318         property = ParseClassMethod(desc, properties, propName, &propEnd, std::move(decorators), isDeclare);
2319         property->SetRange({desc->propStart, propEnd});
2320         return property;
2321     }
2322 
2323     ir::Expression *value = nullptr;
2324 
2325     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
2326         lexer_->NextToken();  // eat equals
2327 
2328         if (isDeclare) {
2329             ThrowSyntaxError("Initializers are not allowed in ambient contexts.");
2330         }
2331         value = ParseExpression();
2332         propEnd = value->End();
2333     }
2334 
2335     ir::Expression *privateId = nullptr;
2336 
2337     if (Extension() == ScriptExtension::JS) {
2338         if (desc->isPrivateIdent) {
2339             ThrowSyntaxError("Private js fields are not supported");
2340         }
2341     } else {
2342         if (desc->isPrivateIdent) {
2343             privateId = AllocNode<ir::TSPrivateIdentifier>(propName, value, typeAnnotation);
2344             privateId->SetRange({desc->propStart, propName->End()});
2345         }
2346     }
2347 
2348     property = AllocNode<ir::ClassProperty>(desc->isPrivateIdent ? privateId : propName, value, typeAnnotation,
2349                                             desc->modifiers, std::move(decorators), desc->isComputed,
2350                                             desc->modifiers & ir::ModifierFlags::DEFINITE);
2351 
2352     property->SetRange({desc->propStart, propEnd});
2353     return property;
2354 }
2355 
CheckClassGeneratorMethod(ClassElmentDescriptor * desc)2356 void ParserImpl::CheckClassGeneratorMethod(ClassElmentDescriptor *desc)
2357 {
2358     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_MULTIPLY) {
2359         return;
2360     }
2361 
2362     ThrowIfPrivateIdent(desc, "Unexpected character in private identifier");
2363 
2364     desc->isGenerator = true;
2365     lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);
2366 }
2367 
CheckClassPrivateIdentifier(ClassElmentDescriptor * desc)2368 void ParserImpl::CheckClassPrivateIdentifier(ClassElmentDescriptor *desc)
2369 {
2370     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_HASH_MARK) {
2371         return;
2372     }
2373 
2374     if (Extension() == ScriptExtension::JS) {
2375         ThrowSyntaxError("JS private class fields are not supported.");
2376     }
2377 
2378     if (Extension() == ScriptExtension::AS) {
2379         return;
2380     }
2381 
2382     if (desc->modifiers != ir::ModifierFlags::NONE) {
2383         ThrowSyntaxError("Unexpected modifier on private identifier");
2384     }
2385 
2386     desc->isPrivateIdent = true;
2387     lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);
2388 }
2389 
ParseClassKeyAnnotation()2390 ir::Expression *ParserImpl::ParseClassKeyAnnotation()
2391 {
2392     if (Extension() == ScriptExtension::TS && lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
2393         lexer_->NextToken();  // eat ':'
2394         TypeAnnotationParsingOptions options =
2395             TypeAnnotationParsingOptions::THROW_ERROR | TypeAnnotationParsingOptions::BREAK_AT_NEW_LINE;
2396         return ParseTsTypeAnnotation(&options);
2397     }
2398 
2399     return nullptr;
2400 }
2401 
ParseDecorator()2402 ir::Decorator *ParserImpl::ParseDecorator()
2403 {
2404     ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_AT);
2405 
2406     lexer::SourcePosition start = lexer_->GetToken().Start();
2407     lexer_->NextToken();  // eat '@'
2408 
2409     ir::Expression *expr = ParseLeftHandSideExpression();
2410     auto *result = AllocNode<ir::Decorator>(expr);
2411     result->SetRange({start, expr->End()});
2412 
2413     return result;
2414 }
2415 
ParseDecorators()2416 ArenaVector<ir::Decorator *> ParserImpl::ParseDecorators()
2417 {
2418     ArenaVector<ir::Decorator *> decorators(Allocator()->Adapter());
2419     auto savedStatus = context_.Status();
2420     context_.Status() |= ParserStatus::IN_DECORATOR;
2421 
2422     while (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_AT) {
2423         decorators.push_back(ParseDecorator());
2424     }
2425 
2426     if (!decorators.empty() && lexer_->GetToken().Type() != lexer::TokenType::KEYW_CLASS &&
2427         (context_.Status() & ParserStatus::IN_CLASS_BODY) == 0 &&
2428         lexer_->GetToken().Type() != lexer::TokenType::KEYW_EXPORT &&
2429         !(lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT &&
2430           lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_DECLARE)) {
2431         ThrowSyntaxError("Decorators are not valid here.", decorators.front()->Start());
2432     }
2433 
2434     context_.Status() = savedStatus;
2435     return decorators;
2436 }
2437 
ParseClassElement(const ArenaVector<ir::Statement * > & properties,ArenaVector<ir::TSIndexSignature * > * indexSignatures,bool hasSuperClass,bool isDeclare,bool isAbstractClass)2438 ir::Statement *ParserImpl::ParseClassElement(const ArenaVector<ir::Statement *> &properties,
2439                                              ArenaVector<ir::TSIndexSignature *> *indexSignatures, bool hasSuperClass,
2440                                              bool isDeclare, bool isAbstractClass)
2441 {
2442     ClassElmentDescriptor desc;
2443 
2444     desc.methodKind = ir::MethodDefinitionKind::METHOD;
2445     desc.newStatus = ParserStatus::ALLOW_SUPER;
2446     desc.hasSuperClass = hasSuperClass;
2447     desc.propStart = lexer_->GetToken().Start();
2448 
2449     auto decorators = ParseDecorators();
2450 
2451     desc.modifiers = ParseModifiers();
2452 
2453     if ((desc.modifiers & ir::ModifierFlags::ABSTRACT) && !isAbstractClass) {
2454         ThrowSyntaxError("Abstract methods can only appear within an abstract class.");
2455     }
2456 
2457     CheckClassPrivateIdentifier(&desc);
2458     CheckClassGeneratorMethod(&desc);
2459     ParseClassKeyModifiers(&desc);
2460 
2461     if (!(desc.modifiers & ir::ModifierFlags::STATIC)) {
2462         context_.Status() |= ParserStatus::ALLOW_THIS_TYPE;
2463     }
2464 
2465     ir::Expression *propName = ParseClassKey(&desc, isDeclare);
2466 
2467     if (desc.methodKind == ir::MethodDefinitionKind::CONSTRUCTOR && !decorators.empty()) {
2468         ThrowSyntaxError("Decorators are not valid here.", decorators.front()->Start());
2469     }
2470 
2471     if (Extension() == ScriptExtension::TS && lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_QUESTION_MARK) {
2472         if (desc.isIndexSignature) {
2473             ThrowSyntaxError("';' expected");
2474         }
2475 
2476         if (desc.methodKind == ir::MethodDefinitionKind::CONSTRUCTOR) {
2477             ThrowSyntaxError("'(' expected");
2478         }
2479 
2480         desc.modifiers |= ir::ModifierFlags::OPTIONAL;
2481         lexer_->NextToken();
2482     } else if (Extension() == ScriptExtension::TS &&
2483                lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_EXCLAMATION_MARK) {
2484         if (desc.isIndexSignature || lexer_->Lookahead() != LEX_CHAR_COLON) {
2485             ThrowSyntaxError("';' expected");
2486         }
2487 
2488         desc.modifiers |= ir::ModifierFlags::DEFINITE;
2489         lexer_->NextToken();
2490     }
2491 
2492     ir::Expression *typeAnnotation = ParseClassKeyAnnotation();
2493 
2494     ir::Statement *property = nullptr;
2495     if (desc.isIndexSignature) {
2496         if (!decorators.empty()) {
2497             ThrowSyntaxError("Decorators are not valid here.", decorators.front()->Start());
2498         }
2499 
2500         if (!typeAnnotation) {
2501             ThrowSyntaxError("An index signature must have a type annotation");
2502         }
2503 
2504         auto *indexSignature =
2505             AllocNode<ir::TSIndexSignature>(propName, typeAnnotation, desc.modifiers & ir::ModifierFlags::READONLY);
2506 
2507         indexSignature->SetRange({indexSignature->Param()->Start(), indexSignature->TypeAnnotation()->End()});
2508 
2509         indexSignatures->push_back(indexSignature);
2510 
2511         property = AllocNode<ir::EmptyStatement>();
2512     } else {
2513         ValidateClassMethodStart(&desc, typeAnnotation);
2514         property = ParseClassProperty(&desc, properties, propName, typeAnnotation, std::move(decorators),
2515                                       isDeclare || (desc.modifiers & ir::ModifierFlags::DECLARE));
2516     }
2517 
2518     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON &&
2519         lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE &&
2520         !(lexer_->GetToken().Flags() & lexer::TokenFlags::NEW_LINE) &&
2521         !(property->IsMethodDefinition() && property->AsMethodDefinition()->Value()->Function()->Body())) {
2522         ThrowSyntaxError("';' expected.");
2523     }
2524 
2525     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
2526         lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);
2527     }
2528 
2529     context_.Status() &= ~ParserStatus::ALLOW_THIS_TYPE;
2530 
2531     return property;
2532 }
2533 
IsConstructor(ir::Statement * stmt)2534 static bool IsConstructor(ir::Statement *stmt)
2535 {
2536     if (!stmt->IsMethodDefinition()) {
2537         return false;
2538     }
2539 
2540     ir::MethodDefinition *def = stmt->AsMethodDefinition();
2541     return def->Kind() == ir::MethodDefinitionKind::CONSTRUCTOR;
2542 }
2543 
CreateImplicitConstructor(bool hasSuperClass,bool isDeclare)2544 ir::MethodDefinition *ParserImpl::CreateImplicitConstructor(bool hasSuperClass, bool isDeclare)
2545 {
2546     ArenaVector<ir::Expression *> params(Allocator()->Adapter());
2547     ArenaVector<ir::Statement *> statements(Allocator()->Adapter());
2548 
2549     auto *paramScope = Binder()->Allocator()->New<binder::FunctionParamScope>(Allocator(), Binder()->GetScope());
2550     auto *scope = Binder()->Allocator()->New<binder::FunctionScope>(Allocator(), paramScope);
2551 
2552     if (hasSuperClass) {
2553         util::StringView argsStr = "args";
2554         params.push_back(AllocNode<ir::SpreadElement>(ir::AstNodeType::REST_ELEMENT,
2555                                                       AllocNode<ir::Identifier>(argsStr, Allocator())));
2556         paramScope->AddParamDecl(Allocator(), params.back());
2557 
2558         ArenaVector<ir::Expression *> callArgs(Allocator()->Adapter());
2559         auto *superExpr = AllocNode<ir::SuperExpression>();
2560         callArgs.push_back(AllocNode<ir::SpreadElement>(ir::AstNodeType::SPREAD_ELEMENT,
2561                                                         AllocNode<ir::Identifier>(argsStr, Allocator())));
2562 
2563         auto *callExpr = AllocNode<ir::CallExpression>(superExpr, std::move(callArgs), nullptr, false);
2564         statements.push_back(AllocNode<ir::ExpressionStatement>(callExpr));
2565     }
2566 
2567     auto *body = AllocNode<ir::BlockStatement>(scope, std::move(statements));
2568     auto *func = AllocNode<ir::ScriptFunction>(scope, std::move(params), nullptr, isDeclare ? nullptr : body, nullptr,
2569                                                ir::ScriptFunctionFlags::CONSTRUCTOR, isDeclare,
2570                                                Extension() == ScriptExtension::TS);
2571     scope->BindNode(func);
2572     paramScope->BindNode(func);
2573     scope->BindParamScope(paramScope);
2574     paramScope->BindFunctionScope(scope);
2575 
2576     auto *funcExpr = AllocNode<ir::FunctionExpression>(func);
2577     auto *key = AllocNode<ir::Identifier>("constructor", Allocator());
2578 
2579     ArenaVector<ir::Decorator *> decorators(Allocator()->Adapter());
2580 
2581     auto *ctor = AllocNode<ir::MethodDefinition>(ir::MethodDefinitionKind::CONSTRUCTOR, key, funcExpr,
2582                                                  ir::ModifierFlags::NONE, Allocator(), std::move(decorators), false);
2583 
2584     return ctor;
2585 }
2586 
IsPropertyKeysAreSame(const ir::Expression * exp1,const ir::Expression * exp2)2587 bool ParserImpl::IsPropertyKeysAreSame(const ir::Expression *exp1, const ir::Expression *exp2)
2588 {
2589     if (exp1->IsIdentifier() && exp2->IsIdentifier()) {
2590         return exp1->AsIdentifier()->Name() == exp2->AsIdentifier()->Name();
2591     }
2592 
2593     if (exp1->IsIdentifier() && exp2->IsStringLiteral()) {
2594         return exp1->AsIdentifier()->Name() == exp2->AsStringLiteral()->Str();
2595     }
2596 
2597     if (exp1->IsStringLiteral() && exp2->IsStringLiteral()) {
2598         return *exp1->AsStringLiteral() == *exp2->AsStringLiteral();
2599     }
2600 
2601     if (exp1->IsStringLiteral() && exp2->IsIdentifier()) {
2602         return exp1->AsStringLiteral()->Str() == exp2->AsIdentifier()->Name();
2603     }
2604 
2605     if (exp1->IsStringLiteral() && exp2->IsNumberLiteral()) {
2606         std::string exp2String = std::to_string(exp2->AsNumberLiteral()->Number<double>());
2607         exp2String.erase(exp2String.find_last_not_of('0'), std::string::npos);
2608         return exp1->AsStringLiteral()->Str().Utf8() == exp2String;
2609     }
2610 
2611     if (exp1->IsNumberLiteral() && exp2->IsNumberLiteral()) {
2612         return exp1->AsNumberLiteral()->Number<double>() == exp2->AsNumberLiteral()->Number<double>();
2613     }
2614 
2615     if (exp1->IsNumberLiteral() && exp2->IsStringLiteral()) {
2616         std::string exp1String = std::to_string(exp1->AsNumberLiteral()->Number<double>());
2617         exp1String.erase(exp1String.find_last_not_of('0'), std::string::npos);
2618         return exp1String == exp2->AsStringLiteral()->Str().Utf8();
2619     }
2620 
2621     return false;
2622 }
2623 
IsMemberExpressionsAreSame(const ir::MemberExpression * mExp1,const ir::MemberExpression * mExp2)2624 bool ParserImpl::IsMemberExpressionsAreSame(const ir::MemberExpression *mExp1, const ir::MemberExpression *mExp2)
2625 {
2626     if (!IsPropertyKeysAreSame(mExp1->Property(), mExp2->Property())) {
2627         return false;
2628     }
2629 
2630     if (mExp1->Object()->IsMemberExpression() && mExp2->Object()->IsMemberExpression()) {
2631         return IsMemberExpressionsAreSame(mExp1->Object()->AsMemberExpression(), mExp2->Object()->AsMemberExpression());
2632     }
2633 
2634     return IsPropertyKeysAreSame(mExp1->Object(), mExp2->Object());
2635 }
2636 
IsMethodDefinitionsAreSame(const ir::MethodDefinition * property,ir::MethodDefinition * overload)2637 bool ParserImpl::IsMethodDefinitionsAreSame(const ir::MethodDefinition *property, ir::MethodDefinition *overload)
2638 {
2639     if (property->Kind() != overload->Kind() || property->IsStatic() != overload->IsStatic()) {
2640         return false;
2641     }
2642 
2643     if (property->Key()->IsMemberExpression() && overload->Key()->IsMemberExpression()) {
2644         return IsMemberExpressionsAreSame(property->Key()->AsMemberExpression(), overload->Key()->AsMemberExpression());
2645     }
2646 
2647     return IsPropertyKeysAreSame(property->Key(), overload->Key());
2648 }
2649 
SetIdentNodeInClassDefinition()2650 ir::Identifier *ParserImpl::SetIdentNodeInClassDefinition()
2651 {
2652     lexer::TokenType keywType = lexer_->GetToken().KeywordType();
2653     CheckStrictReservedWord();
2654 
2655     if (keywType == lexer::TokenType::KEYW_AWAIT && context_.IsModule()) {
2656         ThrowSyntaxError("Unexpected reserved word");
2657     }
2658 
2659     const util::StringView &identStr = lexer_->GetToken().Ident();
2660 
2661     Binder()->AddDecl<binder::ConstDecl>(lexer_->GetToken().Start(), identStr);
2662 
2663     auto *identNode = AllocNode<ir::Identifier>(identStr, Allocator());
2664     identNode->SetRange(lexer_->GetToken().Loc());
2665 
2666     lexer_->NextToken();
2667 
2668     return identNode;
2669 }
2670 
ParseClassDefinition(bool isDeclaration,bool idRequired,bool isDeclare,bool isAbstract)2671 ir::ClassDefinition *ParserImpl::ParseClassDefinition(bool isDeclaration, bool idRequired, bool isDeclare,
2672                                                       bool isAbstract)
2673 {
2674     isDeclare = isDeclare | (context_.Status() & ParserStatus::IN_AMBIENT_CONTEXT);
2675     lexer::SourcePosition startLoc = lexer_->GetToken().Start();
2676     lexer_->NextToken();
2677 
2678     ir::Identifier *identNode = nullptr;
2679 
2680     auto classCtx = binder::LexicalScope<binder::LocalScope>(Binder());
2681 
2682     if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) {
2683         identNode = SetIdentNodeInClassDefinition();
2684     } else if (isDeclaration && idRequired) {
2685         ThrowSyntaxError("Unexpected token, expected an identifier.");
2686     }
2687 
2688     ir::TSTypeParameterDeclaration *typeParamDecl = nullptr;
2689     if (Extension() == ScriptExtension::TS && lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) {
2690         typeParamDecl = ParseTsTypeParameterDeclaration();
2691     }
2692 
2693     // Parse SuperClass
2694     ir::Expression *superClass = nullptr;
2695     bool hasSuperClass = false;
2696 
2697     if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_EXTENDS) {
2698         lexer_->NextToken();
2699         hasSuperClass = true;
2700         superClass = ParseLeftHandSideExpression();
2701     }
2702 
2703     ir::TSTypeParameterInstantiation *superTypeParams = nullptr;
2704     if (Extension() == ScriptExtension::TS && (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN ||
2705                                                lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SHIFT)) {
2706         if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SHIFT) {
2707             lexer_->BackwardToken(lexer::TokenType::PUNCTUATOR_LESS_THAN, 1);
2708         }
2709 
2710         superTypeParams = ParseTsTypeParameterInstantiation();
2711     }
2712 
2713     ArenaVector<ir::TSClassImplements *> implements(Allocator()->Adapter());
2714     if (Extension() == ScriptExtension::TS && lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_IMPLEMENTS) {
2715         lexer_->NextToken();
2716 
2717         while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
2718             lexer::SourcePosition implStart = lexer_->GetToken().Start();
2719 
2720             if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
2721                 ThrowSyntaxError("Identifier expected");
2722             }
2723 
2724             ir::Expression *expr = AllocNode<ir::Identifier>(lexer_->GetToken().Ident(), Allocator());
2725             expr->SetRange(lexer_->GetToken().Loc());
2726 
2727             lexer_->NextToken();
2728 
2729             if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD) {
2730                 expr = ParseTsQualifiedReference(expr);
2731             }
2732 
2733             ir::TSTypeParameterInstantiation *implTypeParams = nullptr;
2734             if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SHIFT) {
2735                 lexer_->BackwardToken(lexer::TokenType::PUNCTUATOR_LESS_THAN, 1);
2736             }
2737 
2738             if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN ||
2739                 lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SHIFT) {
2740                 implTypeParams = ParseTsTypeParameterInstantiation();
2741             }
2742 
2743             auto *impl = AllocNode<ir::TSClassImplements>(expr, implTypeParams);
2744             impl->SetRange({implStart, lexer_->GetToken().End()});
2745             implements.push_back(impl);
2746 
2747             if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
2748                 lexer_->NextToken();
2749                 continue;
2750             }
2751 
2752             if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
2753                 ThrowSyntaxError("',' expected");
2754             }
2755         }
2756 
2757         if (implements.empty()) {
2758             ThrowSyntaxError("Implements clause can not be empty");
2759         }
2760     }
2761 
2762     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
2763         ThrowSyntaxError("Unexpected token, expected '{'");
2764     }
2765 
2766     // Parse ClassBody
2767     auto savedStatus = context_.Status();
2768     context_.Status() |= ParserStatus::IN_CLASS_BODY;
2769     context_.Status() &= ~(ParserStatus::CONSTRUCTOR_FUNCTION);
2770     lexer::SourcePosition classBodyStartLoc = lexer_->GetToken().Start();
2771     lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);
2772 
2773     ir::MethodDefinition *ctor = nullptr;
2774     ArenaVector<ir::Statement *> properties(Allocator()->Adapter());
2775     ArenaVector<ir::TSIndexSignature *> indexSignatures(Allocator()->Adapter());
2776     bool hasConstructorFuncBody = false;
2777     bool isCtorContinuousDefined = true;
2778 
2779     while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
2780         if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
2781             lexer_->NextToken();
2782             continue;
2783         }
2784 
2785         ir::Statement *property = ParseClassElement(properties, &indexSignatures, hasSuperClass, isDeclare, isAbstract);
2786 
2787         if (property->IsEmptyStatement()) {
2788             continue;
2789         }
2790 
2791         if (IsConstructor(property)) {
2792             if (!isDeclare && !isCtorContinuousDefined) {
2793                 ThrowSyntaxError("Constructor implementation is missing.", property->Start());
2794             }
2795 
2796             if (hasConstructorFuncBody) {
2797                 ThrowSyntaxError("Multiple constructor implementations are not allowed.", property->Start());
2798             }
2799             ctor = property->AsMethodDefinition();
2800             hasConstructorFuncBody = ctor->Value()->Function()->Body() != nullptr;
2801             continue;
2802         }
2803         isCtorContinuousDefined = ctor == nullptr;
2804         properties.push_back(property);
2805     }
2806 
2807     context_.Status() = savedStatus;
2808 
2809     lexer::SourcePosition classBodyEndLoc = lexer_->GetToken().End();
2810     if (ctor == nullptr) {
2811         ctor = CreateImplicitConstructor(hasSuperClass, isDeclare);
2812         ctor->SetRange({startLoc, classBodyEndLoc});
2813         hasConstructorFuncBody = !isDeclare;
2814     }
2815     lexer_->NextToken();
2816 
2817     if (!isDeclare && !hasConstructorFuncBody) {
2818         ThrowSyntaxError("Constructor implementation is missing.", ctor->Start());
2819     }
2820 
2821     auto *classDefinition = AllocNode<ir::ClassDefinition>(
2822         classCtx.GetScope(), identNode, typeParamDecl, superTypeParams, std::move(implements), ctor, superClass,
2823         std::move(properties), std::move(indexSignatures), isDeclare, isAbstract);
2824 
2825     classDefinition->SetRange({classBodyStartLoc, classBodyEndLoc});
2826 
2827     return classDefinition;
2828 }
2829 
ParseEnumMembers(ir::Identifier * key,const lexer::SourcePosition & enumStart,bool isConst)2830 ir::TSEnumDeclaration *ParserImpl::ParseEnumMembers(ir::Identifier *key, const lexer::SourcePosition &enumStart,
2831                                                     bool isConst)
2832 {
2833     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
2834         ThrowSyntaxError("'{' expected");
2835     }
2836 
2837     ArenaVector<ir::TSEnumMember *> members(Allocator()->Adapter());
2838     lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);  // eat '{'
2839 
2840     while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
2841         ir::Expression *memberKey = nullptr;
2842         const auto &keyStartLoc = lexer_->GetToken().Start();
2843         binder::EnumDecl *decl {};
2844 
2845         if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) {
2846             memberKey = AllocNode<ir::Identifier>(lexer_->GetToken().Ident(), Allocator());
2847             decl = Binder()->AddDecl<binder::EnumDecl>(keyStartLoc, lexer_->GetToken().Ident());
2848             memberKey->SetRange(lexer_->GetToken().Loc());
2849             lexer_->NextToken();
2850         } else if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_STRING) {
2851             decl = Binder()->AddDecl<binder::EnumDecl>(keyStartLoc, lexer_->GetToken().String());
2852             memberKey = AllocNode<ir::StringLiteral>(lexer_->GetToken().String());
2853             memberKey->SetRange(lexer_->GetToken().Loc());
2854             lexer_->NextToken();
2855         } else {
2856             ThrowSyntaxError("Unexpected token in enum member");
2857         }
2858 
2859         ir::Expression *memberInit = nullptr;
2860         lexer::SourcePosition initStart = lexer_->GetToken().Start();
2861 
2862         if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
2863             lexer_->NextToken();  // eat '='
2864             initStart = lexer_->GetToken().Start();
2865             memberInit = ParseExpression();
2866         }
2867 
2868         auto *member = AllocNode<ir::TSEnumMember>(memberKey, memberInit);
2869         decl->BindNode(member);
2870         member->SetRange({initStart, lexer_->GetToken().End()});
2871         members.push_back(member);
2872 
2873         if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
2874             lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);  // eat ','
2875         }
2876     }
2877 
2878     auto *enumDeclaration =
2879         AllocNode<ir::TSEnumDeclaration>(Binder()->GetScope()->AsLocalScope(), key, std::move(members), isConst);
2880     enumDeclaration->SetRange({enumStart, lexer_->GetToken().End()});
2881     Binder()->GetScope()->BindNode(enumDeclaration);
2882     lexer_->NextToken();  // eat '}'
2883 
2884     return enumDeclaration;
2885 }
2886 
ParseEnumDeclaration(bool isConst)2887 ir::TSEnumDeclaration *ParserImpl::ParseEnumDeclaration(bool isConst)
2888 {
2889     ASSERT(lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_ENUM);
2890     lexer::SourcePosition enumStart = lexer_->GetToken().Start();
2891     lexer_->NextToken();  // eat enum keyword
2892 
2893     if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
2894         ThrowSyntaxError("Identifier expected");
2895     }
2896 
2897     const util::StringView &ident = lexer_->GetToken().Ident();
2898     binder::TSBinding tsBinding(Allocator(), ident);
2899 
2900     auto *key = AllocNode<ir::Identifier>(ident, Allocator());
2901     key->SetRange(lexer_->GetToken().Loc());
2902     key->SetReference();
2903     lexer_->NextToken();
2904 
2905     const auto &bindings = Binder()->GetScope()->Bindings();
2906     auto res = bindings.find(tsBinding.View());
2907     binder::EnumLiteralDecl *decl {};
2908 
2909     if (res == bindings.end()) {
2910         decl = Binder()->AddTsDecl<binder::EnumLiteralDecl>(lexer_->GetToken().Start(), tsBinding.View(), isConst);
2911         binder::LexicalScope enumCtx = binder::LexicalScope<binder::LocalScope>(Binder());
2912         decl->AsEnumLiteralDecl()->BindScope(enumCtx.GetScope());
2913         return ParseEnumMembers(key, enumStart, isConst);
2914     }
2915 
2916     if (!res->second->Declaration()->IsEnumLiteralDecl() ||
2917         (isConst ^ res->second->Declaration()->AsEnumLiteralDecl()->IsConst())) {
2918         Binder()->ThrowRedeclaration(lexer_->GetToken().Start(), ident);
2919     }
2920 
2921     decl = res->second->Declaration()->AsEnumLiteralDecl();
2922 
2923     auto scopeCtx = binder::LexicalScope<binder::LocalScope>::Enter(Binder(), decl->Scope());
2924     return ParseEnumMembers(key, enumStart, isConst);
2925 }
2926 
ValidateFunctionParam(const ArenaVector<ir::Expression * > & params,const ir::Expression * parameter,bool * seenOptional)2927 void ParserImpl::ValidateFunctionParam(const ArenaVector<ir::Expression *> &params, const ir::Expression *parameter,
2928                                        bool *seenOptional)
2929 {
2930     if (!parameter->IsIdentifier()) {
2931         context_.Status() |= ParserStatus::HAS_COMPLEX_PARAM;
2932         if (!parameter->IsRestElement()) {
2933             return;
2934         }
2935 
2936         if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
2937             const char *msg = (Extension() == ScriptExtension::JS ? "Rest parameter must be last formal parameter"
2938                                                                   : "A rest parameter must be last in parameter list");
2939             ThrowSyntaxError(msg);
2940         }
2941         return;
2942     }
2943 
2944     if (Extension() != ScriptExtension::TS) {
2945         return;
2946     }
2947 
2948     bool currentIsOptinal = parameter->AsIdentifier()->IsOptional();
2949     if (*seenOptional && !currentIsOptinal) {
2950         ThrowSyntaxError("A required parameter cannot follow an optional parameter");
2951     }
2952 
2953     *seenOptional |= currentIsOptinal;
2954     const util::StringView &paramName = parameter->AsIdentifier()->Name();
2955 
2956     if (paramName.Is("this")) {
2957         if (!params.empty()) {
2958             ThrowSyntaxError("A 'this' parameter must be the first parameter");
2959         }
2960 
2961         if (context_.Status() & ParserStatus::CONSTRUCTOR_FUNCTION) {
2962             ThrowSyntaxError("A constructor cannot have a 'this' parameter");
2963         }
2964 
2965         if (context_.Status() & ParserStatus::ARROW_FUNCTION) {
2966             ThrowSyntaxError("An arrow function cannot have a 'this' parameter");
2967         }
2968 
2969         if (context_.Status() & ParserStatus::ACCESSOR_FUNCTION) {
2970             ThrowSyntaxError("'get' and 'set' accessors cannot declare 'this' parameters");
2971         }
2972     }
2973 
2974     if (paramName.Is("constructor") && (context_.Status() & ParserStatus::CONSTRUCTOR_FUNCTION)) {
2975         ThrowSyntaxError("'constructor' cannot be used as a parameter property name");
2976     }
2977 }
2978 
ParseFunctionParams(bool isDeclare)2979 ArenaVector<ir::Expression *> ParserImpl::ParseFunctionParams(bool isDeclare)
2980 {
2981     ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS);
2982     lexer_->NextToken();
2983 
2984     ArenaVector<ir::Expression *> params(Allocator()->Adapter());
2985     bool seenOptional = false;
2986 
2987     while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
2988         ir::Expression *parameter = ParseFunctionParameter(isDeclare);
2989         ValidateFunctionParam(params, parameter, &seenOptional);
2990 
2991         params.push_back(parameter);
2992 
2993         if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COMMA &&
2994             lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
2995             ThrowSyntaxError(", expected");
2996         }
2997 
2998         if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
2999             lexer_->NextToken();
3000         }
3001     }
3002 
3003     ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS);
3004     lexer_->NextToken();
3005 
3006     return params;
3007 }
3008 
CheckTypeNameIsReserved(const util::StringView & paramName)3009 bool ParserImpl::CheckTypeNameIsReserved(const util::StringView &paramName)
3010 {
3011     return paramName.Is("number") || paramName.Is("any") || paramName.Is("unknown") || paramName.Is("never") ||
3012            paramName.Is("bigint") || paramName.Is("boolean") || paramName.Is("string") || paramName.Is("string") ||
3013            paramName.Is("void") || paramName.Is("object");
3014 }
3015 
ParseTsTypeParameter(bool throwError,bool addBinding)3016 ir::TSTypeParameter *ParserImpl::ParseTsTypeParameter(bool throwError, bool addBinding)
3017 {
3018     lexer::SourcePosition startLoc = lexer_->GetToken().Start();
3019 
3020     if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
3021         if (!throwError) {
3022             return nullptr;
3023         }
3024 
3025         ThrowSyntaxError("Type parameter declaration expected");
3026     }
3027 
3028     const auto &ident = lexer_->GetToken().Ident();
3029 
3030     if (CheckTypeNameIsReserved(ident)) {
3031         if (!throwError) {
3032             return nullptr;
3033         }
3034 
3035         ThrowSyntaxError("Invalid type parameter name");
3036     }
3037 
3038     auto *paramIdent = AllocNode<ir::Identifier>(ident, Allocator());
3039 
3040     if (addBinding) {
3041         Binder()->AddDecl<binder::LetDecl>(lexer_->GetToken().Start(), ident);
3042     }
3043 
3044     paramIdent->SetRange({lexer_->GetToken().Start(), lexer_->GetToken().End()});
3045 
3046     lexer_->NextToken();
3047 
3048     TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::NO_OPTS;
3049 
3050     if (throwError) {
3051         options |= TypeAnnotationParsingOptions::THROW_ERROR;
3052     }
3053 
3054     ir::Expression *constraint = nullptr;
3055     if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_EXTENDS) {
3056         lexer_->NextToken();
3057         constraint = ParseTsTypeAnnotation(&options);
3058     }
3059 
3060     ir::Expression *defaultType = nullptr;
3061     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
3062         lexer_->NextToken();
3063         defaultType = ParseTsTypeAnnotation(&options);
3064     }
3065 
3066     auto *typeParam = AllocNode<ir::TSTypeParameter>(paramIdent, constraint, defaultType);
3067 
3068     typeParam->SetRange({startLoc, lexer_->GetToken().End()});
3069 
3070     return typeParam;
3071 }
3072 
ParseTsTypeParameterDeclaration(bool throwError)3073 ir::TSTypeParameterDeclaration *ParserImpl::ParseTsTypeParameterDeclaration(bool throwError)
3074 {
3075     ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN);
3076 
3077     auto localCtx = binder::LexicalScope<binder::LocalScope>(Binder());
3078 
3079     lexer::SourcePosition startLoc = lexer_->GetToken().Start();
3080     ArenaVector<ir::TSTypeParameter *> params(Allocator()->Adapter());
3081     bool seenDefault = false;
3082     size_t requiredParams = 0;
3083     lexer_->NextToken();  // eat '<'
3084 
3085     while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_GREATER_THAN) {
3086         ir::TSTypeParameter *currentParam = ParseTsTypeParameter(throwError, true);
3087 
3088         if (!currentParam) {
3089             ASSERT(!throwError);
3090             return nullptr;
3091         }
3092 
3093         if (currentParam->DefaultType()) {
3094             seenDefault = true;
3095         } else if (seenDefault) {
3096             ThrowSyntaxError("Required type parameters may not follow optional type parameters.");
3097         } else {
3098             requiredParams++;
3099         }
3100 
3101         params.push_back(currentParam);
3102 
3103         if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
3104             lexer_->NextToken();
3105             continue;
3106         }
3107 
3108         if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_GREATER_THAN) {
3109             if (!throwError) {
3110                 return nullptr;
3111             }
3112 
3113             ThrowSyntaxError("'>' expected");
3114         }
3115     }
3116 
3117     if (params.empty()) {
3118         ThrowSyntaxError("Type parameter list cannot be empty.");
3119     }
3120 
3121     lexer::SourcePosition endLoc = lexer_->GetToken().End();
3122     lexer_->NextToken();  // eat '>'
3123 
3124     auto *typeParamDecl =
3125         AllocNode<ir::TSTypeParameterDeclaration>(localCtx.GetScope(), std::move(params), requiredParams);
3126     typeParamDecl->SetRange({startLoc, endLoc});
3127     localCtx.GetScope()->BindNode(typeParamDecl);
3128 
3129     return typeParamDecl;
3130 }
3131 
ParseTsTypeParameterInstantiation(bool throwError)3132 ir::TSTypeParameterInstantiation *ParserImpl::ParseTsTypeParameterInstantiation(bool throwError)
3133 {
3134     ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN);
3135     lexer::SourcePosition startLoc = lexer_->GetToken().Start();
3136     ArenaVector<ir::Expression *> params(Allocator()->Adapter());
3137     lexer_->NextToken();  // eat '<'
3138 
3139     while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_GREATER_THAN) {
3140         TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::NO_OPTS;
3141 
3142         if (throwError) {
3143             options |= TypeAnnotationParsingOptions::THROW_ERROR;
3144         }
3145 
3146         ir::Expression *currentParam = ParseTsTypeAnnotation(&options);
3147 
3148         if (!currentParam) {
3149             return nullptr;
3150         }
3151 
3152         params.push_back(currentParam);
3153 
3154         switch (lexer_->GetToken().Type()) {
3155             case lexer::TokenType::PUNCTUATOR_COMMA: {
3156                 lexer_->NextToken();
3157                 continue;
3158             }
3159             case lexer::TokenType::PUNCTUATOR_RIGHT_SHIFT: {
3160                 lexer_->BackwardToken(lexer::TokenType::PUNCTUATOR_GREATER_THAN, 1);
3161                 break;
3162             }
3163             case lexer::TokenType::PUNCTUATOR_UNSIGNED_RIGHT_SHIFT: {
3164                 lexer_->BackwardToken(lexer::TokenType::PUNCTUATOR_GREATER_THAN, 2);
3165                 break;
3166             }
3167             case lexer::TokenType::PUNCTUATOR_GREATER_THAN: {
3168                 break;
3169             }
3170             default: {
3171                 if (throwError) {
3172                     ThrowSyntaxError("'>' expected");
3173                 }
3174 
3175                 return nullptr;
3176             }
3177         }
3178     }
3179 
3180     lexer::SourcePosition endLoc = lexer_->GetToken().End();
3181     lexer_->NextToken();
3182 
3183     auto *typeParamInst = AllocNode<ir::TSTypeParameterInstantiation>(std::move(params));
3184 
3185     typeParamInst->SetRange({startLoc, endLoc});
3186 
3187     return typeParamInst;
3188 }
3189 
ParseFunction(ParserStatus newStatus,bool isDeclare)3190 ir::ScriptFunction *ParserImpl::ParseFunction(ParserStatus newStatus, bool isDeclare)
3191 {
3192     FunctionContext functionContext(this, newStatus | ParserStatus::FUNCTION | ParserStatus::ALLOW_NEW_TARGET);
3193 
3194     FunctionParameterContext funcParamContext(&context_, Binder());
3195     auto *funcParamScope = funcParamContext.LexicalScope().GetScope();
3196 
3197     lexer::SourcePosition startLoc = lexer_->GetToken().Start();
3198 
3199     ir::TSTypeParameterDeclaration *typeParamDecl = nullptr;
3200     if (Extension() == ScriptExtension::TS && lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) {
3201         typeParamDecl = ParseTsTypeParameterDeclaration();
3202     }
3203 
3204     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
3205         ThrowSyntaxError("Unexpected token, expected '('");
3206     }
3207 
3208     if (newStatus & (ParserStatus::ASYNC_FUNCTION | ParserStatus::FUNCTION_DECLARATION)) {
3209         context_.Status() |= ParserStatus::DISALLOW_AWAIT;
3210     }
3211 
3212     ArenaVector<ir::Expression *> params = ParseFunctionParams(isDeclare);
3213 
3214     ir::Expression *returnTypeAnnotation = nullptr;
3215 
3216     if (Extension() == ScriptExtension::TS && lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
3217         lexer_->NextToken();  // eat ':'
3218         TypeAnnotationParsingOptions options =
3219             TypeAnnotationParsingOptions::THROW_ERROR | TypeAnnotationParsingOptions::CAN_BE_TS_TYPE_PREDICATE;
3220         returnTypeAnnotation = ParseTsTypeAnnotation(&options);
3221     }
3222 
3223     auto functionCtx = binder::LexicalScope<binder::FunctionScope>(Binder());
3224     auto *functionScope = functionCtx.GetScope();
3225     functionScope->BindParamScope(funcParamScope);
3226     funcParamScope->BindFunctionScope(functionScope);
3227 
3228     ir::BlockStatement *body = nullptr;
3229     lexer::SourcePosition endLoc = lexer_->GetToken().End();
3230     bool letDeclare = true;
3231 
3232     if (newStatus & ParserStatus::ASYNC_FUNCTION) {
3233         context_.Status() &= ~ParserStatus::DISALLOW_AWAIT;
3234     } else {
3235         context_.Status() |= ParserStatus::DISALLOW_AWAIT;
3236     }
3237 
3238     if (newStatus & ParserStatus::GENERATOR_FUNCTION) {
3239         context_.Status() |= ParserStatus::ALLOW_YIELD;
3240     }
3241 
3242     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
3243         if (Extension() == ScriptExtension::TS && (newStatus & ParserStatus::FUNCTION_DECLARATION)) {
3244             ValidateTsFunctionOverloadParams(params);
3245             functionContext.AddFlag(ir::ScriptFunctionFlags::OVERLOAD);
3246         } else if (!isDeclare && !(context_.Status() & ParserStatus::IN_METHOD_DEFINITION)) {
3247             ThrowSyntaxError("Unexpected token, expected '{'");
3248         } else {
3249             letDeclare = false;
3250             functionContext.AddFlag(ir::ScriptFunctionFlags::OVERLOAD);
3251         }
3252     } else if (isDeclare) {
3253         ThrowSyntaxError("An implementation cannot be declared in ambient contexts.");
3254     } else {
3255         body = ParseBlockStatement(functionScope);
3256         endLoc = body->End();
3257     }
3258 
3259     auto *funcNode =
3260         AllocNode<ir::ScriptFunction>(functionScope, std::move(params), typeParamDecl, body, returnTypeAnnotation,
3261                                       functionContext.Flags(), isDeclare && letDeclare,
3262                                       Extension() == ScriptExtension::TS);
3263     functionScope->BindNode(funcNode);
3264     funcParamScope->BindNode(funcNode);
3265     funcNode->SetRange({startLoc, endLoc});
3266 
3267     return funcNode;
3268 }
3269 
ValidateTsFunctionOverloadParams(const ArenaVector<ir::Expression * > & params)3270 void ParserImpl::ValidateTsFunctionOverloadParams(const ArenaVector<ir::Expression *> &params)
3271 {
3272     for (auto *it : params) {
3273         if (it->IsAssignmentPattern()) {
3274             ThrowSyntaxError(
3275                 "A parameter initializer is only allowed in a function "
3276                 "or constructor implementation.",
3277                 it->Start());
3278         }
3279     }
3280 }
3281 
ParseSpreadElement(ExpressionParseFlags flags)3282 ir::SpreadElement *ParserImpl::ParseSpreadElement(ExpressionParseFlags flags)
3283 {
3284     ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD);
3285     lexer::SourcePosition startLocation = lexer_->GetToken().Start();
3286     bool inPattern = (flags & ExpressionParseFlags::MUST_BE_PATTERN);
3287     lexer_->NextToken();
3288 
3289     ir::Expression *argument {};
3290     if (inPattern) {
3291         argument = ParsePatternElement(ExpressionParseFlags::IN_REST);
3292         if ((flags & ExpressionParseFlags::OBJECT_PATTERN) && !argument->IsIdentifier()) {
3293             ThrowSyntaxError("RestParameter must be followed by an identifier in declaration contexts");
3294         }
3295     } else {
3296         argument = ParseExpression(flags);
3297     }
3298 
3299     ir::Expression *typeAnnotation = nullptr;
3300 
3301     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
3302         lexer_->NextToken();  // eat ':'
3303         TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
3304         typeAnnotation = ParseTsTypeAnnotation(&options);
3305     }
3306 
3307     if (inPattern && argument->IsAssignmentExpression()) {
3308         ThrowSyntaxError("RestParameter does not support an initializer");
3309     }
3310 
3311     lexer::SourcePosition endLoc = typeAnnotation ? typeAnnotation->End() : argument->End();
3312 
3313     auto nodeType = inPattern ? ir::AstNodeType::REST_ELEMENT : ir::AstNodeType::SPREAD_ELEMENT;
3314     auto *spreadElementNode = AllocNode<ir::SpreadElement>(nodeType, argument);
3315     spreadElementNode->SetRange({startLocation, endLoc});
3316 
3317     if (typeAnnotation) {
3318         spreadElementNode->SetTsTypeAnnotation(typeAnnotation);
3319     }
3320 
3321     return spreadElementNode;
3322 }
3323 
CreateTsParameterProperty(ir::Expression * parameter,ir::ModifierFlags modifiers)3324 ir::TSParameterProperty *ParserImpl::CreateTsParameterProperty(ir::Expression *parameter, ir::ModifierFlags modifiers)
3325 {
3326     auto accessibility = ir::AccessibilityOption::NO_OPTS;
3327     bool readonly = false;
3328     bool isStatic = false;
3329     bool isExport = false;
3330 
3331     if (modifiers & ir::ModifierFlags::PRIVATE) {
3332         accessibility = ir::AccessibilityOption::PRIVATE;
3333     } else if ((modifiers & ir::ModifierFlags::PUBLIC)) {
3334         accessibility = ir::AccessibilityOption::PUBLIC;
3335     } else if (modifiers & ir::ModifierFlags::PROTECTED) {
3336         accessibility = ir::AccessibilityOption::PROTECTED;
3337     }
3338 
3339     if (modifiers & ir::ModifierFlags::READONLY) {
3340         readonly = true;
3341     }
3342 
3343     if (modifiers & ir::ModifierFlags::STATIC) {
3344         isStatic = true;
3345     }
3346 
3347     // TODO(Csaba Repasi): Handle export property of TSParameterProperty
3348 
3349     return AllocNode<ir::TSParameterProperty>(accessibility, parameter, readonly, isStatic, isExport);
3350 }
3351 
ParseFunctionParameter(bool isDeclare)3352 ir::Expression *ParserImpl::ParseFunctionParameter(bool isDeclare)
3353 {
3354     if (Extension() == ScriptExtension::TS && lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_THIS) {
3355         lexer_->GetToken().SetTokenType(lexer::TokenType::LITERAL_IDENT);
3356     }
3357 
3358     lexer::SourcePosition parameterStart = lexer_->GetToken().Start();
3359     ir::ModifierFlags modifiers = ParseModifiers();
3360     // TODO(Csaba Repasi): throw error if using strick mode reserved keyword here
3361     if (!(context_.Status() & ParserStatus::CONSTRUCTOR_FUNCTION) && modifiers != ir::ModifierFlags::NONE) {
3362         ThrowSyntaxError("A parameter property is only allowed in a constructor implementation.", parameterStart);
3363     }
3364 
3365     lexer::TokenType tokenType = lexer_->GetToken().Type();
3366     if (tokenType == lexer::TokenType::LITERAL_IDENT &&
3367         (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_ARGUMENTS ||
3368          lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_EVAL)) {
3369         ThrowSyntaxError(
3370             "'eval' or 'arguments' can't be defined or assigned to "
3371             "in strict mode code",
3372             lexer_->GetToken().Start());
3373     }
3374 
3375     ir::Expression *functionParameter = ParsePatternElement(ExpressionParseFlags::NO_OPTS, true, isDeclare);
3376 
3377     if (modifiers != ir::ModifierFlags::NONE && functionParameter->IsRestElement()) {
3378         ThrowSyntaxError("A parameter property cannot be declared using a rest parameter.", parameterStart);
3379     }
3380 
3381     if (modifiers != ir::ModifierFlags::NONE &&
3382         (functionParameter->IsArrayPattern() || functionParameter->IsObjectPattern() ||
3383          (functionParameter->IsAssignmentPattern() &&
3384           (functionParameter->AsAssignmentPattern()->Left()->IsArrayPattern() ||
3385            functionParameter->AsAssignmentPattern()->Left()->IsObjectPattern())))) {
3386         ThrowSyntaxError("A parameter property may not be declared using a binding pattern.", parameterStart);
3387     }
3388 
3389     if (modifiers != ir::ModifierFlags::NONE) {
3390         functionParameter = CreateTsParameterProperty(functionParameter, modifiers);
3391         functionParameter->SetRange({parameterStart, functionParameter->AsTSParameterProperty()->Parameter()->End()});
3392     }
3393 
3394     Binder()->AddParamDecl(functionParameter);
3395 
3396     return functionParameter;
3397 }
3398 
ValidateLvalueAssignmentTarget(ir::Expression * node)3399 void ParserImpl::ValidateLvalueAssignmentTarget(ir::Expression *node)
3400 {
3401     switch (node->Type()) {
3402         case ir::AstNodeType::IDENTIFIER: {
3403             // Check the prevoius ident keyword type
3404             if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_ARGUMENTS) {
3405                 ThrowSyntaxError("Assigning to 'arguments' in strict mode is invalid");
3406             } else if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_EVAL) {
3407                 ThrowSyntaxError("Assigning to 'eval' in strict mode is invalid");
3408             }
3409             break;
3410         }
3411         case ir::AstNodeType::MEMBER_EXPRESSION: {
3412             break;
3413         }
3414         default: {
3415             ThrowSyntaxError("Invalid left-hand side in assignment expression");
3416         }
3417     }
3418 }
3419 
ValidateAssignmentTarget(ExpressionParseFlags flags,ir::Expression * node)3420 void ParserImpl::ValidateAssignmentTarget(ExpressionParseFlags flags, ir::Expression *node)
3421 {
3422     switch (node->Type()) {
3423         case ir::AstNodeType::ARRAY_PATTERN:
3424         case ir::AstNodeType::OBJECT_PATTERN: {
3425             break;
3426         }
3427         case ir::AstNodeType::ARRAY_EXPRESSION:
3428         case ir::AstNodeType::OBJECT_EXPRESSION: {
3429             if (flags & ExpressionParseFlags::POTENTIALLY_IN_PATTERN) {
3430                 return;
3431             }
3432 
3433             [[fallthrough]];
3434         }
3435         default: {
3436             return ValidateLvalueAssignmentTarget(node);
3437         }
3438     }
3439 }
3440 
ValidateArrowParameterBindings(const ir::Expression * node)3441 void ParserImpl::ValidateArrowParameterBindings(const ir::Expression *node)
3442 {
3443     switch (node->Type()) {
3444         case ir::AstNodeType::IDENTIFIER: {
3445             const util::StringView &identifier = node->AsIdentifier()->Name();
3446 
3447             if (context_.IsAsync() && identifier.Is("await")) {
3448                 ThrowSyntaxError("'await' in formal parameter is invalid.", node->Start());
3449             }
3450             break;
3451         }
3452         case ir::AstNodeType::OMITTED_EXPRESSION: {
3453             break;
3454         }
3455         case ir::AstNodeType::REST_ELEMENT: {
3456             ValidateArrowParameterBindings(node->AsRestElement()->Argument());
3457             break;
3458         }
3459         case ir::AstNodeType::PROPERTY: {
3460             break;
3461         }
3462         case ir::AstNodeType::OBJECT_PATTERN: {
3463             const auto &props = node->AsObjectPattern()->Properties();
3464 
3465             for (auto *it : props) {
3466                 ValidateArrowParameterBindings(it);
3467             }
3468             break;
3469         }
3470         case ir::AstNodeType::ARRAY_PATTERN: {
3471             const auto &elements = node->AsArrayPattern()->Elements();
3472 
3473             for (auto *it : elements) {
3474                 ValidateArrowParameterBindings(it);
3475             }
3476             break;
3477         }
3478         case ir::AstNodeType::ASSIGNMENT_PATTERN: {
3479             ValidateArrowParameterBindings(node->AsAssignmentPattern()->Left());
3480             break;
3481         }
3482         default: {
3483             ThrowSyntaxError("Unexpected ArrowParameter element");
3484         }
3485     }
3486 }
3487 
CurrentTokenIsModifier(char32_t nextCp) const3488 bool ParserImpl::CurrentTokenIsModifier(char32_t nextCp) const
3489 {
3490     return (Extension() == ScriptExtension::TS &&
3491             (nextCp != LEX_CHAR_EQUALS || nextCp != LEX_CHAR_SEMICOLON || nextCp != LEX_CHAR_LEFT_PAREN));
3492 }
3493 
ThrowParameterModifierError(ir::ModifierFlags status) const3494 void ParserImpl::ThrowParameterModifierError(ir::ModifierFlags status) const
3495 {
3496     ThrowSyntaxError(
3497         {"'", (status & ir::ModifierFlags::STATIC) ? "static" : ((status & ir::ModifierFlags::ASYNC) ? "async" : "declare") ,
3498          "' modifier cannot appear on a parameter."},
3499         lexer_->GetToken().Start());
3500 }
3501 
ThrowSyntaxError(std::string_view errorMessage) const3502 void ParserImpl::ThrowSyntaxError(std::string_view errorMessage) const
3503 {
3504     ThrowSyntaxError(errorMessage, lexer_->GetToken().Start());
3505 }
3506 
ThrowSyntaxError(std::initializer_list<std::string_view> list) const3507 void ParserImpl::ThrowSyntaxError(std::initializer_list<std::string_view> list) const
3508 {
3509     ThrowSyntaxError(list, lexer_->GetToken().Start());
3510 }
3511 
ThrowSyntaxError(std::initializer_list<std::string_view> list,const lexer::SourcePosition & pos) const3512 void ParserImpl::ThrowSyntaxError(std::initializer_list<std::string_view> list, const lexer::SourcePosition &pos) const
3513 {
3514     std::stringstream ss;
3515 
3516     for (const auto &it : list) {
3517         ss << it;
3518     }
3519 
3520     std::string err = ss.str();
3521 
3522     ThrowSyntaxError(std::string_view {err}, pos);
3523 }
3524 
ThrowSyntaxError(std::string_view errorMessage,const lexer::SourcePosition & pos) const3525 void ParserImpl::ThrowSyntaxError(std::string_view errorMessage, const lexer::SourcePosition &pos) const
3526 {
3527     lexer::LineIndex index(program_.SourceCode());
3528     lexer::SourceLocation loc = index.GetLocation(pos);
3529 
3530     throw Error {ErrorType::SYNTAX, errorMessage, loc.line, loc.col};
3531 }
3532 
Extension() const3533 ScriptExtension ParserImpl::Extension() const
3534 {
3535     return program_.Extension();
3536 }
3537 
GetSourceTextModuleRecord()3538 parser::SourceTextModuleRecord *ParserImpl::GetSourceTextModuleRecord()
3539 {
3540     return Binder()->Program()->ModuleRecord();
3541 }
3542 
AddHotfixHelper(util::Hotfix * hotfixHelper)3543 void ParserImpl::AddHotfixHelper(util::Hotfix *hotfixHelper)
3544 {
3545     program_.AddHotfixHelper(hotfixHelper);
3546 }
3547 
CheckStrictReservedWord() const3548 void ParserImpl::CheckStrictReservedWord() const
3549 {
3550     if (Extension() == ScriptExtension::JS) {
3551         if (lexer_->GetToken().IsJsStrictReservedWord()) {
3552             ThrowSyntaxError("Unexpected reserved word in strict mode.");
3553         }
3554     } else {
3555         if (lexer_->GetToken().KeywordType() >= lexer::TokenType::KEYW_ARGUMENTS) {
3556             ThrowSyntaxError("Unexpected reserved word in strict mode.");
3557         }
3558     }
3559 }
3560 
3561 }  // namespace panda::es2panda::parser
3562