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, ArenaVector<ir::Expression *> const &members)
1513 {
1514 ir::Expression *key = nullptr;
1515
1516 if (member->IsTSPropertySignature()) {
1517 key = member->AsTSPropertySignature()->Key();
1518 } else if (member->IsTSMethodSignature()) {
1519 key = member->AsTSMethodSignature()->Key();
1520 } else {
1521 return;
1522 }
1523
1524 if (!key->IsIdentifier() && !key->IsNumberLiteral() && !key->IsStringLiteral()) {
1525 return;
1526 }
1527
1528 for (auto *it : members) {
1529 ir::Expression *compare = nullptr;
1530
1531 switch (it->Type()) {
1532 case ir::AstNodeType::TS_PROPERTY_SIGNATURE: {
1533 compare = it->AsTSPropertySignature()->Key();
1534 break;
1535 }
1536 case ir::AstNodeType::TS_METHOD_SIGNATURE: {
1537 compare = it->AsTSMethodSignature()->Key();
1538 break;
1539 }
1540 default: {
1541 continue;
1542 }
1543 }
1544
1545 if (!compare->IsIdentifier() && !compare->IsNumberLiteral() && !compare->IsStringLiteral()) {
1546 continue;
1547 }
1548
1549 if (member->IsTSMethodSignature() && it->Type() == ir::AstNodeType::TS_METHOD_SIGNATURE) {
1550 continue;
1551 }
1552
1553 if (GetTSPropertyName(key) == GetTSPropertyName(compare)) {
1554 ThrowSyntaxError("Duplicated identifier", key->Start());
1555 }
1556 }
1557 }
1558
ParseTsTypeLiteralOrInterface()1559 ArenaVector<ir::Expression *> ParserImpl::ParseTsTypeLiteralOrInterface()
1560 {
1561 ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE);
1562
1563 lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT); // eat '{'
1564
1565 ArenaVector<ir::Expression *> members(Allocator()->Adapter());
1566
1567 while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
1568 ir::Expression *member = ParseTsTypeLiteralOrInterfaceMember();
1569
1570 CheckObjectTypeForDuplicatedProperties(member, members);
1571
1572 members.push_back(member);
1573
1574 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
1575 break;
1576 }
1577
1578 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COMMA &&
1579 lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
1580 if (!lexer_->GetToken().NewLine()) {
1581 ThrowSyntaxError("',' expected");
1582 }
1583
1584 if (lexer_->GetToken().IsKeyword()) {
1585 lexer_->GetToken().SetTokenType(lexer::TokenType::LITERAL_IDENT);
1586 }
1587
1588 continue;
1589 }
1590
1591 lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);
1592 }
1593
1594 return members;
1595 }
1596
ParseTsArrayType(ir::Expression * elementType)1597 ir::TSArrayType *ParserImpl::ParseTsArrayType(ir::Expression *elementType)
1598 {
1599 ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET);
1600 lexer_->NextToken(); // eat '['
1601
1602 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
1603 ThrowSyntaxError("']' expected");
1604 }
1605
1606 lexer::SourcePosition endLoc = lexer_->GetToken().End();
1607 lexer_->NextToken(); // eat ']'
1608
1609 lexer::SourcePosition startLoc = elementType->Start();
1610 auto *arrayType = AllocNode<ir::TSArrayType>(elementType);
1611 arrayType->SetRange({startLoc, endLoc});
1612
1613 return arrayType;
1614 }
1615
ParseTsUnionType(ir::Expression * type,bool restrictExtends)1616 ir::TSUnionType *ParserImpl::ParseTsUnionType(ir::Expression *type, bool restrictExtends)
1617 {
1618 ArenaVector<ir::Expression *> types(Allocator()->Adapter());
1619 lexer::SourcePosition startLoc;
1620
1621 TypeAnnotationParsingOptions options =
1622 TypeAnnotationParsingOptions::THROW_ERROR | TypeAnnotationParsingOptions::IN_UNION;
1623
1624 if (restrictExtends) {
1625 options |= TypeAnnotationParsingOptions::RESTRICT_EXTENDS;
1626 }
1627
1628 if (type) {
1629 startLoc = type->Start();
1630 types.push_back(type);
1631 } else {
1632 startLoc = lexer_->GetToken().Start();
1633 }
1634
1635 while (true) {
1636 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_BITWISE_OR) {
1637 break;
1638 }
1639
1640 lexer_->NextToken(); // eat '|'
1641
1642 types.push_back(ParseTsTypeAnnotation(&options));
1643 }
1644
1645 lexer::SourcePosition endLoc = types.back()->End();
1646
1647 auto *unionType = AllocNode<ir::TSUnionType>(std::move(types));
1648 auto *typeVar = binder::Scope::CreateVar(Allocator(), "__type", binder::VariableFlags::TYPE, unionType);
1649 unionType->SetVariable(typeVar);
1650 unionType->SetRange({startLoc, endLoc});
1651
1652 return unionType;
1653 }
1654
ParseTsIntersectionType(ir::Expression * type,bool inUnion,bool restrictExtends)1655 ir::TSIntersectionType *ParserImpl::ParseTsIntersectionType(ir::Expression *type, bool inUnion, bool restrictExtends)
1656 {
1657 ArenaVector<ir::Expression *> types(Allocator()->Adapter());
1658 lexer::SourcePosition startLoc;
1659
1660 TypeAnnotationParsingOptions options =
1661 TypeAnnotationParsingOptions::THROW_ERROR | TypeAnnotationParsingOptions::IN_INTERSECTION;
1662
1663 if (restrictExtends) {
1664 options |= TypeAnnotationParsingOptions::RESTRICT_EXTENDS;
1665 }
1666
1667 if (inUnion) {
1668 options |= TypeAnnotationParsingOptions::IN_UNION;
1669 }
1670
1671 if (type) {
1672 startLoc = type->Start();
1673 types.push_back(type);
1674 } else {
1675 startLoc = lexer_->GetToken().Start();
1676 }
1677
1678 while (true) {
1679 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_BITWISE_AND) {
1680 break;
1681 }
1682
1683 lexer_->NextToken(); // eat '&'
1684
1685 types.push_back(ParseTsTypeAnnotation(&options));
1686 }
1687
1688 lexer::SourcePosition endLoc = types.back()->End();
1689
1690 auto *intersectionType = AllocNode<ir::TSIntersectionType>(std::move(types));
1691 auto *typeVar = binder::Scope::CreateVar(Allocator(), "__type", binder::VariableFlags::TYPE, intersectionType);
1692 intersectionType->SetVariable(typeVar);
1693 intersectionType->SetRange({startLoc, endLoc});
1694
1695 return intersectionType;
1696 }
1697
IsTsFunctionType()1698 bool ParserImpl::IsTsFunctionType()
1699 {
1700 ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS);
1701 const auto startPos = lexer_->Save();
1702 lexer_->NextToken(); // eat '('
1703 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS ||
1704 lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD) {
1705 lexer_->Rewind(startPos);
1706 return true;
1707 }
1708
1709 try {
1710 ParseModifiers();
1711 if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT ||
1712 (Extension() == ScriptExtension::TS && lexer_->GetToken().Type() == lexer::TokenType::KEYW_THIS)) {
1713 lexer_->NextToken();
1714 } else if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET) {
1715 ParseArrayExpression(ExpressionParseFlags::MUST_BE_PATTERN);
1716 } else if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
1717 ParseObjectExpression(ExpressionParseFlags::MUST_BE_PATTERN | ExpressionParseFlags::OBJECT_PATTERN);
1718 } else {
1719 lexer_->Rewind(startPos);
1720 return false;
1721 }
1722 } catch ([[maybe_unused]] const class Error &e) {
1723 lexer_->Rewind(startPos);
1724 return false;
1725 }
1726
1727 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA ||
1728 lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_QUESTION_MARK ||
1729 lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON ||
1730 lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_EQUAL) {
1731 lexer_->Rewind(startPos);
1732 return true;
1733 }
1734
1735 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
1736 lexer_->NextToken(); // eat ')'
1737 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_ARROW) {
1738 lexer_->Rewind(startPos);
1739 return true;
1740 }
1741 }
1742 lexer_->Rewind(startPos);
1743 return false;
1744 }
1745
ParseTsParenthesizedOrFunctionType(ir::Expression * typeAnnotation,bool throwError)1746 ir::Expression *ParserImpl::ParseTsParenthesizedOrFunctionType(ir::Expression *typeAnnotation, bool throwError)
1747 {
1748 if (typeAnnotation) {
1749 return nullptr;
1750 }
1751
1752 lexer::SourcePosition typeStart = lexer_->GetToken().Start();
1753
1754 bool abstractConstructor = lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_ABSTRACT;
1755 if (abstractConstructor) {
1756 lexer_->NextToken(); // eat 'abstract'
1757 }
1758
1759 bool isConstructionType = false;
1760
1761 if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_NEW) {
1762 lexer_->NextToken(); // eat 'new'
1763 isConstructionType = true;
1764
1765 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS &&
1766 lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LESS_THAN) {
1767 if (!throwError) {
1768 return nullptr;
1769 }
1770 ThrowSyntaxError("'(' expected");
1771 }
1772 }
1773
1774 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN || isConstructionType) {
1775 return ParseTsFunctionType(typeStart, isConstructionType, throwError, abstractConstructor);
1776 }
1777
1778 if (IsTsFunctionType()) {
1779 return ParseTsFunctionType(typeStart, false, throwError);
1780 }
1781
1782 ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS);
1783 lexer_->NextToken(); // eat '('
1784
1785 TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::NO_OPTS;
1786 ir::Expression *type = ParseTsTypeAnnotation(&options);
1787
1788 if (throwError && lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
1789 ThrowSyntaxError("')' expected");
1790 }
1791
1792 lexer::SourcePosition endLoc = lexer_->GetToken().End();
1793 lexer_->NextToken(); // eat ')'
1794
1795 auto *result = AllocNode<ir::TSParenthesizedType>(type);
1796 result->SetRange({typeStart, endLoc});
1797
1798 return result;
1799 }
1800
ParseTsFunctionType(lexer::SourcePosition startLoc,bool isConstructionType,bool throwError,bool abstractConstructor)1801 ir::Expression *ParserImpl::ParseTsFunctionType(lexer::SourcePosition startLoc, bool isConstructionType,
1802 bool throwError, bool abstractConstructor)
1803 {
1804 ir::TSTypeParameterDeclaration *typeParamDecl = nullptr;
1805 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) {
1806 typeParamDecl = ParseTsTypeParameterDeclaration(throwError);
1807
1808 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
1809 if (!throwError) {
1810 return nullptr;
1811 }
1812
1813 ThrowSyntaxError("'(' expected");
1814 }
1815 }
1816
1817 FunctionParameterContext funcParamContext(&context_, Binder());
1818 auto *funcParamScope = funcParamContext.LexicalScope().GetScope();
1819
1820 ArenaVector<ir::Expression *> params(Allocator()->Adapter());
1821 try {
1822 params = ParseFunctionParams(true);
1823 } catch (const Error &e) {
1824 if (!throwError) {
1825 return nullptr;
1826 }
1827 throw e;
1828 }
1829
1830 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_ARROW) {
1831 ThrowSyntaxError("'=>' expected");
1832 }
1833
1834 lexer_->NextToken(); // eat '=>'
1835
1836 TypeAnnotationParsingOptions options =
1837 TypeAnnotationParsingOptions::THROW_ERROR | TypeAnnotationParsingOptions::CAN_BE_TS_TYPE_PREDICATE;
1838 ir::Expression *returnTypeAnnotation = ParseTsTypeAnnotation(&options);
1839
1840 ir::Expression *funcType = nullptr;
1841
1842 if (isConstructionType) {
1843 funcType = AllocNode<ir::TSConstructorType>(funcParamScope, std::move(params), typeParamDecl,
1844 returnTypeAnnotation, abstractConstructor);
1845 } else {
1846 funcType =
1847 AllocNode<ir::TSFunctionType>(funcParamScope, std::move(params), typeParamDecl, returnTypeAnnotation);
1848 }
1849
1850 funcType->SetRange({startLoc, returnTypeAnnotation->End()});
1851 funcParamScope->BindNode(funcType);
1852
1853 return funcType;
1854 }
1855
ParseTsBasicType(TypeAnnotationParsingOptions options)1856 ir::Expression *ParserImpl::ParseTsBasicType(TypeAnnotationParsingOptions options)
1857 {
1858 ir::Expression *typeAnnotation = nullptr;
1859
1860 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MINUS) {
1861 lexer_->NextToken();
1862
1863 if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_NUMBER) {
1864 if (options & TypeAnnotationParsingOptions::THROW_ERROR) {
1865 ThrowSyntaxError("Type expected");
1866 } else {
1867 return nullptr;
1868 }
1869 }
1870 }
1871 if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_NUMBER) {
1872 if (lexer_->GetToken().Flags() & lexer::TokenFlags::NUMBER_BIGINT) {
1873 auto *bigintNode = AllocNode<ir::BigIntLiteral>(lexer_->GetToken().BigInt());
1874 bigintNode->SetRange(lexer_->GetToken().Loc());
1875
1876 typeAnnotation = AllocNode<ir::TSLiteralType>(bigintNode);
1877 } else {
1878 auto *numberNode = AllocNode<ir::NumberLiteral>(lexer_->GetToken().Number(), lexer_->GetToken().String());
1879 numberNode->SetRange(lexer_->GetToken().Loc());
1880
1881 typeAnnotation = AllocNode<ir::TSLiteralType>(numberNode);
1882 }
1883 } else if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_STRING) {
1884 auto *stringNode = AllocNode<ir::StringLiteral>(lexer_->GetToken().String());
1885 stringNode->SetRange(lexer_->GetToken().Loc());
1886
1887 typeAnnotation = AllocNode<ir::TSLiteralType>(stringNode);
1888 } else if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_TRUE) {
1889 auto *booleanLiteral = AllocNode<ir::BooleanLiteral>(true);
1890 booleanLiteral->SetRange(lexer_->GetToken().Loc());
1891
1892 typeAnnotation = AllocNode<ir::TSLiteralType>(booleanLiteral);
1893 } else if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_FALSE) {
1894 auto *booleanLiteral = AllocNode<ir::BooleanLiteral>(false);
1895 booleanLiteral->SetRange(lexer_->GetToken().Loc());
1896
1897 typeAnnotation = AllocNode<ir::TSLiteralType>(booleanLiteral);
1898 } else if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_ANY) {
1899 typeAnnotation = AllocNode<ir::TSAnyKeyword>();
1900 } else if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_BOOLEAN) {
1901 typeAnnotation = AllocNode<ir::TSBooleanKeyword>();
1902 } else if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_NUMBER) {
1903 typeAnnotation = AllocNode<ir::TSNumberKeyword>();
1904 } else if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_STRING) {
1905 typeAnnotation = AllocNode<ir::TSStringKeyword>();
1906 } else if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_UNKNOWN) {
1907 typeAnnotation = AllocNode<ir::TSUnknownKeyword>();
1908 } else if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_VOID) {
1909 typeAnnotation = AllocNode<ir::TSVoidKeyword>();
1910 } else if (lexer_->GetToken().KeywordType() == lexer::TokenType::LITERAL_NULL) {
1911 typeAnnotation = AllocNode<ir::TSNullKeyword>();
1912 } else if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_UNDEFINED) {
1913 typeAnnotation = AllocNode<ir::TSUndefinedKeyword>();
1914 } else if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_NEVER) {
1915 typeAnnotation = AllocNode<ir::TSNeverKeyword>();
1916 } else if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_OBJECT) {
1917 typeAnnotation = AllocNode<ir::TSObjectKeyword>();
1918 } else if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_BIGINT) {
1919 typeAnnotation = AllocNode<ir::TSBigintKeyword>();
1920 } else if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_SYMBOL) {
1921 typeAnnotation = AllocNode<ir::TSSymbolKeyword>();
1922 } else {
1923 ThrowSyntaxError("Unexpected type");
1924 }
1925
1926 typeAnnotation->SetRange(lexer_->GetToken().Loc());
1927
1928 lexer_->NextToken();
1929 return typeAnnotation;
1930 }
1931
GetAccessability(ir::ModifierFlags modifiers)1932 static ir::ModifierFlags GetAccessability(ir::ModifierFlags modifiers)
1933 {
1934 if (modifiers & ir::ModifierFlags::PUBLIC) {
1935 return ir::ModifierFlags::PUBLIC;
1936 }
1937
1938 if (modifiers & ir::ModifierFlags::PRIVATE) {
1939 return ir::ModifierFlags::PRIVATE;
1940 }
1941
1942 if (modifiers & ir::ModifierFlags::PROTECTED) {
1943 return ir::ModifierFlags::PROTECTED;
1944 }
1945
1946 return ir::ModifierFlags::NONE;
1947 }
1948
IsModifierKind(const lexer::Token & token)1949 static bool IsModifierKind(const lexer::Token &token)
1950 {
1951 if (token.Type() == lexer::TokenType::LITERAL_IDENT) {
1952 switch (token.KeywordType()) {
1953 case lexer::TokenType::KEYW_PUBLIC:
1954 case lexer::TokenType::KEYW_PRIVATE:
1955 case lexer::TokenType::KEYW_PROTECTED:
1956 case lexer::TokenType::KEYW_STATIC:
1957 case lexer::TokenType::KEYW_ASYNC:
1958 case lexer::TokenType::KEYW_ABSTRACT:
1959 case lexer::TokenType::KEYW_DECLARE:
1960 case lexer::TokenType::KEYW_READONLY:
1961 return true;
1962 default:
1963 return false;
1964 }
1965 }
1966
1967 return false;
1968 }
1969
ParseModifiers()1970 ir::ModifierFlags ParserImpl::ParseModifiers()
1971 {
1972 ir::ModifierFlags resultStatus = ir::ModifierFlags::NONE;
1973 ir::ModifierFlags prevStatus = ir::ModifierFlags::ALL;
1974
1975 while (IsModifierKind(lexer_->GetToken())) {
1976 char32_t nextCp = lexer_->Lookahead();
1977 if (!((Extension() == ScriptExtension::JS && nextCp != LEX_CHAR_LEFT_PAREN) ||
1978 (Extension() == ScriptExtension::TS && nextCp != LEX_CHAR_EQUALS && nextCp != LEX_CHAR_SEMICOLON &&
1979 nextCp != LEX_CHAR_COMMA && nextCp != LEX_CHAR_LEFT_PAREN))) {
1980 break;
1981 }
1982
1983 lexer::TokenFlags tokenFlags = lexer_->GetToken().Flags();
1984 if (tokenFlags & lexer::TokenFlags::HAS_ESCAPE) {
1985 ThrowSyntaxError("Keyword must not contain escaped characters");
1986 }
1987
1988 ir::ModifierFlags actualStatus = ir::ModifierFlags::NONE;
1989 ir::ModifierFlags nextStatus = ir::ModifierFlags::NONE;
1990
1991 switch (lexer_->GetToken().KeywordType()) {
1992 case lexer::TokenType::KEYW_PUBLIC: {
1993 actualStatus = ir::ModifierFlags::PUBLIC;
1994 nextStatus = ir::ModifierFlags::ASYNC | ir::ModifierFlags::STATIC | ir::ModifierFlags::READONLY |
1995 ir::ModifierFlags::DECLARE | ir::ModifierFlags::ABSTRACT;
1996 break;
1997 }
1998 case lexer::TokenType::KEYW_PRIVATE: {
1999 actualStatus = ir::ModifierFlags::PRIVATE;
2000 nextStatus = ir::ModifierFlags::ASYNC | ir::ModifierFlags::STATIC | ir::ModifierFlags::READONLY |
2001 ir::ModifierFlags::DECLARE | ir::ModifierFlags::ABSTRACT;
2002 break;
2003 }
2004 case lexer::TokenType::KEYW_PROTECTED: {
2005 actualStatus = ir::ModifierFlags::PROTECTED;
2006 nextStatus = ir::ModifierFlags::ASYNC | ir::ModifierFlags::STATIC | ir::ModifierFlags::READONLY |
2007 ir::ModifierFlags::DECLARE | ir::ModifierFlags::ABSTRACT;
2008 break;
2009 }
2010 case lexer::TokenType::KEYW_STATIC: {
2011 actualStatus = ir::ModifierFlags::STATIC;
2012 nextStatus = ir::ModifierFlags::ASYNC | ir::ModifierFlags::READONLY | ir::ModifierFlags::DECLARE |
2013 ir::ModifierFlags::ABSTRACT;
2014 break;
2015 }
2016 case lexer::TokenType::KEYW_ASYNC: {
2017 actualStatus = ir::ModifierFlags::ASYNC;
2018 nextStatus = ir::ModifierFlags::READONLY | ir::ModifierFlags::DECLARE | ir::ModifierFlags::ABSTRACT;
2019 break;
2020 }
2021 case lexer::TokenType::KEYW_ABSTRACT: {
2022 actualStatus = ir::ModifierFlags::ABSTRACT;
2023 nextStatus = ir::ModifierFlags::ACCESS | ir::ModifierFlags::ASYNC | ir::ModifierFlags::STATIC |
2024 ir::ModifierFlags::READONLY | ir::ModifierFlags::DECLARE;
2025 break;
2026 }
2027 case lexer::TokenType::KEYW_DECLARE: {
2028 actualStatus = ir::ModifierFlags::DECLARE;
2029 nextStatus = ir::ModifierFlags::ACCESS | ir::ModifierFlags::ASYNC | ir::ModifierFlags::STATIC |
2030 ir::ModifierFlags::READONLY;
2031 break;
2032 }
2033 case lexer::TokenType::KEYW_READONLY: {
2034 actualStatus = ir::ModifierFlags::READONLY;
2035 nextStatus = ir::ModifierFlags::ASYNC | ir::ModifierFlags::DECLARE | ir::ModifierFlags::ABSTRACT;
2036 break;
2037 }
2038 default: {
2039 UNREACHABLE();
2040 }
2041 }
2042
2043 if (lexer_->Lookahead() == LEX_CHAR_COLON || lexer_->Lookahead() == LEX_CHAR_COMMA ||
2044 lexer_->Lookahead() == LEX_CHAR_RIGHT_PAREN || lexer_->Lookahead() == LEX_CHAR_QUESTION ||
2045 lexer_->Lookahead() == LEX_CHAR_RIGHT_BRACE || lexer_->Lookahead() == LEX_CHAR_LESS_THAN) {
2046 break;
2047 }
2048
2049 auto pos = lexer_->Save();
2050 lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);
2051
2052 if ((prevStatus & actualStatus) == 0) {
2053 lexer_->Rewind(pos);
2054 ThrowSyntaxError("Unexpected modifier");
2055 }
2056
2057 if ((resultStatus & actualStatus) != 0) {
2058 lexer_->Rewind(pos);
2059 ThrowSyntaxError("Duplicated modifier is not allowed");
2060 }
2061
2062 if ((context_.Status() & ParserStatus::CONSTRUCTOR_FUNCTION) &&
2063 (actualStatus & ~ir::ModifierFlags::ALLOWED_IN_CTOR_PARAMETER)) {
2064 lexer_->Rewind(pos);
2065 ThrowParameterModifierError(actualStatus);
2066 }
2067
2068 resultStatus |= actualStatus;
2069 prevStatus = nextStatus;
2070 }
2071
2072 return resultStatus;
2073 }
2074
CheckAccessorPair(const ArenaVector<ir::Statement * > & properties,const ir::Expression * propName,ir::MethodDefinitionKind methodKind,ir::ModifierFlags access,bool hasDecorator,lexer::SourcePosition errorInfo)2075 void ParserImpl::CheckAccessorPair(const ArenaVector<ir::Statement *> &properties, const ir::Expression *propName,
2076 ir::MethodDefinitionKind methodKind, ir::ModifierFlags access, bool hasDecorator,
2077 lexer::SourcePosition errorInfo)
2078 {
2079 for (const auto &it : properties) {
2080 if (!it->IsMethodDefinition() || (!hasDecorator && it->AsMethodDefinition()->Kind() != methodKind)) {
2081 continue;
2082 }
2083
2084 const ir::Expression *key = it->AsMethodDefinition()->Key();
2085
2086 if (key->Type() != propName->Type()) {
2087 continue;
2088 }
2089
2090 bool keyIsSame = false;
2091
2092 if (key->IsIdentifier()) {
2093 const util::StringView &strName = propName->AsIdentifier()->Name();
2094 const util::StringView &compareName = (key->AsIdentifier()->Name());
2095
2096 keyIsSame = strName == compareName;
2097 } else if (key->IsNumberLiteral()) {
2098 keyIsSame = *key->AsNumberLiteral() == *propName->AsNumberLiteral();
2099 } else if (key->IsStringLiteral()) {
2100 keyIsSame = *key->AsStringLiteral() == *propName->AsStringLiteral();
2101 }
2102
2103 if (!keyIsSame) {
2104 continue;
2105 }
2106
2107 if (hasDecorator &&
2108 (it->AsMethodDefinition()->Kind() == ir::MethodDefinitionKind::GET ||
2109 it->AsMethodDefinition()->Kind() == ir::MethodDefinitionKind::SET) &&
2110 !it->AsMethodDefinition()->Decorators().empty()) {
2111 ThrowSyntaxError("Decorators cannot be applied to multiple get/set accessors of the same name.", errorInfo);
2112 }
2113
2114 if (it->AsMethodDefinition()->Kind() != methodKind) {
2115 continue;
2116 }
2117
2118 ir::ModifierFlags getAccess = ir::ModifierFlags::NONE;
2119 ir::ModifierFlags setAccess = ir::ModifierFlags::NONE;
2120
2121 if (methodKind == ir::MethodDefinitionKind::GET) {
2122 setAccess = access;
2123 getAccess = GetAccessability(it->AsMethodDefinition()->Modifiers());
2124 } else {
2125 getAccess = access;
2126 setAccess = GetAccessability(it->AsMethodDefinition()->Modifiers());
2127 }
2128
2129 if ((setAccess == ir::ModifierFlags::NONE && getAccess > ir::ModifierFlags::PUBLIC) ||
2130 (setAccess != ir::ModifierFlags::NONE && getAccess > setAccess)) {
2131 ThrowSyntaxError("A get accessor must be at least as accessible as the setter", key->Start());
2132 }
2133 }
2134 }
2135
ParseClassKeyModifiers(ClassElmentDescriptor * desc)2136 void ParserImpl::ParseClassKeyModifiers(ClassElmentDescriptor *desc)
2137 {
2138 if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
2139 return;
2140 }
2141
2142 char32_t nextCp = lexer_->Lookahead();
2143
2144 if ((Extension() == ScriptExtension::JS && nextCp != LEX_CHAR_LEFT_PAREN) ||
2145 (Extension() == ScriptExtension::TS &&
2146 nextCp != LEX_CHAR_EQUALS && nextCp != LEX_CHAR_SEMICOLON && nextCp != LEX_CHAR_LEFT_PAREN &&
2147 nextCp != LEX_CHAR_LESS_THAN && nextCp != LEX_CHAR_QUESTION && nextCp != LEX_CHAR_COLON)) {
2148 if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_GET) {
2149 if (desc->isPrivateIdent) {
2150 ThrowSyntaxError("Private identifier can not be getter");
2151 }
2152
2153 if (lexer_->GetToken().Flags() & lexer::TokenFlags::HAS_ESCAPE) {
2154 ThrowSyntaxError("Keyword must not contain escaped characters");
2155 }
2156
2157 desc->methodKind = ir::MethodDefinitionKind::GET;
2158 desc->methodStart = lexer_->GetToken().Start();
2159
2160 lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);
2161 } else if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_SET) {
2162 if (desc->isPrivateIdent) {
2163 ThrowSyntaxError("Private identifier can not be setter");
2164 }
2165
2166 if (lexer_->GetToken().Flags() & lexer::TokenFlags::HAS_ESCAPE) {
2167 ThrowSyntaxError("Keyword must not contain escaped characters");
2168 }
2169
2170 desc->methodKind = ir::MethodDefinitionKind::SET;
2171 desc->methodStart = lexer_->GetToken().Start();
2172
2173 lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);
2174 }
2175 }
2176 }
2177
ThrowIfPrivateIdent(ClassElmentDescriptor * desc,const char * msg)2178 void ParserImpl::ThrowIfPrivateIdent(ClassElmentDescriptor *desc, const char *msg)
2179 {
2180 if (desc->isPrivateIdent) {
2181 ThrowSyntaxError(msg);
2182 }
2183 }
2184
ValidateClassKey(ClassElmentDescriptor * desc,bool isDeclare)2185 void ParserImpl::ValidateClassKey(ClassElmentDescriptor *desc, bool isDeclare)
2186 {
2187 if ((desc->modifiers & ir::ModifierFlags::ASYNC) &&
2188 (desc->methodKind == ir::MethodDefinitionKind::GET || desc->methodKind == ir::MethodDefinitionKind::SET)) {
2189 ThrowSyntaxError("Async method can not be getter nor setter");
2190 }
2191
2192 const util::StringView &propNameStr = lexer_->GetToken().Ident();
2193
2194 if (propNameStr.Is("constructor")) {
2195 ThrowIfPrivateIdent(desc, "Private identifier can not be constructor");
2196
2197 if (!(desc->modifiers & ir::ModifierFlags::STATIC)) {
2198 if ((desc->modifiers & ir::ModifierFlags::ASYNC) || desc->methodKind == ir::MethodDefinitionKind::GET ||
2199 desc->methodKind == ir::MethodDefinitionKind::SET || desc->isGenerator) {
2200 ThrowSyntaxError("Constructor can not be special method");
2201 }
2202
2203 desc->methodKind = ir::MethodDefinitionKind::CONSTRUCTOR;
2204 desc->methodStart = lexer_->GetToken().Start();
2205 desc->newStatus |= ParserStatus::CONSTRUCTOR_FUNCTION;
2206
2207 if (desc->hasSuperClass) {
2208 desc->newStatus |= ParserStatus::ALLOW_SUPER_CALL;
2209 }
2210 } else if (Extension() == ScriptExtension::TS) {
2211 ThrowSyntaxError("Static modifier can not appear on a constructor");
2212 }
2213 } else if (!isDeclare && propNameStr.Is("prototype") && (desc->modifiers & ir::ModifierFlags::STATIC)) {
2214 ThrowSyntaxError("Classes may not have static property named prototype");
2215 }
2216 }
2217
ParseClassKey(ClassElmentDescriptor * desc,bool isDeclare)2218 ir::Expression *ParserImpl::ParseClassKey(ClassElmentDescriptor *desc, bool isDeclare)
2219 {
2220 ir::Expression *propName = nullptr;
2221 if (lexer_->GetToken().IsKeyword()) {
2222 lexer_->GetToken().SetTokenType(lexer::TokenType::LITERAL_IDENT);
2223 }
2224
2225 switch (lexer_->GetToken().Type()) {
2226 case lexer::TokenType::LITERAL_IDENT: {
2227 ValidateClassKey(desc, isDeclare);
2228
2229 propName = AllocNode<ir::Identifier>(lexer_->GetToken().Ident());
2230 propName->SetRange(lexer_->GetToken().Loc());
2231 break;
2232 }
2233 case lexer::TokenType::LITERAL_STRING: {
2234 ThrowIfPrivateIdent(desc, "Private identifier name can not be string");
2235
2236 propName = AllocNode<ir::StringLiteral>(lexer_->GetToken().String());
2237 propName->SetRange(lexer_->GetToken().Loc());
2238 break;
2239 }
2240 case lexer::TokenType::LITERAL_NUMBER: {
2241 ThrowIfPrivateIdent(desc, "Private identifier name can not be number");
2242
2243 if (lexer_->GetToken().Flags() & lexer::TokenFlags::NUMBER_BIGINT) {
2244 propName = AllocNode<ir::BigIntLiteral>(lexer_->GetToken().BigInt());
2245 } else {
2246 propName = AllocNode<ir::NumberLiteral>(lexer_->GetToken().Number(), lexer_->GetToken().String());
2247 }
2248
2249 propName->SetRange(lexer_->GetToken().Loc());
2250 break;
2251 }
2252 case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET: {
2253 ThrowIfPrivateIdent(desc, "Unexpected character in private identifier");
2254
2255 lexer_->NextToken(); // eat left square bracket
2256
2257 if (Extension() == ScriptExtension::TS && lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT &&
2258 lexer_->Lookahead() == LEX_CHAR_COLON) {
2259 desc->isIndexSignature = true;
2260
2261 propName = AllocNode<ir::Identifier>(lexer_->GetToken().Ident());
2262 propName->SetRange(lexer_->GetToken().Loc());
2263
2264 lexer_->NextToken(); // eat param
2265
2266 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COLON) {
2267 ThrowSyntaxError("':' expected");
2268 }
2269
2270 lexer_->NextToken(); // eat ':'
2271 TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
2272 ir::Expression *typeAnnotation = ParseTsTypeAnnotation(&options);
2273
2274 if (!typeAnnotation->IsTSNumberKeyword() && !typeAnnotation->IsTSStringKeyword()) {
2275 ThrowSyntaxError(
2276 "An index signature parameter type must be either "
2277 "'string' or 'number'");
2278 }
2279
2280 propName->SetTsTypeAnnotation(typeAnnotation);
2281
2282 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
2283 ThrowSyntaxError("']' expected");
2284 }
2285
2286 lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);
2287
2288 return propName;
2289 }
2290
2291 desc->isComputed = true;
2292
2293 propName = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
2294
2295 if (Extension() == ScriptExtension::TS) {
2296 // TODO(songqi): Determine whether MemberExpression is a symbol during type check.
2297 desc->invalidComputedProperty = !propName->IsNumberLiteral() &&
2298 util::Helpers::GetSignedNumberLiteral(propName) == util::SignedNumberLiteral::UNRECOGNIZED &&
2299 !propName->IsStringLiteral() && !propName->IsMemberExpression() && !propName->IsIdentifier();
2300 }
2301
2302 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
2303 ThrowSyntaxError("Unexpected token, expected ']'");
2304 }
2305 break;
2306 }
2307 default: {
2308 ThrowSyntaxError("Unexpected token in class property");
2309 }
2310 }
2311
2312 lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);
2313
2314 return propName;
2315 }
2316
ValidateClassMethodStart(ClassElmentDescriptor * desc,ir::Expression * typeAnnotation)2317 void ParserImpl::ValidateClassMethodStart(ClassElmentDescriptor *desc, ir::Expression *typeAnnotation)
2318 {
2319 if (Extension() == ScriptExtension::JS) {
2320 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
2321 return;
2322 }
2323 desc->classMethod = true;
2324 }
2325
2326 if (Extension() == ScriptExtension::TS &&
2327 lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS && desc->isPrivateIdent) {
2328 ThrowSyntaxError("A method cannot be named with a private identifier");
2329 }
2330
2331 if (Extension() == ScriptExtension::TS) {
2332 if (!typeAnnotation && (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS ||
2333 lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN)) {
2334 if ((desc->modifiers & (ir::ModifierFlags::DECLARE | ir::ModifierFlags::READONLY))) {
2335 ThrowSyntaxError("Class method can not be declare nor readonly");
2336 }
2337 desc->classMethod = true;
2338 } else {
2339 if ((desc->modifiers & ir::ModifierFlags::ASYNC) || desc->isGenerator) {
2340 ThrowSyntaxError("Expected '('");
2341 }
2342 desc->classField = true;
2343
2344 if (desc->invalidComputedProperty) {
2345 ThrowSyntaxError(
2346 "Computed property name must refer to a symbol or "
2347 "literal expression whos value is "
2348 "number or string");
2349 }
2350 }
2351 }
2352
2353 if (desc->modifiers & ir::ModifierFlags::ASYNC) {
2354 desc->newStatus |= ParserStatus::ASYNC_FUNCTION;
2355 }
2356
2357 if (desc->isGenerator) {
2358 desc->newStatus |= ParserStatus::GENERATOR_FUNCTION;
2359 }
2360 }
2361
ValidateClassSetter(ClassElmentDescriptor * desc,const ArenaVector<ir::Statement * > & properties,ir::Expression * propName,ir::ScriptFunction * func,bool hasDecorator,lexer::SourcePosition errorInfo)2362 void ParserImpl::ValidateClassSetter(ClassElmentDescriptor *desc, const ArenaVector<ir::Statement *> &properties,
2363 ir::Expression *propName, ir::ScriptFunction *func, bool hasDecorator,
2364 lexer::SourcePosition errorInfo)
2365 {
2366 if (func->Params().size() != 1) {
2367 ThrowSyntaxError("Setter must have exactly one formal parameter");
2368 }
2369
2370 if (Extension() == ScriptExtension::TS && !(desc->modifiers & ir::ModifierFlags::STATIC)) {
2371 ir::ModifierFlags access = GetAccessability(desc->modifiers);
2372 CheckAccessorPair(properties, propName, ir::MethodDefinitionKind::GET, access, hasDecorator, errorInfo);
2373 }
2374 }
2375
ValidateClassGetter(ClassElmentDescriptor * desc,const ArenaVector<ir::Statement * > & properties,ir::Expression * propName,ir::ScriptFunction * func,bool hasDecorator,lexer::SourcePosition errorInfo)2376 void ParserImpl::ValidateClassGetter(ClassElmentDescriptor *desc, const ArenaVector<ir::Statement *> &properties,
2377 ir::Expression *propName, ir::ScriptFunction *func, bool hasDecorator,
2378 lexer::SourcePosition errorInfo)
2379 {
2380 if (!func->Params().empty()) {
2381 ThrowSyntaxError("Getter must not have formal parameters");
2382 }
2383
2384 if (Extension() == ScriptExtension::TS && !(desc->modifiers & ir::ModifierFlags::STATIC)) {
2385 ir::ModifierFlags access = GetAccessability(desc->modifiers);
2386
2387 CheckAccessorPair(properties, propName, ir::MethodDefinitionKind::SET, access, hasDecorator, errorInfo);
2388 }
2389 }
2390
ParseClassMethod(ClassElmentDescriptor * desc,const ArenaVector<ir::Statement * > & properties,ir::Expression * propName,lexer::SourcePosition * propEnd,ArenaVector<ir::Decorator * > && decorators,bool isDeclare)2391 ir::MethodDefinition *ParserImpl::ParseClassMethod(ClassElmentDescriptor *desc,
2392 const ArenaVector<ir::Statement *> &properties,
2393 ir::Expression *propName, lexer::SourcePosition *propEnd,
2394 ArenaVector<ir::Decorator *> &&decorators, bool isDeclare)
2395 {
2396 if (Extension() == ScriptExtension::TS) {
2397 if (desc->methodKind == ir::MethodDefinitionKind::SET || desc->methodKind == ir::MethodDefinitionKind::GET) {
2398 desc->newStatus |= ParserStatus::ACCESSOR_FUNCTION;
2399 }
2400
2401 desc->newStatus |= ParserStatus::IN_METHOD_DEFINITION;
2402 }
2403
2404 if (isDeclare && (desc->newStatus & ParserStatus::ASYNC_FUNCTION)) {
2405 ThrowSyntaxError("'async' modifier cannot be used in an ambient context.");
2406 }
2407
2408 if (isDeclare && desc->isGenerator) {
2409 ThrowSyntaxError("Generators are not allowed in an ambient context.");
2410 }
2411
2412 ArenaVector<ir::ParamDecorators> paramDecorators(Allocator()->Adapter());
2413 ir::ScriptFunction *func = ParseFunction(desc->newStatus, isDeclare, ¶mDecorators);
2414 if (func->Body() != nullptr) {
2415 lexer_->NextToken();
2416 }
2417
2418 if (func->IsOverload() && !decorators.empty()) {
2419 ThrowSyntaxError("A decorator can only decorate a method implementation, not an overload.",
2420 decorators.front()->Start());
2421 }
2422
2423 auto *funcExpr = AllocNode<ir::FunctionExpression>(func);
2424 funcExpr->SetRange(func->Range());
2425
2426 lexer::SourcePosition errorInfo = decorators.empty() ? func->Start() : decorators[0]->Start();
2427
2428 if (desc->methodKind == ir::MethodDefinitionKind::SET) {
2429 ValidateClassSetter(desc, properties, propName, func, !decorators.empty(), errorInfo);
2430 } else if (desc->methodKind == ir::MethodDefinitionKind::GET) {
2431 ValidateClassGetter(desc, properties, propName, func, !decorators.empty(), errorInfo);
2432 }
2433
2434 *propEnd = func->End();
2435 func->AddFlag(ir::ScriptFunctionFlags::METHOD);
2436 auto *method = AllocNode<ir::MethodDefinition>(desc->methodKind, propName, funcExpr, desc->modifiers, Allocator(),
2437 std::move(decorators), std::move(paramDecorators),
2438 desc->isComputed);
2439 method->SetRange(funcExpr->Range());
2440 return method;
2441 }
2442
ParseClassProperty(ClassElmentDescriptor * desc,const ArenaVector<ir::Statement * > & properties,ir::Expression * propName,ir::Expression * typeAnnotation,ArenaVector<ir::Decorator * > && decorators,bool isDeclare)2443 ir::Statement *ParserImpl::ParseClassProperty(ClassElmentDescriptor *desc,
2444 const ArenaVector<ir::Statement *> &properties, ir::Expression *propName,
2445 ir::Expression *typeAnnotation, ArenaVector<ir::Decorator *> &&decorators,
2446 bool isDeclare)
2447 {
2448 lexer::SourcePosition propEnd = propName->End();
2449 ir::Statement *property = nullptr;
2450
2451 if (desc->classMethod) {
2452 property = ParseClassMethod(desc, properties, propName, &propEnd, std::move(decorators), isDeclare);
2453 property->SetRange({desc->propStart, propEnd});
2454 return property;
2455 }
2456
2457 ir::Expression *value = nullptr;
2458
2459 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
2460 lexer_->NextToken(); // eat equals
2461
2462 if (isDeclare) {
2463 ThrowSyntaxError("Initializers are not allowed in ambient contexts.");
2464 }
2465 // TODO(songqi):static classProperty's value can use super keyword in TypeScript4.4.
2466 // Currently only Parser is supported, Compiler support requires Transformer.
2467 context_.Status() |= ParserStatus::ALLOW_SUPER;
2468 value = ParseExpression();
2469 context_.Status() &= ~ParserStatus::ALLOW_SUPER;
2470 propEnd = value->End();
2471 }
2472
2473 ir::Expression *privateId = nullptr;
2474
2475 if (Extension() == ScriptExtension::JS) {
2476 if (desc->isPrivateIdent) {
2477 ThrowSyntaxError("Private js fields are not supported");
2478 }
2479 } else {
2480 if (desc->isPrivateIdent) {
2481 privateId = AllocNode<ir::TSPrivateIdentifier>(propName, value, typeAnnotation);
2482 privateId->SetRange({desc->propStart, propName->End()});
2483 }
2484 }
2485
2486 property = AllocNode<ir::ClassProperty>(desc->isPrivateIdent ? privateId : propName, value, typeAnnotation,
2487 desc->modifiers, std::move(decorators), desc->isComputed,
2488 desc->modifiers & ir::ModifierFlags::DEFINITE);
2489
2490 property->SetRange({desc->propStart, propEnd});
2491 return property;
2492 }
2493
CheckClassGeneratorMethod(ClassElmentDescriptor * desc)2494 void ParserImpl::CheckClassGeneratorMethod(ClassElmentDescriptor *desc)
2495 {
2496 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_MULTIPLY) {
2497 return;
2498 }
2499
2500 ThrowIfPrivateIdent(desc, "Unexpected character in private identifier");
2501
2502 desc->isGenerator = true;
2503 lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);
2504 }
2505
CheckClassPrivateIdentifier(ClassElmentDescriptor * desc)2506 void ParserImpl::CheckClassPrivateIdentifier(ClassElmentDescriptor *desc)
2507 {
2508 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_HASH_MARK) {
2509 return;
2510 }
2511
2512 if (Extension() == ScriptExtension::JS) {
2513 ThrowSyntaxError("JS private class fields are not supported.");
2514 }
2515
2516 if (Extension() == ScriptExtension::AS) {
2517 return;
2518 }
2519
2520 if (desc->modifiers & ~ir::ModifierFlags::READONLY) {
2521 ThrowSyntaxError("Unexpected modifier on private identifier");
2522 }
2523
2524 desc->isPrivateIdent = true;
2525 lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);
2526 }
2527
ParseClassKeyAnnotation()2528 ir::Expression *ParserImpl::ParseClassKeyAnnotation()
2529 {
2530 if (Extension() == ScriptExtension::TS && lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
2531 lexer_->NextToken(); // eat ':'
2532 TypeAnnotationParsingOptions options =
2533 TypeAnnotationParsingOptions::THROW_ERROR | TypeAnnotationParsingOptions::BREAK_AT_NEW_LINE;
2534 return ParseTsTypeAnnotation(&options);
2535 }
2536
2537 return nullptr;
2538 }
2539
ParseDecorator()2540 ir::Decorator *ParserImpl::ParseDecorator()
2541 {
2542 ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_AT);
2543
2544 lexer::SourcePosition start = lexer_->GetToken().Start();
2545 lexer_->NextToken(); // eat '@'
2546
2547 ir::Expression *expr = ParseLeftHandSideExpression();
2548 auto *result = AllocNode<ir::Decorator>(expr);
2549 result->SetRange({start, expr->End()});
2550
2551 return result;
2552 }
2553
ParseDecorators()2554 ArenaVector<ir::Decorator *> ParserImpl::ParseDecorators()
2555 {
2556 ArenaVector<ir::Decorator *> decorators(Allocator()->Adapter());
2557 auto savedStatus = context_.Status();
2558 context_.Status() |= ParserStatus::IN_DECORATOR;
2559
2560 while (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_AT) {
2561 decorators.push_back(ParseDecorator());
2562 }
2563
2564 if (!decorators.empty() && lexer_->GetToken().Type() != lexer::TokenType::KEYW_CLASS &&
2565 (context_.Status() & ParserStatus::IN_CLASS_BODY) == 0 &&
2566 lexer_->GetToken().Type() != lexer::TokenType::KEYW_EXPORT &&
2567 !(lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT &&
2568 (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_DECLARE ||
2569 lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_ABSTRACT))) {
2570 ThrowSyntaxError("Decorators are not valid here.", decorators.front()->Start());
2571 }
2572
2573 context_.Status() = savedStatus;
2574 return decorators;
2575 }
2576
ParseClassElement(const ArenaVector<ir::Statement * > & properties,ArenaVector<ir::TSIndexSignature * > * indexSignatures,bool hasSuperClass,bool isDeclare,bool isAbstractClass)2577 ir::Statement *ParserImpl::ParseClassElement(const ArenaVector<ir::Statement *> &properties,
2578 ArenaVector<ir::TSIndexSignature *> *indexSignatures, bool hasSuperClass,
2579 bool isDeclare, bool isAbstractClass)
2580 {
2581 ClassElmentDescriptor desc;
2582
2583 desc.methodKind = ir::MethodDefinitionKind::METHOD;
2584 desc.newStatus = ParserStatus::ALLOW_SUPER;
2585 desc.hasSuperClass = hasSuperClass;
2586 desc.propStart = lexer_->GetToken().Start();
2587
2588 auto decorators = ParseDecorators();
2589
2590 desc.modifiers = ParseModifiers();
2591
2592 if ((desc.modifiers & ir::ModifierFlags::ABSTRACT) && !isAbstractClass) {
2593 ThrowSyntaxError("Abstract methods can only appear within an abstract class.");
2594 }
2595
2596 CheckClassPrivateIdentifier(&desc);
2597 CheckClassGeneratorMethod(&desc);
2598 ParseClassKeyModifiers(&desc);
2599
2600 if (!(desc.modifiers & ir::ModifierFlags::STATIC)) {
2601 context_.Status() |= ParserStatus::ALLOW_THIS_TYPE;
2602 }
2603
2604 ir::Expression *propName = ParseClassKey(&desc, isDeclare);
2605
2606 if (desc.methodKind == ir::MethodDefinitionKind::CONSTRUCTOR && !decorators.empty()) {
2607 ThrowSyntaxError("Decorators are not valid here.", decorators.front()->Start());
2608 }
2609
2610 if (Extension() == ScriptExtension::TS && lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_QUESTION_MARK) {
2611 if (desc.isIndexSignature) {
2612 ThrowSyntaxError("';' expected");
2613 }
2614
2615 if (desc.methodKind == ir::MethodDefinitionKind::CONSTRUCTOR) {
2616 ThrowSyntaxError("'(' expected");
2617 }
2618
2619 desc.modifiers |= ir::ModifierFlags::OPTIONAL;
2620 lexer_->NextToken();
2621 } else if (Extension() == ScriptExtension::TS &&
2622 lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_EXCLAMATION_MARK) {
2623 if (desc.isIndexSignature || lexer_->Lookahead() != LEX_CHAR_COLON) {
2624 ThrowSyntaxError("';' expected");
2625 }
2626
2627 desc.modifiers |= ir::ModifierFlags::DEFINITE;
2628 lexer_->NextToken();
2629 }
2630
2631 ir::Expression *typeAnnotation = ParseClassKeyAnnotation();
2632
2633 ir::Statement *property = nullptr;
2634 if (desc.isIndexSignature) {
2635 if (!decorators.empty()) {
2636 ThrowSyntaxError("Decorators are not valid here.", decorators.front()->Start());
2637 }
2638
2639 if (!typeAnnotation) {
2640 ThrowSyntaxError("An index signature must have a type annotation");
2641 }
2642
2643 auto *indexSignature =
2644 AllocNode<ir::TSIndexSignature>(propName, typeAnnotation, desc.modifiers & ir::ModifierFlags::READONLY);
2645
2646 indexSignature->SetRange({indexSignature->Param()->Start(), indexSignature->TypeAnnotation()->End()});
2647
2648 indexSignatures->push_back(indexSignature);
2649
2650 property = AllocNode<ir::EmptyStatement>();
2651 } else {
2652 ValidateClassMethodStart(&desc, typeAnnotation);
2653 property = ParseClassProperty(&desc, properties, propName, typeAnnotation, std::move(decorators),
2654 isDeclare || (desc.modifiers & ir::ModifierFlags::DECLARE));
2655 }
2656
2657 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON &&
2658 lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE &&
2659 !(lexer_->GetToken().Flags() & lexer::TokenFlags::NEW_LINE) &&
2660 !(property->IsMethodDefinition() && property->AsMethodDefinition()->Value()->Function()->Body())) {
2661 ThrowSyntaxError("';' expected.");
2662 }
2663
2664 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
2665 lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);
2666 }
2667
2668 context_.Status() &= ~ParserStatus::ALLOW_THIS_TYPE;
2669
2670 return property;
2671 }
2672
IsConstructor(ir::Statement * stmt)2673 static bool IsConstructor(ir::Statement *stmt)
2674 {
2675 if (!stmt->IsMethodDefinition()) {
2676 return false;
2677 }
2678
2679 ir::MethodDefinition *def = stmt->AsMethodDefinition();
2680 return def->Kind() == ir::MethodDefinitionKind::CONSTRUCTOR;
2681 }
2682
CreateImplicitConstructor(ir::Expression * superClass,bool hasSuperClass,bool isDeclare)2683 ir::MethodDefinition *ParserImpl::CreateImplicitConstructor(ir::Expression *superClass,
2684 bool hasSuperClass, bool isDeclare)
2685 {
2686 ArenaVector<ir::Expression *> params(Allocator()->Adapter());
2687 ArenaVector<ir::Statement *> statements(Allocator()->Adapter());
2688
2689 auto *paramScope = Binder()->Allocator()->New<binder::FunctionParamScope>(Allocator(), Binder()->GetScope());
2690 auto *scope = Binder()->Allocator()->New<binder::FunctionScope>(Allocator(), paramScope);
2691
2692 if (hasSuperClass) {
2693 if (Extension() != ScriptExtension::TS || !superClass->IsNullLiteral()) {
2694 util::StringView argsStr = "args";
2695 params.push_back(AllocNode<ir::SpreadElement>(ir::AstNodeType::REST_ELEMENT,
2696 AllocNode<ir::Identifier>(argsStr)));
2697 paramScope->AddParamDecl(Allocator(), params.back());
2698
2699 ArenaVector<ir::Expression *> callArgs(Allocator()->Adapter());
2700 auto *superExpr = AllocNode<ir::SuperExpression>();
2701 callArgs.push_back(AllocNode<ir::SpreadElement>(ir::AstNodeType::SPREAD_ELEMENT,
2702 AllocNode<ir::Identifier>(argsStr)));
2703
2704 auto *callExpr = AllocNode<ir::CallExpression>(superExpr, std::move(callArgs), nullptr, false);
2705 statements.push_back(AllocNode<ir::ExpressionStatement>(callExpr));
2706 }
2707 }
2708
2709 auto *body = AllocNode<ir::BlockStatement>(scope, std::move(statements));
2710 auto *func = AllocNode<ir::ScriptFunction>(scope, std::move(params), nullptr, isDeclare ? nullptr : body, nullptr,
2711 ir::ScriptFunctionFlags::CONSTRUCTOR, isDeclare,
2712 Extension() == ScriptExtension::TS);
2713 scope->BindNode(func);
2714 paramScope->BindNode(func);
2715 scope->BindParamScope(paramScope);
2716 paramScope->BindFunctionScope(scope);
2717
2718 auto *funcExpr = AllocNode<ir::FunctionExpression>(func);
2719 auto *key = AllocNode<ir::Identifier>("constructor");
2720
2721 ArenaVector<ir::Decorator *> decorators(Allocator()->Adapter());
2722 ArenaVector<ir::ParamDecorators> paramDecorators(Allocator()->Adapter());
2723 auto *ctor = AllocNode<ir::MethodDefinition>(ir::MethodDefinitionKind::CONSTRUCTOR, key, funcExpr,
2724 ir::ModifierFlags::NONE, Allocator(), std::move(decorators),
2725 std::move(paramDecorators), false);
2726
2727 return ctor;
2728 }
2729
IsPropertyKeysAreSame(const ir::Expression * exp1,const ir::Expression * exp2)2730 bool ParserImpl::IsPropertyKeysAreSame(const ir::Expression *exp1, const ir::Expression *exp2)
2731 {
2732 if (exp1->IsIdentifier() && exp2->IsIdentifier()) {
2733 return exp1->AsIdentifier()->Name() == exp2->AsIdentifier()->Name();
2734 }
2735
2736 if (exp1->IsIdentifier() && exp2->IsStringLiteral()) {
2737 return exp1->AsIdentifier()->Name() == exp2->AsStringLiteral()->Str();
2738 }
2739
2740 if (exp1->IsStringLiteral() && exp2->IsStringLiteral()) {
2741 return *exp1->AsStringLiteral() == *exp2->AsStringLiteral();
2742 }
2743
2744 if (exp1->IsStringLiteral() && exp2->IsIdentifier()) {
2745 return exp1->AsStringLiteral()->Str() == exp2->AsIdentifier()->Name();
2746 }
2747
2748 if (exp1->IsStringLiteral() && exp2->IsNumberLiteral()) {
2749 std::string exp2String = std::to_string(exp2->AsNumberLiteral()->Number<double>());
2750 exp2String.erase(exp2String.find_last_not_of('0'), std::string::npos);
2751 return exp1->AsStringLiteral()->Str().Utf8() == exp2String;
2752 }
2753
2754 if (exp1->IsNumberLiteral() && exp2->IsNumberLiteral()) {
2755 return exp1->AsNumberLiteral()->Number<double>() == exp2->AsNumberLiteral()->Number<double>();
2756 }
2757
2758 if (exp1->IsNumberLiteral() && exp2->IsStringLiteral()) {
2759 std::string exp1String = std::to_string(exp1->AsNumberLiteral()->Number<double>());
2760 exp1String.erase(exp1String.find_last_not_of('0'), std::string::npos);
2761 return exp1String == exp2->AsStringLiteral()->Str().Utf8();
2762 }
2763
2764 return false;
2765 }
2766
IsMemberExpressionsAreSame(const ir::MemberExpression * mExp1,const ir::MemberExpression * mExp2)2767 bool ParserImpl::IsMemberExpressionsAreSame(const ir::MemberExpression *mExp1, const ir::MemberExpression *mExp2)
2768 {
2769 if (!IsPropertyKeysAreSame(mExp1->Property(), mExp2->Property())) {
2770 return false;
2771 }
2772
2773 if (mExp1->Object()->IsMemberExpression() && mExp2->Object()->IsMemberExpression()) {
2774 return IsMemberExpressionsAreSame(mExp1->Object()->AsMemberExpression(), mExp2->Object()->AsMemberExpression());
2775 }
2776
2777 return IsPropertyKeysAreSame(mExp1->Object(), mExp2->Object());
2778 }
2779
IsMethodDefinitionsAreSame(const ir::MethodDefinition * property,ir::MethodDefinition * overload)2780 bool ParserImpl::IsMethodDefinitionsAreSame(const ir::MethodDefinition *property, ir::MethodDefinition *overload)
2781 {
2782 if (property->Kind() != overload->Kind() || property->IsStatic() != overload->IsStatic()) {
2783 return false;
2784 }
2785
2786 if (property->Key()->IsMemberExpression() && overload->Key()->IsMemberExpression()) {
2787 return IsMemberExpressionsAreSame(property->Key()->AsMemberExpression(), overload->Key()->AsMemberExpression());
2788 }
2789
2790 return IsPropertyKeysAreSame(property->Key(), overload->Key());
2791 }
2792
SetIdentNodeInClassDefinition(bool isDeclare,binder::ConstDecl ** decl)2793 ir::Identifier *ParserImpl::SetIdentNodeInClassDefinition(bool isDeclare, binder::ConstDecl **decl)
2794 {
2795 lexer::TokenType keywType = lexer_->GetToken().KeywordType();
2796 CheckStrictReservedWord();
2797
2798 if (keywType == lexer::TokenType::KEYW_AWAIT && context_.IsModule()) {
2799 ThrowSyntaxError("Unexpected reserved word");
2800 }
2801
2802 const util::StringView &identStr = lexer_->GetToken().Ident();
2803
2804 *decl = Binder()->AddDecl<binder::ConstDecl>(lexer_->GetToken().Start(), isDeclare, identStr);
2805
2806 auto *identNode = AllocNode<ir::Identifier>(identStr);
2807 identNode->SetRange(lexer_->GetToken().Loc());
2808
2809 lexer_->NextToken();
2810
2811 return identNode;
2812 }
2813
ParseClassDefinition(bool isDeclaration,bool idRequired,bool isDeclare,bool isAbstract)2814 ir::ClassDefinition *ParserImpl::ParseClassDefinition(bool isDeclaration, bool idRequired, bool isDeclare,
2815 bool isAbstract)
2816 {
2817 isDeclare = isDeclare | (context_.Status() & ParserStatus::IN_AMBIENT_CONTEXT);
2818 lexer::SourcePosition startLoc = lexer_->GetToken().Start();
2819 lexer_->NextToken();
2820
2821 binder::ConstDecl *decl = nullptr;
2822 ir::Identifier *identNode = nullptr;
2823
2824 auto classCtx = binder::LexicalScope<binder::LocalScope>(Binder());
2825
2826 if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT && (Extension() != ScriptExtension::TS ||
2827 lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_IMPLEMENTS)) {
2828 identNode = SetIdentNodeInClassDefinition(isDeclare, &decl);
2829 } else if (isDeclaration && idRequired) {
2830 ThrowSyntaxError("Unexpected token, expected an identifier.");
2831 }
2832
2833 ir::TSTypeParameterDeclaration *typeParamDecl = nullptr;
2834 if (Extension() == ScriptExtension::TS && lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) {
2835 typeParamDecl = ParseTsTypeParameterDeclaration();
2836 }
2837
2838 // Parse SuperClass
2839 ir::Expression *superClass = nullptr;
2840 bool hasSuperClass = false;
2841
2842 if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_EXTENDS) {
2843 lexer_->NextToken();
2844 hasSuperClass = true;
2845 superClass = ParseLeftHandSideExpression();
2846 }
2847
2848 ir::TSTypeParameterInstantiation *superTypeParams = nullptr;
2849 if (Extension() == ScriptExtension::TS && (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN ||
2850 lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SHIFT)) {
2851 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SHIFT) {
2852 lexer_->BackwardToken(lexer::TokenType::PUNCTUATOR_LESS_THAN, 1);
2853 }
2854
2855 superTypeParams = ParseTsTypeParameterInstantiation();
2856 }
2857
2858 ArenaVector<ir::TSClassImplements *> implements(Allocator()->Adapter());
2859 if (Extension() == ScriptExtension::TS && lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_IMPLEMENTS) {
2860 lexer_->NextToken();
2861
2862 while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
2863 lexer::SourcePosition implStart = lexer_->GetToken().Start();
2864
2865 if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
2866 ThrowSyntaxError("Identifier expected");
2867 }
2868
2869 ir::Expression *expr = AllocNode<ir::Identifier>(lexer_->GetToken().Ident());
2870 expr->SetRange(lexer_->GetToken().Loc());
2871 expr->AsIdentifier()->SetReference();
2872
2873 lexer_->NextToken();
2874
2875 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD) {
2876 expr = ParseTsQualifiedReference(expr);
2877 }
2878
2879 ir::TSTypeParameterInstantiation *implTypeParams = nullptr;
2880 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SHIFT) {
2881 lexer_->BackwardToken(lexer::TokenType::PUNCTUATOR_LESS_THAN, 1);
2882 }
2883
2884 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN ||
2885 lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SHIFT) {
2886 implTypeParams = ParseTsTypeParameterInstantiation();
2887 }
2888
2889 auto *impl = AllocNode<ir::TSClassImplements>(expr, implTypeParams);
2890 impl->SetRange({implStart, lexer_->GetToken().End()});
2891 implements.push_back(impl);
2892
2893 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
2894 lexer_->NextToken();
2895 continue;
2896 }
2897
2898 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
2899 ThrowSyntaxError("',' expected");
2900 }
2901 }
2902
2903 if (implements.empty()) {
2904 ThrowSyntaxError("Implements clause can not be empty");
2905 }
2906 }
2907
2908 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
2909 ThrowSyntaxError("Unexpected token, expected '{'");
2910 }
2911
2912 // Parse ClassBody
2913 auto savedStatus = context_.Status();
2914 context_.Status() |= ParserStatus::IN_CLASS_BODY;
2915 context_.Status() &= ~(ParserStatus::CONSTRUCTOR_FUNCTION);
2916 lexer::SourcePosition classBodyStartLoc = lexer_->GetToken().Start();
2917 lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);
2918
2919 ir::MethodDefinition *ctor = nullptr;
2920 ArenaVector<ir::Statement *> properties(Allocator()->Adapter());
2921 ArenaVector<ir::TSIndexSignature *> indexSignatures(Allocator()->Adapter());
2922 bool hasConstructorFuncBody = false;
2923 bool isCtorContinuousDefined = true;
2924
2925 while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
2926 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
2927 lexer_->NextToken();
2928 continue;
2929 }
2930
2931 ir::Statement *property = ParseClassElement(properties, &indexSignatures, hasSuperClass, isDeclare, isAbstract);
2932
2933 if (property->IsEmptyStatement()) {
2934 continue;
2935 }
2936
2937 if (IsConstructor(property)) {
2938 if (!isDeclare && !isCtorContinuousDefined) {
2939 ThrowSyntaxError("Constructor implementation is missing.", property->Start());
2940 }
2941
2942 if (hasConstructorFuncBody) {
2943 ThrowSyntaxError("Multiple constructor implementations are not allowed.", property->Start());
2944 }
2945 ctor = property->AsMethodDefinition();
2946 hasConstructorFuncBody = ctor->Value()->Function()->Body() != nullptr;
2947 continue;
2948 }
2949 isCtorContinuousDefined = ctor == nullptr;
2950 properties.push_back(property);
2951 }
2952
2953 context_.Status() = savedStatus;
2954
2955 lexer::SourcePosition classBodyEndLoc = lexer_->GetToken().End();
2956 if (ctor == nullptr) {
2957 ctor = CreateImplicitConstructor(superClass, hasSuperClass, isDeclare);
2958 ctor->SetRange({startLoc, classBodyEndLoc});
2959 hasConstructorFuncBody = !isDeclare;
2960 }
2961 lexer_->NextToken();
2962
2963 ValidateClassConstructor(ctor, properties, superClass, isDeclare, hasConstructorFuncBody, hasSuperClass);
2964
2965 auto *classDefinition = AllocNode<ir::ClassDefinition>(
2966 classCtx.GetScope(), identNode, typeParamDecl, superTypeParams, std::move(implements), ctor, superClass,
2967 std::move(properties), std::move(indexSignatures), isDeclare, isAbstract);
2968
2969 classDefinition->SetRange({classBodyStartLoc, classBodyEndLoc});
2970 if (decl != nullptr) {
2971 decl->BindNode(classDefinition);
2972 }
2973
2974 return classDefinition;
2975 }
2976
ValidateClassConstructor(ir::MethodDefinition * ctor,ArenaVector<ir::Statement * > & properties,ir::Expression * superClass,bool isDeclare,bool hasConstructorFuncBody,bool hasSuperClass)2977 void ParserImpl::ValidateClassConstructor(ir::MethodDefinition *ctor,
2978 ArenaVector<ir::Statement *> &properties,
2979 ir::Expression *superClass,
2980 bool isDeclare, bool hasConstructorFuncBody, bool hasSuperClass)
2981 {
2982 if (!hasConstructorFuncBody) {
2983 if (isDeclare) {
2984 return;
2985 }
2986 ThrowSyntaxError("Constructor implementation is missing.", ctor->Start());
2987 }
2988
2989 if (Extension() != ScriptExtension::TS || !hasSuperClass) {
2990 return;
2991 }
2992
2993 bool hasSuperCall = false;
2994 FindSuperCallInConstructor(ctor, &hasSuperCall);
2995 if (hasSuperCall) {
2996 if (superClass->IsNullLiteral()) {
2997 ThrowSyntaxError("A constructor cannot contain a super call when its class extends null.", ctor->Start());
2998 }
2999
3000 if (SuperCallShouldBeFirst(ctor, properties)) {
3001 ir::Statement *firstStat = nullptr;
3002 ASSERT(ctor->Function()->Body()->IsBlockStatement());
3003 ir::BlockStatement *blockStat = ctor->Function()->Body()->AsBlockStatement();
3004 for (auto iter = blockStat->Statements().begin(); iter != blockStat->Statements().end();) {
3005 if ((*iter)->IsExpressionStatement() &&
3006 (*iter)->AsExpressionStatement()->GetExpression()->IsStringLiteral()) {
3007 iter++;
3008 } else {
3009 firstStat = *iter;
3010 break;
3011 }
3012 }
3013
3014 if (firstStat == nullptr || !firstStat->IsExpressionStatement() ||
3015 !firstStat->AsExpressionStatement()->GetExpression()->IsCallExpression() ||
3016 !firstStat->AsExpressionStatement()->GetExpression()->AsCallExpression()
3017 ->Callee()->IsSuperExpression()) {
3018 ThrowSyntaxError("A super call must be the first statement in the constructor when a class contains "
3019 "initialized properties, parameter properties, or private identifiers.",
3020 ctor->Start());
3021 }
3022 }
3023 } else if (!superClass->IsNullLiteral()) {
3024 ThrowSyntaxError("Constructors for derived classes must contain a super call.", ctor->Start());
3025 }
3026 }
3027
SuperCallShouldBeFirst(ir::MethodDefinition * ctor,ArenaVector<ir::Statement * > & properties)3028 bool ParserImpl::SuperCallShouldBeFirst(ir::MethodDefinition *ctor, ArenaVector<ir::Statement *> &properties)
3029 {
3030 for (const auto *property : properties) {
3031 if (property->IsClassProperty() && (property->AsClassProperty()->Value() != nullptr ||
3032 property->AsClassProperty()->Key()->IsTSPrivateIdentifier())) {
3033 return true;
3034 }
3035 }
3036
3037 for (const auto ¶m : ctor->Function()->Params()) {
3038 if (param->IsTSParameterProperty() &&
3039 (param->AsTSParameterProperty()->Accessibility() != ir::AccessibilityOption::NO_OPTS ||
3040 param->AsTSParameterProperty()->Readonly())) {
3041 return true;
3042 }
3043 }
3044 return false;
3045 }
3046
FindSuperCallInConstructor(const ir::AstNode * parent,bool * hasSuperCall)3047 void ParserImpl::FindSuperCallInConstructor(const ir::AstNode *parent, bool *hasSuperCall)
3048 {
3049 parent->Iterate([this, hasSuperCall](auto *childNode) {
3050 FindSuperCallInConstructorChildNode(childNode, hasSuperCall);
3051 });
3052 }
3053
FindSuperCallInConstructorChildNode(const ir::AstNode * childNode,bool * hasSuperCall)3054 void ParserImpl::FindSuperCallInConstructorChildNode(const ir::AstNode *childNode, bool *hasSuperCall)
3055 {
3056 if (*hasSuperCall) {
3057 return;
3058 }
3059 switch (childNode->Type()) {
3060 case ir::AstNodeType::CALL_EXPRESSION: {
3061 if (childNode->AsCallExpression()->Callee()->IsSuperExpression()) {
3062 *hasSuperCall = true;
3063 }
3064 break;
3065 }
3066 case ir::AstNodeType::CLASS_DEFINITION: {
3067 break;
3068 }
3069 default: {
3070 FindSuperCallInConstructor(childNode, hasSuperCall);
3071 break;
3072 }
3073 }
3074 }
3075
ParseEnumMembers(ir::Identifier * key,const lexer::SourcePosition & enumStart,bool isExport,bool isDeclare,bool isConst)3076 ir::TSEnumDeclaration *ParserImpl::ParseEnumMembers(ir::Identifier *key, const lexer::SourcePosition &enumStart,
3077 bool isExport, bool isDeclare, bool isConst)
3078 {
3079 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
3080 ThrowSyntaxError("'{' expected");
3081 }
3082
3083 ArenaVector<ir::TSEnumMember *> members(Allocator()->Adapter());
3084 lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT); // eat '{'
3085
3086 while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
3087 ir::Expression *memberKey = nullptr;
3088 const auto &keyStartLoc = lexer_->GetToken().Start();
3089 binder::EnumDecl *decl {};
3090
3091 if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) {
3092 memberKey = AllocNode<ir::Identifier>(lexer_->GetToken().Ident());
3093 decl = Binder()->AddDecl<binder::EnumDecl>(keyStartLoc, isDeclare, lexer_->GetToken().Ident());
3094 memberKey->SetRange(lexer_->GetToken().Loc());
3095 lexer_->NextToken();
3096 } else if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_STRING) {
3097 memberKey = AllocNode<ir::StringLiteral>(lexer_->GetToken().String());
3098 decl = Binder()->AddDecl<binder::EnumDecl>(keyStartLoc, isDeclare, lexer_->GetToken().String());
3099 memberKey->SetRange(lexer_->GetToken().Loc());
3100 lexer_->NextToken();
3101 } else {
3102 ThrowSyntaxError("Unexpected token in enum member");
3103 }
3104
3105 ir::Expression *memberInit = nullptr;
3106 lexer::SourcePosition initStart = lexer_->GetToken().Start();
3107
3108 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
3109 lexer_->NextToken(); // eat '='
3110 initStart = lexer_->GetToken().Start();
3111 memberInit = ParseExpression();
3112 }
3113
3114 auto *member = AllocNode<ir::TSEnumMember>(memberKey, memberInit);
3115 decl->BindNode(member);
3116 member->SetRange({initStart, lexer_->GetToken().End()});
3117 members.push_back(member);
3118
3119 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
3120 lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT); // eat ','
3121 }
3122 }
3123
3124 auto *enumDeclaration = AllocNode<ir::TSEnumDeclaration>(
3125 Binder()->GetScope()->AsTSEnumScope(), key, std::move(members), isExport, isDeclare, isConst);
3126 enumDeclaration->SetRange({enumStart, lexer_->GetToken().End()});
3127 Binder()->GetScope()->BindNode(enumDeclaration);
3128 lexer_->NextToken(); // eat '}'
3129
3130 return enumDeclaration;
3131 }
3132
ParseEnumDeclaration(bool isExport,bool isDeclare,bool isConst)3133 ir::TSEnumDeclaration *ParserImpl::ParseEnumDeclaration(bool isExport, bool isDeclare, bool isConst)
3134 {
3135 ASSERT(lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_ENUM);
3136 lexer::SourcePosition enumStart = lexer_->GetToken().Start();
3137 lexer_->NextToken(); // eat enum keyword
3138
3139 if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
3140 ThrowSyntaxError("Identifier expected");
3141 }
3142
3143 const util::StringView &ident = lexer_->GetToken().Ident();
3144 auto *currentScope = Binder()->GetScope();
3145 binder::Variable *res = currentScope->FindLocalTSVariable<binder::TSBindingType::ENUMLITERAL>(ident);
3146 if (res == nullptr && isExport && currentScope->IsTSModuleScope()) {
3147 res = currentScope->AsTSModuleScope()->FindExportTSVariable<binder::TSBindingType::ENUMLITERAL>(ident);
3148 if (res != nullptr) {
3149 currentScope->AddLocalTSVariable<binder::TSBindingType::ENUMLITERAL>(ident, res);
3150 }
3151 }
3152 if (res == nullptr) {
3153 Binder()->AddTsDecl<binder::EnumLiteralDecl>(lexer_->GetToken().Start(), isDeclare,
3154 Allocator(), ident, isExport, isConst);
3155 res = currentScope->FindLocalTSVariable<binder::TSBindingType::ENUMLITERAL>(ident);
3156 if (isExport && currentScope->IsTSModuleScope()) {
3157 currentScope->AsTSModuleScope()->AddExportTSVariable<binder::TSBindingType::ENUMLITERAL>(ident, res);
3158 }
3159 res->AsEnumLiteralVariable()->SetEnumMembers(Allocator()->New<binder::VariableMap>(Allocator()->Adapter()));
3160 }
3161 binder::VariableMap *enumMemberBindings = res->AsEnumLiteralVariable()->GetEnumMembers();
3162
3163 auto *key = AllocNode<ir::Identifier>(ident);
3164 key->SetRange(lexer_->GetToken().Loc());
3165 key->SetReference();
3166 lexer_->NextToken();
3167
3168 if (!res->Declaration()->IsEnumLiteralDecl() ||
3169 (isConst ^ res->Declaration()->AsEnumLiteralDecl()->IsConst())) {
3170 Binder()->ThrowRedeclaration(lexer_->GetToken().Start(), ident);
3171 }
3172
3173 auto enumCtx = binder::LexicalScope<binder::TSEnumScope>(Binder(), enumMemberBindings);
3174 auto *enumDeclaration = ParseEnumMembers(key, enumStart, isExport, isDeclare, isConst);
3175 res->Declaration()->AsEnumLiteralDecl()->Add(enumDeclaration);
3176
3177 return enumDeclaration;
3178 }
3179
ValidateFunctionParam(const ArenaVector<ir::Expression * > & params,const ir::Expression * parameter,bool * seenOptional)3180 void ParserImpl::ValidateFunctionParam(const ArenaVector<ir::Expression *> ¶ms, const ir::Expression *parameter,
3181 bool *seenOptional)
3182 {
3183 if (!parameter->IsIdentifier()) {
3184 context_.Status() |= ParserStatus::HAS_COMPLEX_PARAM;
3185 if (!parameter->IsRestElement()) {
3186 return;
3187 }
3188
3189 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
3190 const char *msg = (Extension() == ScriptExtension::JS ? "Rest parameter must be last formal parameter"
3191 : "A rest parameter must be last in parameter list");
3192 ThrowSyntaxError(msg);
3193 }
3194 return;
3195 }
3196
3197 if (Extension() != ScriptExtension::TS) {
3198 return;
3199 }
3200
3201 bool currentIsOptinal = parameter->AsIdentifier()->IsOptional();
3202 if (*seenOptional && !currentIsOptinal) {
3203 ThrowSyntaxError("A required parameter cannot follow an optional parameter");
3204 }
3205
3206 *seenOptional |= currentIsOptinal;
3207 const util::StringView ¶mName = parameter->AsIdentifier()->Name();
3208
3209 if (paramName.Is("this")) {
3210 if (!params.empty()) {
3211 ThrowSyntaxError("A 'this' parameter must be the first parameter");
3212 }
3213
3214 if (context_.Status() & ParserStatus::CONSTRUCTOR_FUNCTION) {
3215 ThrowSyntaxError("A constructor cannot have a 'this' parameter");
3216 }
3217
3218 if (context_.Status() & ParserStatus::ARROW_FUNCTION) {
3219 ThrowSyntaxError("An arrow function cannot have a 'this' parameter");
3220 }
3221
3222 if (context_.Status() & ParserStatus::ACCESSOR_FUNCTION) {
3223 ThrowSyntaxError("'get' and 'set' accessors cannot declare 'this' parameters");
3224 }
3225 }
3226
3227 if (paramName.Is("constructor") && (context_.Status() & ParserStatus::CONSTRUCTOR_FUNCTION)) {
3228 ThrowSyntaxError("'constructor' cannot be used as a parameter property name");
3229 }
3230 }
3231
ParseFunctionParams(bool isDeclare,ArenaVector<ir::ParamDecorators> * paramDecorators)3232 ArenaVector<ir::Expression *> ParserImpl::ParseFunctionParams(bool isDeclare,
3233 ArenaVector<ir::ParamDecorators> *paramDecorators)
3234 {
3235 ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS);
3236 lexer_->NextToken();
3237
3238 ArenaVector<ir::Expression *> params(Allocator()->Adapter());
3239 bool seenOptional = false;
3240
3241 size_t index = 0;
3242 while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
3243 if (context_.Status() & ParserStatus::IN_METHOD_DEFINITION) {
3244 auto decorators = ParseDecorators();
3245 if (!decorators.empty()) {
3246 ASSERT(paramDecorators != nullptr);
3247 paramDecorators->push_back({index, std::move(decorators)});
3248 }
3249 }
3250
3251 ir::Expression *parameter = ParseFunctionParameter(isDeclare);
3252 ValidateFunctionParam(params, parameter, &seenOptional);
3253
3254 params.push_back(parameter);
3255
3256 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COMMA &&
3257 lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
3258 ThrowSyntaxError(", expected");
3259 }
3260
3261 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
3262 lexer_->NextToken();
3263 }
3264
3265 index++;
3266 }
3267
3268 ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS);
3269 lexer_->NextToken();
3270
3271 return params;
3272 }
3273
CheckTypeNameIsReserved(const util::StringView & paramName)3274 bool ParserImpl::CheckTypeNameIsReserved(const util::StringView ¶mName)
3275 {
3276 return paramName.Is("number") || paramName.Is("any") || paramName.Is("unknown") || paramName.Is("never") ||
3277 paramName.Is("bigint") || paramName.Is("boolean") || paramName.Is("string") || paramName.Is("string") ||
3278 paramName.Is("void") || paramName.Is("object");
3279 }
3280
ParseTsTypeParameter(bool throwError,bool addBinding)3281 ir::TSTypeParameter *ParserImpl::ParseTsTypeParameter(bool throwError, bool addBinding)
3282 {
3283 lexer::SourcePosition startLoc = lexer_->GetToken().Start();
3284
3285 if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
3286 if (!throwError) {
3287 return nullptr;
3288 }
3289
3290 ThrowSyntaxError("Type parameter declaration expected");
3291 }
3292
3293 const auto &ident = lexer_->GetToken().Ident();
3294
3295 if (CheckTypeNameIsReserved(ident)) {
3296 if (!throwError) {
3297 return nullptr;
3298 }
3299
3300 ThrowSyntaxError("Invalid type parameter name");
3301 }
3302
3303 auto *paramIdent = AllocNode<ir::Identifier>(ident);
3304
3305 if (addBinding) {
3306 Binder()->AddDecl<binder::LetDecl>(lexer_->GetToken().Start(), false, ident);
3307 }
3308
3309 paramIdent->SetRange({lexer_->GetToken().Start(), lexer_->GetToken().End()});
3310
3311 lexer_->NextToken();
3312
3313 TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::NO_OPTS;
3314
3315 if (throwError) {
3316 options |= TypeAnnotationParsingOptions::THROW_ERROR;
3317 }
3318
3319 ir::Expression *constraint = nullptr;
3320 if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_EXTENDS) {
3321 lexer_->NextToken();
3322 constraint = ParseTsTypeAnnotation(&options);
3323 }
3324
3325 ir::Expression *defaultType = nullptr;
3326 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
3327 lexer_->NextToken();
3328 defaultType = ParseTsTypeAnnotation(&options);
3329 }
3330
3331 auto *typeParam = AllocNode<ir::TSTypeParameter>(paramIdent, constraint, defaultType);
3332
3333 typeParam->SetRange({startLoc, lexer_->GetToken().End()});
3334
3335 return typeParam;
3336 }
3337
ParseTsTypeParameterDeclaration(bool throwError)3338 ir::TSTypeParameterDeclaration *ParserImpl::ParseTsTypeParameterDeclaration(bool throwError)
3339 {
3340 ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN);
3341
3342 auto localCtx = binder::LexicalScope<binder::LocalScope>(Binder());
3343
3344 lexer::SourcePosition startLoc = lexer_->GetToken().Start();
3345 ArenaVector<ir::TSTypeParameter *> params(Allocator()->Adapter());
3346 bool seenDefault = false;
3347 size_t requiredParams = 0;
3348 lexer_->NextToken(); // eat '<'
3349
3350 while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_GREATER_THAN) {
3351 ir::TSTypeParameter *currentParam = ParseTsTypeParameter(throwError, true);
3352
3353 if (!currentParam) {
3354 ASSERT(!throwError);
3355 return nullptr;
3356 }
3357
3358 if (currentParam->DefaultType()) {
3359 seenDefault = true;
3360 } else if (seenDefault) {
3361 ThrowSyntaxError("Required type parameters may not follow optional type parameters.");
3362 } else {
3363 requiredParams++;
3364 }
3365
3366 params.push_back(currentParam);
3367
3368 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
3369 lexer_->NextToken();
3370 continue;
3371 }
3372
3373 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_GREATER_THAN) {
3374 if (!throwError) {
3375 return nullptr;
3376 }
3377
3378 ThrowSyntaxError("'>' expected");
3379 }
3380 }
3381
3382 if (params.empty()) {
3383 ThrowSyntaxError("Type parameter list cannot be empty.");
3384 }
3385
3386 lexer::SourcePosition endLoc = lexer_->GetToken().End();
3387 lexer_->NextToken(); // eat '>'
3388
3389 auto *typeParamDecl =
3390 AllocNode<ir::TSTypeParameterDeclaration>(localCtx.GetScope(), std::move(params), requiredParams);
3391 typeParamDecl->SetRange({startLoc, endLoc});
3392 localCtx.GetScope()->BindNode(typeParamDecl);
3393
3394 return typeParamDecl;
3395 }
3396
ParseTsTypeParameterInstantiation(bool throwError)3397 ir::TSTypeParameterInstantiation *ParserImpl::ParseTsTypeParameterInstantiation(bool throwError)
3398 {
3399 ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN);
3400 lexer::SourcePosition startLoc = lexer_->GetToken().Start();
3401 ArenaVector<ir::Expression *> params(Allocator()->Adapter());
3402 lexer_->NextToken(); // eat '<'
3403
3404 while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_GREATER_THAN) {
3405 TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::NO_OPTS;
3406
3407 if (throwError) {
3408 options |= TypeAnnotationParsingOptions::THROW_ERROR;
3409 }
3410
3411 ir::Expression *currentParam = ParseTsTypeAnnotation(&options);
3412
3413 if (!currentParam) {
3414 return nullptr;
3415 }
3416
3417 params.push_back(currentParam);
3418
3419 switch (lexer_->GetToken().Type()) {
3420 case lexer::TokenType::PUNCTUATOR_COMMA: {
3421 lexer_->NextToken();
3422 continue;
3423 }
3424 case lexer::TokenType::PUNCTUATOR_RIGHT_SHIFT: {
3425 lexer_->BackwardToken(lexer::TokenType::PUNCTUATOR_GREATER_THAN, 1);
3426 break;
3427 }
3428 case lexer::TokenType::PUNCTUATOR_UNSIGNED_RIGHT_SHIFT: {
3429 lexer_->BackwardToken(lexer::TokenType::PUNCTUATOR_GREATER_THAN, 2);
3430 break;
3431 }
3432 case lexer::TokenType::PUNCTUATOR_GREATER_THAN: {
3433 break;
3434 }
3435 default: {
3436 if (throwError) {
3437 ThrowSyntaxError("'>' expected");
3438 }
3439
3440 return nullptr;
3441 }
3442 }
3443 }
3444
3445 lexer::SourcePosition endLoc = lexer_->GetToken().End();
3446 lexer_->NextToken();
3447
3448 auto *typeParamInst = AllocNode<ir::TSTypeParameterInstantiation>(std::move(params));
3449
3450 typeParamInst->SetRange({startLoc, endLoc});
3451
3452 return typeParamInst;
3453 }
3454
ParseFunction(ParserStatus newStatus,bool isDeclare,ArenaVector<ir::ParamDecorators> * paramDecorators)3455 ir::ScriptFunction *ParserImpl::ParseFunction(ParserStatus newStatus,
3456 bool isDeclare,
3457 ArenaVector<ir::ParamDecorators> *paramDecorators)
3458 {
3459 FunctionContext functionContext(this, newStatus | ParserStatus::FUNCTION | ParserStatus::ALLOW_NEW_TARGET);
3460
3461 FunctionParameterContext funcParamContext(&context_, Binder());
3462 auto *funcParamScope = funcParamContext.LexicalScope().GetScope();
3463
3464 lexer::SourcePosition startLoc = lexer_->GetToken().Start();
3465
3466 ir::TSTypeParameterDeclaration *typeParamDecl = nullptr;
3467 if (Extension() == ScriptExtension::TS && lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) {
3468 typeParamDecl = ParseTsTypeParameterDeclaration();
3469 }
3470
3471 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
3472 ThrowSyntaxError("Unexpected token, expected '('");
3473 }
3474
3475 if (newStatus & (ParserStatus::ASYNC_FUNCTION | ParserStatus::FUNCTION_DECLARATION)) {
3476 context_.Status() |= ParserStatus::DISALLOW_AWAIT;
3477 }
3478
3479 ArenaVector<ir::Expression *> params = ParseFunctionParams(isDeclare, paramDecorators);
3480
3481 ir::Expression *returnTypeAnnotation = nullptr;
3482
3483 if (Extension() == ScriptExtension::TS && lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
3484 lexer_->NextToken(); // eat ':'
3485 TypeAnnotationParsingOptions options =
3486 TypeAnnotationParsingOptions::THROW_ERROR | TypeAnnotationParsingOptions::CAN_BE_TS_TYPE_PREDICATE;
3487 returnTypeAnnotation = ParseTsTypeAnnotation(&options);
3488 }
3489
3490 auto functionCtx = binder::LexicalScope<binder::FunctionScope>(Binder());
3491 auto *functionScope = functionCtx.GetScope();
3492 functionScope->BindParamScope(funcParamScope);
3493 funcParamScope->BindFunctionScope(functionScope);
3494
3495 ir::BlockStatement *body = nullptr;
3496 lexer::SourcePosition endLoc = lexer_->GetToken().End();
3497 bool letDeclare = true;
3498
3499 if (newStatus & ParserStatus::ASYNC_FUNCTION) {
3500 context_.Status() &= ~ParserStatus::DISALLOW_AWAIT;
3501 } else {
3502 context_.Status() |= ParserStatus::DISALLOW_AWAIT;
3503 }
3504
3505 if (newStatus & ParserStatus::GENERATOR_FUNCTION) {
3506 context_.Status() |= ParserStatus::ALLOW_YIELD;
3507 }
3508
3509 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
3510 if (Extension() == ScriptExtension::TS && (newStatus & ParserStatus::FUNCTION_DECLARATION)) {
3511 ValidateTsFunctionOverloadParams(params);
3512 functionContext.AddFlag(ir::ScriptFunctionFlags::OVERLOAD);
3513 } else if (!isDeclare && !(context_.Status() & ParserStatus::IN_METHOD_DEFINITION)) {
3514 ThrowSyntaxError("Unexpected token, expected '{'");
3515 } else {
3516 letDeclare = false;
3517 functionContext.AddFlag(ir::ScriptFunctionFlags::OVERLOAD);
3518 }
3519 } else if (isDeclare) {
3520 ThrowSyntaxError("An implementation cannot be declared in ambient contexts.");
3521 } else {
3522 body = ParseBlockStatement(functionScope);
3523 endLoc = body->End();
3524 }
3525
3526 auto *funcNode =
3527 AllocNode<ir::ScriptFunction>(functionScope, std::move(params), typeParamDecl, body, returnTypeAnnotation,
3528 functionContext.Flags(), isDeclare && letDeclare,
3529 Extension() == ScriptExtension::TS);
3530 functionScope->BindNode(funcNode);
3531 funcParamScope->BindNode(funcNode);
3532 funcNode->SetRange({startLoc, endLoc});
3533
3534 return funcNode;
3535 }
3536
ValidateTsFunctionOverloadParams(const ArenaVector<ir::Expression * > & params)3537 void ParserImpl::ValidateTsFunctionOverloadParams(const ArenaVector<ir::Expression *> ¶ms)
3538 {
3539 for (auto *it : params) {
3540 if (it->IsAssignmentPattern()) {
3541 ThrowSyntaxError(
3542 "A parameter initializer is only allowed in a function "
3543 "or constructor implementation.",
3544 it->Start());
3545 }
3546 }
3547 }
3548
ParseSpreadElement(ExpressionParseFlags flags)3549 ir::SpreadElement *ParserImpl::ParseSpreadElement(ExpressionParseFlags flags)
3550 {
3551 ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD);
3552 lexer::SourcePosition startLocation = lexer_->GetToken().Start();
3553 bool inPattern = (flags & ExpressionParseFlags::MUST_BE_PATTERN);
3554 lexer_->NextToken();
3555
3556 ir::Expression *argument {};
3557 if (inPattern) {
3558 argument = ParsePatternElement(ExpressionParseFlags::IN_REST);
3559 if ((flags & ExpressionParseFlags::OBJECT_PATTERN) && !argument->IsIdentifier()) {
3560 ThrowSyntaxError("RestParameter must be followed by an identifier in declaration contexts");
3561 }
3562 } else {
3563 argument = ParseExpression(flags);
3564 }
3565
3566 ir::Expression *typeAnnotation = nullptr;
3567
3568 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
3569 lexer_->NextToken(); // eat ':'
3570 TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
3571 typeAnnotation = ParseTsTypeAnnotation(&options);
3572 }
3573
3574 if (inPattern && argument->IsAssignmentExpression()) {
3575 ThrowSyntaxError("RestParameter does not support an initializer");
3576 }
3577
3578 lexer::SourcePosition endLoc = typeAnnotation ? typeAnnotation->End() : argument->End();
3579
3580 auto nodeType = inPattern ? ir::AstNodeType::REST_ELEMENT : ir::AstNodeType::SPREAD_ELEMENT;
3581 auto *spreadElementNode = AllocNode<ir::SpreadElement>(nodeType, argument);
3582 spreadElementNode->SetRange({startLocation, endLoc});
3583
3584 if (typeAnnotation) {
3585 spreadElementNode->SetTsTypeAnnotation(typeAnnotation);
3586 }
3587
3588 return spreadElementNode;
3589 }
3590
CreateTsParameterProperty(ir::Expression * parameter,ir::ModifierFlags modifiers)3591 ir::TSParameterProperty *ParserImpl::CreateTsParameterProperty(ir::Expression *parameter, ir::ModifierFlags modifiers)
3592 {
3593 auto accessibility = ir::AccessibilityOption::NO_OPTS;
3594 bool readonly = false;
3595 bool isStatic = false;
3596 bool isExport = false;
3597
3598 if (modifiers & ir::ModifierFlags::PRIVATE) {
3599 accessibility = ir::AccessibilityOption::PRIVATE;
3600 } else if ((modifiers & ir::ModifierFlags::PUBLIC)) {
3601 accessibility = ir::AccessibilityOption::PUBLIC;
3602 } else if (modifiers & ir::ModifierFlags::PROTECTED) {
3603 accessibility = ir::AccessibilityOption::PROTECTED;
3604 }
3605
3606 if (modifiers & ir::ModifierFlags::READONLY) {
3607 readonly = true;
3608 }
3609
3610 if (modifiers & ir::ModifierFlags::STATIC) {
3611 isStatic = true;
3612 }
3613
3614 // TODO(Csaba Repasi): Handle export property of TSParameterProperty
3615
3616 return AllocNode<ir::TSParameterProperty>(accessibility, parameter, readonly, isStatic, isExport);
3617 }
3618
ParseFunctionParameter(bool isDeclare)3619 ir::Expression *ParserImpl::ParseFunctionParameter(bool isDeclare)
3620 {
3621 if (Extension() == ScriptExtension::TS && lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_THIS) {
3622 lexer_->GetToken().SetTokenType(lexer::TokenType::LITERAL_IDENT);
3623 }
3624
3625 lexer::SourcePosition parameterStart = lexer_->GetToken().Start();
3626 ir::ModifierFlags modifiers = ParseModifiers();
3627 // TODO(Csaba Repasi): throw error if using strick mode reserved keyword here
3628 if (!(context_.Status() & ParserStatus::CONSTRUCTOR_FUNCTION) && modifiers != ir::ModifierFlags::NONE) {
3629 ThrowSyntaxError("A parameter property is only allowed in a constructor implementation.", parameterStart);
3630 }
3631
3632 lexer::TokenType tokenType = lexer_->GetToken().Type();
3633 if (tokenType == lexer::TokenType::LITERAL_IDENT &&
3634 (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_ARGUMENTS ||
3635 lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_EVAL)) {
3636 ThrowSyntaxError(
3637 "'eval' or 'arguments' can't be defined or assigned to "
3638 "in strict mode code",
3639 lexer_->GetToken().Start());
3640 }
3641
3642 ir::Expression *functionParameter = ParsePatternElement(ExpressionParseFlags::NO_OPTS, true, isDeclare);
3643
3644 if (modifiers != ir::ModifierFlags::NONE && functionParameter->IsRestElement()) {
3645 ThrowSyntaxError("A parameter property cannot be declared using a rest parameter.", parameterStart);
3646 }
3647
3648 if (modifiers != ir::ModifierFlags::NONE &&
3649 (functionParameter->IsArrayPattern() || functionParameter->IsObjectPattern() ||
3650 (functionParameter->IsAssignmentPattern() &&
3651 (functionParameter->AsAssignmentPattern()->Left()->IsArrayPattern() ||
3652 functionParameter->AsAssignmentPattern()->Left()->IsObjectPattern())))) {
3653 ThrowSyntaxError("A parameter property may not be declared using a binding pattern.", parameterStart);
3654 }
3655
3656 if (modifiers != ir::ModifierFlags::NONE) {
3657 functionParameter = CreateTsParameterProperty(functionParameter, modifiers);
3658 functionParameter->SetRange({parameterStart, functionParameter->AsTSParameterProperty()->Parameter()->End()});
3659 }
3660
3661 Binder()->AddParamDecl(functionParameter);
3662
3663 return functionParameter;
3664 }
3665
ValidateLvalueAssignmentTarget(ir::Expression * node) const3666 void ParserImpl::ValidateLvalueAssignmentTarget(ir::Expression *node) const
3667 {
3668 switch (node->Type()) {
3669 case ir::AstNodeType::IDENTIFIER: {
3670 // Check the prevoius ident name
3671 if (node->AsIdentifier()->Name().Is("arguments")) {
3672 ThrowSyntaxError("Assigning to 'arguments' in strict mode is invalid");
3673 } else if (node->AsIdentifier()->Name().Is("eval")) {
3674 ThrowSyntaxError("Assigning to 'eval' in strict mode is invalid");
3675 }
3676 break;
3677 }
3678 case ir::AstNodeType::MEMBER_EXPRESSION: {
3679 break;
3680 }
3681 case ir::AstNodeType::TS_AS_EXPRESSION: {
3682 ValidateLvalueAssignmentTarget(node->AsTSAsExpression()->Expr());
3683 break;
3684 }
3685 case ir::AstNodeType::TS_TYPE_ASSERTION: {
3686 ValidateLvalueAssignmentTarget(node->AsTSTypeAssertion()->GetExpression());
3687 break;
3688 }
3689 default: {
3690 ThrowSyntaxError("Invalid left-hand side in assignment expression");
3691 }
3692 }
3693 }
3694
ValidateAssignmentTarget(ExpressionParseFlags flags,ir::Expression * node)3695 void ParserImpl::ValidateAssignmentTarget(ExpressionParseFlags flags, ir::Expression *node)
3696 {
3697 switch (node->Type()) {
3698 case ir::AstNodeType::ARRAY_PATTERN:
3699 case ir::AstNodeType::OBJECT_PATTERN: {
3700 break;
3701 }
3702 case ir::AstNodeType::ARRAY_EXPRESSION:
3703 case ir::AstNodeType::OBJECT_EXPRESSION: {
3704 if (flags & ExpressionParseFlags::POTENTIALLY_IN_PATTERN) {
3705 return;
3706 }
3707
3708 [[fallthrough]];
3709 }
3710 default: {
3711 return ValidateLvalueAssignmentTarget(node);
3712 }
3713 }
3714 }
3715
ValidateArrowParameterBindings(const ir::Expression * node)3716 void ParserImpl::ValidateArrowParameterBindings(const ir::Expression *node)
3717 {
3718 switch (node->Type()) {
3719 case ir::AstNodeType::IDENTIFIER: {
3720 const util::StringView &identifier = node->AsIdentifier()->Name();
3721
3722 if (context_.IsAsync() && identifier.Is("await")) {
3723 ThrowSyntaxError("'await' in formal parameter is invalid.", node->Start());
3724 }
3725 break;
3726 }
3727 case ir::AstNodeType::OMITTED_EXPRESSION: {
3728 break;
3729 }
3730 case ir::AstNodeType::REST_ELEMENT: {
3731 ValidateArrowParameterBindings(node->AsRestElement()->Argument());
3732 break;
3733 }
3734 case ir::AstNodeType::PROPERTY: {
3735 break;
3736 }
3737 case ir::AstNodeType::OBJECT_PATTERN: {
3738 const auto &props = node->AsObjectPattern()->Properties();
3739
3740 for (auto *it : props) {
3741 ValidateArrowParameterBindings(it);
3742 }
3743 break;
3744 }
3745 case ir::AstNodeType::ARRAY_PATTERN: {
3746 const auto &elements = node->AsArrayPattern()->Elements();
3747
3748 for (auto *it : elements) {
3749 ValidateArrowParameterBindings(it);
3750 }
3751 break;
3752 }
3753 case ir::AstNodeType::ASSIGNMENT_PATTERN: {
3754 ValidateArrowParameterBindings(node->AsAssignmentPattern()->Left());
3755 break;
3756 }
3757 default: {
3758 ThrowSyntaxError("Unexpected ArrowParameter element");
3759 }
3760 }
3761 }
3762
CurrentTokenIsModifier(char32_t nextCp) const3763 bool ParserImpl::CurrentTokenIsModifier(char32_t nextCp) const
3764 {
3765 return (Extension() == ScriptExtension::TS &&
3766 (nextCp != LEX_CHAR_EQUALS || nextCp != LEX_CHAR_SEMICOLON || nextCp != LEX_CHAR_LEFT_PAREN));
3767 }
3768
ThrowParameterModifierError(ir::ModifierFlags status) const3769 void ParserImpl::ThrowParameterModifierError(ir::ModifierFlags status) const
3770 {
3771 ThrowSyntaxError(
3772 {"'", (status & ir::ModifierFlags::STATIC) ? "static" : ((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
3846 } // namespace panda::es2panda::parser
3847