summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibJS/Parser.cpp
diff options
context:
space:
mode:
authorAli Mohammad Pur <ali.mpfard@gmail.com>2021-06-11 01:38:30 +0430
committerAndreas Kling <kling@serenityos.org>2021-06-11 00:30:09 +0200
commit3234697ecacb41e15e230a450f2759f404c8b047 (patch)
tree54b9b4de011c95644a4ceb3ce694b79bdcf0ce49 /Userland/Libraries/LibJS/Parser.cpp
parentc53a86a3fe530d6adaa095944a59a8a0333be3c6 (diff)
downloadserenity-3234697ecacb41e15e230a450f2759f404c8b047.zip
LibJS: Implement generator functions (only in bytecode mode)
Diffstat (limited to 'Userland/Libraries/LibJS/Parser.cpp')
-rw-r--r--Userland/Libraries/LibJS/Parser.cpp29
1 files changed, 26 insertions, 3 deletions
diff --git a/Userland/Libraries/LibJS/Parser.cpp b/Userland/Libraries/LibJS/Parser.cpp
index c1a8051f94..bca6539426 100644
--- a/Userland/Libraries/LibJS/Parser.cpp
+++ b/Userland/Libraries/LibJS/Parser.cpp
@@ -590,9 +590,9 @@ NonnullRefPtr<ClassExpression> Parser::parse_class_expression(bool expect_class_
constructor_body->append(create_ast_node<ExpressionStatement>({ m_parser_state.m_current_token.filename(), rule_start.position(), position() }, move(super_call)));
constructor_body->add_variables(m_parser_state.m_var_scopes.last());
- constructor = create_ast_node<FunctionExpression>({ m_parser_state.m_current_token.filename(), rule_start.position(), position() }, class_name, move(constructor_body), Vector { FunctionNode::Parameter { FlyString { "args" }, nullptr, true } }, 0, NonnullRefPtrVector<VariableDeclaration>(), true);
+ constructor = create_ast_node<FunctionExpression>({ m_parser_state.m_current_token.filename(), rule_start.position(), position() }, class_name, move(constructor_body), Vector { FunctionNode::Parameter { FlyString { "args" }, nullptr, true } }, 0, NonnullRefPtrVector<VariableDeclaration>(), false, true);
} else {
- constructor = create_ast_node<FunctionExpression>({ m_parser_state.m_current_token.filename(), rule_start.position(), position() }, class_name, move(constructor_body), Vector<FunctionNode::Parameter> {}, 0, NonnullRefPtrVector<VariableDeclaration>(), true);
+ constructor = create_ast_node<FunctionExpression>({ m_parser_state.m_current_token.filename(), rule_start.position(), position() }, class_name, move(constructor_body), Vector<FunctionNode::Parameter> {}, 0, NonnullRefPtrVector<VariableDeclaration>(), false, true);
}
}
@@ -634,6 +634,7 @@ NonnullRefPtr<Expression> Parser::parse_primary_expression()
syntax_error("'super' keyword unexpected here");
return create_ast_node<SuperExpression>({ m_parser_state.m_current_token.filename(), rule_start.position(), position() });
case TokenType::Identifier: {
+ read_as_identifier:;
if (!try_parse_arrow_function_expression_failed_at_position(position())) {
auto arrow_function_result = try_parse_arrow_function_expression(false);
if (!arrow_function_result.is_null())
@@ -674,6 +675,10 @@ NonnullRefPtr<Expression> Parser::parse_primary_expression()
}
return parse_new_expression();
}
+ case TokenType::Yield:
+ if (!m_parser_state.m_in_generator_function_context)
+ goto read_as_identifier;
+ return parse_yield_expression();
default:
expected("primary expression");
consume();
@@ -1256,6 +1261,16 @@ NonnullRefPtr<NewExpression> Parser::parse_new_expression()
return create_ast_node<NewExpression>({ m_parser_state.m_current_token.filename(), rule_start.position(), position() }, move(callee), move(arguments));
}
+NonnullRefPtr<YieldExpression> Parser::parse_yield_expression()
+{
+ auto rule_start = push_start();
+ consume(TokenType::Yield);
+ RefPtr<Expression> argument;
+ if (match_expression())
+ argument = parse_expression(0);
+ return create_ast_node<YieldExpression>({ m_parser_state.m_current_token.filename(), rule_start.position(), position() }, move(argument));
+}
+
NonnullRefPtr<ReturnStatement> Parser::parse_return_statement()
{
auto rule_start = push_start();
@@ -1336,9 +1351,14 @@ NonnullRefPtr<FunctionNodeType> Parser::parse_function_node(u8 parse_options)
ScopePusher scope(*this, ScopePusher::Var | ScopePusher::Function);
+ auto is_generator = false;
String name;
if (parse_options & FunctionNodeParseOptions::CheckForFunctionAndName) {
consume(TokenType::Function);
+ is_generator = match(TokenType::Asterisk);
+ if (is_generator)
+ consume(TokenType::Asterisk);
+
if (FunctionNodeType::must_have_name() || match(TokenType::Identifier))
name = consume(TokenType::Identifier).value();
}
@@ -1351,6 +1371,7 @@ NonnullRefPtr<FunctionNodeType> Parser::parse_function_node(u8 parse_options)
function_length = parameters.size();
TemporaryChange change(m_parser_state.m_in_function_context, true);
+ TemporaryChange generator_change(m_parser_state.m_in_generator_function_context, m_parser_state.m_in_generator_function_context || is_generator);
auto old_labels_in_scope = move(m_parser_state.m_labels_in_scope);
ScopeGuard guard([&]() {
m_parser_state.m_labels_in_scope = move(old_labels_in_scope);
@@ -1360,7 +1381,7 @@ NonnullRefPtr<FunctionNodeType> Parser::parse_function_node(u8 parse_options)
auto body = parse_block_statement(is_strict);
body->add_variables(m_parser_state.m_var_scopes.last());
body->add_functions(m_parser_state.m_function_scopes.last());
- return create_ast_node<FunctionNodeType>({ m_parser_state.m_current_token.filename(), rule_start.position(), position() }, name, move(body), move(parameters), function_length, NonnullRefPtrVector<VariableDeclaration>(), is_strict);
+ return create_ast_node<FunctionNodeType>({ m_parser_state.m_current_token.filename(), rule_start.position(), position() }, name, move(body), move(parameters), function_length, NonnullRefPtrVector<VariableDeclaration>(), is_generator, is_strict);
}
Vector<FunctionNode::Parameter> Parser::parse_formal_parameters(int& function_length, u8 parse_options)
@@ -2009,6 +2030,7 @@ bool Parser::match_expression() const
|| type == TokenType::This
|| type == TokenType::Super
|| type == TokenType::RegexLiteral
+ || type == TokenType::Yield
|| match_unary_prefixed_expression();
}
@@ -2085,6 +2107,7 @@ bool Parser::match_statement() const
auto type = m_parser_state.m_current_token.type();
return match_expression()
|| type == TokenType::Return
+ || type == TokenType::Yield
|| type == TokenType::Do
|| type == TokenType::If
|| type == TokenType::Throw