• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024-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 "lexer/lexer.h"
19 #include "ir/typeNode.h"
20 #include "ir/expressions/identifier.h"
21 #include "ir/expressions/blockExpression.h"
22 #include "ir/expressions/sequenceExpression.h"
23 #include "ir/statements/blockStatement.h"
24 #include "ir/statements/expressionStatement.h"
25 #include "ir/base/methodDefinition.h"
26 #include "ir/ts/tsInterfaceBody.h"
27 #include "parser/parserStatusContext.h"
28 #include "generated/diagnostic.h"
29 
30 namespace ark::es2panda::parser {
31 //================================================================================================//
32 //  Methods to create AST node(s) from the specified string (part of valid ETS-code!)
33 //================================================================================================//
34 
35 // NOLINTBEGIN(modernize-avoid-c-arrays)
36 inline constexpr char const FORMAT_SIGNATURE = '@';
37 inline constexpr char const TYPE_FORMAT_NODE = 'T';
38 inline constexpr char const GENERAL_FORMAT_NODE = 'N';
39 inline constexpr char const IDENTIFIER_FORMAT_NODE = 'I';
40 
41 // NOLINTEND(modernize-avoid-c-arrays)
42 
GetFormatPlaceholderType()43 ParserImpl::NodeFormatType ETSParser::GetFormatPlaceholderType()
44 {
45     ES2PANDA_ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_FORMAT);
46     Lexer()->NextToken();
47 
48     bool isArray = false;
49     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET) {
50         isArray = true;
51         Lexer()->NextToken();
52     }
53 
54     ES2PANDA_ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_IDENT);
55     char const *const identData = Lexer()->GetToken().Ident().Bytes();
56 
57     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic, cert-err34-c)
58     auto identNumber = std::atoi(identData + 1U);
59     if (identNumber <= 0) {
60         LogError(diagnostic::INVALID_NODE_NUMBER, {}, Lexer()->GetToken().Start());
61         ES2PANDA_UNREACHABLE();
62     }
63 
64     return {isArray, *identData,
65             static_cast<decltype(std::get<2>(std::declval<ParserImpl::NodeFormatType>()))>(identNumber - 1)};
66 }
67 
ParseExpressionFormatPlaceholder()68 ir::Expression *ETSParser::ParseExpressionFormatPlaceholder()
69 {
70     if (insertingNodes_.empty()) {
71         LogUnexpectedToken(lexer::TokenType::PUNCTUATOR_FORMAT);
72         const auto &rangeToken = Lexer()->GetToken().Loc();
73         Lexer()->NextToken();
74         return AllocBrokenExpression(rangeToken);
75     }
76 
77     ParserImpl::NodeFormatType nodeFormat = GetFormatPlaceholderType();
78     if (std::get<0>(nodeFormat)) {
79         LogError(diagnostic::INVALID_NODE_TYPE, {}, Lexer()->GetToken().Start());
80         ES2PANDA_UNREACHABLE();
81     }
82 
83     if (auto const placeholderType = std::get<1>(nodeFormat); placeholderType == TYPE_FORMAT_NODE) {
84         return ParseTypeFormatPlaceholder(std::make_optional(std::move(nodeFormat)));
85     } else if (placeholderType == IDENTIFIER_FORMAT_NODE) {  // NOLINT(readability-else-after-return)
86         return ParseIdentifierFormatPlaceholder(std::make_optional(std::move(nodeFormat)));
87     } else if (placeholderType != EXPRESSION_FORMAT_NODE) {  // NOLINT(readability-else-after-return)
88         LogError(diagnostic::INVALID_NODE_TYPE, {}, Lexer()->GetToken().Start());
89         ES2PANDA_UNREACHABLE();
90     }
91 
92     auto const placeholderNumber = std::get<2>(nodeFormat);
93     auto *const insertingNode =
94         placeholderNumber < insertingNodes_.size() ? insertingNodes_[placeholderNumber] : nullptr;
95     if (insertingNode == nullptr || !insertingNode->IsExpression()) {
96         LogError(diagnostic::INVALID_INSERT_NODE, {}, Lexer()->GetToken().Start());
97         ES2PANDA_UNREACHABLE();
98     }
99 
100     auto *const insertExpression = insertingNode->AsExpression();
101     Lexer()->NextToken();
102     return insertExpression;
103 }
104 
ParseTypeFormatPlaceholder(std::optional<ParserImpl::NodeFormatType> nodeFormat)105 ir::TypeNode *ETSParser::ParseTypeFormatPlaceholder(std::optional<ParserImpl::NodeFormatType> nodeFormat)
106 {
107     if (!nodeFormat.has_value()) {
108         if (insertingNodes_.empty()) {
109             LogUnexpectedToken(lexer::TokenType::PUNCTUATOR_FORMAT);
110             return AllocBrokenType(Lexer()->GetToken().Loc());
111         }
112 
113         nodeFormat = GetFormatPlaceholderType();
114         if (std::get<0>(*nodeFormat) || std::get<1>(*nodeFormat) != TYPE_FORMAT_NODE) {
115             return nullptr;
116         }
117     }
118 
119     auto const placeholderNumber = std::get<2>(*nodeFormat);
120     auto *const insertingNode =
121         placeholderNumber < insertingNodes_.size() ? insertingNodes_[placeholderNumber] : nullptr;
122     if (insertingNode == nullptr || !insertingNode->IsExpression() || !insertingNode->AsExpression()->IsTypeNode()) {
123         LogError(diagnostic::INVALID_INSERT_NODE, {}, Lexer()->GetToken().Start());
124         ES2PANDA_UNREACHABLE();
125     }
126 
127     auto *const insertType = insertingNode->AsExpression()->AsTypeNode();
128     Lexer()->NextToken();
129     return insertType;
130 }
131 
ParseIdentifierFormatPlaceholder(std::optional<ParserImpl::NodeFormatType> nodeFormat)132 ir::Identifier *ETSParser::ParseIdentifierFormatPlaceholder(std::optional<ParserImpl::NodeFormatType> nodeFormat)
133 {
134     if (!nodeFormat.has_value()) {
135         if (insertingNodes_.empty()) {
136             LogError(diagnostic::INSERT_NODE_ABSENT, {}, Lexer()->GetToken().Start());
137             return nullptr;
138         }
139 
140         nodeFormat = GetFormatPlaceholderType();
141         if (std::get<0>(*nodeFormat) || std::get<1>(*nodeFormat) != IDENTIFIER_FORMAT_NODE) {
142             LogError(diagnostic::INVALID_NODE_TYPE, {}, Lexer()->GetToken().Start());
143             return nullptr;
144         }
145     }
146 
147     auto const placeholderNumber = std::get<2>(*nodeFormat);
148     auto *const insertingNode =
149         placeholderNumber < insertingNodes_.size() ? insertingNodes_[placeholderNumber] : nullptr;
150     if (insertingNode == nullptr || !insertingNode->IsExpression() || !insertingNode->AsExpression()->IsIdentifier()) {
151         LogError(diagnostic::INVALID_INSERT_NODE, {}, Lexer()->GetToken().Start());
152         ES2PANDA_UNREACHABLE();
153     }
154 
155     auto *const insertIdentifier = insertingNode->AsExpression()->AsIdentifier();
156     Lexer()->NextToken();
157     return insertIdentifier;
158 }
159 
ParseStatementFormatPlaceholder()160 ir::Statement *ETSParser::ParseStatementFormatPlaceholder()
161 {
162     if (insertingNodes_.empty()) {
163         LogError(diagnostic::INSERT_NODE_ABSENT, {}, Lexer()->GetToken().Start());
164         return AllocBrokenStatement(Lexer()->GetToken().Start());
165     }
166 
167     ParserImpl::NodeFormatType nodeFormat = GetFormatPlaceholderType();
168     if (std::get<0>(nodeFormat) || std::get<1>(nodeFormat) != STATEMENT_FORMAT_NODE) {
169         LogError(diagnostic::INVALID_NODE_TYPE, {}, Lexer()->GetToken().Start());
170         ES2PANDA_UNREACHABLE();
171     }
172 
173     auto const placeholderNumber = std::get<2>(nodeFormat);
174     auto *const insertingNode =
175         placeholderNumber < insertingNodes_.size() ? insertingNodes_[placeholderNumber] : nullptr;
176     if (insertingNode == nullptr || !insertingNode->IsStatement()) {
177         LogError(diagnostic::INVALID_INSERT_NODE, {}, Lexer()->GetToken().Start());
178         ES2PANDA_UNREACHABLE();
179     }
180 
181     Lexer()->NextToken();
182     return insertingNode->AsStatement();
183 }
184 
ParseTypeParametersFormatPlaceholder()185 ir::AstNode *ETSParser::ParseTypeParametersFormatPlaceholder()
186 {
187     ParserImpl::NodeFormatType nodeFormat = GetFormatPlaceholderType();
188     if (std::get<0>(nodeFormat) || std::get<1>(nodeFormat) != EXPRESSION_FORMAT_NODE) {
189         LogError(diagnostic::INVALID_NODE_TYPE, {}, Lexer()->GetToken().Start());
190         ES2PANDA_UNREACHABLE();
191     }
192 
193     auto const placeholderNumber = std::get<2>(nodeFormat);
194     if (placeholderNumber >= insertingNodes_.size()) {
195         LogError(diagnostic::INSERT_NODE_ABSENT, {}, Lexer()->GetToken().Start());
196         ES2PANDA_UNREACHABLE();
197     }
198 
199     auto *const insertingNode = insertingNodes_[placeholderNumber];
200     if (insertingNode != nullptr && !insertingNode->IsTSTypeParameterDeclaration() &&
201         !insertingNode->IsTSTypeParameterInstantiation()) {
202         return nullptr;
203     }
204 
205     Lexer()->NextToken();
206     return insertingNode;
207 }
208 
ParseAstNodesArrayFormatPlaceholder()209 ArenaVector<ir::AstNode *> &ETSParser::ParseAstNodesArrayFormatPlaceholder()
210 {
211     if (insertingNodes_.empty()) {
212         LogError(diagnostic::INSERT_NODE_ABSENT, {}, Lexer()->GetToken().Start());
213         ES2PANDA_UNREACHABLE();
214     }
215 
216     ParserImpl::NodeFormatType nodeFormat = GetFormatPlaceholderType();
217     if (!std::get<0>(nodeFormat) || std::get<1>(nodeFormat) != GENERAL_FORMAT_NODE) {
218         LogError(diagnostic::INVALID_NODE_TYPE, {}, Lexer()->GetToken().Start());
219         ES2PANDA_UNREACHABLE();
220     }
221 
222     auto const placeholderNumber = std::get<2>(nodeFormat);
223     auto *const insertingNode =
224         placeholderNumber < insertingNodes_.size() ? insertingNodes_[placeholderNumber] : nullptr;
225     if (insertingNode == nullptr || !insertingNode->IsTSInterfaceBody()) {
226         LogError(diagnostic::INVALID_INSERT_NODE, {}, Lexer()->GetToken().Start());
227         ES2PANDA_UNREACHABLE();
228     }
229 
230     Lexer()->NextToken();
231     return insertingNode->AsTSInterfaceBody()->Body();
232 }
233 
ParseStatementsArrayFormatPlaceholder()234 ArenaVector<ir::Statement *> &ETSParser::ParseStatementsArrayFormatPlaceholder()
235 {
236     if (insertingNodes_.empty()) {
237         LogError(diagnostic::INSERT_NODE_ABSENT, {}, Lexer()->GetToken().Start());
238         ES2PANDA_UNREACHABLE();
239     }
240 
241     ParserImpl::NodeFormatType nodeFormat = GetFormatPlaceholderType();
242     if (!std::get<0>(nodeFormat) || std::get<1>(nodeFormat) != STATEMENT_FORMAT_NODE) {
243         LogError(diagnostic::INVALID_NODE_TYPE, {}, Lexer()->GetToken().Start());
244         ES2PANDA_UNREACHABLE();
245     }
246 
247     auto const placeholderNumber = std::get<2>(nodeFormat);
248     auto *const insertingNode =
249         placeholderNumber < insertingNodes_.size() ? insertingNodes_[placeholderNumber] : nullptr;
250     if (insertingNode == nullptr || !insertingNode->IsBlockExpression()) {
251         LogError(diagnostic::INVALID_INSERT_NODE, {}, Lexer()->GetToken().Start());
252         ES2PANDA_UNREACHABLE();
253     }
254 
255     Lexer()->NextToken();
256     return insertingNode->AsBlockExpression()->Statements();
257 }
258 
ParseExpressionsArrayFormatPlaceholder()259 ArenaVector<ir::Expression *> &ETSParser::ParseExpressionsArrayFormatPlaceholder()
260 {
261     if (insertingNodes_.empty()) {
262         LogError(diagnostic::INSERT_NODE_ABSENT, {}, Lexer()->GetToken().Start());
263         ES2PANDA_UNREACHABLE();
264     }
265 
266     ParserImpl::NodeFormatType nodeFormat = GetFormatPlaceholderType();
267     if (!std::get<0>(nodeFormat) || std::get<1>(nodeFormat) != EXPRESSION_FORMAT_NODE) {
268         LogError(diagnostic::INVALID_NODE_TYPE, {}, Lexer()->GetToken().Start());
269         ES2PANDA_UNREACHABLE();
270     }
271 
272     auto const placeholderNumber = std::get<2>(nodeFormat);
273     auto *const insertingNode =
274         placeholderNumber < insertingNodes_.size() ? insertingNodes_[placeholderNumber] : nullptr;
275     if (insertingNode == nullptr || !insertingNode->IsSequenceExpression()) {
276         LogError(diagnostic::INVALID_INSERT_NODE, {}, Lexer()->GetToken().Start());
277         ES2PANDA_UNREACHABLE();
278     }
279 
280     Lexer()->NextToken();
281     return insertingNode->AsSequenceExpression()->Sequence();
282 }
283 
CreateStatement(std::string_view const sourceCode)284 ir::Statement *ETSParser::CreateStatement(std::string_view const sourceCode)
285 {
286     util::UString source {sourceCode, Allocator()};
287     auto const isp = InnerSourceParser(this);
288     auto const lexer = InitLexer({GetContext().FormattingFileName(), source.View().Utf8()});
289 
290     lexer::SourcePosition const startLoc = lexer->GetToken().Start();
291     lexer->NextToken();
292 
293     auto statements = ParseStatementList(StatementParsingFlags::STMT_GLOBAL_LEXICAL);
294     auto const statementNumber = statements.size();
295     if (statementNumber == 0U) {
296         return nullptr;
297     }
298 
299     if (statementNumber == 1U) {
300         return statements[0U];
301     }
302 
303     auto *const blockStmt = AllocNode<ir::BlockStatement>(Allocator(), std::move(statements));
304     ES2PANDA_ASSERT(blockStmt != nullptr);
305     blockStmt->SetRange({startLoc, lexer->GetToken().End()});
306 
307     for (auto *statement : blockStmt->Statements()) {
308         statement->SetParent(blockStmt);
309     }
310 
311     return blockStmt;
312 }
313 
CreateFormattedExpression(std::string_view const sourceCode,ArenaVector<ir::Expression * > & args)314 ir::Expression *ETSParser::CreateFormattedExpression(std::string_view const sourceCode,
315                                                      ArenaVector<ir::Expression *> &args)
316 {
317     std::vector<ir::AstNode *> insertingNodes {};
318     insertingNodes.reserve(args.size());
319     for (auto it : args) {
320         ProcessFormattedArg(insertingNodes, it);
321     }
322 
323     return CreateFormattedExpression(sourceCode, insertingNodes);
324 }
325 
CreateFormattedStatement(std::string_view const sourceCode,std::vector<ir::AstNode * > & insertingNodes)326 ir::Statement *ETSParser::CreateFormattedStatement(std::string_view const sourceCode,
327                                                    std::vector<ir::AstNode *> &insertingNodes)
328 {
329     insertingNodes_.swap(insertingNodes);
330     auto const statement = CreateStatement(sourceCode);
331     insertingNodes_.swap(insertingNodes);
332     return statement;
333 }
334 
CreateFormattedTypeAnnotation(std::string_view const sourceCode)335 ir::TypeNode *ETSParser::CreateFormattedTypeAnnotation(std::string_view const sourceCode)
336 {
337     util::UString source {sourceCode, Allocator()};
338     auto const isp = InnerSourceParser(this);
339     auto const lexer = InitLexer({GetContext().FormattingFileName(), source.View().Utf8()});
340     lexer->NextToken();
341     TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::NO_OPTS;
342     return ParseTypeAnnotation(&options);
343 }
344 
CreateFormattedTypeAnnotation(std::string_view const sourceCode,std::vector<ir::AstNode * > & args)345 ir::TypeNode *ETSParser::CreateFormattedTypeAnnotation(std::string_view const sourceCode,
346                                                        std::vector<ir::AstNode *> &args)
347 {
348     insertingNodes_.swap(args);
349     auto typeAnnotation = CreateFormattedTypeAnnotation(sourceCode);
350     insertingNodes_.swap(args);
351     return typeAnnotation;
352 }
353 
CreateStatements(std::string_view const sourceCode)354 ArenaVector<ir::Statement *> ETSParser::CreateStatements(std::string_view const sourceCode)
355 {
356     util::UString source {sourceCode, Allocator()};
357     auto const isp = InnerSourceParser(this);
358     auto const lexer = InitLexer({GetContext().FormattingFileName(), source.View().Utf8()});
359 
360     lexer->NextToken();
361     return ParseStatementList(StatementParsingFlags::STMT_GLOBAL_LEXICAL);
362 }
363 
CreateFormattedStatements(std::string_view const sourceCode,std::vector<ir::AstNode * > & insertingNodes)364 ArenaVector<ir::Statement *> ETSParser::CreateFormattedStatements(std::string_view const sourceCode,
365                                                                   std::vector<ir::AstNode *> &insertingNodes)
366 {
367     insertingNodes_.swap(insertingNodes);
368     auto statements = CreateStatements(sourceCode);
369     insertingNodes_.swap(insertingNodes);
370     return statements;
371 }
372 
373 //  NOTE: this method returns only a single (the first) class filed definition.
374 //  It seems that it is possible to have several of them be parsed at a time but nobody knows how...
CreateFormattedClassFieldDefinition(std::string_view sourceCode,std::vector<ir::AstNode * > & insertingNodes)375 ir::AstNode *ETSParser::CreateFormattedClassFieldDefinition(std::string_view sourceCode,
376                                                             std::vector<ir::AstNode *> &insertingNodes)
377 {
378     static ArenaVector<ir::AstNode *> const DUMMY_ARRAY {Allocator()->Adapter()};
379     insertingNodes_.swap(insertingNodes);
380 
381     auto *const property = CreateClassElement(sourceCode, DUMMY_ARRAY, ir::ClassDefinitionModifiers::NONE);
382     ES2PANDA_ASSERT(property != nullptr);
383     if (!property->IsTSInterfaceBody() || property->AsTSInterfaceBody()->Body().empty()) {
384         LogError(diagnostic::INVALID_CLASS_FIELD, {}, Lexer()->GetToken().Start());
385         ES2PANDA_UNREACHABLE();
386     }
387 
388     insertingNodes_.swap(insertingNodes);
389     return property->AsTSInterfaceBody()->Body().front();
390 }
391 
CreateFormattedClassMethodDefinition(std::string_view sourceCode,std::vector<ir::AstNode * > & insertingNodes)392 ir::AstNode *ETSParser::CreateFormattedClassMethodDefinition(std::string_view sourceCode,
393                                                              std::vector<ir::AstNode *> &insertingNodes)
394 {
395     static ArenaVector<ir::AstNode *> const DUMMY_ARRAY {Allocator()->Adapter()};
396     insertingNodes_.swap(insertingNodes);
397 
398     auto *const property = CreateClassElement(sourceCode, DUMMY_ARRAY, ir::ClassDefinitionModifiers::NONE);
399     ES2PANDA_ASSERT(property != nullptr);
400     if (!property->IsMethodDefinition()) {
401         LogError(diagnostic::INVALID_CLASS_METHOD, {}, Lexer()->GetToken().Start());
402         ES2PANDA_UNREACHABLE();
403     }
404 
405     insertingNodes_.swap(insertingNodes);
406     return property;
407 }
408 
CreateFormattedClassElement(std::string_view sourceCode,std::vector<ir::AstNode * > & insertingNodes,const ArenaVector<ir::AstNode * > & properties,ir::ClassDefinitionModifiers modifiers)409 ir::AstNode *ETSParser::CreateFormattedClassElement(std::string_view sourceCode,
410                                                     std::vector<ir::AstNode *> &insertingNodes,
411                                                     const ArenaVector<ir::AstNode *> &properties,
412                                                     ir::ClassDefinitionModifiers modifiers)
413 {
414     insertingNodes_.swap(insertingNodes);
415     auto *const classElement = CreateClassElement(sourceCode, properties, modifiers);
416     insertingNodes_.swap(insertingNodes);
417     return classElement;
418 }
419 
420 //  NOTE: the method has limited functionality - it returns 'ir::TSInterfaceBody' placeholder for the field
421 //  declaration(s) (properties themselves are in ->Body() member) and does not perform any check of the node returned.
422 //  Also the node isn't placed in the providing properties container.
CreateClassElement(std::string_view sourceCode,const ArenaVector<ir::AstNode * > & properties,ir::ClassDefinitionModifiers modifiers)423 ir::AstNode *ETSParser::CreateClassElement(std::string_view sourceCode, const ArenaVector<ir::AstNode *> &properties,
424                                            ir::ClassDefinitionModifiers modifiers)
425 {
426     util::UString source {sourceCode, Allocator()};
427     auto const isp = InnerSourceParser(this);
428     auto const lexer = InitLexer({GetContext().FormattingFileName(), source.View().Utf8()});
429 
430     auto savedCtx = SavedStatusContext<ParserStatus::IN_CLASS_BODY>(&GetContext());
431     SavedClassPrivateContext classContext(this);
432 
433     lexer->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);
434 
435     return ParseClassElement(properties, modifiers, ir::ModifierFlags::NONE);
436 }
437 
CreateFormattedClassDeclaration(std::string_view sourceCode,std::vector<ir::AstNode * > & insertingNodes,bool const allowStatic)438 ir::Statement *ETSParser::CreateFormattedClassDeclaration(std::string_view sourceCode,
439                                                           std::vector<ir::AstNode *> &insertingNodes,
440                                                           bool const allowStatic)
441 {
442     insertingNodes_.swap(insertingNodes);
443     auto *const classDeclaration = CreateClassDeclaration(sourceCode, allowStatic);
444     insertingNodes_.swap(insertingNodes);
445     return classDeclaration;
446 }
447 
CreateClassDeclaration(std::string_view sourceCode,bool allowStatic)448 ir::Statement *ETSParser::CreateClassDeclaration(std::string_view sourceCode, bool allowStatic)
449 {
450     util::UString source {sourceCode, Allocator()};
451     auto const isp = InnerSourceParser(this);
452     auto const lexer = InitLexer({GetContext().FormattingFileName(), source.View().Utf8()});
453 
454     auto savedCtx = SavedStatusContext<ParserStatus::IN_CLASS_BODY>(&GetContext());
455 
456     auto modifiers = ir::ClassDefinitionModifiers::ID_REQUIRED | ir::ClassDefinitionModifiers::CLASS_DECL;
457     ir::ModifierFlags flags = ir::ModifierFlags::NONE;
458 
459     lexer->NextToken();
460 
461     switch (auto tokenType = Lexer()->GetToken().Type(); tokenType) {
462         case lexer::TokenType::KEYW_STATIC: {
463             if (!allowStatic) {
464                 LogUnexpectedToken(Lexer()->GetToken());
465             }
466             [[fallthrough]];
467         }
468         case lexer::TokenType::KEYW_ABSTRACT:
469         case lexer::TokenType::KEYW_FINAL: {
470             flags = ParseClassModifiers();
471             if (allowStatic && (flags & ir::ModifierFlags::STATIC) == 0U) {
472                 modifiers |= ir::ClassDefinitionModifiers::INNER;
473             }
474 
475             if (auto const tokType = Lexer()->GetToken().Type(); tokType != lexer::TokenType::KEYW_CLASS) {
476                 LogUnexpectedToken(Lexer()->GetToken());
477             }
478             [[fallthrough]];
479         }
480         case lexer::TokenType::KEYW_CLASS: {
481             return ParseClassDeclaration(modifiers);
482         }
483         default: {
484             LogUnexpectedToken(Lexer()->GetToken());
485             return nullptr;
486         }
487     }
488 }
489 
CreateConstructorDefinition(ir::ModifierFlags modifiers,std::string_view const sourceCode)490 ir::MethodDefinition *ETSParser::CreateConstructorDefinition(ir::ModifierFlags modifiers,
491                                                              std::string_view const sourceCode)
492 {
493     util::UString source {sourceCode, Allocator()};
494     auto const isp = InnerSourceParser(this);
495     auto const lexer = InitLexer({GetContext().FormattingFileName(), source.View().Utf8()});
496 
497     auto const startLoc = Lexer()->GetToken().Start();
498     Lexer()->NextToken();
499 
500     if (IsClassMethodModifier(Lexer()->GetToken().Type())) {
501         modifiers |= ParseClassMethodModifiers(false);
502     }
503 
504     if (Lexer()->GetToken().Type() != lexer::TokenType::KEYW_CONSTRUCTOR) {
505         LogExpectedToken(lexer::TokenType::KEYW_CONSTRUCTOR);
506     }
507 
508     if ((modifiers & ir::ModifierFlags::ASYNC) != 0) {
509         LogError(diagnostic::ASYNC_CONSTRUCTOR);
510         ES2PANDA_UNREACHABLE();
511     }
512 
513     auto *memberName = AllocNode<ir::Identifier>(Lexer()->GetToken().Ident(), Allocator());
514     modifiers |= ir::ModifierFlags::CONSTRUCTOR;
515     Lexer()->NextToken();
516 
517     auto *const methodDefinition = ParseClassMethodDefinition(memberName, modifiers, true);
518     ES2PANDA_ASSERT(methodDefinition != nullptr);
519     methodDefinition->SetStart(startLoc);
520 
521     return methodDefinition;
522 }
523 
CreateExpression(std::string_view const sourceCode,ExpressionParseFlags const flags)524 ir::Expression *ETSParser::CreateExpression(std::string_view const sourceCode, ExpressionParseFlags const flags)
525 {
526     util::UString source {sourceCode, Allocator()};
527     auto const isp = InnerSourceParser(this);
528     auto const lexer = InitLexer({GetContext().FormattingFileName(), source.View().Utf8()});
529 
530     lexer->NextToken();
531 
532     ir::Expression *returnExpression = ParseExpression(flags);
533     return returnExpression;
534 }
535 
CreateFormattedExpression(std::string_view const sourceCode,std::vector<ir::AstNode * > & insertingNodes)536 ir::Expression *ETSParser::CreateFormattedExpression(std::string_view const sourceCode,
537                                                      std::vector<ir::AstNode *> &insertingNodes)
538 {
539     ir::Expression *returnExpression;
540     insertingNodes_.swap(insertingNodes);
541 
542     if (auto statements = CreateStatements(sourceCode);
543         statements.size() == 1U && statements.back()->IsExpressionStatement()) {
544         returnExpression = statements.back()->AsExpressionStatement()->GetExpression();
545     } else {
546         returnExpression = AllocNode<ir::BlockExpression>(std::move(statements));
547     }
548 
549     insertingNodes_.swap(insertingNodes);
550     return returnExpression;
551 }
552 
CreateTopLevelStatement(std::string_view const sourceCode)553 ir::Statement *ETSParser::CreateTopLevelStatement(std::string_view const sourceCode)
554 {
555     util::UString source {sourceCode, Allocator()};
556     auto const isp = InnerSourceParser(this);
557     auto const lexer = InitLexer({GetContext().FormattingFileName(), source.View().Utf8()});
558 
559     lexer->NextToken();
560 
561     return ParseTopLevelStatement();
562 }
563 
CreateFormattedTopLevelStatement(std::string_view const sourceCode,std::vector<ir::AstNode * > & insertingNodes)564 ir::Statement *ETSParser::CreateFormattedTopLevelStatement(std::string_view const sourceCode,
565                                                            std::vector<ir::AstNode *> &insertingNodes)
566 {
567     insertingNodes_.swap(insertingNodes);
568     auto const statement = CreateTopLevelStatement(sourceCode);
569     insertingNodes_.swap(insertingNodes);
570     return statement;
571 }
572 
CreateTypeAnnotation(TypeAnnotationParsingOptions * options,std::string_view const sourceCode)573 ir::TypeNode *ETSParser::CreateTypeAnnotation(TypeAnnotationParsingOptions *options, std::string_view const sourceCode)
574 {
575     util::UString source {sourceCode, Allocator()};
576     auto const isp = InnerSourceParser(this);
577     auto const lexer = InitLexer({GetContext().FormattingFileName(), source.View().Utf8()});
578 
579     lexer->NextToken();
580     return ParseTypeAnnotation(options);
581 }
582 }  // namespace ark::es2panda::parser
583