diff --git a/Libraries/LibJS/AST.h b/Libraries/LibJS/AST.h index c41c0050d6..338facf098 100644 --- a/Libraries/LibJS/AST.h +++ b/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(); } diff --git a/Libraries/LibJS/Parser.cpp b/Libraries/LibJS/Parser.cpp index c73b267a1a..10383c57fb 100644 --- a/Libraries/LibJS/Parser.cpp +++ b/Libraries/LibJS/Parser.cpp @@ -206,9 +206,7 @@ NonnullRefPtr 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 Parser::parse_statement() return parse_while_statement(); case TokenType::Debugger: return parse_debugger_statement(); + case TokenType::Semicolon: + consume(); + return create_ast_node(); 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 diff --git a/Libraries/LibJS/Tests/empty-statements.js b/Libraries/LibJS/Tests/empty-statements.js new file mode 100644 index 0000000000..9cde4241b7 --- /dev/null +++ b/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); +}