mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-22 07:30:19 +00:00
LibJS: Parse "try", "catch" and "finally"
This is the first step towards support exceptions. :^)
This commit is contained in:
parent
404de10a15
commit
c33d4aefc3
Notes:
sideshowbarker
2024-07-19 08:10:00 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/c33d4aefc3e
5 changed files with 132 additions and 1 deletions
9
Base/home/anon/js/try.js
Normal file
9
Base/home/anon/js/try.js
Normal 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");
|
||||
}
|
|
@ -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 {};
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in a new issue