Преглед на файлове

LibJS: Parse labelled statements

All statements now have an optional label string that can be null.
Matthew Olsson преди 5 години
родител
ревизия
10bf4ba3dc
променени са 4 файла, в които са добавени 44 реда и са изтрити 0 реда
  1. 6 0
      Libraries/LibJS/AST.h
  2. 24 0
      Libraries/LibJS/Parser.cpp
  3. 1 0
      Libraries/LibJS/Parser.h
  4. 13 0
      Libraries/LibJS/Tests/labels.js

+ 6 - 0
Libraries/LibJS/AST.h

@@ -70,6 +70,12 @@ private:
 };
 
 class Statement : public ASTNode {
+public:
+    const FlyString& label() const { return m_label; }
+    void set_label(FlyString string) { m_label = string; }
+
+protected:
+    FlyString m_label;
 };
 
 class EmptyStatement final : public Statement {

+ 24 - 0
Libraries/LibJS/Parser.cpp

@@ -269,6 +269,9 @@ NonnullRefPtr<Statement> Parser::parse_statement()
         consume();
         return create_ast_node<EmptyStatement>();
     default:
+        auto result = try_parse_labelled_statement();
+        if (!result.is_null())
+            return result.release_nonnull();
         if (match_expression()) {
             auto expr = parse_expression(0);
             consume_or_insert_semicolon();
@@ -383,6 +386,27 @@ RefPtr<FunctionExpression> Parser::try_parse_arrow_function_expression(bool expe
     return nullptr;
 }
 
+RefPtr<Statement> Parser::try_parse_labelled_statement()
+{
+    save_state();
+    ArmedScopeGuard state_rollback_guard = [&] {
+        load_state();
+    };
+
+    auto identifier = consume(TokenType::Identifier).value();
+    if (!match(TokenType::Colon))
+        return {};
+    consume(TokenType::Colon);
+
+    if (!match_statement())
+        return {};
+    auto statement = parse_statement();
+
+    statement->set_label(identifier);
+    state_rollback_guard.disarm();
+    return statement;
+}
+
 NonnullRefPtr<Expression> Parser::parse_primary_expression()
 {
     if (match_unary_prefixed_expression())

+ 1 - 0
Libraries/LibJS/Parser.h

@@ -78,6 +78,7 @@ public:
     NonnullRefPtr<CallExpression> parse_call_expression(NonnullRefPtr<Expression>);
     NonnullRefPtr<NewExpression> parse_new_expression();
     RefPtr<FunctionExpression> try_parse_arrow_function_expression(bool expect_parens);
+    RefPtr<Statement> try_parse_labelled_statement();
 
     struct Error {
         String message;

+ 13 - 0
Libraries/LibJS/Tests/labels.js

@@ -0,0 +1,13 @@
+load("test-common.js");
+
+try {
+    test:
+    {
+        let o = 1;
+        assert(o === 1);
+    }
+
+    console.log("PASS");
+} catch (e) {
+    console.log("FAIL: " + e);
+}