diff --git a/Libraries/LibJS/AST.h b/Libraries/LibJS/AST.h index 4b942fc8bb..5fe383a315 100644 --- a/Libraries/LibJS/AST.h +++ b/Libraries/LibJS/AST.h @@ -154,6 +154,8 @@ class FunctionDeclaration final : public Statement , public FunctionNode { public: + static bool must_have_name() { return true; } + FunctionDeclaration(String name, NonnullRefPtr body, Vector parameters = {}) : FunctionNode(move(name), move(body), move(parameters)) { @@ -169,6 +171,8 @@ private: class FunctionExpression final : public Expression , public FunctionNode { public: + static bool must_have_name() { return false; } + FunctionExpression(String name, NonnullRefPtr body, Vector parameters = {}) : FunctionNode(move(name), move(body), move(parameters)) { diff --git a/Libraries/LibJS/Parser.cpp b/Libraries/LibJS/Parser.cpp index 051fec8983..e474abb6ed 100644 --- a/Libraries/LibJS/Parser.cpp +++ b/Libraries/LibJS/Parser.cpp @@ -187,7 +187,7 @@ NonnullRefPtr Parser::parse_statement() switch (m_current_token.type()) { case TokenType::Function: - return parse_function_declaration(); + return parse_function_node(); case TokenType::CurlyOpen: return parse_block_statement(); case TokenType::Return: @@ -231,6 +231,8 @@ NonnullRefPtr Parser::parse_primary_expression() return create_ast_node(); case TokenType::CurlyOpen: return parse_object_expression(); + case TokenType::Function: + return parse_function_node(); default: m_has_errors = true; expected("primary expression (missing switch case)"); @@ -416,10 +418,17 @@ NonnullRefPtr Parser::parse_block_statement() return block; } -NonnullRefPtr Parser::parse_function_declaration() +template +NonnullRefPtr Parser::parse_function_node() { consume(TokenType::Function); - auto name = consume(TokenType::Identifier).value(); + String name; + if (FunctionNodeType::must_have_name()) { + name = consume(TokenType::Identifier).value(); + } else { + if (match(TokenType::Identifier)) + name = consume(TokenType::Identifier).value(); + } consume(TokenType::ParenOpen); Vector parameters; while (match(TokenType::Identifier)) { @@ -432,7 +441,7 @@ NonnullRefPtr Parser::parse_function_declaration() } consume(TokenType::ParenClose); auto body = parse_block_statement(); - return create_ast_node(name, move(body), move(parameters)); + return create_ast_node(name, move(body), move(parameters)); } NonnullRefPtr Parser::parse_variable_declaration() @@ -526,6 +535,7 @@ bool Parser::match_expression() const || type == TokenType::CurlyOpen || type == TokenType::BracketOpen || type == TokenType::ParenOpen + || type == TokenType::Function || match_unary_prefixed_expression(); } diff --git a/Libraries/LibJS/Parser.h b/Libraries/LibJS/Parser.h index 229c507e11..6115c9424b 100644 --- a/Libraries/LibJS/Parser.h +++ b/Libraries/LibJS/Parser.h @@ -43,10 +43,12 @@ public: NonnullRefPtr parse_program(); + template + NonnullRefPtr parse_function_node(); + NonnullRefPtr parse_statement(); NonnullRefPtr parse_block_statement(); NonnullRefPtr parse_return_statement(); - NonnullRefPtr parse_function_declaration(); NonnullRefPtr parse_variable_declaration(); NonnullRefPtr parse_for_statement();