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