LibJS: Implement for statement
This commit is contained in:
parent
e88f2f15ee
commit
097e1af4e8
Notes:
sideshowbarker
2024-07-19 08:44:52 +09:00
Author: https://github.com/deoxxa Commit: https://github.com/SerenityOS/serenity/commit/097e1af4e87 Pull-request: https://github.com/SerenityOS/serenity/pull/1425 Reviewed-by: https://github.com/sunverwerth
6 changed files with 119 additions and 0 deletions
|
@ -105,6 +105,30 @@ Value WhileStatement::execute(Interpreter& interpreter) const
|
|||
return last_value;
|
||||
}
|
||||
|
||||
Value ForStatement::execute(Interpreter& interpreter) const
|
||||
{
|
||||
Value last_value = js_undefined();
|
||||
|
||||
if (m_init)
|
||||
m_init->execute(interpreter);
|
||||
|
||||
if (m_test) {
|
||||
while (m_test->execute(interpreter).to_boolean()) {
|
||||
last_value = interpreter.run(*m_body);
|
||||
if (m_update)
|
||||
m_update->execute(interpreter);
|
||||
}
|
||||
} else {
|
||||
while (true) {
|
||||
last_value = interpreter.run(*m_body);
|
||||
if (m_update)
|
||||
m_update->execute(interpreter);
|
||||
}
|
||||
}
|
||||
|
||||
return last_value;
|
||||
}
|
||||
|
||||
Value BinaryExpression::execute(Interpreter& interpreter) const
|
||||
{
|
||||
auto lhs_result = m_lhs->execute(interpreter);
|
||||
|
@ -362,6 +386,21 @@ void WhileStatement::dump(int indent) const
|
|||
body().dump(indent + 1);
|
||||
}
|
||||
|
||||
void ForStatement::dump(int indent) const
|
||||
{
|
||||
ASTNode::dump(indent);
|
||||
|
||||
print_indent(indent);
|
||||
printf("For\n");
|
||||
if (init())
|
||||
init()->dump(indent + 1);
|
||||
if (test())
|
||||
test()->dump(indent + 1);
|
||||
if (update())
|
||||
update()->dump(indent + 1);
|
||||
body().dump(indent + 1);
|
||||
}
|
||||
|
||||
Value Identifier::execute(Interpreter& interpreter) const
|
||||
{
|
||||
return interpreter.get_variable(string());
|
||||
|
|
|
@ -211,6 +211,33 @@ private:
|
|||
NonnullOwnPtr<ScopeNode> m_body;
|
||||
};
|
||||
|
||||
class ForStatement : public Statement {
|
||||
public:
|
||||
ForStatement(OwnPtr<Statement> init, OwnPtr<Expression> test, OwnPtr<Expression> update, NonnullOwnPtr<ScopeNode> body)
|
||||
: m_init(move(init))
|
||||
, m_test(move(test))
|
||||
, m_update(move(update))
|
||||
, m_body(move(body))
|
||||
{
|
||||
}
|
||||
|
||||
const Statement* init() const { return m_init; }
|
||||
const Expression* test() const { return m_test; }
|
||||
const Expression* update() const { return m_update; }
|
||||
const ScopeNode& body() const { return *m_body; }
|
||||
|
||||
virtual Value execute(Interpreter&) const override;
|
||||
virtual void dump(int indent) const override;
|
||||
|
||||
private:
|
||||
virtual const char* class_name() const override { return "ForStatement"; }
|
||||
|
||||
OwnPtr<Statement> m_init;
|
||||
OwnPtr<Expression> m_test;
|
||||
OwnPtr<Expression> m_update;
|
||||
NonnullOwnPtr<ScopeNode> m_body;
|
||||
};
|
||||
|
||||
enum class BinaryOp {
|
||||
Plus,
|
||||
Minus,
|
||||
|
|
|
@ -51,6 +51,7 @@ Lexer::Lexer(StringView source)
|
|||
s_keywords.set("do", TokenType::Do);
|
||||
s_keywords.set("else", TokenType::Else);
|
||||
s_keywords.set("finally", TokenType::Finally);
|
||||
s_keywords.set("for", TokenType::For);
|
||||
s_keywords.set("function", TokenType::Function);
|
||||
s_keywords.set("if", TokenType::If);
|
||||
s_keywords.set("interface", TokenType::Interface);
|
||||
|
|
|
@ -66,6 +66,8 @@ NonnullOwnPtr<Statement> Parser::parse_statement()
|
|||
return parse_return_statement();
|
||||
case TokenType::Var:
|
||||
return parse_variable_declaration();
|
||||
case TokenType::For:
|
||||
return parse_for_statement();
|
||||
default:
|
||||
m_has_errors = true;
|
||||
expected("statement (missing switch case)");
|
||||
|
@ -251,6 +253,53 @@ NonnullOwnPtr<VariableDeclaration> Parser::parse_variable_declaration()
|
|||
return make<VariableDeclaration>(make<Identifier>(name), move(initializer), DeclarationType::Var);
|
||||
}
|
||||
|
||||
NonnullOwnPtr<ForStatement> Parser::parse_for_statement()
|
||||
{
|
||||
consume(TokenType::For);
|
||||
|
||||
consume(TokenType::ParenOpen);
|
||||
|
||||
OwnPtr<Statement> init = nullptr;
|
||||
switch (m_current_token.type()) {
|
||||
case TokenType::Var:
|
||||
init = parse_variable_declaration();
|
||||
break;
|
||||
case TokenType::Semicolon:
|
||||
break;
|
||||
default:
|
||||
init = parse_statement();
|
||||
break;
|
||||
}
|
||||
|
||||
consume(TokenType::Semicolon);
|
||||
|
||||
OwnPtr<Expression> test = nullptr;
|
||||
switch (m_current_token.type()) {
|
||||
case TokenType::Semicolon:
|
||||
break;
|
||||
default:
|
||||
test = parse_expression();
|
||||
break;
|
||||
}
|
||||
|
||||
consume(TokenType::Semicolon);
|
||||
|
||||
OwnPtr<Expression> update = nullptr;
|
||||
switch (m_current_token.type()) {
|
||||
case TokenType::Semicolon:
|
||||
break;
|
||||
default:
|
||||
update = parse_expression();
|
||||
break;
|
||||
}
|
||||
|
||||
consume(TokenType::ParenClose);
|
||||
|
||||
auto body = parse_block_statement();
|
||||
|
||||
return make<ForStatement>(move(init), move(test), move(update), move(body));
|
||||
}
|
||||
|
||||
bool Parser::match(TokenType type) const
|
||||
{
|
||||
return m_current_token.type() == type;
|
||||
|
@ -306,6 +355,7 @@ bool Parser::match_statement() const
|
|||
|| type == TokenType::If
|
||||
|| type == TokenType::Try
|
||||
|| type == TokenType::While
|
||||
|| type == TokenType::For
|
||||
|| type == TokenType::Const
|
||||
|| type == TokenType::CurlyOpen
|
||||
|| type == TokenType::Var;
|
||||
|
|
|
@ -42,6 +42,7 @@ public:
|
|||
NonnullOwnPtr<ReturnStatement> parse_return_statement();
|
||||
NonnullOwnPtr<FunctionDeclaration> parse_function_declaration();
|
||||
NonnullOwnPtr<VariableDeclaration> parse_variable_declaration();
|
||||
NonnullOwnPtr<ForStatement> parse_for_statement();
|
||||
|
||||
NonnullOwnPtr<Expression> parse_expression();
|
||||
NonnullOwnPtr<Expression> parse_primary_expression();
|
||||
|
|
|
@ -58,6 +58,7 @@ enum class TokenType {
|
|||
ExclamationMarkEquals,
|
||||
ExclamationMarkEqualsEquals,
|
||||
Finally,
|
||||
For,
|
||||
Function,
|
||||
GreaterThan,
|
||||
GreaterThanEquals,
|
||||
|
|
Loading…
Add table
Reference in a new issue