1/**
2 * Copyright (c) 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#include "ETSNolintParser.h"
18#include <utility>
19
20#include "macros.h"
21#include "parser/parserFlags.h"
22#include "parser/parserStatusContext.h"
23#include "util/helpers.h"
24#include "util/language.h"
25#include "utils/arena_containers.h"
26#include "varbinder/varbinder.h"
27#include "varbinder/ETSBinder.h"
28#include "lexer/lexer.h"
29#include "lexer/ETSLexer.h"
30#include "ir/astNode.h"
31
32#include "ir/statements/namespaceDeclaration.h"
33
34namespace ark::es2panda::parser {
35class FunctionContext;
36
37using namespace std::literals::string_literals;
38
39ir::NamespaceDeclaration *ETSParser::ParseNamespaceDeclaration(ir::ModifierFlags flags)
40{
41    if ((GetContext().Status() & ParserStatus::IN_NAMESPACE) == 0) {
42        ThrowSyntaxError("Namespace not enabled in here.");
43    }
44
45    const lexer::SourcePosition startLoc = Lexer()->GetToken().Start();
46    auto modifiers = ir::ClassDefinitionModifiers::NONE;
47    if (IsExternal()) {
48        modifiers |= ir::ClassDefinitionModifiers::FROM_EXTERNAL;
49    }
50
51    ir::NamespaceDefinition *namespaceDefinition = ParseNamespaceDefinition(modifiers, flags);
52
53    auto *namespaceDecl = AllocNode<ir::NamespaceDeclaration>(namespaceDefinition);
54
55    namespaceDecl->SetRange({startLoc, Lexer()->GetToken().End()});
56    return namespaceDecl;
57}
58
59ir::NamespaceDefinition *ETSParser::ParseNamespaceDefinition(ir::ClassDefinitionModifiers modifiers,
60                                                             ir::ModifierFlags flags)
61{
62    Lexer()->NextToken();
63    flags |= ir::ModifierFlags::DECLARE;
64    ir::Identifier *identNode = ParseClassIdent(modifiers);
65
66    ArenaVector<ir::AstNode *> properties(Allocator()->Adapter());
67    ir::MethodDefinition *ctor = nullptr;
68    lexer::SourceRange bodyRange;
69
70    std::tie(ctor, properties, bodyRange) = ParseNamespaceBody(modifiers, flags);
71
72    auto def =
73        AllocNode<ir::NamespaceDefinition>(identNode, std::move(properties), ctor, flags, GetContext().GetLanguage());
74    def->SetRange(bodyRange);
75    return def;
76}
77
78ETSParser::NamespaceBody ETSParser::ParseNamespaceBody(ir::ClassDefinitionModifiers modifiers, ir::ModifierFlags flags)
79{
80    auto savedCtx = SavedStatusContext<ParserStatus::IN_CLASS_BODY>(&GetContext());
81
82    lexer::SourcePosition startLoc = Lexer()->GetToken().Start();
83    Lexer()->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);
84
85    ir::MethodDefinition *ctor = nullptr;
86    ArenaVector<ir::AstNode *> properties(Allocator()->Adapter());
87
88    SavedClassPrivateContext classContext(this);
89
90    if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_FORMAT &&
91        Lexer()->Lookahead() == static_cast<char32_t>(ARRAY_FORMAT_NODE)) {
92        properties = std::move(ParseAstNodesArrayFormatPlaceholder());
93        if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
94            ThrowSyntaxError("Expected a '}'");
95        }
96    } else {
97        while (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
98            if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
99                Lexer()->NextToken();
100                continue;
101            }
102
103            ir::AstNode *property = ParseClassElement(properties, modifiers, flags);
104
105            if (CheckClassElement(property, ctor, properties)) {
106                continue;
107            }
108
109            properties.push_back(property);
110        }
111    }
112
113    lexer::SourcePosition endLoc = Lexer()->GetToken().End();
114    Lexer()->NextToken();
115
116    return {ctor, std::move(properties), lexer::SourceRange {startLoc, endLoc}};
117}
118
119}  // namespace ark::es2panda::parser
120