1 /**
2 * Copyright (c) 2021-2024 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 "ETSparser.h"
17
18 #include "lexer/lexer.h"
19 #include "ir/expressions/literals/undefinedLiteral.h"
20 #include "ir/ets/etsTuple.h"
21
22 namespace ark::es2panda::parser {
23 class FunctionContext;
24
25 using namespace std::literals::string_literals;
26
ParseLaunchExpression(ExpressionParseFlags flags)27 ir::Expression *ETSParser::ParseLaunchExpression(ExpressionParseFlags flags)
28 {
29 lexer::SourcePosition start = Lexer()->GetToken().Start();
30 Lexer()->NextToken(); // eat launch
31
32 lexer::SourcePosition exprStart = Lexer()->GetToken().Start();
33 ir::Expression *expr = ParseLeftHandSideExpression(flags);
34 if (expr == nullptr || !expr->IsCallExpression()) {
35 LogSyntaxError("Only call expressions are allowed after 'launch'", exprStart);
36 return nullptr;
37 }
38 auto call = expr->AsCallExpression();
39 auto *launchExpression = AllocNode<ir::ETSLaunchExpression>(call);
40 launchExpression->SetRange({start, call->End()});
41
42 return launchExpression;
43 }
44
45 // NOLINTBEGIN(modernize-avoid-c-arrays)
46 static constexpr char const NO_DEFAULT_FOR_REST[] = "Rest parameter cannot have the default value.";
47 // NOLINTEND(modernize-avoid-c-arrays)
48
GetArgumentsSourceView(lexer::Lexer * lexer,const util::StringView::Iterator & lexerPos)49 static std::string GetArgumentsSourceView(lexer::Lexer *lexer, const util::StringView::Iterator &lexerPos)
50 {
51 std::string value = lexer->SourceView(lexerPos.Index(), lexer->Save().Iterator().Index()).Mutf8();
52 while (value.back() == ' ') {
53 value.pop_back();
54 }
55
56 if (value.back() == ')' || value.back() == ',') {
57 value.pop_back();
58 }
59
60 return value;
61 }
62
ParseFunctionParameterExpression(ir::AnnotatedExpression * const paramIdent,ir::ETSUndefinedType * defaultUndef)63 ir::Expression *ETSParser::ParseFunctionParameterExpression(ir::AnnotatedExpression *const paramIdent,
64 ir::ETSUndefinedType *defaultUndef)
65 {
66 ir::ETSParameterExpression *paramExpression;
67 if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
68 auto const lexerPos = Lexer()->Save().Iterator();
69 Lexer()->NextToken(); // eat '='
70
71 if (paramIdent->IsRestElement()) {
72 LogSyntaxError(NO_DEFAULT_FOR_REST);
73 }
74
75 if ((GetContext().Status() & ParserStatus::ALLOW_DEFAULT_VALUE) != 0) {
76 LogSyntaxError("Default value is allowed only for optional parameters");
77 }
78
79 if (defaultUndef != nullptr) {
80 LogSyntaxError("Not enable default value with default undefined");
81 }
82 if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS ||
83 Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
84 LogSyntaxError("You didn't set the value.");
85 }
86
87 auto defaultValue = ParseExpression();
88 if (!paramIdent->IsIdentifier() || defaultValue == nullptr) { // Error processing.
89 return nullptr;
90 }
91
92 paramExpression = AllocNode<ir::ETSParameterExpression>(paramIdent->AsIdentifier(), defaultValue);
93
94 std::string value = GetArgumentsSourceView(Lexer(), lexerPos);
95 paramExpression->SetLexerSaved(util::UString(value, Allocator()).View());
96 paramExpression->SetRange({paramIdent->Start(), paramExpression->Initializer()->End()});
97 } else if (paramIdent == nullptr) { // Error processing.
98 return nullptr;
99 } else if (paramIdent->IsIdentifier()) {
100 auto *typeAnnotation = paramIdent->AsIdentifier()->TypeAnnotation();
101
102 const auto typeAnnotationValue = [this, typeAnnotation,
103 defaultUndef]() -> std::pair<ir::Expression *, std::string> {
104 if (typeAnnotation == nullptr) {
105 return std::make_pair(nullptr, "");
106 }
107 return std::make_pair(defaultUndef != nullptr ? AllocNode<ir::UndefinedLiteral>() : nullptr, "undefined");
108 }();
109
110 paramExpression =
111 AllocNode<ir::ETSParameterExpression>(paramIdent->AsIdentifier(), std::get<0>(typeAnnotationValue));
112 if (defaultUndef != nullptr) {
113 paramExpression->SetLexerSaved(util::UString(std::get<1>(typeAnnotationValue), Allocator()).View());
114 }
115 paramExpression->SetRange({paramIdent->Start(), paramIdent->End()});
116 } else {
117 paramExpression = AllocNode<ir::ETSParameterExpression>(paramIdent->AsRestElement(), nullptr);
118 paramExpression->SetRange({paramIdent->Start(), paramIdent->End()});
119 }
120 return paramExpression;
121 }
122
ResolveArgumentUnaryExpr(ExpressionParseFlags flags)123 ir::Expression *ETSParser::ResolveArgumentUnaryExpr(ExpressionParseFlags flags)
124 {
125 switch (Lexer()->GetToken().Type()) {
126 case lexer::TokenType::PUNCTUATOR_PLUS:
127 case lexer::TokenType::PUNCTUATOR_MINUS:
128 case lexer::TokenType::PUNCTUATOR_TILDE:
129 case lexer::TokenType::PUNCTUATOR_EXCLAMATION_MARK:
130 case lexer::TokenType::PUNCTUATOR_DOLLAR_DOLLAR:
131 case lexer::TokenType::PUNCTUATOR_PLUS_PLUS:
132 case lexer::TokenType::PUNCTUATOR_MINUS_MINUS:
133 case lexer::TokenType::KEYW_TYPEOF: {
134 return ParseUnaryOrPrefixUpdateExpression();
135 }
136 default: {
137 return ParseLeftHandSideExpression(flags);
138 }
139 }
140 }
141
142 // NOLINTNEXTLINE(google-default-arguments)
ParseUnaryOrPrefixUpdateExpression(ExpressionParseFlags flags)143 ir::Expression *ETSParser::ParseUnaryOrPrefixUpdateExpression(ExpressionParseFlags flags)
144 {
145 auto tokenFlags = lexer::NextTokenFlags::NONE;
146 lexer::TokenType operatorType = Lexer()->GetToken().Type();
147
148 switch (operatorType) {
149 case lexer::TokenType::PUNCTUATOR_MINUS:
150 tokenFlags = lexer::NextTokenFlags::UNARY_MINUS;
151 [[fallthrough]];
152 case lexer::TokenType::PUNCTUATOR_PLUS_PLUS:
153 case lexer::TokenType::PUNCTUATOR_MINUS_MINUS:
154 case lexer::TokenType::PUNCTUATOR_PLUS:
155 case lexer::TokenType::PUNCTUATOR_TILDE:
156 case lexer::TokenType::PUNCTUATOR_DOLLAR_DOLLAR:
157 case lexer::TokenType::PUNCTUATOR_EXCLAMATION_MARK:
158 case lexer::TokenType::KEYW_TYPEOF: {
159 break;
160 }
161 case lexer::TokenType::KEYW_LAUNCH: {
162 return ParseLaunchExpression(flags);
163 }
164 default: {
165 return ParseLeftHandSideExpression(flags);
166 }
167 }
168
169 auto start = Lexer()->GetToken().Start();
170 Lexer()->NextToken(tokenFlags);
171
172 ir::Expression *argument = ResolveArgumentUnaryExpr(flags);
173
174 if (argument == nullptr) {
175 return nullptr;
176 }
177
178 if (lexer::Token::IsUpdateToken(operatorType)) {
179 if (!argument->IsIdentifier() && !argument->IsMemberExpression()) {
180 LogSyntaxError("Invalid left-hand side in prefix operation");
181 }
182 }
183
184 lexer::SourcePosition end = argument->End();
185
186 ir::Expression *returnExpr = nullptr;
187 if (lexer::Token::IsUpdateToken(operatorType)) {
188 returnExpr = AllocNode<ir::UpdateExpression>(argument, operatorType, true);
189 } else if (operatorType == lexer::TokenType::KEYW_TYPEOF) {
190 returnExpr = AllocNode<ir::TypeofExpression>(argument);
191 } else if (operatorType == lexer::TokenType::PUNCTUATOR_MINUS) {
192 returnExpr = !argument->IsNumberLiteral() ? AllocNode<ir::UnaryExpression>(argument, operatorType) : argument;
193 } else {
194 returnExpr = AllocNode<ir::UnaryExpression>(argument, operatorType);
195 }
196
197 returnExpr->SetRange({start, end});
198
199 return returnExpr;
200 }
201
202 // NOLINTNEXTLINE(google-default-arguments)
ParsePropertyDefinition(ExpressionParseFlags flags)203 ir::Expression *ETSParser::ParsePropertyDefinition(ExpressionParseFlags flags)
204 {
205 ir::PropertyKind propertyKind = ir::PropertyKind::INIT;
206 ParserStatus methodStatus = ParserStatus::NO_OPTS;
207
208 const auto startPos = Lexer()->Save();
209 Lexer()->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);
210 lexer::SourcePosition start = Lexer()->GetToken().Start();
211
212 if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD) {
213 return ParseSpreadElement(flags);
214 }
215
216 if (Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) {
217 if (ParsePropertyModifiers(flags, &propertyKind, &methodStatus)) {
218 return ParseShorthandProperty(&startPos);
219 }
220 } else if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MULTIPLY) {
221 ParseGeneratorPropertyModifier(flags, &methodStatus);
222 }
223
224 bool isComputed = Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET;
225 ir::Expression *key = ParsePropertyKey(flags);
226
227 ir::Expression *value = ParsePropertyValue(&propertyKind, &methodStatus, flags);
228 if (key == nullptr || value == nullptr) { // Error processing.
229 return nullptr;
230 }
231
232 lexer::SourcePosition end = value->End();
233
234 auto *returnProperty =
235 AllocNode<ir::Property>(propertyKind, key, value, methodStatus != ParserStatus::NO_OPTS, isComputed);
236 returnProperty->SetRange({start, end});
237
238 return returnProperty;
239 }
240
241 // NOLINTNEXTLINE(google-default-arguments)
ParseDefaultPrimaryExpression(ExpressionParseFlags flags)242 ir::Expression *ETSParser::ParseDefaultPrimaryExpression(ExpressionParseFlags flags)
243 {
244 auto startLoc = Lexer()->GetToken().Start();
245 auto savedPos = Lexer()->Save();
246 TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::POTENTIAL_CLASS_LITERAL |
247 TypeAnnotationParsingOptions::IGNORE_FUNCTION_TYPE |
248 TypeAnnotationParsingOptions::DISALLOW_UNION;
249 ir::TypeNode *potentialType = ParseTypeAnnotation(&options);
250
251 if (potentialType != nullptr) {
252 if (potentialType->IsTSArrayType()) {
253 return potentialType;
254 }
255
256 if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD) {
257 Lexer()->NextToken(); // eat '.'
258 }
259
260 if (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_CLASS || IsStructKeyword()) {
261 Lexer()->NextToken(); // eat 'class' and 'struct'
262 auto *classLiteral = AllocNode<ir::ETSClassLiteral>(potentialType);
263 classLiteral->SetRange({startLoc, Lexer()->GetToken().End()});
264 return classLiteral;
265 }
266 }
267
268 Lexer()->Rewind(savedPos);
269
270 Lexer()->NextToken();
271 bool pretendArrow = Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_ARROW;
272 Lexer()->Rewind(savedPos);
273
274 if (Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_IDENT && !pretendArrow) {
275 return ParsePrimaryExpressionIdent(flags);
276 }
277
278 LogSyntaxError({"Unexpected token '", lexer::TokenToString(Lexer()->GetToken().Type()), "'."});
279 return nullptr;
280 }
281
ParsePrimaryExpressionWithLiterals(ExpressionParseFlags flags)282 ir::Expression *ETSParser::ParsePrimaryExpressionWithLiterals(ExpressionParseFlags flags)
283 {
284 switch (Lexer()->GetToken().Type()) {
285 case lexer::TokenType::LITERAL_TRUE:
286 case lexer::TokenType::LITERAL_FALSE: {
287 return ParseBooleanLiteral();
288 }
289 case lexer::TokenType::LITERAL_NULL: {
290 return ParseNullLiteral();
291 }
292 case lexer::TokenType::KEYW_UNDEFINED: {
293 return ParseUndefinedLiteral();
294 }
295 case lexer::TokenType::LITERAL_NUMBER: {
296 return ParseNumberLiteral();
297 }
298 case lexer::TokenType::LITERAL_STRING: {
299 return ParseStringLiteral();
300 }
301 case lexer::TokenType::LITERAL_CHAR: {
302 return ParseCharLiteral();
303 }
304 default: {
305 return ParseDefaultPrimaryExpression(flags);
306 }
307 }
308 }
309
310 // NOLINTNEXTLINE(google-default-arguments)
ParsePrimaryExpression(ExpressionParseFlags flags)311 ir::Expression *ETSParser::ParsePrimaryExpression(ExpressionParseFlags flags)
312 {
313 switch (Lexer()->GetToken().Type()) {
314 case lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS: {
315 return ParseCoverParenthesizedExpressionAndArrowParameterList(flags);
316 }
317 case lexer::TokenType::KEYW_THIS: {
318 return ParseThisExpression();
319 }
320 case lexer::TokenType::KEYW_SUPER: {
321 return ParseSuperExpression();
322 }
323 case lexer::TokenType::KEYW_NEW: {
324 return ParseNewExpression();
325 }
326 case lexer::TokenType::KEYW_ASYNC: {
327 return ParseAsyncExpression();
328 }
329 case lexer::TokenType::KEYW_AWAIT: {
330 return ParseAwaitExpression();
331 }
332 case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET: {
333 return ParseArrayExpression(CarryPatternFlags(flags));
334 }
335 case lexer::TokenType::PUNCTUATOR_LEFT_BRACE: {
336 return ParseObjectExpression(CarryPatternFlags(flags));
337 }
338 case lexer::TokenType::PUNCTUATOR_BACK_TICK: {
339 return ParseTemplateLiteral();
340 }
341 case lexer::TokenType::KEYW_TYPE: {
342 LogSyntaxError("Type alias is allowed only as top-level declaration");
343 ParseTypeAliasDeclaration(); // Try to parse type alias and drop the result.
344 return nullptr;
345 }
346 case lexer::TokenType::PUNCTUATOR_FORMAT: {
347 return ParseExpressionFormatPlaceholder();
348 }
349 case lexer::TokenType::KEYW_TYPEOF: {
350 return ParseUnaryOrPrefixUpdateExpression();
351 }
352 case lexer::TokenType::KEYW_IMPORT: {
353 return ParseETSImportExpression();
354 }
355 default: {
356 return ParsePrimaryExpressionWithLiterals(flags);
357 }
358 }
359 }
360
IsPunctuartorSpecialCharacter(lexer::TokenType tokenType)361 bool IsPunctuartorSpecialCharacter(lexer::TokenType tokenType)
362 {
363 switch (tokenType) {
364 case lexer::TokenType::PUNCTUATOR_COLON:
365 case lexer::TokenType::PUNCTUATOR_COMMA:
366 case lexer::TokenType::PUNCTUATOR_RIGHT_SHIFT:
367 case lexer::TokenType::PUNCTUATOR_UNSIGNED_RIGHT_SHIFT:
368 case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET:
369 case lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET:
370 case lexer::TokenType::PUNCTUATOR_LESS_THAN:
371 case lexer::TokenType::PUNCTUATOR_GREATER_THAN:
372 case lexer::TokenType::PUNCTUATOR_BITWISE_OR:
373 return true;
374 default:
375 return false;
376 }
377 }
378
IsArrowFunctionExpressionStart()379 bool ETSParser::IsArrowFunctionExpressionStart()
380 {
381 const auto savedPos = Lexer()->Save();
382 ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS);
383 Lexer()->NextToken();
384 auto tokenType = Lexer()->GetToken().Type();
385
386 size_t openBrackets = 1;
387 bool expectIdentifier = true;
388 while (tokenType != lexer::TokenType::EOS && openBrackets > 0) {
389 lexer::NextTokenFlags flag = lexer::NextTokenFlags::NONE;
390 switch (tokenType) {
391 case lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS:
392 --openBrackets;
393 break;
394 case lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS:
395 ++openBrackets;
396 break;
397 case lexer::TokenType::PUNCTUATOR_COMMA:
398 expectIdentifier = true;
399 break;
400 // (DZ) need for correct processing of possible number literals
401 case lexer::TokenType::PUNCTUATOR_MINUS:
402 flag = lexer::NextTokenFlags::UNARY_MINUS;
403 break;
404 case lexer::TokenType::PUNCTUATOR_SEMI_COLON:
405 Lexer()->Rewind(savedPos);
406 return false;
407 default:
408 if (!expectIdentifier) {
409 break;
410 }
411 if (tokenType != lexer::TokenType::LITERAL_IDENT &&
412 tokenType != lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD) {
413 Lexer()->Rewind(savedPos);
414 return false;
415 }
416 expectIdentifier = false;
417 }
418 Lexer()->NextToken(flag);
419 tokenType = Lexer()->GetToken().Type();
420 }
421
422 while (tokenType != lexer::TokenType::EOS && tokenType != lexer::TokenType::PUNCTUATOR_ARROW) {
423 if (lexer::Token::IsPunctuatorToken(tokenType) && !IsPunctuartorSpecialCharacter(tokenType)) {
424 break;
425 }
426 Lexer()->NextToken();
427 tokenType = Lexer()->GetToken().Type();
428 }
429 Lexer()->Rewind(savedPos);
430 return tokenType == lexer::TokenType::PUNCTUATOR_ARROW;
431 }
432
ParseArrowFunctionExpression()433 ir::ArrowFunctionExpression *ETSParser::ParseArrowFunctionExpression()
434 {
435 auto newStatus = ParserStatus::ARROW_FUNCTION;
436 auto *func = ParseFunction(newStatus);
437 auto *arrowFuncNode = AllocNode<ir::ArrowFunctionExpression>(func);
438 arrowFuncNode->SetRange(func->Range());
439 return arrowFuncNode;
440 }
441
442 // NOLINTNEXTLINE(google-default-arguments)
ParseCoverParenthesizedExpressionAndArrowParameterList(ExpressionParseFlags flags)443 ir::Expression *ETSParser::ParseCoverParenthesizedExpressionAndArrowParameterList(ExpressionParseFlags flags)
444 {
445 ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS);
446 if (IsArrowFunctionExpressionStart()) {
447 return ParseArrowFunctionExpression();
448 }
449
450 lexer::SourcePosition start = Lexer()->GetToken().Start();
451 Lexer()->NextToken();
452
453 ExpressionParseFlags newFlags = ExpressionParseFlags::ACCEPT_COMMA;
454 if ((flags & ExpressionParseFlags::INSTANCEOF) != 0) {
455 newFlags |= ExpressionParseFlags::INSTANCEOF;
456 };
457
458 ir::Expression *expr = ParseExpression(newFlags);
459
460 if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
461 LogExpectedToken(lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS);
462 }
463
464 if (expr == nullptr) { // Error processing.
465 return nullptr;
466 }
467
468 expr->SetGrouped();
469 expr->SetRange({start, Lexer()->GetToken().End()});
470 Lexer()->NextToken();
471
472 return expr;
473 }
474
GetPostPrimaryExpression(ir::Expression * returnExpression,lexer::SourcePosition startLoc,bool ignoreCallExpression,bool * isChainExpression)475 std::optional<ir::Expression *> ETSParser::GetPostPrimaryExpression(ir::Expression *returnExpression,
476 lexer::SourcePosition startLoc,
477 bool ignoreCallExpression,
478 [[maybe_unused]] bool *isChainExpression)
479 {
480 switch (Lexer()->GetToken().Type()) {
481 case lexer::TokenType::PUNCTUATOR_QUESTION_DOT:
482 if (*isChainExpression) {
483 return std::nullopt; // terminate current chain
484 }
485 *isChainExpression = true;
486 Lexer()->NextToken(); // eat ?.
487
488 if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET) {
489 return ParseElementAccess(returnExpression, true);
490 }
491
492 if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
493 return ParseCallExpression(returnExpression, true, false);
494 }
495
496 return ParsePropertyAccess(returnExpression, true);
497 case lexer::TokenType::PUNCTUATOR_PERIOD:
498 Lexer()->NextToken(); // eat period
499
500 return ParsePropertyAccess(returnExpression);
501 case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET:
502 return ParseElementAccess(returnExpression);
503 case lexer::TokenType::PUNCTUATOR_LEFT_SHIFT:
504 case lexer::TokenType::PUNCTUATOR_LESS_THAN:
505 if (ParsePotentialGenericFunctionCall(returnExpression, &returnExpression, startLoc,
506 ignoreCallExpression)) {
507 return std::nullopt;
508 }
509
510 return returnExpression;
511 case lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS:
512 if (ignoreCallExpression) {
513 return std::nullopt;
514 }
515 return ParseCallExpression(returnExpression, false, false);
516 case lexer::TokenType::PUNCTUATOR_EXCLAMATION_MARK: {
517 const bool shouldBreak = ParsePotentialNonNullExpression(&returnExpression, startLoc);
518 if (shouldBreak) {
519 return std::nullopt;
520 }
521
522 return returnExpression;
523 }
524 case lexer::TokenType::PUNCTUATOR_FORMAT:
525 case lexer::TokenType::PUNCTUATOR_ARROW:
526 LogUnexpectedToken(Lexer()->GetToken().Type());
527 [[fallthrough]];
528 default:
529 return std::nullopt;
530 }
531 }
532
ParsePostPrimaryExpression(ir::Expression * primaryExpr,lexer::SourcePosition startLoc,bool ignoreCallExpression,bool * isChainExpression)533 ir::Expression *ETSParser::ParsePostPrimaryExpression(ir::Expression *primaryExpr, lexer::SourcePosition startLoc,
534 bool ignoreCallExpression,
535 [[maybe_unused]] bool *isChainExpression)
536 {
537 ir::Expression *returnExpression = primaryExpr;
538
539 while (true) {
540 auto expr = GetPostPrimaryExpression(returnExpression, startLoc, ignoreCallExpression, isChainExpression);
541 if (expr.has_value()) {
542 returnExpression = expr.value();
543 continue;
544 }
545
546 break;
547 }
548
549 return returnExpression;
550 }
551
ParsePotentialAsExpression(ir::Expression * primaryExpr)552 ir::Expression *ETSParser::ParsePotentialAsExpression(ir::Expression *primaryExpr)
553 {
554 ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::KEYW_AS);
555 Lexer()->NextToken();
556
557 TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::REPORT_ERROR;
558 ir::TypeNode *type = ParseTypeAnnotation(&options);
559
560 if (type == nullptr) {
561 // Error processing
562 // Failed to parse type annotation for AsExpression
563 return nullptr;
564 }
565
566 auto *asExpression = AllocNode<ir::TSAsExpression>(primaryExpr, type, false);
567 asExpression->SetRange(primaryExpr->Range());
568 return asExpression;
569 }
570
571 // Extracted from 'ParseNewExpression()' to reduce function's size
CreateClassDefinitionForNewExpression(ArenaVector<ir::Expression * > & arguments,ir::TypeNode * typeReference,ir::TypeNode * baseTypeReference)572 ir::ClassDefinition *ETSParser::CreateClassDefinitionForNewExpression(ArenaVector<ir::Expression *> &arguments,
573 ir::TypeNode *typeReference,
574 ir::TypeNode *baseTypeReference)
575 {
576 lexer::SourcePosition endLoc = typeReference->End();
577
578 if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
579 if (baseTypeReference != nullptr) {
580 LogSyntaxError("Can not use 'new' on primitive types.", baseTypeReference->Start());
581 }
582
583 Lexer()->NextToken();
584
585 while (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
586 ir::Expression *argument = ParseExpression();
587 arguments.push_back(argument);
588
589 if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
590 Lexer()->NextToken();
591 continue;
592 }
593 }
594
595 endLoc = Lexer()->GetToken().End();
596 Lexer()->NextToken();
597 }
598
599 ir::ClassDefinition *classDefinition {};
600
601 if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
602 ArenaVector<ir::TSClassImplements *> implements(Allocator()->Adapter());
603 auto modifiers = ir::ClassDefinitionModifiers::ANONYMOUS | ir::ClassDefinitionModifiers::HAS_SUPER;
604 auto [ctor, properties, bodyRange] = ParseClassBody(modifiers);
605
606 auto newIdent = AllocNode<ir::Identifier>("#0", Allocator());
607 classDefinition = AllocNode<ir::ClassDefinition>(
608 "#0", newIdent, nullptr, nullptr, std::move(implements), ctor, // remove name
609 typeReference->Clone(Allocator(), nullptr), std::move(properties), modifiers, ir::ModifierFlags::NONE,
610 Language(Language::Id::ETS));
611
612 classDefinition->SetRange(bodyRange);
613 }
614
615 return classDefinition;
616 }
617
ParseNewExpression()618 ir::Expression *ETSParser::ParseNewExpression()
619 {
620 lexer::SourcePosition start = Lexer()->GetToken().Start();
621
622 Lexer()->NextToken(); // eat new
623
624 TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::REPORT_ERROR;
625 ir::TypeNode *baseTypeReference = ParseBaseTypeReference(&options);
626 ir::TypeNode *typeReference = baseTypeReference;
627 if (typeReference == nullptr) {
628 options |= TypeAnnotationParsingOptions::IGNORE_FUNCTION_TYPE | TypeAnnotationParsingOptions::ALLOW_WILDCARD |
629 TypeAnnotationParsingOptions::POTENTIAL_NEW_ARRAY;
630 typeReference = ParseTypeReference(&options);
631 if (typeReference == nullptr) {
632 typeReference = ParseTypeAnnotation(&options);
633 }
634 } else if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
635 LogSyntaxError("Invalid { after base types.");
636 Lexer()->NextToken(); // eat '{'
637 }
638
639 if (typeReference == nullptr) { // Error processing.
640 return nullptr;
641 }
642
643 if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET) {
644 Lexer()->NextToken();
645 ir::Expression *dimension = ParseExpression();
646
647 auto endLoc = Lexer()->GetToken().End();
648 ExpectToken(lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET);
649
650 if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET) {
651 auto *arrInstance = AllocNode<ir::ETSNewArrayInstanceExpression>(typeReference, dimension);
652 arrInstance->SetRange({start, endLoc});
653 return arrInstance;
654 }
655
656 ArenaVector<ir::Expression *> dimensions(Allocator()->Adapter());
657 dimensions.push_back(dimension);
658
659 do {
660 Lexer()->NextToken();
661 dimensions.push_back(ParseExpression());
662
663 endLoc = Lexer()->GetToken().End();
664 ExpectToken(lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET);
665 } while (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET);
666
667 auto *multiArray = AllocNode<ir::ETSNewMultiDimArrayInstanceExpression>(typeReference, std::move(dimensions));
668 multiArray->SetRange({start, endLoc});
669 return multiArray;
670 }
671
672 ArenaVector<ir::Expression *> arguments(Allocator()->Adapter());
673 ir::ClassDefinition *classDefinition =
674 CreateClassDefinitionForNewExpression(arguments, typeReference, baseTypeReference);
675
676 auto *newExprNode =
677 AllocNode<ir::ETSNewClassInstanceExpression>(typeReference, std::move(arguments), classDefinition);
678 newExprNode->SetRange({start, Lexer()->GetToken().End()});
679
680 return newExprNode;
681 }
682
ParseAsyncExpression()683 ir::Expression *ETSParser::ParseAsyncExpression()
684 {
685 Lexer()->NextToken(); // eat 'async'
686 if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS ||
687 !IsArrowFunctionExpressionStart()) {
688 LogExpectedToken(lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS);
689 }
690
691 auto newStatus = ParserStatus::NEED_RETURN_TYPE | ParserStatus::ARROW_FUNCTION | ParserStatus::ASYNC_FUNCTION;
692 auto *func = ParseFunction(newStatus);
693 auto *arrowFuncNode = AllocNode<ir::ArrowFunctionExpression>(func);
694 arrowFuncNode->SetRange(func->Range());
695 return arrowFuncNode;
696 }
697
ParseAwaitExpression()698 ir::Expression *ETSParser::ParseAwaitExpression()
699 {
700 lexer::SourcePosition start = Lexer()->GetToken().Start();
701 Lexer()->NextToken();
702 ir::Expression *argument = ParseExpression();
703 auto *awaitExpression = AllocNode<ir::AwaitExpression>(argument);
704 awaitExpression->SetRange({start, Lexer()->GetToken().End()});
705 return awaitExpression;
706 }
707
ParseETSImportExpression()708 ir::Expression *ETSParser::ParseETSImportExpression()
709 {
710 lexer::SourcePosition startLoc = Lexer()->GetToken().Start();
711 ExpectToken(lexer::TokenType::KEYW_IMPORT);
712 ExpectToken(lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS);
713 ir::Expression *source = ParseExpression();
714 lexer::SourcePosition endLoc = Lexer()->GetToken().Start();
715 ExpectToken(lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS);
716
717 auto *importExpression = AllocNode<ir::ImportExpression>(source);
718 importExpression->SetRange({startLoc, endLoc});
719 return importExpression;
720 }
721
ParsePotentialExpressionSequence(ir::Expression * expr,ExpressionParseFlags flags)722 ir::Expression *ETSParser::ParsePotentialExpressionSequence(ir::Expression *expr, ExpressionParseFlags flags)
723 {
724 if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA &&
725 (flags & ExpressionParseFlags::ACCEPT_COMMA) != 0 && (flags & ExpressionParseFlags::IN_FOR) != 0U) {
726 return ParseSequenceExpression(expr, (flags & ExpressionParseFlags::ACCEPT_REST) != 0);
727 }
728
729 return expr;
730 }
731
ParsePotentialNonNullExpression(ir::Expression ** expression,const lexer::SourcePosition startLoc)732 bool ETSParser::ParsePotentialNonNullExpression(ir::Expression **expression, const lexer::SourcePosition startLoc)
733 {
734 if (expression == nullptr || Lexer()->GetToken().NewLine()) {
735 return true;
736 }
737
738 const auto nonNullExpr = AllocNode<ir::TSNonNullExpression>(*expression);
739 nonNullExpr->SetRange({startLoc, Lexer()->GetToken().End()});
740
741 *expression = nonNullExpr;
742
743 Lexer()->NextToken();
744
745 return false;
746 }
747
ValidateInstanceOfExpression(ir::Expression * expr)748 void ETSParser::ValidateInstanceOfExpression(ir::Expression *expr)
749 {
750 ValidateGroupedExpression(expr);
751 lexer::TokenType tokenType = Lexer()->GetToken().Type();
752 if (tokenType == lexer::TokenType::PUNCTUATOR_LESS_THAN) {
753 auto options = TypeAnnotationParsingOptions::NO_OPTS;
754
755 // Run checks to validate type declarations
756 // Should provide helpful messages with incorrect declarations like the following:
757 // `instanceof A<String;`
758 ParseTypeParameterDeclaration(&options);
759
760 // Display error message even when type declaration is correct
761 // `instanceof A<String>;`
762 LogSyntaxError("Invalid right-hand side in 'instanceof' expression");
763 }
764 }
765
766 // NOLINTNEXTLINE(google-default-arguments)
ParseExpression(ExpressionParseFlags flags)767 ir::Expression *ETSParser::ParseExpression(ExpressionParseFlags flags)
768 {
769 if (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_YIELD &&
770 (flags & ExpressionParseFlags::DISALLOW_YIELD) == 0U) {
771 ir::YieldExpression *yieldExpr = ParseYieldExpression();
772
773 return ParsePotentialExpressionSequence(yieldExpr, flags);
774 }
775
776 ir::Expression *unaryExpressionNode = ParseUnaryOrPrefixUpdateExpression(flags);
777 if (unaryExpressionNode == nullptr) {
778 return nullptr;
779 }
780
781 if ((flags & ExpressionParseFlags::INSTANCEOF) != 0) {
782 ValidateInstanceOfExpression(unaryExpressionNode);
783 }
784
785 ir::Expression *assignmentExpression = ParseAssignmentExpression(unaryExpressionNode, flags);
786
787 if (Lexer()->GetToken().NewLine()) {
788 return assignmentExpression;
789 }
790
791 if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA &&
792 (flags & ExpressionParseFlags::ACCEPT_COMMA) != 0U && (flags & ExpressionParseFlags::IN_FOR) != 0U) {
793 return ParseSequenceExpression(assignmentExpression, (flags & ExpressionParseFlags::ACCEPT_REST) != 0U);
794 }
795
796 return assignmentExpression;
797 }
798
799 } // namespace ark::es2panda::parser
800