LibJS: Parse "try", "catch" and "finally"

This is the first step towards support exceptions. :^)
This commit is contained in:
Andreas Kling 2020-03-24 14:03:55 +01:00
parent 404de10a15
commit c33d4aefc3
Notes: sideshowbarker 2024-07-19 08:10:00 +09:00
5 changed files with 132 additions and 1 deletions

9
Base/home/anon/js/try.js Normal file
View file

@ -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");
}

View file

@ -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 {};
}
}

View file

@ -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;
};
}

View file

@ -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

View file

@ -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();