mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 04:28:13 +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
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;
|
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 };
|
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();
|
return parse_for_statement();
|
||||||
case TokenType::If:
|
case TokenType::If:
|
||||||
return parse_if_statement();
|
return parse_if_statement();
|
||||||
|
case TokenType::Try:
|
||||||
|
return parse_try_statement();
|
||||||
default:
|
default:
|
||||||
if (match_expression())
|
if (match_expression())
|
||||||
return adopt(*new ExpressionStatement(parse_expression(0)));
|
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);
|
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()
|
NonnullRefPtr<IfStatement> Parser::parse_if_statement()
|
||||||
{
|
{
|
||||||
consume(TokenType::If);
|
consume(TokenType::If);
|
||||||
|
@ -660,7 +696,6 @@ bool Parser::match_statement() const
|
||||||
|| type == TokenType::Function
|
|| type == TokenType::Function
|
||||||
|| type == TokenType::Return
|
|| type == TokenType::Return
|
||||||
|| type == TokenType::Let
|
|| type == TokenType::Let
|
||||||
|| type == TokenType::Catch
|
|
||||||
|| type == TokenType::Class
|
|| type == TokenType::Class
|
||||||
|| type == TokenType::Delete
|
|| type == TokenType::Delete
|
||||||
|| type == TokenType::Do
|
|| type == TokenType::Do
|
||||||
|
|
|
@ -52,6 +52,8 @@ public:
|
||||||
NonnullRefPtr<VariableDeclaration> parse_variable_declaration();
|
NonnullRefPtr<VariableDeclaration> parse_variable_declaration();
|
||||||
NonnullRefPtr<ForStatement> parse_for_statement();
|
NonnullRefPtr<ForStatement> parse_for_statement();
|
||||||
NonnullRefPtr<IfStatement> parse_if_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_expression(int min_precedence, Associativity associate = Associativity::Right);
|
||||||
NonnullRefPtr<Expression> parse_primary_expression();
|
NonnullRefPtr<Expression> parse_primary_expression();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue