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