Browse Source

LibJS: Parse labels in continue and break statements

Matthew Olsson 5 years ago
parent
commit
03615a7872
2 changed files with 32 additions and 6 deletions
  1. 16 2
      Libraries/LibJS/AST.h
  2. 16 4
      Libraries/LibJS/Parser.cpp

+ 16 - 2
Libraries/LibJS/AST.h

@@ -1048,22 +1048,36 @@ private:
 
 class BreakStatement final : public Statement {
 public:
-    BreakStatement() { }
+    BreakStatement(FlyString target_label)
+        : m_target_label(target_label)
+    {
+    }
 
     virtual Value execute(Interpreter&) const override;
 
+    const FlyString& target_label() const { return m_target_label; }
+
 private:
     virtual const char* class_name() const override { return "BreakStatement"; }
+
+    FlyString m_target_label;
 };
 
 class ContinueStatement final : public Statement {
 public:
-    ContinueStatement() { }
+    ContinueStatement(FlyString target_label)
+        : m_target_label(target_label)
+    {
+    }
 
     virtual Value execute(Interpreter&) const override;
 
+    const FlyString& target_label() const { return m_target_label; }
+
 private:
     virtual const char* class_name() const override { return "ContinueStatement"; }
+
+    FlyString m_target_label;
 };
 
 class DebuggerStatement final : public Statement {

+ 16 - 4
Libraries/LibJS/Parser.cpp

@@ -1112,17 +1112,29 @@ NonnullRefPtr<ThrowStatement> Parser::parse_throw_statement()
 NonnullRefPtr<BreakStatement> Parser::parse_break_statement()
 {
     consume(TokenType::Break);
+    FlyString target_label;
+    if (match(TokenType::Semicolon)) {
+        consume();
+        return create_ast_node<BreakStatement>(target_label);
+    }
+    if (match_identifier_name() && !m_parser_state.m_current_token.trivia().contains('\n'))
+        target_label = consume().value();
     consume_or_insert_semicolon();
-    // FIXME: Handle labels. When fixing this, take care to correctly implement semicolon insertion
-    return create_ast_node<BreakStatement>();
+    return create_ast_node<BreakStatement>(target_label);
 }
 
 NonnullRefPtr<ContinueStatement> Parser::parse_continue_statement()
 {
     consume(TokenType::Continue);
+    FlyString target_label;
+    if (match(TokenType::Semicolon)) {
+        consume();
+        return create_ast_node<ContinueStatement>(target_label);
+    }
+    if (match_identifier_name() && !m_parser_state.m_current_token.trivia().contains('\n'))
+        target_label = consume().value();
     consume_or_insert_semicolon();
-    // FIXME: Handle labels. When fixing this, take care to correctly implement semicolon insertion
-    return create_ast_node<ContinueStatement>();
+    return create_ast_node<ContinueStatement>(target_label);
 }
 
 NonnullRefPtr<ConditionalExpression> Parser::parse_conditional_expression(NonnullRefPtr<Expression> test)