diff --git a/es2panda/compiler/core/dynamicContext.cpp b/es2panda/compiler/core/dynamicContext.cpp index 73e9e9ddcb08b589c09a48c9d822fe1497086fb4..f4402d572dbb1f83c5883664152aaac04e48e80a 100644 --- a/es2panda/compiler/core/dynamicContext.cpp +++ b/es2panda/compiler/core/dynamicContext.cpp @@ -36,7 +36,7 @@ DynamicContext::~DynamicContext() LabelContext::LabelContext(PandaGen *pg, const ir::LabelledStatement *labelledStmt) : DynamicContext(pg, LabelTarget(labelledStmt->Ident()->Name())), labelledStmt_(labelledStmt) { - if (!labelledStmt->Body()->IsBlockStatement()) { + if (!labelledStmt->Body()->IsBlockStatement() && !labelledStmt->Body()->IsIfStatement()) { return; } diff --git a/es2panda/parser/context/parserContext.h b/es2panda/parser/context/parserContext.h index 757a3d5be8ed1d6600a9a3da6fcdd3f53dc537b9..95d9743ee52981b64a578ad6e60951b8274d852a 100644 --- a/es2panda/parser/context/parserContext.h +++ b/es2panda/parser/context/parserContext.h @@ -59,6 +59,7 @@ enum class ParserStatus { IN_AMBIENT_CONTEXT = (1 << 24), IN_CLASS_BODY = (1 << 25), IN_DECORATOR = (1 << 26), + DISALLOW_CONTINUE = (1 << 27), }; DEFINE_BITOPS(ParserStatus) diff --git a/es2panda/parser/parserImpl.h b/es2panda/parser/parserImpl.h index e73468a66427f1e910a1fc4261bc6cc2c7e85ebe..9a4d37a1e9452ec9ceb7e138ae9fcad92767ae2d 100644 --- a/es2panda/parser/parserImpl.h +++ b/es2panda/parser/parserImpl.h @@ -392,6 +392,8 @@ private: void CheckLabelledFunction(const ir::Statement *node); void CheckDeclare(); + bool IsLabelFollowedByIterationStatement(); + bool ParseDirective(ArenaVector *statements); void ParseDirectivePrologue(ArenaVector *statements); ArenaVector ParseStatementList(StatementParsingFlags flags = StatementParsingFlags::ALLOW_LEXICAL); diff --git a/es2panda/parser/statementParser.cpp b/es2panda/parser/statementParser.cpp index c1e63e01d48f552c25d9f51ea0a9d6d625c6ff3a..7a0df02cc9e60065d9a342e28fb8ce1c6145dff4 100644 --- a/es2panda/parser/statementParser.cpp +++ b/es2panda/parser/statementParser.cpp @@ -116,6 +116,27 @@ void ParserImpl::CheckDeclare() } } +bool ParserImpl::IsLabelFollowedByIterationStatement() +{ + lexer_->NextToken(); + + switch (lexer_->GetToken().Type()) { + case lexer::TokenType::KEYW_DO: + case lexer::TokenType::KEYW_FOR: + case lexer::TokenType::KEYW_WHILE: { + return true; + } + case lexer::TokenType::LITERAL_IDENT: { + if (lexer_->Lookahead() == LEX_CHAR_COLON) { + lexer_->NextToken(); + return IsLabelFollowedByIterationStatement(); + } + } + default: + return false; + } + return false; +} ir::Statement *ParserImpl::ParseStatement(StatementParsingFlags flags) { bool isDeclare = false; @@ -877,7 +898,8 @@ ir::ContinueStatement *ParserImpl::ParseContinueStatement() const auto &label = lexer_->GetToken().Ident(); const ParserContext *labelCtx = context_.FindLabel(label); - if (!labelCtx || !(labelCtx->Status() & ParserStatus::IN_ITERATION)) { + if (!labelCtx || !(labelCtx->Status() & ParserStatus::IN_ITERATION) || + (labelCtx->Status() & ParserStatus::DISALLOW_CONTINUE)) { ThrowSyntaxError("Undefined label"); } @@ -1345,6 +1367,10 @@ ir::IfStatement *ParserImpl::ParseIfStatement() ir::LabelledStatement *ParserImpl::ParseLabelledStatement(const lexer::LexerPosition &pos) { + const auto savedPos = lexer_->Save(); + bool isLabelFollowedByIterationStatement = IsLabelFollowedByIterationStatement(); + lexer_->Rewind(savedPos); + const util::StringView &actualLabel = pos.token.Ident(); // TODO(frobert) : check correctness @@ -1356,7 +1382,12 @@ ir::LabelledStatement *ParserImpl::ParseLabelledStatement(const lexer::LexerPosi ThrowSyntaxError("Label already declared", pos.token.Start()); } - SavedParserContext newCtx(this, ParserStatus::IN_LABELED, actualLabel); + SavedParserContext newCtx(this, ParserStatus::IN_LABELED | context_.Status(), actualLabel); + if (isLabelFollowedByIterationStatement) { + context_.Status() &= ~ParserStatus::DISALLOW_CONTINUE; + } else { + context_.Status() |= ParserStatus::DISALLOW_CONTINUE; + } auto *identNode = AllocNode(actualLabel, Allocator()); identNode->SetRange(pos.token.Loc());