diff options
-rw-r--r-- | Base/home/anon/js/try.js | 9 | ||||
-rw-r--r-- | Libraries/LibJS/AST.cpp | 40 | ||||
-rw-r--r-- | Libraries/LibJS/AST.h | 45 | ||||
-rw-r--r-- | Libraries/LibJS/Parser.cpp | 37 | ||||
-rw-r--r-- | Libraries/LibJS/Parser.h | 2 |
5 files changed, 132 insertions, 1 deletions
diff --git a/Base/home/anon/js/try.js b/Base/home/anon/js/try.js new file mode 100644 index 0000000000..26e950aa06 --- /dev/null +++ b/Base/home/anon/js/try.js @@ -0,0 +1,9 @@ +try { + console.log("you should see me"); + foo(); + console.log("not me"); +} catch (e) { + console.log("catch"); +} finally { + console.log("finally"); +} diff --git a/Libraries/LibJS/AST.cpp b/Libraries/LibJS/AST.cpp index f89b3b0f5a..936f48d18c 100644 --- a/Libraries/LibJS/AST.cpp +++ b/Libraries/LibJS/AST.cpp @@ -715,4 +715,44 @@ Value ArrayExpression::execute(Interpreter& interpreter) const return array; } +void TryStatement::dump(int indent) const +{ + ASTNode::dump(indent); + print_indent(indent); + printf("(Block)\n"); + block().dump(indent + 1); + + if (handler()) { + print_indent(indent); + printf("(Handler)\n"); + handler()->dump(indent + 1); + } + + if (finalizer()) { + print_indent(indent); + printf("(Finalizer)\n"); + finalizer()->dump(indent + 1); + } +} + +void CatchClause::dump(int indent) const +{ + print_indent(indent); + printf("CatchClause"); + if (!m_parameter.is_null()) + printf(" (%s)", m_parameter.characters()); + printf("\n"); + body().dump(indent + 1); +} + +Value TryStatement::execute(Interpreter&) const +{ + return {}; +} + +Value CatchClause::execute(Interpreter&) const +{ + return {}; +} + } diff --git a/Libraries/LibJS/AST.h b/Libraries/LibJS/AST.h index d52335be8e..6a8e3f9f9c 100644 --- a/Libraries/LibJS/AST.h +++ b/Libraries/LibJS/AST.h @@ -630,4 +630,49 @@ private: bool m_computed { false }; }; +class CatchClause final : public ASTNode { +public: + CatchClause(const FlyString& parameter, NonnullRefPtr<BlockStatement> body) + : m_parameter(parameter) + , m_body(move(body)) + { + } + + const FlyString& parameter() const { return m_parameter; } + const BlockStatement& body() const { return m_body; } + + virtual void dump(int indent) const override; + virtual Value execute(Interpreter&) const override; + +private: + virtual const char* class_name() const override { return "CatchClause"; } + + FlyString m_parameter; + NonnullRefPtr<BlockStatement> m_body; +}; + +class TryStatement final : public Statement { +public: + TryStatement(NonnullRefPtr<BlockStatement> block, RefPtr<CatchClause> handler, RefPtr<BlockStatement> finalizer) + : m_block(move(block)) + , m_handler(move(handler)) + , m_finalizer(move(finalizer)) + { + } + + const BlockStatement& block() const { return m_block; } + const CatchClause* handler() const { return m_handler; } + const BlockStatement* finalizer() const { return m_finalizer; } + + virtual void dump(int indent) const override; + virtual Value execute(Interpreter&) const override; + +private: + virtual const char* class_name() const override { return "TryStatement"; } + + NonnullRefPtr<BlockStatement> m_block; + RefPtr<CatchClause> m_handler; + RefPtr<BlockStatement> m_finalizer; +}; + } diff --git a/Libraries/LibJS/Parser.cpp b/Libraries/LibJS/Parser.cpp index 082f83f457..77e892e553 100644 --- a/Libraries/LibJS/Parser.cpp +++ b/Libraries/LibJS/Parser.cpp @@ -197,6 +197,8 @@ NonnullRefPtr<Statement> Parser::parse_statement() return parse_for_statement(); case TokenType::If: return parse_if_statement(); + case TokenType::Try: + return parse_try_statement(); default: if (match_expression()) return adopt(*new ExpressionStatement(parse_expression(0))); @@ -518,6 +520,40 @@ NonnullRefPtr<VariableDeclaration> Parser::parse_variable_declaration() return create_ast_node<VariableDeclaration>(create_ast_node<Identifier>(name), move(initializer), declaration_type); } +NonnullRefPtr<TryStatement> Parser::parse_try_statement() +{ + consume(TokenType::Try); + + auto block = parse_block_statement(); + + RefPtr<CatchClause> handler; + if (match(TokenType::Catch)) + handler = parse_catch_clause(); + + RefPtr<BlockStatement> finalizer; + if (match(TokenType::Finally)) { + consume(); + finalizer = parse_block_statement(); + } + + return create_ast_node<TryStatement>(move(block), move(handler), move(finalizer)); +} + +NonnullRefPtr<CatchClause> Parser::parse_catch_clause() +{ + consume(TokenType::Catch); + + String parameter; + if (match(TokenType::ParenOpen)) { + consume(); + parameter = consume(TokenType::Identifier).value(); + consume(TokenType::ParenClose); + } + + auto body = parse_block_statement(); + return create_ast_node<CatchClause>(parameter, move(body)); +} + NonnullRefPtr<IfStatement> Parser::parse_if_statement() { consume(TokenType::If); @@ -660,7 +696,6 @@ bool Parser::match_statement() const || type == TokenType::Function || type == TokenType::Return || type == TokenType::Let - || type == TokenType::Catch || type == TokenType::Class || type == TokenType::Delete || type == TokenType::Do diff --git a/Libraries/LibJS/Parser.h b/Libraries/LibJS/Parser.h index 4634a02b7f..7d131347b7 100644 --- a/Libraries/LibJS/Parser.h +++ b/Libraries/LibJS/Parser.h @@ -52,6 +52,8 @@ public: NonnullRefPtr<VariableDeclaration> parse_variable_declaration(); NonnullRefPtr<ForStatement> parse_for_statement(); NonnullRefPtr<IfStatement> parse_if_statement(); + NonnullRefPtr<TryStatement> parse_try_statement(); + NonnullRefPtr<CatchClause> parse_catch_clause(); NonnullRefPtr<Expression> parse_expression(int min_precedence, Associativity associate = Associativity::Right); NonnullRefPtr<Expression> parse_primary_expression(); |