summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Base/home/anon/js/try.js9
-rw-r--r--Libraries/LibJS/AST.cpp40
-rw-r--r--Libraries/LibJS/AST.h45
-rw-r--r--Libraries/LibJS/Parser.cpp37
-rw-r--r--Libraries/LibJS/Parser.h2
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();