summaryrefslogtreecommitdiff
path: root/Libraries/LibJS/Parser.cpp
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2020-03-19 11:52:56 +0100
committerAndreas Kling <kling@serenityos.org>2020-03-19 11:54:11 +0100
commit07679e347cbe58aa90ea039013c0f884cf9ee7b2 (patch)
treeff2ab3fa4aaf7cc11d9fdf23c1b9481d24fa8fd4 /Libraries/LibJS/Parser.cpp
parentb1b4c9844e63a65a19f5772c614df29015b37ce1 (diff)
downloadserenity-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/Parser.cpp')
-rw-r--r--Libraries/LibJS/Parser.cpp18
1 files changed, 14 insertions, 4 deletions
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();
}