diff options
author | Andreas Kling <kling@serenityos.org> | 2020-11-28 15:05:57 +0100 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-11-28 17:16:48 +0100 |
commit | d617120499fd243dd52fa2e2db8a2183a7054b98 (patch) | |
tree | 0b7bf8e8ac5fc9fbc2201cd002d8f3f9c2aa6970 | |
parent | 98f2da9834e80b125983fe59c804e39bc362f7ce (diff) | |
download | serenity-d617120499fd243dd52fa2e2db8a2183a7054b98.zip |
LibJS: Parse "with" statements :^)
-rw-r--r-- | Libraries/LibJS/AST.cpp | 17 | ||||
-rw-r--r-- | Libraries/LibJS/AST.h | 21 | ||||
-rw-r--r-- | Libraries/LibJS/Parser.cpp | 16 | ||||
-rw-r--r-- | Libraries/LibJS/Parser.h | 1 |
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 = {}); |