diff options
author | Andreas Kling <kling@serenityos.org> | 2020-03-19 11:52:56 +0100 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-03-19 11:54:11 +0100 |
commit | 07679e347cbe58aa90ea039013c0f884cf9ee7b2 (patch) | |
tree | ff2ab3fa4aaf7cc11d9fdf23c1b9481d24fa8fd4 /Libraries/LibJS | |
parent | b1b4c9844e63a65a19f5772c614df29015b37ce1 (diff) | |
download | serenity-07679e347cbe58aa90ea039013c0f884cf9ee7b2.zip |
LibJS: Parse FunctionExpressions
FunctionExpression is mostly like FunctionDeclaration, except the name
is optional. Share the parsing logic in parse_function_node<NodeType>.
This allows us to do nice things like:
document.addEventListener("DOMContentLoaded", function() {
alert("Hello friends!");
});
Diffstat (limited to 'Libraries/LibJS')
-rw-r--r-- | Libraries/LibJS/AST.h | 4 | ||||
-rw-r--r-- | Libraries/LibJS/Parser.cpp | 18 | ||||
-rw-r--r-- | Libraries/LibJS/Parser.h | 4 |
3 files changed, 21 insertions, 5 deletions
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<ScopeNode> body, Vector<String> 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<ScopeNode> body, Vector<String> 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<Statement> Parser::parse_statement() switch (m_current_token.type()) { case TokenType::Function: - return parse_function_declaration(); + return parse_function_node<FunctionDeclaration>(); case TokenType::CurlyOpen: return parse_block_statement(); case TokenType::Return: @@ -231,6 +231,8 @@ NonnullRefPtr<Expression> Parser::parse_primary_expression() return create_ast_node<UndefinedLiteral>(); case TokenType::CurlyOpen: return parse_object_expression(); + case TokenType::Function: + return parse_function_node<FunctionExpression>(); default: m_has_errors = true; expected("primary expression (missing switch case)"); @@ -416,10 +418,17 @@ NonnullRefPtr<BlockStatement> Parser::parse_block_statement() return block; } -NonnullRefPtr<FunctionDeclaration> Parser::parse_function_declaration() +template<typename FunctionNodeType> +NonnullRefPtr<FunctionNodeType> 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<String> parameters; while (match(TokenType::Identifier)) { @@ -432,7 +441,7 @@ NonnullRefPtr<FunctionDeclaration> Parser::parse_function_declaration() } consume(TokenType::ParenClose); auto body = parse_block_statement(); - return create_ast_node<FunctionDeclaration>(name, move(body), move(parameters)); + return create_ast_node<FunctionNodeType>(name, move(body), move(parameters)); } NonnullRefPtr<VariableDeclaration> 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<Program> parse_program(); + template<typename FunctionNodeType> + NonnullRefPtr<FunctionNodeType> parse_function_node(); + NonnullRefPtr<Statement> parse_statement(); NonnullRefPtr<BlockStatement> parse_block_statement(); NonnullRefPtr<ReturnStatement> parse_return_statement(); - NonnullRefPtr<FunctionDeclaration> parse_function_declaration(); NonnullRefPtr<VariableDeclaration> parse_variable_declaration(); NonnullRefPtr<ForStatement> parse_for_statement(); |