From 859324178bbf9c127761c1d30f56520a3cfda8d3 Mon Sep 17 00:00:00 2001 From: dakeQI Date: Sat, 16 Dec 2023 14:59:28 +0000 Subject: [PATCH] Fix using of the await keyword in some declaration statements Issue: I8P094 Test: test_es2abc Signed-off-by: dakeQI Change-Id: I1ea9a3f84feea4488cf73b88c4ecafe69083bd5f --- es2panda/parser/parserImpl.cpp | 135 ++--- es2panda/parser/parserImpl.h | 8 +- es2panda/parser/statementParser.cpp | 239 +++++---- .../ts/test-toplevel-await4-expected.txt | 442 +++++++++++++++++ .../test/parser/ts/test-toplevel-await4.ts | 26 + .../ts/test-toplevel-await5-expected.txt | 463 ++++++++++++++++++ .../test/parser/ts/test-toplevel-await5.ts | 32 ++ 7 files changed, 1178 insertions(+), 167 deletions(-) create mode 100644 es2panda/test/parser/ts/test-toplevel-await4-expected.txt create mode 100644 es2panda/test/parser/ts/test-toplevel-await4.ts create mode 100644 es2panda/test/parser/ts/test-toplevel-await5-expected.txt create mode 100644 es2panda/test/parser/ts/test-toplevel-await5.ts diff --git a/es2panda/parser/parserImpl.cpp b/es2panda/parser/parserImpl.cpp index c601d57d6b..d38f483426 100644 --- a/es2panda/parser/parserImpl.cpp +++ b/es2panda/parser/parserImpl.cpp @@ -2992,7 +2992,9 @@ bool ParserImpl::IsMethodDefinitionsAreSame(const ir::MethodDefinition *property ir::Identifier *ParserImpl::SetIdentNodeInClassDefinition(bool isDeclare, binder::ConstDecl **decl) { - CheckStrictReservedWord(); + if (!isDeclare) { + CheckStrictReservedWord(); + } const util::StringView &identStr = lexer_->GetToken().Ident(); @@ -3032,17 +3034,9 @@ ir::ClassDefinition *ParserImpl::ParseClassDefinition(bool isDeclaration, bool i } // Parse SuperClass - ir::Expression *superClass = nullptr; bool hasSuperClass = false; bool isExtendsFromNull = false; - - if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_EXTENDS) { - lexer_->NextToken(); - hasSuperClass = true; - superClass = ParseLeftHandSideExpression(); - ASSERT(superClass != nullptr); - isExtendsFromNull = superClass->IsNullLiteral(); - } + ir::Expression *superClass = ParseSuperClass(isDeclare, &hasSuperClass, &isExtendsFromNull); ir::TSTypeParameterInstantiation *superTypeParams = nullptr; if (Extension() == ScriptExtension::TS && (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN || @@ -3054,55 +3048,7 @@ ir::ClassDefinition *ParserImpl::ParseClassDefinition(bool isDeclaration, bool i superTypeParams = ParseTsTypeParameterInstantiation(); } - ArenaVector implements(Allocator()->Adapter()); - if (Extension() == ScriptExtension::TS && lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_IMPLEMENTS) { - lexer_->NextToken(); - - while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) { - lexer::SourcePosition implStart = lexer_->GetToken().Start(); - - if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) { - ThrowSyntaxError("Identifier expected"); - } - - ir::Expression *expr = AllocNode(lexer_->GetToken().Ident()); - expr->SetRange(lexer_->GetToken().Loc()); - expr->AsIdentifier()->SetReference(); - - lexer_->NextToken(); - - if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD) { - expr = ParseTsQualifiedReference(expr); - } - - ir::TSTypeParameterInstantiation *implTypeParams = nullptr; - if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SHIFT) { - lexer_->BackwardToken(lexer::TokenType::PUNCTUATOR_LESS_THAN, 1); - } - - if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN || - lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SHIFT) { - implTypeParams = ParseTsTypeParameterInstantiation(); - } - - auto *impl = AllocNode(expr, implTypeParams); - impl->SetRange({implStart, lexer_->GetToken().End()}); - implements.push_back(impl); - - if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) { - lexer_->NextToken(); - continue; - } - - if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) { - ThrowSyntaxError("',' expected"); - } - } - - if (implements.empty()) { - ThrowSyntaxError("Implements clause can not be empty"); - } - } + ArenaVector implements = ParseTSClassImplements(isDeclare); if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) { ThrowSyntaxError("Unexpected token, expected '{'"); @@ -3187,6 +3133,74 @@ ir::ClassDefinition *ParserImpl::ParseClassDefinition(bool isDeclaration, bool i return classDefinition; } +ir::Expression *ParserImpl::ParseSuperClass(bool isDeclare, bool *hasSuperClass, bool *isExtendsFromNull) +{ + ir::Expression *superClass = nullptr; + if (lexer_->GetToken().Type() != lexer::TokenType::KEYW_EXTENDS) { + return nullptr; + } + + lexer_->NextToken(); + if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_AWAIT && isDeclare) { + lexer_->GetToken().SetTokenType(lexer::TokenType::LITERAL_IDENT); + } + + *hasSuperClass = true; + superClass = ParseLeftHandSideExpression(); + ASSERT(superClass != nullptr); + *isExtendsFromNull = superClass->IsNullLiteral(); + + return superClass; +} + +ArenaVector ParserImpl::ParseTSClassImplements(bool isDeclare) +{ + ArenaVector implements(Allocator()->Adapter()); + + if (Extension() != ScriptExtension::TS || lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_IMPLEMENTS) { + return implements; + } + + lexer_->NextToken(); + while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) { + lexer::SourcePosition implStart = lexer_->GetToken().Start(); + if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT && + !(lexer_->GetToken().Type() == lexer::TokenType::KEYW_AWAIT && isDeclare)) { + ThrowSyntaxError("Identifier expected"); + } + ir::Expression *expr = AllocNode(lexer_->GetToken().Ident()); + expr->SetRange(lexer_->GetToken().Loc()); + expr->AsIdentifier()->SetReference(); + lexer_->NextToken(); + if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD) { + expr = ParseTsQualifiedReference(expr); + } + ir::TSTypeParameterInstantiation *implTypeParams = nullptr; + if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SHIFT) { + lexer_->BackwardToken(lexer::TokenType::PUNCTUATOR_LESS_THAN, 1); + } + if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN || + lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SHIFT) { + implTypeParams = ParseTsTypeParameterInstantiation(); + } + auto *impl = AllocNode(expr, implTypeParams); + impl->SetRange({implStart, lexer_->GetToken().End()}); + implements.push_back(impl); + if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) { + lexer_->NextToken(); + continue; + } + if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) { + ThrowSyntaxError("',' expected"); + } + } + if (implements.empty()) { + ThrowSyntaxError("Implements clause can not be empty"); + } + + return implements; +} + void ParserImpl::ValidateClassConstructor(const ir::MethodDefinition *ctor, const ArenaVector &properties, bool isDeclare, bool hasConstructorFuncBody, @@ -3413,7 +3427,8 @@ ir::TSEnumDeclaration *ParserImpl::ParseEnumDeclaration(bool isExport, bool isDe lexer::SourcePosition enumStart = lexer_->GetToken().Start(); lexer_->NextToken(); // eat enum keyword - if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) { + if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT && + lexer_->GetToken().Type() != lexer::TokenType::KEYW_AWAIT) { ThrowSyntaxError("Identifier expected"); } diff --git a/es2panda/parser/parserImpl.h b/es2panda/parser/parserImpl.h index 082c437e5d..2f91ded5ef 100644 --- a/es2panda/parser/parserImpl.h +++ b/es2panda/parser/parserImpl.h @@ -330,7 +330,8 @@ private: ir::Identifier *SetIdentNodeInClassDefinition(bool isDeclare, binder::ConstDecl **decl); ir::ClassDefinition *ParseClassDefinition(bool isDeclaration, bool idRequired = true, bool isDeclare = false, bool isAbstract = false); - + ir::Expression *ParseSuperClass(bool isDeclare, bool *hasSuperClass, bool *isExtendsFromNull); + ArenaVector ParseTSClassImplements(bool isDeclare); void ValidateClassConstructor(const ir::MethodDefinition *ctor, const ArenaVector &properties, bool isDeclare, bool hasConstructorFuncBody, @@ -559,16 +560,19 @@ private: bool isExport, bool isDeclare, bool isConst); ir::TSEnumDeclaration *ParseEnumDeclaration(bool isExport = false, bool isDeclare = false, bool isConst = false); ir::TSInterfaceDeclaration *ParseTsInterfaceDeclaration(bool isDeclare); + void ValidateTsInterfaceName(bool isDeclare); + ArenaVector ParseTsInterfaceExtends(); ir::SwitchCaseStatement *ParseSwitchCaseStatement(bool *seenDefault); ir::SwitchStatement *ParseSwitchStatement(); ir::ThrowStatement *ParseThrowStatement(); ir::Expression *ParseCatchParam(); ir::CatchClause *ParseCatchClause(); ir::TryStatement *ParseTryStatement(); - void ValidateDeclaratorId(); + void ValidateDeclaratorId(bool isDeclare); ir::VariableDeclarator *ParseVariableDeclaratorInitializer(ir::Expression *init, VariableParsingFlags flags, const lexer::SourcePosition &startLoc, bool isDeclare); ir::VariableDeclarator *ParseVariableDeclarator(VariableParsingFlags flags, bool isDeclare); + ir::Expression *ParseVariableDeclaratorKey(VariableParsingFlags flags, bool isDeclare, bool *isDefinite); ir::Statement *ParseVariableDeclaration(VariableParsingFlags flags = VariableParsingFlags::NO_OPTS, bool isDeclare = false, bool isExport = false); ir::WhileStatement *ParseWhileStatement(); diff --git a/es2panda/parser/statementParser.cpp b/es2panda/parser/statementParser.cpp index 606436468c..d6b80f1f65 100644 --- a/es2panda/parser/statementParser.cpp +++ b/es2panda/parser/statementParser.cpp @@ -159,6 +159,9 @@ bool ParserImpl::IsTsDeclarationStatement() const auto keywordType = lexer_->GetToken().KeywordType(); lexer_->NextToken(); + if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_AWAIT) { + lexer_->GetToken().SetTokenType(lexer::TokenType::LITERAL_IDENT); + } switch (keywordType) { case lexer::TokenType::KEYW_MODULE: case lexer::TokenType::KEYW_NAMESPACE: { @@ -318,9 +321,15 @@ ir::TSModuleDeclaration *ParserImpl::ParseTsModuleDeclaration(bool isDeclare, bo if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_NAMESPACE) { lexer_->NextToken(); + if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_AWAIT) { + lexer_->GetToken().SetTokenType(lexer::TokenType::LITERAL_IDENT); + } } else { ASSERT(lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_MODULE); lexer_->NextToken(); + if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_AWAIT) { + lexer_->GetToken().SetTokenType(lexer::TokenType::LITERAL_IDENT); + } if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_STRING) { return ParseTsAmbientExternalModuleDeclaration(startLoc, isDeclare); } @@ -687,7 +696,8 @@ ir::TSTypeAliasDeclaration *ParserImpl::ParseTsTypeAliasDeclaration(bool isDecla lexer::SourcePosition typeStart = lexer_->GetToken().Start(); lexer_->NextToken(); // eat type keyword - if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) { + if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT && + !(lexer_->GetToken().Type() == lexer::TokenType::KEYW_AWAIT && isDeclare)) { ThrowSyntaxError("Identifier expected"); } @@ -735,16 +745,7 @@ ir::TSInterfaceDeclaration *ParserImpl::ParseTsInterfaceDeclaration(bool isDecla lexer::SourcePosition interfaceStart = lexer_->GetToken().Start(); lexer_->NextToken(); // eat interface keyword - if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) { - ThrowSyntaxError("Identifier expected"); - } - - if (lexer_->GetToken().IsReservedTypeName()) { - std::string errMsg("Interface name cannot be '"); - errMsg.append(TokenToString(lexer_->GetToken().KeywordType())); - errMsg.append("'"); - ThrowSyntaxError(errMsg.c_str()); - } + ValidateTsInterfaceName(isDeclare); const util::StringView &ident = lexer_->GetToken().Ident(); binder::TSBinding tsBinding(Allocator(), ident); @@ -774,53 +775,7 @@ ir::TSInterfaceDeclaration *ParserImpl::ParseTsInterfaceDeclaration(bool isDecla typeParamDecl = ParseTsTypeParameterDeclaration(true, true); } - ArenaVector extends(Allocator()->Adapter()); - if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_EXTENDS) { - lexer_->NextToken(); // eat extends keyword - while (true) { - if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) { - ThrowSyntaxError("Identifier expected"); - } - - const lexer::SourcePosition &heritageStart = lexer_->GetToken().Start(); - lexer::SourcePosition heritageEnd = lexer_->GetToken().End(); - ir::Expression *expr = AllocNode(lexer_->GetToken().Ident()); - expr->AsIdentifier()->SetReference(); - expr->SetRange(lexer_->GetToken().Loc()); - - if (lexer_->Lookahead() == LEX_CHAR_LESS_THAN) { - lexer_->ForwardToken(lexer::TokenType::PUNCTUATOR_LESS_THAN, 1); - } else { - lexer_->NextToken(); - } - - if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD) { - expr = ParseTsQualifiedReference(expr); - } - - ir::TSTypeParameterInstantiation *typeParamInst = nullptr; - if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) { - typeParamInst = ParseTsTypeParameterInstantiation(); - heritageEnd = typeParamInst->End(); - } - - auto *typeReference = AllocNode(expr, typeParamInst); - typeReference->SetRange({heritageStart, heritageEnd}); - auto *heritage = AllocNode(typeReference); - heritage->SetRange(typeReference->Range()); - extends.push_back(heritage); - - if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE) { - break; - } - - if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COMMA) { - ThrowSyntaxError("',' expected"); - } - - lexer_->NextToken(); - } - } + ArenaVector extends = ParseTsInterfaceExtends(); lexer::SourcePosition bodyStart = lexer_->GetToken().Start(); auto members = ParseTsTypeLiteralOrInterface(); @@ -845,6 +800,69 @@ ir::TSInterfaceDeclaration *ParserImpl::ParseTsInterfaceDeclaration(bool isDecla return interfaceDecl; } +void ParserImpl::ValidateTsInterfaceName(bool isDeclare) +{ + if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT && + !(lexer_->GetToken().Type() == lexer::TokenType::KEYW_AWAIT && isDeclare)) { + ThrowSyntaxError("Identifier expected"); + } + + if (lexer_->GetToken().IsReservedTypeName()) { + std::string errMsg("Interface name cannot be '"); + errMsg.append(TokenToString(lexer_->GetToken().KeywordType())); + errMsg.append("'"); + ThrowSyntaxError(errMsg.c_str()); + } +} + +ArenaVector ParserImpl::ParseTsInterfaceExtends() +{ + ArenaVector extends(Allocator()->Adapter()); + + if (lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_EXTENDS) { + return extends; + } + + lexer_->NextToken(); // eat extends keyword + while (true) { + if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) { + ThrowSyntaxError("Identifier expected"); + } + const lexer::SourcePosition &heritageStart = lexer_->GetToken().Start(); + lexer::SourcePosition heritageEnd = lexer_->GetToken().End(); + ir::Expression *expr = AllocNode(lexer_->GetToken().Ident()); + expr->AsIdentifier()->SetReference(); + expr->SetRange(lexer_->GetToken().Loc()); + if (lexer_->Lookahead() == LEX_CHAR_LESS_THAN) { + lexer_->ForwardToken(lexer::TokenType::PUNCTUATOR_LESS_THAN, 1); + } else { + lexer_->NextToken(); + } + if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD) { + expr = ParseTsQualifiedReference(expr); + } + ir::TSTypeParameterInstantiation *typeParamInst = nullptr; + if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) { + typeParamInst = ParseTsTypeParameterInstantiation(); + heritageEnd = typeParamInst->End(); + } + auto *typeReference = AllocNode(expr, typeParamInst); + typeReference->SetRange({heritageStart, heritageEnd}); + auto *heritage = AllocNode(typeReference); + heritage->SetRange(typeReference->Range()); + extends.push_back(heritage); + if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE) { + break; + } + if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COMMA) { + ThrowSyntaxError("',' expected"); + } + lexer_->NextToken(); + } + + return extends; +} + void ParserImpl::CheckFunctionDeclaration(StatementParsingFlags flags) { if (flags & StatementParsingFlags::ALLOW_LEXICAL) { @@ -1914,7 +1932,7 @@ ir::TryStatement *ParserImpl::ParseTryStatement() } // TODO(frobert) : merge into lexer::LexerNextTokenFlags -void ParserImpl::ValidateDeclaratorId() +void ParserImpl::ValidateDeclaratorId(bool isDeclare) { if (context_.Status() & ParserStatus::IN_AMBIENT_CONTEXT) { return; @@ -1922,7 +1940,7 @@ void ParserImpl::ValidateDeclaratorId() switch (lexer_->GetToken().KeywordType()) { case lexer::TokenType::KEYW_AWAIT: { - if (context_.IsModule() && !program_.IsDtsFile() && !context_.IsTsModule()) { + if (context_.IsModule() && !program_.IsDtsFile() && !context_.IsTsModule() && !isDeclare) { ThrowSyntaxError("'await' is not permitted as an identifier in module code"); } break; @@ -1981,53 +1999,10 @@ ir::VariableDeclarator *ParserImpl::ParseVariableDeclaratorInitializer(ir::Expre ir::VariableDeclarator *ParserImpl::ParseVariableDeclarator(VariableParsingFlags flags, bool isDeclare) { - ir::Expression *init = nullptr; lexer::SourcePosition startLoc = lexer_->GetToken().Start(); - switch (lexer_->GetToken().Type()) { - case lexer::TokenType::LITERAL_IDENT: { - ValidateDeclaratorId(); - - if (!(flags & VariableParsingFlags::VAR) && - lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_LET) { - ThrowSyntaxError("let is disallowed as a lexically bound name"); - } - - const util::StringView &identStr = lexer_->GetToken().Ident(); - init = AllocNode(identStr); - init->SetRange(lexer_->GetToken().Loc()); - - if (Extension() == ScriptExtension::TS) { - init->AsIdentifier()->SetReference(); - } - - lexer_->NextToken(); - break; - } - case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET: { - init = ParseArrayExpression(ExpressionParseFlags::MUST_BE_PATTERN); - break; - } - case lexer::TokenType::PUNCTUATOR_LEFT_BRACE: { - init = ParseObjectExpression(ExpressionParseFlags::MUST_BE_PATTERN); - break; - } - default: { - ThrowSyntaxError("Unexpected token in variable declaration"); - } - } bool isDefinite = false; - if (Extension() == ScriptExtension::TS) { - if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_EXCLAMATION_MARK) { - lexer_->NextToken(); // eat '!' - isDefinite = true; - } - if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) { - lexer_->NextToken(); // eat ':' - TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR; - init->SetTsTypeAnnotation(ParseTsTypeAnnotation(&options)); - } - } + ir::Expression *init = ParseVariableDeclaratorKey(flags, isDeclare, &isDefinite); ir::VariableDeclarator *declarator {}; @@ -2076,10 +2051,64 @@ ir::VariableDeclarator *ParserImpl::ParseVariableDeclarator(VariableParsingFlags return declarator; } +ir::Expression *ParserImpl::ParseVariableDeclaratorKey(VariableParsingFlags flags, bool isDeclare, bool *isDefinite) +{ + if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_AWAIT && isDeclare) { + lexer_->GetToken().SetTokenType(lexer::TokenType::LITERAL_IDENT); + } + + ir::Expression *init = nullptr; + switch (lexer_->GetToken().Type()) { + case lexer::TokenType::LITERAL_IDENT: { + ValidateDeclaratorId(isDeclare); + + if (!(flags & VariableParsingFlags::VAR) && + lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_LET) { + ThrowSyntaxError("let is disallowed as a lexically bound name"); + } + + const util::StringView &identStr = lexer_->GetToken().Ident(); + init = AllocNode(identStr); + init->SetRange(lexer_->GetToken().Loc()); + + if (Extension() == ScriptExtension::TS) { + init->AsIdentifier()->SetReference(); + } + + lexer_->NextToken(); + break; + } + case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET: { + init = ParseArrayExpression(ExpressionParseFlags::MUST_BE_PATTERN); + break; + } + case lexer::TokenType::PUNCTUATOR_LEFT_BRACE: { + init = ParseObjectExpression(ExpressionParseFlags::MUST_BE_PATTERN); + break; + } + default: { + ThrowSyntaxError("Unexpected token in variable declaration"); + } + } + + if (Extension() == ScriptExtension::TS) { + if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_EXCLAMATION_MARK) { + lexer_->NextToken(); // eat '!' + *isDefinite = true; + } + if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) { + lexer_->NextToken(); // eat ':' + TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR; + init->SetTsTypeAnnotation(ParseTsTypeAnnotation(&options)); + } + } + + return init; +} + ir::Statement *ParserImpl::ParseVariableDeclaration(VariableParsingFlags flags, bool isDeclare, bool isExport) { lexer::SourcePosition startLoc = lexer_->GetToken().Start(); - if (!(flags & VariableParsingFlags::NO_SKIP_VAR_KIND)) { lexer_->NextToken(); } diff --git a/es2panda/test/parser/ts/test-toplevel-await4-expected.txt b/es2panda/test/parser/ts/test-toplevel-await4-expected.txt new file mode 100644 index 0000000000..b8c2c912d5 --- /dev/null +++ b/es2panda/test/parser/ts/test-toplevel-await4-expected.txt @@ -0,0 +1,442 @@ +{ + "type": "Program", + "statements": [ + { + "type": "ExportNamedDeclaration", + "declaration": null, + "source": null, + "specifiers": [], + "loc": { + "start": { + "line": 17, + "column": 1 + }, + "end": { + "line": 17, + "column": 12 + } + } + }, + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "await", + "typeAnnotation": { + "type": "TSAnyKeyword", + "loc": { + "start": { + "line": 18, + "column": 22 + }, + "end": { + "line": 18, + "column": 25 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 15 + }, + "end": { + "line": 18, + "column": 20 + } + } + }, + "init": null, + "loc": { + "start": { + "line": 18, + "column": 15 + }, + "end": { + "line": 18, + "column": 20 + } + } + } + ], + "kind": "const", + "declare": true, + "loc": { + "start": { + "line": 18, + "column": 9 + }, + "end": { + "line": 18, + "column": 26 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "C", + "loc": { + "start": { + "line": 19, + "column": 15 + }, + "end": { + "line": 19, + "column": 16 + } + } + }, + "superClass": { + "type": "Identifier", + "name": "await", + "loc": { + "start": { + "line": 19, + "column": 25 + }, + "end": { + "line": 19, + "column": 30 + } + } + }, + "implements": [ + { + "type": "TSClassImplements", + "expression": { + "type": "Identifier", + "name": "await", + "loc": { + "start": { + "line": 19, + "column": 42 + }, + "end": { + "line": 19, + "column": 47 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 42 + }, + "end": { + "line": 19, + "column": 49 + } + } + } + ], + "constructor": { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": null, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "RestElement", + "argument": { + "type": "Identifier", + "name": "args", + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "declare": true, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 9 + }, + "end": { + "line": 21, + "column": 2 + } + } + }, + "body": [ + { + "type": "ClassProperty", + "key": { + "type": "Identifier", + "name": "await", + "loc": { + "start": { + "line": 20, + "column": 5 + }, + "end": { + "line": 20, + "column": 10 + } + } + }, + "static": false, + "readonly": false, + "declare": false, + "optional": false, + "computed": false, + "typeAnnotation": { + "type": "TSNumberKeyword", + "loc": { + "start": { + "line": 20, + "column": 12 + }, + "end": { + "line": 20, + "column": 18 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 5 + }, + "end": { + "line": 20, + "column": 10 + } + } + } + ], + "indexSignatures": [], + "loc": { + "start": { + "line": 19, + "column": 48 + }, + "end": { + "line": 21, + "column": 2 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 9 + }, + "end": { + "line": 21, + "column": 2 + } + } + }, + { + "type": "TSModuleDeclaration", + "id": { + "type": "Identifier", + "name": "await", + "loc": { + "start": { + "line": 23, + "column": 11 + }, + "end": { + "line": 23, + "column": 16 + } + } + }, + "body": { + "type": "TSModuleBlock", + "body": [], + "loc": { + "start": { + "line": 23, + "column": 17 + }, + "end": { + "line": 23, + "column": 20 + } + } + }, + "declare": false, + "global": false, + "loc": { + "start": { + "line": 23, + "column": 1 + }, + "end": { + "line": 24, + "column": 7 + } + } + }, + { + "type": "TSModuleDeclaration", + "id": { + "type": "Identifier", + "name": "await", + "loc": { + "start": { + "line": 24, + "column": 8 + }, + "end": { + "line": 24, + "column": 13 + } + } + }, + "body": { + "type": "TSModuleBlock", + "body": [], + "loc": { + "start": { + "line": 24, + "column": 14 + }, + "end": { + "line": 24, + "column": 17 + } + } + }, + "declare": false, + "global": false, + "loc": { + "start": { + "line": 24, + "column": 1 + }, + "end": { + "line": 26, + "column": 8 + } + } + }, + { + "type": "TSInterfaceDeclaration", + "body": { + "type": "TSInterfaceBody", + "body": [], + "loc": { + "start": { + "line": 26, + "column": 25 + }, + "end": { + "line": 26, + "column": 28 + } + } + }, + "id": { + "type": "Identifier", + "name": "await", + "loc": { + "start": { + "line": 26, + "column": 19 + }, + "end": { + "line": 26, + "column": 24 + } + } + }, + "extends": [], + "loc": { + "start": { + "line": 26, + "column": 9 + }, + "end": { + "line": 26, + "column": 28 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 27, + "column": 1 + } + } +} diff --git a/es2panda/test/parser/ts/test-toplevel-await4.ts b/es2panda/test/parser/ts/test-toplevel-await4.ts new file mode 100644 index 0000000000..80aaf53932 --- /dev/null +++ b/es2panda/test/parser/ts/test-toplevel-await4.ts @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2023 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 { }; +declare const await: any; +declare class C extends await implements await { + await: number; +} + +namespace await { } +module await { } + +declare interface await { } diff --git a/es2panda/test/parser/ts/test-toplevel-await5-expected.txt b/es2panda/test/parser/ts/test-toplevel-await5-expected.txt new file mode 100644 index 0000000000..39dd5fee55 --- /dev/null +++ b/es2panda/test/parser/ts/test-toplevel-await5-expected.txt @@ -0,0 +1,463 @@ +{ + "type": "Program", + "statements": [ + { + "type": "ExportNamedDeclaration", + "declaration": null, + "source": null, + "specifiers": [], + "loc": { + "start": { + "line": 17, + "column": 1 + }, + "end": { + "line": 17, + "column": 12 + } + } + }, + { + "type": "TSDeclareFunction", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "await", + "loc": { + "start": { + "line": 18, + "column": 18 + }, + "end": { + "line": 18, + "column": 23 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "declare": true, + "loc": { + "start": { + "line": 18, + "column": 9 + }, + "end": { + "line": 18, + "column": 26 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 9 + }, + "end": { + "line": 18, + "column": 26 + } + } + }, + { + "type": "TSModuleDeclaration", + "id": { + "type": "Identifier", + "name": "ns", + "loc": { + "start": { + "line": 20, + "column": 11 + }, + "end": { + "line": 20, + "column": 13 + } + } + }, + "body": { + "type": "TSModuleBlock", + "body": [ + { + "type": "TSEnumDeclaration", + "id": { + "type": "Identifier", + "name": "await", + "loc": { + "start": { + "line": 21, + "column": 10 + }, + "end": { + "line": 21, + "column": 15 + } + } + }, + "members": [ + { + "type": "TSEnumMember", + "id": { + "type": "Identifier", + "name": "await", + "loc": { + "start": { + "line": 22, + "column": 9 + }, + "end": { + "line": 22, + "column": 14 + } + } + }, + "initializer": { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 22, + "column": 17 + }, + "end": { + "line": 22, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 17 + }, + "end": { + "line": 23, + "column": 6 + } + } + } + ], + "const": false, + "loc": { + "start": { + "line": 21, + "column": 5 + }, + "end": { + "line": 23, + "column": 6 + } + } + } + ], + "loc": { + "start": { + "line": 20, + "column": 14 + }, + "end": { + "line": 24, + "column": 2 + } + } + }, + "declare": false, + "global": false, + "loc": { + "start": { + "line": 20, + "column": 1 + }, + "end": { + "line": 26, + "column": 10 + } + } + }, + { + "type": "TSModuleDeclaration", + "id": { + "type": "Identifier", + "name": "ns1", + "loc": { + "start": { + "line": 26, + "column": 11 + }, + "end": { + "line": 26, + "column": 14 + } + } + }, + "body": { + "type": "TSModuleBlock", + "body": [ + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "await", + "loc": { + "start": { + "line": 27, + "column": 19 + }, + "end": { + "line": 27, + "column": 24 + } + } + }, + "superClass": null, + "implements": [], + "constructor": { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": null, + "generator": false, + "async": false, + "expression": false, + "params": [], + "declare": true, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 27, + "column": 13 + }, + "end": { + "line": 29, + "column": 6 + } + } + }, + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "await", + "loc": { + "start": { + "line": 28, + "column": 9 + }, + "end": { + "line": 28, + "column": 14 + } + } + }, + "kind": "method", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": null, + "generator": false, + "async": false, + "expression": false, + "params": [], + "returnType": { + "type": "TSVoidKeyword", + "loc": { + "start": { + "line": 28, + "column": 18 + }, + "end": { + "line": 28, + "column": 22 + } + } + }, + "loc": { + "start": { + "line": 28, + "column": 14 + }, + "end": { + "line": 28, + "column": 23 + } + } + }, + "loc": { + "start": { + "line": 28, + "column": 14 + }, + "end": { + "line": 28, + "column": 23 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 28, + "column": 9 + }, + "end": { + "line": 28, + "column": 23 + } + } + } + ], + "indexSignatures": [], + "loc": { + "start": { + "line": 27, + "column": 25 + }, + "end": { + "line": 29, + "column": 6 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 27, + "column": 13 + }, + "end": { + "line": 29, + "column": 6 + } + } + } + ], + "loc": { + "start": { + "line": 26, + "column": 15 + }, + "end": { + "line": 30, + "column": 2 + } + } + }, + "declare": false, + "global": false, + "loc": { + "start": { + "line": 26, + "column": 1 + }, + "end": { + "line": 32, + "column": 8 + } + } + }, + { + "type": "TSTypeAliasDeclaration", + "id": { + "type": "Identifier", + "name": "await", + "loc": { + "start": { + "line": 32, + "column": 14 + }, + "end": { + "line": 32, + "column": 19 + } + } + }, + "typeAnnotation": { + "type": "TSNumberKeyword", + "loc": { + "start": { + "line": 32, + "column": 22 + }, + "end": { + "line": 32, + "column": 28 + } + } + }, + "declare": true, + "loc": { + "start": { + "line": 32, + "column": 9 + }, + "end": { + "line": 32, + "column": 29 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 33, + "column": 1 + } + } +} diff --git a/es2panda/test/parser/ts/test-toplevel-await5.ts b/es2panda/test/parser/ts/test-toplevel-await5.ts new file mode 100644 index 0000000000..351d0a13ba --- /dev/null +++ b/es2panda/test/parser/ts/test-toplevel-await5.ts @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2023 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 { }; +declare function await(); + +namespace ns { + enum await { + await = 1 + } +} + +namespace ns1 { + declare class await { + await(): void; + } +} + +declare type await = number; -- Gitee