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