From 9ffb19a54e2fbca71d4848edc09feceeb094f1c8 Mon Sep 17 00:00:00 2001 From: peterseres Date: Fri, 12 Jul 2024 14:40:11 +0200 Subject: [PATCH] [ArkTS] Support single export directive Fixes #17732 internal issue. Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/IAD3AH?from=project-issue Testing:Parser tests and in the core pr Reason: To support single export directive Change-Id: I27451a15de1f8ffef0b635731ccedb8841ec9eba Signed-off-by: Peter Seres --- ets2panda/parser/ETSparser.cpp | 27 +++++++++++++++++-- ets2panda/parser/ETSparser.h | 1 + ets2panda/parser/ETSparserStatements.cpp | 27 ++++++++++++------- ...t_type_variable_at_definition-expected.txt | 2 +- .../single_export_as_n-expected.txt | 1 + .../ets/single_export/single_export_as_n.sts | 18 +++++++++++++ .../single_export_from_n-expected.txt | 1 + .../single_export/single_export_from_n.sts | 13 +++++++++ .../single_export_n-expected.txt | 1 + .../ets/single_export/single_export_n.sts | 19 +++++++++++++ 10 files changed, 98 insertions(+), 12 deletions(-) create mode 100644 ets2panda/test/parser/ets/single_export/single_export_as_n-expected.txt create mode 100644 ets2panda/test/parser/ets/single_export/single_export_as_n.sts create mode 100644 ets2panda/test/parser/ets/single_export/single_export_from_n-expected.txt create mode 100644 ets2panda/test/parser/ets/single_export/single_export_from_n.sts create mode 100644 ets2panda/test/parser/ets/single_export/single_export_n-expected.txt create mode 100644 ets2panda/test/parser/ets/single_export/single_export_n.sts diff --git a/ets2panda/parser/ETSparser.cpp b/ets2panda/parser/ETSparser.cpp index bb478ce458..39a45061df 100644 --- a/ets2panda/parser/ETSparser.cpp +++ b/ets2panda/parser/ETSparser.cpp @@ -884,12 +884,13 @@ void ETSParser::ThrowIfVarDeclaration(VariableParsingFlags flags) ir::Statement *ETSParser::ParseExport(lexer::SourcePosition startLoc, ir::ModifierFlags modifiers) { ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MULTIPLY || - Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE); + Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE || + Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_IDENT); ArenaVector specifiers(Allocator()->Adapter()); if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MULTIPLY) { ParseNameSpaceSpecifier(&specifiers, true); - } else { + } else if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE) { auto specs = ParseNamedSpecifiers(); if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_FROM) { @@ -904,6 +905,8 @@ ir::Statement *ETSParser::ParseExport(lexer::SourcePosition startLoc, ir::Modifi result->AddModifier(modifiers); return result; } + } else { + return ParseSingleExport(modifiers); } // re-export directive @@ -1032,6 +1035,26 @@ ArenaVector ETSParser::ParseImportDeclarations() return statements; } +ir::ExportNamedDeclaration *ETSParser::ParseSingleExport(ir::ModifierFlags modifiers) +{ + lexer::Token token = Lexer()->GetToken(); + auto *exported = AllocNode(token.Ident(), Allocator()); + exported->SetReference(); + exported->SetRange(Lexer()->GetToken().Loc()); + + Lexer()->NextToken(); // eat exported variable name + + ArenaVector exports(Allocator()->Adapter()); + + exports.emplace_back(AllocNode(exported, ParseNamedExport(token))); + auto result = AllocNode(Allocator(), static_cast(nullptr), + std::move(exports)); + result->AddModifier(modifiers); + ConsumeSemicolon(result); + + return result; +} + ArenaVector ETSParser::ParseNamedSpecifiers() { // NOTE(user): handle qualifiedName in file bindings: qualifiedName '.' '*' diff --git a/ets2panda/parser/ETSparser.h b/ets2panda/parser/ETSparser.h index d5d8c6dd04..d0a7e697f2 100644 --- a/ets2panda/parser/ETSparser.h +++ b/ets2panda/parser/ETSparser.h @@ -248,6 +248,7 @@ private: std::vector ParseSources(); std::tuple> ParseFromClause(bool requireFrom); ArenaVector ParseNamedSpecifiers(); + ir::ExportNamedDeclaration *ParseSingleExport(ir::ModifierFlags modifiers); ArenaVector ParseImportDeclarations(); parser::Program *ParseSource(const SourceFile &sourceFile); void AddExternalSource(const std::vector &programs); diff --git a/ets2panda/parser/ETSparserStatements.cpp b/ets2panda/parser/ETSparserStatements.cpp index 81961f9bc3..108e4f8d3d 100644 --- a/ets2panda/parser/ETSparserStatements.cpp +++ b/ets2panda/parser/ETSparserStatements.cpp @@ -138,6 +138,19 @@ ArenaVector ETSParser::ParseTopLevelStatements() return statements; } +static ir::Statement *ValidateExportableStatement(ETSParser *parser, ir::Statement *stmt, + ark::es2panda::ir::ModifierFlags memberModifiers) +{ + if (stmt != nullptr) { + if ((memberModifiers & ir::ModifierFlags::EXPORT_TYPE) != 0U && + !(stmt->IsClassDeclaration() || stmt->IsTSInterfaceDeclaration() || stmt->IsTSTypeAliasDeclaration())) { + parser->ThrowSyntaxError("Can only type export class or interface!", stmt->Start()); + } + stmt->AddModifier(memberModifiers); + } + return stmt; +} + ir::Statement *ETSParser::ParseTopLevelDeclStatement(StatementParsingFlags flags) { auto [memberModifiers, startLoc] = ParseMemberModifiers(); @@ -175,20 +188,16 @@ ir::Statement *ETSParser::ParseTopLevelDeclStatement(StatementParsingFlags flags } case lexer::TokenType::LITERAL_IDENT: { result = ParseIdentKeyword(); + if (result == nullptr && (memberModifiers & (ir::ModifierFlags::EXPORTED)) != 0U) { + return ParseExport(startLoc, memberModifiers); + } break; } default: { } } - if (result != nullptr) { - if ((memberModifiers & ir::ModifierFlags::EXPORT_TYPE) != 0U && - !(result->IsClassDeclaration() || result->IsTSInterfaceDeclaration() || - result->IsTSTypeAliasDeclaration())) { - ThrowSyntaxError("Can only type export class or interface!"); - } - result->AddModifier(memberModifiers); - } - return result; + + return ValidateExportableStatement(this, result, memberModifiers); } ir::Statement *ETSParser::ParseTopLevelStatement() diff --git a/ets2panda/test/compiler/ets/export_type_variable_at_definition-expected.txt b/ets2panda/test/compiler/ets/export_type_variable_at_definition-expected.txt index 10560edc38..685c78436c 100644 --- a/ets2panda/test/compiler/ets/export_type_variable_at_definition-expected.txt +++ b/ets2panda/test/compiler/ets/export_type_variable_at_definition-expected.txt @@ -1 +1 @@ -SyntaxError: Can only type export class or interface! [export_type_variable_at_definition.sts:17:1] +SyntaxError: Can only type export class or interface! [export_type_variable_at_definition.sts:16:13] diff --git a/ets2panda/test/parser/ets/single_export/single_export_as_n-expected.txt b/ets2panda/test/parser/ets/single_export/single_export_as_n-expected.txt new file mode 100644 index 0000000000..6e5b466236 --- /dev/null +++ b/ets2panda/test/parser/ets/single_export/single_export_as_n-expected.txt @@ -0,0 +1 @@ +SyntaxError: Unexpected token [single_export_as_n.sts:16:10] diff --git a/ets2panda/test/parser/ets/single_export/single_export_as_n.sts b/ets2panda/test/parser/ets/single_export/single_export_as_n.sts new file mode 100644 index 0000000000..9257a41168 --- /dev/null +++ b/ets2panda/test/parser/ets/single_export/single_export_as_n.sts @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export a as A + +let a = 2; diff --git a/ets2panda/test/parser/ets/single_export/single_export_from_n-expected.txt b/ets2panda/test/parser/ets/single_export/single_export_from_n-expected.txt new file mode 100644 index 0000000000..fb2150a2fe --- /dev/null +++ b/ets2panda/test/parser/ets/single_export/single_export_from_n-expected.txt @@ -0,0 +1 @@ +SyntaxError: Unexpected token [single_export_from_n.sts:13:10] diff --git a/ets2panda/test/parser/ets/single_export/single_export_from_n.sts b/ets2panda/test/parser/ets/single_export/single_export_from_n.sts new file mode 100644 index 0000000000..a5fe2bf6aa --- /dev/null +++ b/ets2panda/test/parser/ets/single_export/single_export_from_n.sts @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License");W + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export a from "./type" diff --git a/ets2panda/test/parser/ets/single_export/single_export_n-expected.txt b/ets2panda/test/parser/ets/single_export/single_export_n-expected.txt new file mode 100644 index 0000000000..1f2ee49160 --- /dev/null +++ b/ets2panda/test/parser/ets/single_export/single_export_n-expected.txt @@ -0,0 +1 @@ +SyntaxError: Unexpected token [single_export_n.sts:16:9] diff --git a/ets2panda/test/parser/ets/single_export/single_export_n.sts b/ets2panda/test/parser/ets/single_export/single_export_n.sts new file mode 100644 index 0000000000..83d372af02 --- /dev/null +++ b/ets2panda/test/parser/ets/single_export/single_export_n.sts @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export v,m + +let v = 1 +let m = 2 -- Gitee