1/**
2 * Copyright (c) 2021-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 "checker/types/ets/etsEnumType.h"
31#include "ir/astNode.h"
32#include "ir/base/classDefinition.h"
33#include "ir/base/decorator.h"
34#include "ir/base/catchClause.h"
35#include "ir/base/classProperty.h"
36#include "ir/base/scriptFunction.h"
37#include "ir/base/methodDefinition.h"
38#include "ir/base/classStaticBlock.h"
39#include "ir/base/spreadElement.h"
40#include "ir/expressions/identifier.h"
41#include "ir/expressions/functionExpression.h"
42#include "ir/statements/functionDeclaration.h"
43#include "ir/statements/expressionStatement.h"
44#include "ir/statements/classDeclaration.h"
45#include "ir/statements/variableDeclarator.h"
46#include "ir/statements/variableDeclaration.h"
47#include "ir/expressions/dummyNode.h"
48#include "ir/expressions/callExpression.h"
49#include "ir/expressions/thisExpression.h"
50#include "ir/expressions/typeofExpression.h"
51#include "ir/expressions/memberExpression.h"
52#include "ir/expressions/updateExpression.h"
53#include "ir/expressions/arrowFunctionExpression.h"
54#include "ir/expressions/unaryExpression.h"
55#include "ir/expressions/yieldExpression.h"
56#include "ir/expressions/awaitExpression.h"
57#include "ir/expressions/literals/nullLiteral.h"
58#include "ir/expressions/literals/numberLiteral.h"
59#include "ir/expressions/literals/stringLiteral.h"
60#include "ir/expressions/literals/undefinedLiteral.h"
61#include "ir/module/importDeclaration.h"
62#include "ir/module/importDefaultSpecifier.h"
63#include "ir/module/importSpecifier.h"
64#include "ir/module/exportSpecifier.h"
65#include "ir/module/exportNamedDeclaration.h"
66#include "ir/statements/assertStatement.h"
67#include "ir/statements/blockStatement.h"
68#include "ir/statements/ifStatement.h"
69#include "ir/statements/labelledStatement.h"
70#include "ir/statements/switchStatement.h"
71#include "ir/statements/throwStatement.h"
72#include "ir/statements/tryStatement.h"
73#include "ir/statements/whileStatement.h"
74#include "ir/statements/forOfStatement.h"
75#include "ir/statements/doWhileStatement.h"
76#include "ir/statements/breakStatement.h"
77#include "ir/statements/debuggerStatement.h"
78#include "ir/ets/etsLaunchExpression.h"
79#include "ir/ets/etsClassLiteral.h"
80#include "ir/ets/etsPrimitiveType.h"
81#include "ir/ets/etsPackageDeclaration.h"
82#include "ir/ets/etsReExportDeclaration.h"
83#include "ir/ets/etsWildcardType.h"
84#include "ir/ets/etsNewArrayInstanceExpression.h"
85#include "ir/ets/etsTuple.h"
86#include "ir/ets/etsFunctionType.h"
87#include "ir/ets/etsNewClassInstanceExpression.h"
88#include "ir/ets/etsNewMultiDimArrayInstanceExpression.h"
89#include "ir/ets/etsScript.h"
90#include "ir/ets/etsTypeReference.h"
91#include "ir/ets/etsTypeReferencePart.h"
92#include "ir/ets/etsNullishTypes.h"
93#include "ir/ets/etsUnionType.h"
94#include "ir/ets/etsImportSource.h"
95#include "ir/ets/etsImportDeclaration.h"
96#include "ir/ets/etsStructDeclaration.h"
97#include "ir/ets/etsParameterExpression.h"
98#include "ir/module/importNamespaceSpecifier.h"
99#include "ir/ts/tsAsExpression.h"
100#include "ir/ts/tsInterfaceDeclaration.h"
101#include "ir/ts/tsEnumDeclaration.h"
102#include "ir/ts/tsTypeParameterInstantiation.h"
103#include "ir/ts/tsInterfaceBody.h"
104#include "ir/ts/tsImportEqualsDeclaration.h"
105#include "ir/ts/tsArrayType.h"
106#include "ir/ts/tsQualifiedName.h"
107#include "ir/ts/tsTypeReference.h"
108#include "ir/ts/tsTypeParameter.h"
109#include "ir/ts/tsInterfaceHeritage.h"
110#include "ir/ts/tsFunctionType.h"
111#include "ir/ts/tsClassImplements.h"
112#include "ir/ts/tsEnumMember.h"
113#include "ir/ts/tsTypeAliasDeclaration.h"
114#include "ir/ts/tsTypeParameterDeclaration.h"
115#include "ir/ts/tsNonNullExpression.h"
116#include "ir/ts/tsThisType.h"
117#include "generated/signatures.h"
118
119namespace ark::es2panda::parser {
120class FunctionContext;
121
122using namespace std::literals::string_literals;
123
124ArenaVector<ir::Statement *> ETSParser::ParseTopLevelStatements()
125{
126    ArenaVector<ir::Statement *> statements(Allocator()->Adapter());
127    while (Lexer()->GetToken().Type() != lexer::TokenType::EOS) {
128        if (Lexer()->TryEatTokenType(lexer::TokenType::PUNCTUATOR_SEMI_COLON)) {
129            continue;
130        }
131        auto stmt = ParseTopLevelStatement();
132        GetContext().Status() &= ~ParserStatus::IN_AMBIENT_CONTEXT;
133        if (stmt != nullptr) {
134            statements.emplace_back(stmt);
135        }
136    }
137
138    return statements;
139}
140
141static ir::Statement *ValidateExportableStatement(ETSParser *parser, ir::Statement *stmt,
142                                                  ark::es2panda::ir::ModifierFlags memberModifiers)
143{
144    if (stmt != nullptr) {
145        if ((memberModifiers & ir::ModifierFlags::EXPORT_TYPE) != 0U &&
146            !(stmt->IsClassDeclaration() || stmt->IsTSInterfaceDeclaration() || stmt->IsTSTypeAliasDeclaration())) {
147            parser->ThrowSyntaxError("Can only type export class or interface!", stmt->Start());
148        }
149        stmt->AddModifier(memberModifiers);
150    }
151    return stmt;
152}
153
154ir::Statement *ETSParser::ParseTopLevelDeclStatement(StatementParsingFlags flags)
155{
156    auto [memberModifiers, startLoc] = ParseMemberModifiers();
157    if ((memberModifiers & (ir::ModifierFlags::EXPORTED)) != 0U &&
158        (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MULTIPLY ||
159         Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE)) {
160        return ParseExport(startLoc, memberModifiers);
161    }
162
163    ir::Statement *result = nullptr;
164    auto token = Lexer()->GetToken();
165    switch (token.Type()) {
166        case lexer::TokenType::KEYW_FUNCTION: {
167            result = ParseFunctionDeclaration(false, memberModifiers);
168            if (result != nullptr) {  // Error processing.
169                result->SetStart(startLoc);
170            }
171            break;
172        }
173        case lexer::TokenType::KEYW_CONST: {
174            memberModifiers |= ir::ModifierFlags::CONST;
175            [[fallthrough]];
176        }
177        case lexer::TokenType::KEYW_LET: {
178            result = ParseStatement(flags);
179            break;
180        }
181        case lexer::TokenType::KEYW_NAMESPACE:
182        case lexer::TokenType::KEYW_STATIC:
183        case lexer::TokenType::KEYW_ABSTRACT:
184        case lexer::TokenType::KEYW_FINAL:
185        case lexer::TokenType::KEYW_ENUM:
186        case lexer::TokenType::KEYW_INTERFACE:
187        case lexer::TokenType::KEYW_CLASS: {
188            result = ParseTypeDeclaration(false);
189            break;
190        }
191        case lexer::TokenType::LITERAL_IDENT: {
192            result = ParseIdentKeyword();
193            if (result == nullptr && (memberModifiers & (ir::ModifierFlags::EXPORTED)) != 0U) {
194                return ParseExport(startLoc, memberModifiers);
195            }
196            break;
197        }
198        default: {
199        }
200    }
201
202    return ValidateExportableStatement(this, result, memberModifiers);
203}
204
205ir::Statement *ETSParser::ParseTopLevelStatement()
206{
207    const auto flags = StatementParsingFlags::ALLOW_LEXICAL;
208
209    auto result = ParseTopLevelDeclStatement(flags);
210    if (result == nullptr) {
211        result = ParseStatement(flags);
212    }
213    return result;
214}
215
216ArenaVector<ir::Statement *> ETSParser::ParseTopLevelDeclaration()
217{
218    auto topStatements = ParseTopLevelStatements();
219    Lexer()->NextToken();
220    return topStatements;
221}
222
223void ETSParser::ValidateLabeledStatement(lexer::TokenType type)
224{
225    if (type != lexer::TokenType::KEYW_DO && type != lexer::TokenType::KEYW_WHILE &&
226        type != lexer::TokenType::KEYW_FOR && type != lexer::TokenType::KEYW_SWITCH) {
227        ThrowSyntaxError("Label must be followed by a loop statement", Lexer()->GetToken().Start());
228    }
229}
230
231void ETSParser::ValidateForInStatement()
232{
233    ThrowUnexpectedToken(lexer::TokenType::KEYW_IN);
234}
235
236ir::DebuggerStatement *ETSParser::ParseDebuggerStatement()
237{
238    ThrowUnexpectedToken(lexer::TokenType::KEYW_DEBUGGER);
239}
240
241ir::Statement *ETSParser::ParseFunctionStatement(const StatementParsingFlags flags)
242{
243    ASSERT((flags & StatementParsingFlags::GLOBAL) == 0);
244    LogSyntaxError("Nested functions are not allowed");
245    ParserImpl::ParseFunctionStatement(flags);  // Try to parse function body but skip result.
246    return nullptr;
247}
248
249ir::Statement *ETSParser::ParseAssertStatement()
250{
251    lexer::SourcePosition startLoc = Lexer()->GetToken().Start();
252    Lexer()->NextToken();
253
254    ir::Expression *test = ParseExpression();
255    lexer::SourcePosition endLoc = test->End();
256    ir::Expression *second = nullptr;
257
258    if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
259        Lexer()->NextToken();  // eat ':'
260        second = ParseExpression();
261        endLoc = second->End();
262    }
263
264    auto *asStatement = AllocNode<ir::AssertStatement>(test, second);
265    asStatement->SetRange({startLoc, endLoc});
266    ConsumeSemicolon(asStatement);
267
268    return asStatement;
269}
270
271ir::Statement *ETSParser::ParseTryStatement()
272{
273    lexer::SourcePosition startLoc = Lexer()->GetToken().Start();
274    Lexer()->NextToken();  // eat the 'try' keyword
275
276    if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
277        ThrowSyntaxError("Unexpected token, expected '{'");
278    }
279
280    ir::BlockStatement *body = ParseBlockStatement();
281
282    ArenaVector<ir::CatchClause *> catchClauses(Allocator()->Adapter());
283
284    while (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_CATCH) {
285        ir::CatchClause *clause {};
286
287        clause = ParseCatchClause();
288
289        catchClauses.push_back(clause);
290    }
291
292    ir::BlockStatement *finalizer = nullptr;
293    if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_FINALLY) {
294        Lexer()->NextToken();  // eat 'finally' keyword
295
296        finalizer = ParseBlockStatement();
297    }
298
299    if (catchClauses.empty() && finalizer == nullptr) {
300        ThrowSyntaxError("A try statement should contain either finally clause or at least one catch clause.",
301                         startLoc);
302    }
303
304    lexer::SourcePosition endLoc = finalizer != nullptr ? finalizer->End() : catchClauses.back()->End();
305
306    ArenaVector<std::pair<compiler::LabelPair, const ir::Statement *>> finalizerInsertions(Allocator()->Adapter());
307
308    auto *tryStatement = AllocNode<ir::TryStatement>(body, std::move(catchClauses), finalizer, finalizerInsertions);
309    tryStatement->SetRange({startLoc, endLoc});
310    ConsumeSemicolon(tryStatement);
311
312    return tryStatement;
313}
314
315// NOLINTNEXTLINE(google-default-arguments)
316ir::ClassDeclaration *ETSParser::ParseClassStatement([[maybe_unused]] StatementParsingFlags flags,
317                                                     ir::ClassDefinitionModifiers modifiers, ir::ModifierFlags modFlags)
318{
319    return ParseClassDeclaration(modifiers | ir::ClassDefinitionModifiers::ID_REQUIRED |
320                                     ir::ClassDefinitionModifiers::CLASS_DECL | ir::ClassDefinitionModifiers::LOCAL,
321                                 modFlags);
322}
323
324// NOLINTNEXTLINE(google-default-arguments)
325ir::ETSStructDeclaration *ETSParser::ParseStructStatement([[maybe_unused]] StatementParsingFlags flags,
326                                                          [[maybe_unused]] ir::ClassDefinitionModifiers modifiers,
327                                                          [[maybe_unused]] ir::ModifierFlags modFlags)
328{
329    ThrowSyntaxError("Illegal start of expression", Lexer()->GetToken().Start());
330}
331
332}  // namespace ark::es2panda::parser
333