mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 16:17:45 +00:00
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!"); });
This commit is contained in:
parent
b1b4c9844e
commit
07679e347c
3 changed files with 21 additions and 5 deletions
|
@ -154,6 +154,8 @@ class FunctionDeclaration final
|
||||||
: public Statement
|
: public Statement
|
||||||
, public FunctionNode {
|
, public FunctionNode {
|
||||||
public:
|
public:
|
||||||
|
static bool must_have_name() { return true; }
|
||||||
|
|
||||||
FunctionDeclaration(String name, NonnullRefPtr<ScopeNode> body, Vector<String> parameters = {})
|
FunctionDeclaration(String name, NonnullRefPtr<ScopeNode> body, Vector<String> parameters = {})
|
||||||
: FunctionNode(move(name), move(body), move(parameters))
|
: FunctionNode(move(name), move(body), move(parameters))
|
||||||
{
|
{
|
||||||
|
@ -169,6 +171,8 @@ private:
|
||||||
class FunctionExpression final : public Expression
|
class FunctionExpression final : public Expression
|
||||||
, public FunctionNode {
|
, public FunctionNode {
|
||||||
public:
|
public:
|
||||||
|
static bool must_have_name() { return false; }
|
||||||
|
|
||||||
FunctionExpression(String name, NonnullRefPtr<ScopeNode> body, Vector<String> parameters = {})
|
FunctionExpression(String name, NonnullRefPtr<ScopeNode> body, Vector<String> parameters = {})
|
||||||
: FunctionNode(move(name), move(body), move(parameters))
|
: FunctionNode(move(name), move(body), move(parameters))
|
||||||
{
|
{
|
||||||
|
|
|
@ -187,7 +187,7 @@ NonnullRefPtr<Statement> Parser::parse_statement()
|
||||||
|
|
||||||
switch (m_current_token.type()) {
|
switch (m_current_token.type()) {
|
||||||
case TokenType::Function:
|
case TokenType::Function:
|
||||||
return parse_function_declaration();
|
return parse_function_node<FunctionDeclaration>();
|
||||||
case TokenType::CurlyOpen:
|
case TokenType::CurlyOpen:
|
||||||
return parse_block_statement();
|
return parse_block_statement();
|
||||||
case TokenType::Return:
|
case TokenType::Return:
|
||||||
|
@ -231,6 +231,8 @@ NonnullRefPtr<Expression> Parser::parse_primary_expression()
|
||||||
return create_ast_node<UndefinedLiteral>();
|
return create_ast_node<UndefinedLiteral>();
|
||||||
case TokenType::CurlyOpen:
|
case TokenType::CurlyOpen:
|
||||||
return parse_object_expression();
|
return parse_object_expression();
|
||||||
|
case TokenType::Function:
|
||||||
|
return parse_function_node<FunctionExpression>();
|
||||||
default:
|
default:
|
||||||
m_has_errors = true;
|
m_has_errors = true;
|
||||||
expected("primary expression (missing switch case)");
|
expected("primary expression (missing switch case)");
|
||||||
|
@ -416,10 +418,17 @@ NonnullRefPtr<BlockStatement> Parser::parse_block_statement()
|
||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
|
|
||||||
NonnullRefPtr<FunctionDeclaration> Parser::parse_function_declaration()
|
template<typename FunctionNodeType>
|
||||||
|
NonnullRefPtr<FunctionNodeType> Parser::parse_function_node()
|
||||||
{
|
{
|
||||||
consume(TokenType::Function);
|
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);
|
consume(TokenType::ParenOpen);
|
||||||
Vector<String> parameters;
|
Vector<String> parameters;
|
||||||
while (match(TokenType::Identifier)) {
|
while (match(TokenType::Identifier)) {
|
||||||
|
@ -432,7 +441,7 @@ NonnullRefPtr<FunctionDeclaration> Parser::parse_function_declaration()
|
||||||
}
|
}
|
||||||
consume(TokenType::ParenClose);
|
consume(TokenType::ParenClose);
|
||||||
auto body = parse_block_statement();
|
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()
|
NonnullRefPtr<VariableDeclaration> Parser::parse_variable_declaration()
|
||||||
|
@ -526,6 +535,7 @@ bool Parser::match_expression() const
|
||||||
|| type == TokenType::CurlyOpen
|
|| type == TokenType::CurlyOpen
|
||||||
|| type == TokenType::BracketOpen
|
|| type == TokenType::BracketOpen
|
||||||
|| type == TokenType::ParenOpen
|
|| type == TokenType::ParenOpen
|
||||||
|
|| type == TokenType::Function
|
||||||
|| match_unary_prefixed_expression();
|
|| match_unary_prefixed_expression();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,10 +43,12 @@ public:
|
||||||
|
|
||||||
NonnullRefPtr<Program> parse_program();
|
NonnullRefPtr<Program> parse_program();
|
||||||
|
|
||||||
|
template<typename FunctionNodeType>
|
||||||
|
NonnullRefPtr<FunctionNodeType> parse_function_node();
|
||||||
|
|
||||||
NonnullRefPtr<Statement> parse_statement();
|
NonnullRefPtr<Statement> parse_statement();
|
||||||
NonnullRefPtr<BlockStatement> parse_block_statement();
|
NonnullRefPtr<BlockStatement> parse_block_statement();
|
||||||
NonnullRefPtr<ReturnStatement> parse_return_statement();
|
NonnullRefPtr<ReturnStatement> parse_return_statement();
|
||||||
NonnullRefPtr<FunctionDeclaration> parse_function_declaration();
|
|
||||||
NonnullRefPtr<VariableDeclaration> parse_variable_declaration();
|
NonnullRefPtr<VariableDeclaration> parse_variable_declaration();
|
||||||
NonnullRefPtr<ForStatement> parse_for_statement();
|
NonnullRefPtr<ForStatement> parse_for_statement();
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue