1 /**
2 * Copyright (c) 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 #include "lexer/lexer.h"
18 #include "ir/astNode.h"
19 #include "ir/ets/etsModule.h"
20 #include "utils/arena_containers.h"
21 #include "util/errorRecovery.h"
22 #include "generated/diagnostic.h"
23
24 namespace ark::es2panda::parser {
25
26 using namespace std::literals::string_literals;
27
ParseNamespaceStatement(ir::ModifierFlags memberModifiers)28 ir::ETSModule *ETSParser::ParseNamespaceStatement(ir::ModifierFlags memberModifiers)
29 {
30 auto modifiers = ir::ModifierFlags::NONE;
31 if (((memberModifiers & ir::ModifierFlags::EXPORT) != 0)) {
32 modifiers |= ir::ModifierFlags::EXPORT;
33 }
34 if (((memberModifiers & ir::ModifierFlags::DEFAULT_EXPORT) != 0)) {
35 modifiers |= ir::ModifierFlags::DEFAULT_EXPORT;
36 }
37 if ((memberModifiers & ir::ModifierFlags::DECLARE) != 0 || InAmbientContext()) {
38 modifiers |= ir::ModifierFlags::DECLARE;
39 GetContext().Status() |= ParserStatus::IN_AMBIENT_CONTEXT;
40 }
41 GetContext().Status() |= ParserStatus::IN_NAMESPACE;
42 IncrementNamespaceNestedRank();
43
44 auto *result = ParseNamespace(modifiers);
45
46 DecrementNamespaceNestedRank();
47 if (GetNamespaceNestedRank() == 0) {
48 GetContext().Status() &= ~ParserStatus::IN_NAMESPACE;
49 }
50 if ((memberModifiers & ir::ModifierFlags::DECLARE) != 0) {
51 GetContext().Status() &= ~ParserStatus::IN_AMBIENT_CONTEXT;
52 }
53 return result->AsETSModule();
54 }
55
ParseNamespace(ir::ModifierFlags flags)56 ir::Statement *ETSParser::ParseNamespace(ir::ModifierFlags flags)
57 {
58 if ((GetContext().Status() & ParserStatus::IN_NAMESPACE) == 0) {
59 LogError(diagnostic::NAMESPACE_ONLY_TOP_OR_IN_NAMESPACE);
60 }
61 auto start = Lexer()->GetToken().Start();
62 ir::ETSModule *ns = ParseNamespaceImp(flags);
63 ES2PANDA_ASSERT(ns != nullptr);
64 ns->SetRange({start, Lexer()->GetToken().Start()});
65 return ns;
66 }
67
ParseNamespaceImp(ir::ModifierFlags flags)68 ir::ETSModule *ETSParser::ParseNamespaceImp(ir::ModifierFlags flags)
69 {
70 Lexer()->NextToken();
71 auto *result = AllocNode<ir::ETSModule>(Allocator(), ArenaVector<ir::Statement *>(Allocator()->Adapter()),
72 ExpectIdentifier(), ir::ModuleFlag::NAMESPACE, globalProgram_);
73 ES2PANDA_ASSERT(result != nullptr);
74 ir::ETSModule *parent = result;
75 ir::ETSModule *child = nullptr;
76 while (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD) {
77 Lexer()->NextToken();
78 auto start = Lexer()->GetToken().Start();
79 child = AllocNode<ir::ETSModule>(Allocator(), ArenaVector<ir::Statement *>(Allocator()->Adapter()),
80 ExpectIdentifier(), ir::ModuleFlag::NAMESPACE, globalProgram_);
81 ES2PANDA_ASSERT(child != nullptr);
82 child->SetParent(parent);
83 child->SetRange({start, Lexer()->GetToken().Start()});
84 child->AddModifier(ir::ModifierFlags::EXPORT);
85 if ((flags & ir::ModifierFlags::DECLARE) != 0) {
86 child->AddModifier(ir::ModifierFlags::DECLARE);
87 }
88 ES2PANDA_ASSERT(parent != nullptr);
89 parent->Statements().emplace_back(child);
90 parent = child;
91 }
92 ExpectToken(lexer::TokenType::PUNCTUATOR_LEFT_BRACE);
93 ArenaVector<ir::Statement *> statements(Allocator()->Adapter());
94 while (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
95 util::ErrorRecursionGuard infiniteLoopBlocker(Lexer());
96 if (Lexer()->GetToken().Type() == lexer::TokenType::EOS) {
97 LogError(diagnostic::UNEXPECTED_TOKEN);
98 break;
99 }
100 if (Lexer()->TryEatTokenType(lexer::TokenType::PUNCTUATOR_SEMI_COLON)) {
101 continue;
102 }
103 auto st = ParseTopLevelStatement();
104 if (st != nullptr) {
105 statements.emplace_back(st);
106 }
107 }
108 Lexer()->NextToken();
109 if (child != nullptr) {
110 child->SetNamespaceChainLastNode();
111 child->SetStatements(std::move(statements));
112 } else {
113 result->SetNamespaceChainLastNode();
114 result->SetStatements(std::move(statements));
115 }
116 result->AddModifier(flags);
117 return result;
118 }
119
120 } // namespace ark::es2panda::parser
121