summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2020-11-28 15:05:57 +0100
committerAndreas Kling <kling@serenityos.org>2020-11-28 17:16:48 +0100
commitd617120499fd243dd52fa2e2db8a2183a7054b98 (patch)
tree0b7bf8e8ac5fc9fbc2201cd002d8f3f9c2aa6970
parent98f2da9834e80b125983fe59c804e39bc362f7ce (diff)
downloadserenity-d617120499fd243dd52fa2e2db8a2183a7054b98.zip
LibJS: Parse "with" statements :^)
-rw-r--r--Libraries/LibJS/AST.cpp17
-rw-r--r--Libraries/LibJS/AST.h21
-rw-r--r--Libraries/LibJS/Parser.cpp16
-rw-r--r--Libraries/LibJS/Parser.h1
4 files changed, 55 insertions, 0 deletions
diff --git a/Libraries/LibJS/AST.cpp b/Libraries/LibJS/AST.cpp
index c57abaea10..e8880cd402 100644
--- a/Libraries/LibJS/AST.cpp
+++ b/Libraries/LibJS/AST.cpp
@@ -255,6 +255,11 @@ Value IfStatement::execute(Interpreter& interpreter, GlobalObject& global_object
return js_undefined();
}
+Value WithStatement::execute(Interpreter&, GlobalObject&) const
+{
+ ASSERT_NOT_REACHED();
+}
+
Value WhileStatement::execute(Interpreter& interpreter, GlobalObject& global_object) const
{
Value last_value = js_undefined();
@@ -1142,6 +1147,18 @@ void WhileStatement::dump(int indent) const
body().dump(indent + 1);
}
+void WithStatement::dump(int indent) const
+{
+ ASTNode::dump(indent);
+
+ print_indent(indent + 1);
+ printf("Object\n");
+ object().dump(indent + 2);
+ print_indent(indent + 1);
+ printf("Body\n");
+ body().dump(indent + 2);
+}
+
void DoWhileStatement::dump(int indent) const
{
ASTNode::dump(indent);
diff --git a/Libraries/LibJS/AST.h b/Libraries/LibJS/AST.h
index 9f5a8deb61..51360fb4b8 100644
--- a/Libraries/LibJS/AST.h
+++ b/Libraries/LibJS/AST.h
@@ -351,6 +351,27 @@ private:
NonnullRefPtr<Statement> m_body;
};
+class WithStatement final : public Statement {
+public:
+ WithStatement(NonnullRefPtr<Expression> object, NonnullRefPtr<Statement> body)
+ : m_object(move(object))
+ , m_body(move(body))
+ {
+ }
+
+ const Expression& object() const { return *m_object; }
+ const Statement& body() const { return *m_body; }
+
+ virtual Value execute(Interpreter&, GlobalObject&) const override;
+ virtual void dump(int indent) const override;
+
+private:
+ virtual const char* class_name() const override { return "WithStatement"; }
+
+ NonnullRefPtr<Expression> m_object;
+ NonnullRefPtr<Statement> m_body;
+};
+
class ForStatement final : public Statement {
public:
ForStatement(RefPtr<ASTNode> init, RefPtr<Expression> test, RefPtr<Expression> update, NonnullRefPtr<Statement> body)
diff --git a/Libraries/LibJS/Parser.cpp b/Libraries/LibJS/Parser.cpp
index b04530ff8f..1596e64651 100644
--- a/Libraries/LibJS/Parser.cpp
+++ b/Libraries/LibJS/Parser.cpp
@@ -327,6 +327,8 @@ NonnullRefPtr<Statement> Parser::parse_statement()
return parse_do_while_statement();
case TokenType::While:
return parse_while_statement();
+ case TokenType::With:
+ return parse_with_statement();
case TokenType::Debugger:
return parse_debugger_statement();
case TokenType::Semicolon:
@@ -1580,6 +1582,19 @@ NonnullRefPtr<SwitchStatement> Parser::parse_switch_statement()
return create_ast_node<SwitchStatement>(move(determinant), move(cases));
}
+NonnullRefPtr<WithStatement> Parser::parse_with_statement()
+{
+ consume(TokenType::With);
+ consume(TokenType::ParenOpen);
+
+ auto object = parse_expression(0);
+
+ consume(TokenType::ParenClose);
+
+ auto body = parse_statement();
+ return create_ast_node<WithStatement>(move(object), move(body));
+}
+
NonnullRefPtr<SwitchCase> Parser::parse_switch_case()
{
RefPtr<Expression> test;
@@ -1847,6 +1862,7 @@ bool Parser::match_statement() const
|| type == TokenType::Throw
|| type == TokenType::Try
|| type == TokenType::While
+ || type == TokenType::With
|| type == TokenType::For
|| type == TokenType::CurlyOpen
|| type == TokenType::Switch
diff --git a/Libraries/LibJS/Parser.h b/Libraries/LibJS/Parser.h
index ac719569cf..2672eca4d8 100644
--- a/Libraries/LibJS/Parser.h
+++ b/Libraries/LibJS/Parser.h
@@ -79,6 +79,7 @@ public:
NonnullRefPtr<ContinueStatement> parse_continue_statement();
NonnullRefPtr<DoWhileStatement> parse_do_while_statement();
NonnullRefPtr<WhileStatement> parse_while_statement();
+ NonnullRefPtr<WithStatement> parse_with_statement();
NonnullRefPtr<DebuggerStatement> parse_debugger_statement();
NonnullRefPtr<ConditionalExpression> parse_conditional_expression(NonnullRefPtr<Expression> test);
NonnullRefPtr<Expression> parse_expression(int min_precedence, Associativity associate = Associativity::Right, Vector<TokenType> forbidden = {});