浏览代码

LibJS: Support empty statements

We already skipped random semicolons in Parser::parse_program(), but now
they are properly matched and parsed as empty statements - and thus
recognized as a valid body of an if / else / while / ... statement.
Linus Groh 5 年之前
父节点
当前提交
32742709dc
共有 3 个文件被更改,包括 23 次插入4 次删除
  1. 6 0
      Libraries/LibJS/AST.h
  2. 6 4
      Libraries/LibJS/Parser.cpp
  3. 11 0
      Libraries/LibJS/Tests/empty-statements.js

+ 6 - 0
Libraries/LibJS/AST.h

@@ -71,6 +71,12 @@ private:
 class Statement : public ASTNode {
 };
 
+class EmptyStatement final : public Statement {
+public:
+    Value execute(Interpreter&) const override { return js_undefined(); }
+    const char* class_name() const override { return "EmptyStatement"; }
+};
+
 class ErrorStatement final : public Statement {
 public:
     Value execute(Interpreter&) const override { return js_undefined(); }

+ 6 - 4
Libraries/LibJS/Parser.cpp

@@ -206,9 +206,7 @@ NonnullRefPtr<Program> Parser::parse_program()
     ScopePusher scope(*this, ScopePusher::Var | ScopePusher::Let);
     auto program = adopt(*new Program);
     while (!done()) {
-        if (match(TokenType::Semicolon)) {
-            consume();
-        } else if (match_statement()) {
+        if (match_statement()) {
             program->append(parse_statement());
         } else {
             expected("statement");
@@ -255,6 +253,9 @@ NonnullRefPtr<Statement> Parser::parse_statement()
         return parse_while_statement();
     case TokenType::Debugger:
          return parse_debugger_statement();
+    case TokenType::Semicolon:
+        consume();
+        return create_ast_node<EmptyStatement>();
     default:
         if (match_expression()) {
             auto expr = parse_expression(0);
@@ -1176,7 +1177,8 @@ bool Parser::match_statement() const
         || type == TokenType::Break
         || type == TokenType::Continue
         || type == TokenType::Var
-        || type == TokenType::Debugger;
+        || type == TokenType::Debugger
+        || type == TokenType::Semicolon;
 }
 
 bool Parser::match_identifier_name() const

+ 11 - 0
Libraries/LibJS/Tests/empty-statements.js

@@ -0,0 +1,11 @@
+try {
+    ;;;
+    if (true);
+    if (false); else if (false); else;
+    while (false);
+    do; while (false);
+
+    console.log("PASS");
+} catch (e) {
+    console.log("FAIL: " + e);
+}