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